From 99ade727568130fdb8cb03ff052dc1b0f7515006 Mon Sep 17 00:00:00 2001 From: John Date: Tue, 9 Jan 2024 22:39:58 -0600 Subject: [PATCH] interpreter: fix variable resolution and assignment --- libconlang/src/interpreter.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/libconlang/src/interpreter.rs b/libconlang/src/interpreter.rs index 8db2dc8..1487a1f 100644 --- a/libconlang/src/interpreter.rs +++ b/libconlang/src/interpreter.rs @@ -351,21 +351,25 @@ impl Interpret for Operation { impl Interpret for Assign { fn interpret(&self, env: &mut Environment) -> IResult { use operator::Assign; - let math::Assign { target, operator, init } = self; + let math::Assign { target: Identifier { name, .. }, operator, init } = self; let init = init.interpret(env)?; - let target = env.get_mut(&target.name)?; + let target = env.get_mut(name)?; if let Assign::Assign = operator { use std::mem::discriminant as variant; // runtime typecheck match target { - value if variant(value) == variant(&init) => { + Some(value) if variant(value) == variant(&init) => { *value = init; } + value @ None => *value = Some(init), _ => Err(Error::TypeError)?, } return Ok(ConValue::Empty); } + let Some(target) = target else { + return Err(Error::NotInitialized(name.into())); + }; match operator { Assign::AddAssign => target.add_assign(init)?, @@ -803,22 +807,22 @@ pub mod env { pub fn frame(&mut self, name: &'static str) -> Frame { Frame::new(self, name) } - /// Resolves a variable mutably + /// Resolves a variable mutably. /// - /// Returns a mutable reference to the variable's record, if it exists - pub fn get_mut(&mut self, id: &str) -> IResult<&mut ConValue> { - for (frame, _) in self.frames.iter_mut() { - match frame.get_mut(id) { - Some(Some(var)) => return Ok(var), - Some(None) => return Err(Error::NotInitialized(id.into())), - _ => (), + /// Returns a mutable reference to the variable's record, if it exists. + pub fn get_mut(&mut self, id: &str) -> IResult<&mut Option> { + for (frame, _) in self.frames.iter_mut().rev() { + if let Some(var) = frame.get_mut(id) { + return Ok(var); } } Err(Error::NotDefined(id.into())) } - /// Resolves a variable immutably + /// Resolves a variable immutably. + /// + /// Returns a reference to the variable's contents, if it is defined and initialized. pub fn get(&self, id: &str) -> IResult<&ConValue> { - for (frame, _) in self.frames.iter() { + for (frame, _) in self.frames.iter().rev() { match frame.get(id) { Some(Some(var)) => return Ok(var), Some(None) => return Err(Error::NotInitialized(id.into())),