compose_eval/expression/
assignment.rs

1use crate::access::Access;
2use crate::{Eval, Evaluated, Machine};
3use compose_library::diag::{At, SourceResult, StrResult, bail};
4use compose_library::{Value, ops};
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        match self.op() {
11            AssignOp::Assign => apply_assignment(self, vm, |_init, rhs| Ok(rhs.clone())),
12            AssignOp::AddAssign => apply_assignment(self, vm, ops::add),
13            AssignOp::SubAssign => apply_assignment(self, vm, ops::sub),
14            AssignOp::MulAssign => apply_assignment(self, vm, ops::mul),
15            other => bail!(self.span(), "unsupported assignment operator: {:?}", other),
16        }
17    }
18}
19
20fn apply_assignment(
21    binary: ast::Assignment,
22    vm: &mut Machine,
23    op: fn(&Value, &Value) -> StrResult<Value>,
24) -> SourceResult<Evaluated> {
25    // assignments are right associative
26    let rhs = binary.rhs().eval(vm)?;
27
28    let lhs = binary.lhs().access(vm)?;
29    let value = op(&lhs, &rhs.value).at(binary.span())?;
30    *lhs = value;
31
32    Ok(Evaluated::unit())
33}