1use std::collections::HashMap;
6
7use anyhow::{anyhow, Result};
8
9use crate::ops::math::{Expr, Assign};
10
11pub type Env = HashMap<String, i64>;
13
14pub fn eval_expr(expr: &Expr, env: &mut Env) -> Result<i64> {
16 match expr {
17 Expr::Number(n) => Ok(*n),
18
19 Expr::Var(name) => env
20 .get(name)
21 .cloned()
22 .ok_or_else(|| anyhow!("variable `{}` not defined", name)),
23
24 Expr::Mul(l, r) => Ok(eval_expr(l, env)? * eval_expr(r, env)?),
25
26 Expr::Add(l, r) => Ok(eval_expr(l, env)? + eval_expr(r, env)?),
27
28 Expr::Sub(l, r) => Ok(eval_expr(l, env)? - eval_expr(r, env)?),
29
30 Expr::Ref { var, modifier } => {
31 let val = env
32 .get(var)
33 .cloned()
34 .ok_or_else(|| anyhow!("variable `{}` not defined", var))?;
35 match modifier {
38 Some(mod_val) => Ok(val % mod_val),
39 None => Ok(val),
40 }
41 }
42 }
43}
44
45pub fn run_program(assignments: &[Assign]) -> Result<Env> {
48 let mut env = Env::new();
49
50 for assign in assignments {
51 let value = eval_expr(&assign.value, &mut env)?;
52 env.insert(assign.name.clone(), value);
53 }
54
55 Ok(env)
56}