diff --git a/src/ast.rs b/src/ast.rs index 39354de..d811fde 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -59,6 +59,13 @@ impl Location { pub fn new_variable(name: impl Into) -> Self { Self::Variable { name: name.into() } } + + pub fn new_field(table: impl Into, name: impl Into) -> Self { + Self::Field { + table: Box::new(table.into()), + index: Box::new(Expression::new_constant(name.into())), + } + } } impl Expression { diff --git a/src/twopass.rs b/src/twopass.rs index 27b9200..88f1937 100644 --- a/src/twopass.rs +++ b/src/twopass.rs @@ -427,4 +427,36 @@ mod tests { assert_eq!(ret, Some(3.into())); assert_eq!(env.get("x".into()), Some(1.into())); } + + #[test] + fn test_self_assign() { + let testee = Function { + name: Some("testee".into()), + args: vec![], + body: vec![ + Statement::Assign { + target: Location::new_variable("x"), + source: Box::new(Expression::new_constant(42)), + }, + Statement::Local { + name: "x".into(), + init: Some(Box::new(Expression::new_variable("x"))), + }, + Statement::Assign { + target: Location::new_field(Expression::new_variable("_ENV"), "x"), + source: Box::new(Expression::new_constant(666)), + }, + Statement::Local { + name: "y".into(), + init: Some(Box::new(Expression::new_variable("x"))), + }, + ], + ret: Some(Box::new(Expression::new_variable("y"))), + }; + let env = crate::types::Table::default(); + let testee = build(&testee); + let ret = testee.call(Some(env.clone().into()), &[]); + assert_eq!(ret, Some(42.into())); + assert_eq!(env.get("x".into()), Some(666.into())); + } }