From d861d91397e532667ebb718370d965a0b1212ac3 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Wed, 8 Feb 2023 01:54:53 -0500 Subject: [PATCH] Fix ', add if and = along with bools --- kr/src/ast.rs | 14 +++++++++++--- kr/src/grammar.lalrpop | 8 ++++---- kr/src/main.rs | 28 ++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/kr/src/ast.rs b/kr/src/ast.rs index 386cd14..a18bffb 100644 --- a/kr/src/ast.rs +++ b/kr/src/ast.rs @@ -1,15 +1,23 @@ use std::rc::Rc; -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub enum Form { + Nil, Int(i32), + Bool(bool), Symbol(String), Pair(Rc
,Rc), - DeriComb { se: Rc, de: Option, params: Rc, body: Rc }, PrimComb(String, fn(Rc, Rc) -> Rc), - Nil, + DeriComb { se: Rc, de: Option, params: Rc, body: Rc }, } impl Form { + pub fn truthy(&self) -> bool { + match self { + Form::Bool(b) => *b, + Form::Nil => false, + _ => true, + } + } pub fn int(&self) -> Option { match self { Form::Int(i) => Some(*i), diff --git a/kr/src/grammar.lalrpop b/kr/src/grammar.lalrpop index 65b7f4b..6a429f2 100644 --- a/kr/src/grammar.lalrpop +++ b/kr/src/grammar.lalrpop @@ -8,7 +8,7 @@ pub Term: Form = { NUM => Form::Int(i32::from_str(<>).unwrap()), SYM => Form::Symbol(<>.to_owned()), "(" ")" => <>.unwrap_or(Form::Nil), - "'" => Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(<>)), + "'" => Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(Form::Pair(Rc::new(<>), Rc::new(Form::Nil)))), }; ListInside: Form = { => Form::Pair(Rc::new(<>), Rc::new(Form::Nil)), @@ -20,8 +20,8 @@ match { ")", ".", "'", - r"[0-9]+" => NUM, - r"[a-zA-Z+*/_-][\w+*/_-]*" => SYM, - r"(;[^\n]*\n)|\s+" => { } + r"[0-9]+" => NUM, + r"[a-zA-Z+*/_=-][\w+*/=_-]*" => SYM, + r"(;[^\n]*\n)|\s+" => { } } diff --git a/kr/src/main.rs b/kr/src/main.rs index 341bf33..8e7367b 100644 --- a/kr/src/main.rs +++ b/kr/src/main.rs @@ -105,8 +105,20 @@ fn main() { Rc::new(Form::DeriComb { se: e, de, params, body }) }))), - ("quote", Rc::new(Form::PrimComb("quote".to_owned(), |e, p| { - p + ("=", Rc::new(Form::PrimComb("=".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()); + let b = eval(e, p.cdr().unwrap().car().unwrap()); + Rc::new(Form::Bool(a == b)) + }))), + ("if", Rc::new(Form::PrimComb("if".to_owned(), |e, p| { + if eval(Rc::clone(&e), p.car().unwrap()).truthy() { + eval(e, p.cdr().unwrap().car().unwrap()) + } else if let Some(els) = p.cdr().unwrap().cdr().and_then(|x| x.car()) { + eval(e, els) + } else { + // should we really allow this? (2 arg if with no else) + Rc::new(Form::Nil) + } }))), ("+", Rc::new(Form::PrimComb("+".to_owned(), |e, p| { let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); @@ -124,9 +136,17 @@ fn main() { ("cdr", Rc::new(Form::PrimComb("cdr".to_owned(), |e, p| { eval(Rc::clone(&e), p.car().unwrap()).cdr().unwrap() }))), + ("quote", Rc::new(Form::PrimComb("quote".to_owned(), |e, p| { + p.car().unwrap() + }))), ]); //let input = "(+ 2 (car (cons 4 '(1 2))))"; - let input = "((vau d p (+ (eval (car p) d) 13)) (+ 1 3))"; - let result = eval(env, Rc::new(grammar::TermParser::new().parse(input).unwrap())); + let input = "(= 17 ((vau d p (+ (eval (car p) d) 13)) (+ 1 3)))"; + //let input = "(if (= 2 2) (+ 1 2) (+ 3 4))"; + //let input = "(quote a)"; + //let input = "'a"; + let parsed_input = grammar::TermParser::new().parse(input).unwrap(); + println!("Parsed input is {:?}", parsed_input); + let result = eval(env, Rc::new(parsed_input)); println!("Result is {:?}", result); }