1use super::{operation, Evaluator, NameSpace};
2use crate::ir::{Expr, Program};
3use crate::{MiniError, MiniResult, Printer};
4
5#[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}