From 740b14f9da344df93f4fa16557a920e95c698923 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Wed, 6 Nov 2024 17:37:57 -0500 Subject: [PATCH] keep working on vm --- src/main.rs | 7 ++----- src/value.rs | 16 ++++++++-------- src/vm.rs | 53 ++++++++++++++++++++++++++++------------------------ 3 files changed, 39 insertions(+), 37 deletions(-) diff --git a/src/main.rs b/src/main.rs index c8682d3..ce1cf8c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,12 +59,9 @@ pub fn main() { .unwrap(); println!("{}", ast); - let mut ctx = Ctx { - local_names: vec!["foo"], - local_values: vec![Value::Keyword("foo")], - }; + let mut ctx = vec![("foo", Value::Number(42.0))]; - let result = eval(ast, &mut ctx).unwrap(); + let result = eval(&ast, &mut ctx).unwrap(); println!("{}", result); } diff --git a/src/value.rs b/src/value.rs index 9783a41..2deb170 100644 --- a/src/value.rs +++ b/src/value.rs @@ -19,18 +19,18 @@ pub struct Fn<'src> { } #[derive(Debug, PartialEq)] -pub enum Value { +pub enum Value<'src> { Nil, Boolean(bool), Number(f64), - Keyword(&'static str), - String(&'static str), + Keyword(&'src str), + String(&'src str), // on the heap for now Tuple(Rc>), // ref-counted, immutable, persistent List(Rc>), // ref-counted, immutable, persistent - Dict(Rc>), + Dict(Rc>), // Fn(Rc>), // Set(HashSet), // Sets are hard @@ -44,8 +44,8 @@ pub enum Value { // pkgs, nses, tests } -impl<'src> Clone for Value { - fn clone(&self) -> Value { +impl<'src> Clone for Value<'src> { + fn clone(&self) -> Value<'src> { match self { Value::Nil => Value::Nil, Value::Boolean(b) => Value::Boolean(b.clone()), @@ -59,7 +59,7 @@ impl<'src> Clone for Value { } } -impl<'src> fmt::Display for Value { +impl<'src> fmt::Display for Value<'src> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { Value::Nil => write!(f, "nil"), @@ -89,7 +89,7 @@ impl<'src> fmt::Display for Value { } } -impl Value { +impl<'src> Value<'src> { pub fn bool(&self) -> bool { match self { Value::Nil | Value::Boolean(false) => false, diff --git a/src/vm.rs b/src/vm.rs index b312faa..abea333 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -18,33 +18,31 @@ pub struct LudusError { // 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)>, + pub locals: Vec<(&'src str, Value<'src>)>, } -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; - } +impl<'src> Ctx<'src> { + pub fn resolve(&self, name: &'src str) -> Value { + if let Some((_, val)) = self.locals.iter().rev().find(|(bound, _)| *bound == name) { + val.clone() + } else { + unreachable!() } - value } - pub fn store(&mut self, name: &'static str, value: Value) { - self.local_names.push(name); - self.local_values.push(value); + pub fn store(&mut self, name: &'src str, value: Value<'src>) { + self.locals.push((name, value)); } } -pub fn eval<'src>(ast: Ast<'src>, ctx: &mut Ctx) -> Result { +pub fn eval<'src, 'a>( + ast: &Ast<'src>, + ctx: &'a mut Vec<(&'src str, Value<'src>)>, +) -> Result, LudusError> { match ast { Ast::Nil => Ok(Value::Nil), - Ast::Boolean(b) => Ok(Value::Boolean(b)), - Ast::Number(n) => Ok(Value::Number(n)), + 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) => { @@ -55,30 +53,37 @@ pub fn eval<'src>(ast: Ast<'src>, ctx: &mut Ctx) -> Result { Ok(result) } Ast::If(cond, if_true, if_false) => { - let truthy = eval((*cond).0, ctx)?.bool(); + let truthy = eval(&cond.0, ctx)?.bool(); if truthy { let (if_true, _) = *if_true; - eval(if_true, ctx) + eval(&if_true, ctx) } else { - let (if_false, _) = *if_false; - eval(if_false, ctx) + 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)?) + 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)?); + vect.push(eval(&member.0, ctx)?); } Ok(Value::Tuple(Rc::new(vect))) } - Ast::Word(w) => Ok(ctx.resolve(w)), + Ast::Word(w) => { + let val = if let Some((_, value)) = ctx.iter().rev().find(|(name, _)| w == name) { + value.clone() + } else { + unreachable!() + }; + Ok(val) + } _ => todo!(), } }