diff --git a/src/value.rs b/src/value.rs index c53fc9a..1181719 100644 --- a/src/value.rs +++ b/src/value.rs @@ -25,10 +25,12 @@ pub enum Value<'src> { // ref-counted, immutable, persistent List(Vector), // ref-counted, immutable, persistent + // dicts may only use keywords as keys Dict(HashMap<&'src str, Self>), Box(&'src str, Rc>), Fn(Rc>), Base(Base<'src>), + Recur(Vec), // Set(HashSet), // Sets are hard // Sets require Eq @@ -57,6 +59,7 @@ impl<'src> Clone for Value<'src> { Value::Box(name, b) => Value::Box(name, b.clone()), Value::Placeholder => Value::Placeholder, Value::Base(b) => Value::Base(b.clone()), + Value::Recur(..) => unreachable!(), } } } @@ -111,6 +114,7 @@ impl<'src> fmt::Display for Value<'src> { }; write!(f, "base fn {}", name) } + Value::Recur(..) => unreachable!(), } } } diff --git a/src/vm.rs b/src/vm.rs index 9a4b284..9995fca 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -482,7 +482,23 @@ pub fn eval<'src, 'a>( Ast::Pair(..) => { unreachable!() } - Ast::Loop(_, _) => todo!(), - Ast::Recur(_) => todo!(), + Ast::Loop(init, clauses) => { + let mut args = eval(&init.0, ctx)?; + loop { + let result = match_clauses(&args, clauses, ctx)?; + if let Value::Recur(recur_args) = result { + args = Value::Tuple(Rc::new(recur_args)); + } else { + return Ok(result); + } + } + } + Ast::Recur(args) => { + let mut vect = Vec::new(); + for arg in args { + vect.push(eval(&arg.0, ctx)?); + } + Ok(Value::Recur(vect)) + } } }