From 79b169d9513017b9849696d0d49f78b0b8401076 Mon Sep 17 00:00:00 2001 From: mark Date: Thu, 11 May 2023 01:56:33 +0200 Subject: [PATCH] fixed bug where all but the first loop iterations would write data to the mutable variables from the last iteration(s) even though the variables are supposed to be completely local: is_init can be set on steatements that have an output_to to force them to always redeclare and never reassign the new value. --- mers/src/script/code_runnable.rs | 26 ++++++++++++++++---------- mers/src/script/to_runnable.rs | 6 +++--- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/mers/src/script/code_runnable.rs b/mers/src/script/code_runnable.rs index 8a1b220..85dc9a8 100755 --- a/mers/src/script/code_runnable.rs +++ b/mers/src/script/code_runnable.rs @@ -81,27 +81,33 @@ impl RFunction { #[derive(Clone, Debug)] pub struct RStatement { - pub output_to: Option<(usize, usize)>, + // (_, _, is_init) + pub output_to: Option<(usize, usize, bool)>, statement: Box, pub force_output_type: Option, } impl RStatement { pub fn run(&self, vars: &mut Vec, info: &GSInfo) -> VData { let out = self.statement.run(vars, info); - if let Some((v, derefs)) = self.output_to { - let mut val = dereference_n(&mut vars[v], derefs); - fn dereference_n(d: &mut VData, n: usize) -> VData { - if n > 0 { - if let VDataEnum::Reference(v) = &mut d.data.lock().unwrap().0 { - dereference_n(v, n - 1) + if let Some((v, derefs, is_init)) = self.output_to { + // let mut parent = None; + let mut val = &mut vars[v]; + fn deref(n: usize, val: &mut VData, is_init: bool, out: VData) { + if n == 0 { + if is_init { + *val = out.inner().to(); } else { - unreachable!("dereferencing something that isn't a reference in assignment") + val.assign(out.inner()); } } else { - d.clone_mut() + if let VDataEnum::Reference(r) = &mut val.data().0 { + deref(n - 1, r, is_init, out) + } else { + unreachable!("cannot derefence: not a reference."); + } } } - val.assign(out.inner()); + deref(derefs, val, is_init, out); VDataEnum::Tuple(vec![]).to() } else { out diff --git a/mers/src/script/to_runnable.rs b/mers/src/script/to_runnable.rs index aeceb96..c2d50aa 100755 --- a/mers/src/script/to_runnable.rs +++ b/mers/src/script/to_runnable.rs @@ -652,11 +652,11 @@ fn statement( )); } linfo.vars.insert(opt.clone(), (ginfo.vars, out)); - statement.output_to = Some((ginfo.vars, 0)); + statement.output_to = Some((ginfo.vars, 0, true)); ginfo.vars += 1; } else { // mutate existing variable - statement.output_to = Some((*var_id, *derefs)); + statement.output_to = Some((*var_id, *derefs, false)); } } else { let mut out = statement.out(ginfo); @@ -672,7 +672,7 @@ fn statement( } } linfo.vars.insert(opt.clone(), (ginfo.vars, out)); - statement.output_to = Some((ginfo.vars, *derefs)); + statement.output_to = Some((ginfo.vars, *derefs, true)); ginfo.vars += 1; } }