use crate::parser::*; use crate::value::*; use imbl::Vector; use std::rc::Rc; #[derive(Clone, Debug)] pub struct LudusError { msg: String, } // oy // lifetimes are a mess // I need 'src kind of everywhere // But (maybe) using 'src in eval // for ctx // means I can't borrow it mutably // I guess the question is how to get // the branches for Ast::Block and Ast::If // to work with a mutable borrow of ctx pub struct Ctx<'src> { locals: Vec<(&'src str, Value)>, } impl Ctx { pub fn resolve(&self, name: &str) -> Value { let len = self.local_names.len(); let mut value = Value::Nil; for i in (0..len).rev() { if self.local_names[i] == name { value = self.local_values[i].clone(); break; } } value } pub fn store(&mut self, name: &'static str, value: Value) { self.local_names.push(name); self.local_values.push(value); } } pub fn eval<'src>(ast: Ast<'src>, ctx: &mut Ctx) -> Result { match ast { Ast::Nil => Ok(Value::Nil), Ast::Boolean(b) => Ok(Value::Boolean(b)), Ast::Number(n) => Ok(Value::Number(n)), Ast::Keyword(k) => Ok(Value::Keyword(k.clone())), Ast::String(s) => Ok(Value::String(s.clone())), Ast::Block(exprs) => { let mut result = Value::Nil; for (expr, _) in exprs { result = eval(expr, ctx)?; } Ok(result) } Ast::If(cond, if_true, if_false) => { let truthy = eval((*cond).0, ctx)?.bool(); if truthy { let (if_true, _) = *if_true; eval(if_true, ctx) } else { let (if_false, _) = *if_false; eval(if_false, ctx) } } Ast::List(members) => { let mut vect = Vector::new(); for member in members { vect.push_back(eval(member.0, ctx)?) } Ok(Value::List(Rc::new(vect))) } Ast::Tuple(members) => { let mut vect = Vec::new(); for member in members { vect.push(eval(member.0, ctx)?); } Ok(Value::Tuple(Rc::new(vect))) } Ast::Word(w) => Ok(ctx.resolve(w)), _ => todo!(), } }