mini_lang/eval/
eager.rs

1use super::{operation, Evaluator, NameSpace};
2use crate::ir::{Expr, Program};
3use crate::{MiniError, MiniResult, Printer};
4
5/// The eager evaluator
6#[derive(Copy, Clone, Debug, PartialEq, Eq)]
7pub struct EagerEval;
8
9impl Evaluator for EagerEval {
10    type Err = MiniError;
11    fn evaluate<P: Printer>(&self, ir: Program, printer: &mut P) -> Result<(), Self::Err> {
12        let Program {
13            funcs,
14            vars,
15            prints,
16        } = ir;
17
18        let mut ns = NameSpace::new();
19        for var in vars {
20            let val = eval_expr(var, &mut ns, &funcs)?;
21            ns.register(val);
22        }
23
24        for print in prints {
25            printer
26                .print(eval_expr(print, &mut ns, &funcs)?)
27                .map_err(MiniError::from_error)?;
28        }
29        Ok(())
30    }
31}
32
33fn funccall(
34    func: Expr,
35    args: Vec<Expr>,
36    ns: &mut NameSpace<i32>,
37    funcs: &[Expr],
38) -> MiniResult<i32> {
39    let depth = ns.chunk();
40    for arg in args {
41        let val = eval_expr(arg, ns, funcs)?;
42        ns.register(val);
43    }
44    let res = eval_expr(func.circulate(depth), ns, funcs)?;
45    ns.back();
46    Ok(res)
47}
48
49fn eval_expr(expr: Expr, ns: &mut NameSpace<i32>, funcs: &[Expr]) -> MiniResult<i32> {
50    Ok(match expr {
51        Expr::Value(v) => v,
52        Expr::Variable(depth, id) => *ns.get(depth, id)?,
53        Expr::Operation(op, lhs, rhs) => {
54            operation(op, eval_expr(*lhs, ns, funcs)?, eval_expr(*rhs, ns, funcs)?)?
55        }
56        Expr::FuncCall(f, a) => funccall(funcs[f].clone(), a, ns, funcs)?,
57        Expr::If(c, t, f) => {
58            if eval_expr(*c, ns, funcs)? != 0 {
59                eval_expr(*t, ns, funcs)?
60            } else {
61                eval_expr(*f, ns, funcs)?
62            }
63        }
64    })
65}