add assignments
This commit is contained in:
parent
d913d8b7a9
commit
985822b03f
53
src/run.rs
53
src/run.rs
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user