add assignments

This commit is contained in:
numzero 2025-04-11 20:40:45 +03:00
parent d913d8b7a9
commit 985822b03f

View File

@ -1,7 +1,7 @@
use std::{collections::HashMap, fmt::Debug, rc::Rc}; use std::{collections::HashMap, fmt::Debug, rc::Rc};
use crate::{ use crate::{
ast::{Constant, Expression, Location}, ast::{Constant, Expression, Location, Statement},
types::{Value, ValueInner}, types::{Value, ValueInner},
}; };
@ -104,6 +104,43 @@ impl Eval for Expression {
} }
} }
pub trait Exec {
fn exec(&self, scope: &mut Scope);
}
impl Exec for Statement {
fn exec(&self, scope: &mut Scope) {
match self {
Statement::Assign { target, source } => {
let value = source.eval(scope);
match target {
Location::Variable { name } => {
scope.set(name.into(), value);
}
Location::Field { table, index } => {
let table = table.eval(scope);
let Some(ValueInner::Table(table)) = table else {
panic!("attempt to index non-table value {table:?}")
};
let index = index.eval(scope);
let Some(index) = index else {
panic!("attempt to index with a nil value")
};
table.set(index, value);
}
};
}
Statement::Call { callee, args } => {
Expression::Call {
callee: callee.clone(),
args: args.clone(),
}
.eval(scope);
}
}
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
@ -178,4 +215,18 @@ mod tests {
Some(49.into()) Some(49.into())
); );
} }
#[test]
fn test_var_assign() {
let mut scope = Scope::default();
assert_eq!(scope.get("foo"), None);
assert_eq!(scope.get("bar"), None);
ast::Statement::Assign {
target: ast::Location::Variable { name: "foo".into() },
source: Box::new(ast::Expression::Constant(ast::Constant::Number(42))),
}
.exec(&mut scope);
assert_eq!(scope.get("foo"), Some(42.into()));
assert_eq!(scope.get("bar"), None);
}
} }