compose_eval/expression/
assignment.rs

1use crate::access::Access;
2use crate::{Eval, Evaluated, Machine};
3use compose_library::diag::{bail, At, SourceResult};
4use compose_library::{ops, Value};
5use compose_syntax::ast;
6use compose_syntax::ast::{AssignOp, AstNode};
7
8impl Eval for ast::Assignment<'_> {
9    fn eval(self, vm: &mut Machine) -> SourceResult<Evaluated> {
10        let op = match self.op() {
11            AssignOp::Assign => |_init: &Value, rhs: &Value| Ok(rhs.clone()),
12            AssignOp::AddAssign => ops::add,
13            AssignOp::SubAssign => ops::sub,
14            AssignOp::MulAssign => ops::mul,
15            AssignOp::DivAssign => ops::div,
16            other => bail!(self.span(), "unsupported assignment operator: {:?}", other),
17        };
18
19        // assignments are right associative
20        let rhs = self.rhs().eval(vm)?;
21
22        let lhs = self.lhs().access(vm)?;
23        let value = op(&lhs, &rhs.value).at(self.span())?;
24        *lhs = value;
25
26        Ok(Evaluated::unit())
27    }
28}