diff --git a/src/lisp/prelude.rs b/src/lisp/prelude.rs index a3e9c3f..a740228 100644 --- a/src/lisp/prelude.rs +++ b/src/lisp/prelude.rs @@ -97,7 +97,7 @@ pub fn prelude_lambda(_env: &Environment, expr: Expression) -> Result Result { let [bindings, body] = expr.try_into()?; - let bindings = CellIterator::new(bindings) + let bindings = CellIterator::new(eval(env, bindings)?) .map(|e| { let (s, e) = e?.try_into()?; if let Expression::Symbol(s) = s { @@ -158,6 +158,14 @@ pub fn prelude_gt(env: &Environment, expr: Expression) -> Result Result { + let [a] = expr.try_into()?; + match a { + Expression::Nil => Ok(Expression::True), + _ => Ok(Expression::Nil), + } +} + pub fn prelude_set(env: &Environment, expr: Expression) -> Result { let [s, e] = expr.try_into()?; @@ -178,6 +186,31 @@ pub fn prelude_print(env: &Environment, expr: Expression) -> Result Result { + let [a, b] = expr.try_into()?; + Ok(Expression::Cell( + Box::new(eval(env, a)?), + Box::new(eval(env, b)?), + )) +} + +pub fn prelude_car(env: &Environment, expr: Expression) -> Result { + let [arg] = expr.try_into()?; + let (a, _) = eval(env, arg)?.try_into()?; + Ok(a) +} + +pub fn prelude_cdr(env: &Environment, expr: Expression) -> Result { + let [arg] = expr.try_into()?; + let (_, b) = eval(env, arg)?.try_into()?; + Ok(b) +} + +pub fn prelude_eval(env: &Environment, expr: Expression) -> Result { + let [e] = expr.try_into()?; + eval(env, eval(env, e)?) +} + pub fn mk_prelude(layer: &mut EnvironmentLayer) { layer.set("+".to_string(), Expression::Function(prelude_add)); layer.set("-".to_string(), Expression::Function(prelude_sub)); @@ -185,10 +218,15 @@ pub fn mk_prelude(layer: &mut EnvironmentLayer) { layer.set("/".to_string(), Expression::Function(prelude_div)); layer.set("lambda".to_string(), Expression::Function(prelude_lambda)); layer.set("if".to_string(), Expression::Function(prelude_if)); - layer.set("==".to_string(), Expression::Function(prelude_eq)); + layer.set("=".to_string(), Expression::Function(prelude_eq)); layer.set("<".to_string(), Expression::Function(prelude_lt)); layer.set(">".to_string(), Expression::Function(prelude_gt)); + layer.set("not".to_string(), Expression::Function(prelude_not)); layer.set("let".to_string(), Expression::Function(prelude_let)); layer.set("set".to_string(), Expression::Function(prelude_set)); layer.set("print".to_string(), Expression::Function(prelude_print)); + layer.set("cons".to_string(), Expression::Function(prelude_cons)); + layer.set("car".to_string(), Expression::Function(prelude_car)); + layer.set("cdr".to_string(), Expression::Function(prelude_cdr)); + layer.set("eval".to_string(), Expression::Function(prelude_eval)); } diff --git a/src/main.rs b/src/main.rs index 26ac13f..70d05c3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,20 +5,26 @@ use parser::ExpressionStream; use crate::lisp::{eval, Environment}; fn main() { - let program1 = "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)"; - let program2 = "(set 'myvar \"hello world!\")"; - let program3 = "(print myvar) (print 'myvar)"; + let programs = [ + "((lambda (x y) (+ (if (< x 10) (* x 11) x) y)) 2 20)", + "(set 'myvar \"hello world!\")", + "(print myvar) (print 'myvar)", + "(car (cons 'a 'b)) (cdr (cons 'c 'd)) (cons 'a 'b)", + "(eval (car (cons 'myvar 'b)))", + "(set 'pow (lambda (a b) (if (= b 0) 1 (* a (pow a (- b 1))))))", + "pow", + "(pow 2 10)", + "(let '((fib . (lambda (n) (if (< n 2) n (+ (fib (- n 1)) (fib (- n 2))))))) (fib 10))", + ]; let environment = Environment::default(); - for r in ExpressionStream::from_char_stream( - program1 - .chars() - .chain(program2.chars()) - .chain(program3.chars()), - ) { + for r in ExpressionStream::from_char_stream(programs.iter().map(|p| p.chars()).flatten()) { match r { - Err(err) => println!("ParserError: {:?}", err), + Err(err) => { + println!("ParserError: {:?}", err); + break; + } Ok(expr) => { println!("Evaluating: {}", expr.clone()); match eval(&environment, expr) { @@ -30,5 +36,4 @@ fn main() { } println!("Interpreter Done!"); - println!("Environment: {:?}", environment); }