Skip to main content

nomiscript/
eval.rs

1use crate::ast::{Expr, Program};
2use crate::compiler::expr::{eval_value, format_expr};
3use crate::error::{Error, Result};
4use crate::runtime::{SymbolTable, Value};
5
6pub fn eval_program(symbols: &mut SymbolTable, program: &Program) -> Result<Value> {
7    if program.exprs.is_empty() {
8        return Ok(Value::Nil);
9    }
10    for expr in &program.exprs[..program.exprs.len() - 1] {
11        eval_value(symbols, expr)?;
12    }
13    let value = eval_value(symbols, program.exprs.last().unwrap())?;
14    expr_to_value(&value)
15}
16
17fn expr_to_value(expr: &Expr) -> Result<Value> {
18    match expr {
19        Expr::Nil => Ok(Value::Nil),
20        Expr::Bool(b) => Ok(Value::Bool(*b)),
21        Expr::Number(n) => Ok(Value::Number(*n)),
22        Expr::String(s) => Ok(Value::String(s.clone())),
23        Expr::Symbol(s) => Ok(Value::Symbol(s.clone())),
24        Expr::Quote(inner) => quoted_to_value(inner),
25        Expr::List(_) => Ok(Value::String(format_expr(expr))),
26        Expr::Lambda(_, _) => Ok(Value::String(format_expr(expr))),
27        Expr::RuntimeValue(val) => Ok(val.clone()),
28        _ => Err(Error::Compile(format!("unsupported expression: {expr:?}"))),
29    }
30}
31
32fn quoted_to_value(inner: &Expr) -> Result<Value> {
33    match inner {
34        Expr::Nil => Ok(Value::Nil),
35        Expr::Bool(b) => Ok(Value::Bool(*b)),
36        Expr::Number(n) => Ok(Value::Number(*n)),
37        Expr::String(s) => Ok(Value::String(s.clone())),
38        Expr::Symbol(s) => Ok(Value::Symbol(s.clone())),
39        Expr::List(elems) => {
40            let inner: Vec<_> = elems.iter().map(format_expr).collect();
41            Ok(Value::String(format!("({})", inner.join(" "))))
42        }
43        _ => Err(Error::Compile(format!(
44            "unsupported quoted expression: {inner:?}"
45        ))),
46    }
47}