Fix ', add if and = along with bools
This commit is contained in:
@@ -1,15 +1,23 @@
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Eq, PartialEq)]
|
||||||
pub enum Form {
|
pub enum Form {
|
||||||
|
Nil,
|
||||||
Int(i32),
|
Int(i32),
|
||||||
|
Bool(bool),
|
||||||
Symbol(String),
|
Symbol(String),
|
||||||
Pair(Rc<Form>,Rc<Form>),
|
Pair(Rc<Form>,Rc<Form>),
|
||||||
DeriComb { se: Rc<Form>, de: Option<String>, params: Rc<Form>, body: Rc<Form> },
|
|
||||||
PrimComb(String, fn(Rc<Form>, Rc<Form>) -> Rc<Form>),
|
PrimComb(String, fn(Rc<Form>, Rc<Form>) -> Rc<Form>),
|
||||||
Nil,
|
DeriComb { se: Rc<Form>, de: Option<String>, params: Rc<Form>, body: Rc<Form> },
|
||||||
}
|
}
|
||||||
impl Form {
|
impl Form {
|
||||||
|
pub fn truthy(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Form::Bool(b) => *b,
|
||||||
|
Form::Nil => false,
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn int(&self) -> Option<i32> {
|
pub fn int(&self) -> Option<i32> {
|
||||||
match self {
|
match self {
|
||||||
Form::Int(i) => Some(*i),
|
Form::Int(i) => Some(*i),
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ pub Term: Form = {
|
|||||||
NUM => Form::Int(i32::from_str(<>).unwrap()),
|
NUM => Form::Int(i32::from_str(<>).unwrap()),
|
||||||
SYM => Form::Symbol(<>.to_owned()),
|
SYM => Form::Symbol(<>.to_owned()),
|
||||||
"(" <ListInside?> ")" => <>.unwrap_or(Form::Nil),
|
"(" <ListInside?> ")" => <>.unwrap_or(Form::Nil),
|
||||||
"'" <Term> => Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(<>)),
|
"'" <Term> => Form::Pair(Rc::new(Form::Symbol("quote".to_owned())), Rc::new(Form::Pair(Rc::new(<>), Rc::new(Form::Nil)))),
|
||||||
};
|
};
|
||||||
ListInside: Form = {
|
ListInside: Form = {
|
||||||
<Term> => Form::Pair(Rc::new(<>), Rc::new(Form::Nil)),
|
<Term> => Form::Pair(Rc::new(<>), Rc::new(Form::Nil)),
|
||||||
@@ -21,7 +21,7 @@ match {
|
|||||||
".",
|
".",
|
||||||
"'",
|
"'",
|
||||||
r"[0-9]+" => NUM,
|
r"[0-9]+" => NUM,
|
||||||
r"[a-zA-Z+*/_-][\w+*/_-]*" => SYM,
|
r"[a-zA-Z+*/_=-][\w+*/=_-]*" => SYM,
|
||||||
r"(;[^\n]*\n)|\s+" => { }
|
r"(;[^\n]*\n)|\s+" => { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -105,8 +105,20 @@ fn main() {
|
|||||||
|
|
||||||
Rc::new(Form::DeriComb { se: e, de, params, body })
|
Rc::new(Form::DeriComb { se: e, de, params, body })
|
||||||
}))),
|
}))),
|
||||||
("quote", Rc::new(Form::PrimComb("quote".to_owned(), |e, p| {
|
("=", Rc::new(Form::PrimComb("=".to_owned(), |e, p| {
|
||||||
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| {
|
("+", Rc::new(Form::PrimComb("+".to_owned(), |e, p| {
|
||||||
let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap();
|
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| {
|
("cdr", Rc::new(Form::PrimComb("cdr".to_owned(), |e, p| {
|
||||||
eval(Rc::clone(&e), p.car().unwrap()).cdr().unwrap()
|
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 = "(+ 2 (car (cons 4 '(1 2))))";
|
||||||
let input = "((vau d p (+ (eval (car p) d) 13)) (+ 1 3))";
|
let input = "(= 17 ((vau d p (+ (eval (car p) d) 13)) (+ 1 3)))";
|
||||||
let result = eval(env, Rc::new(grammar::TermParser::new().parse(input).unwrap()));
|
//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);
|
println!("Result is {:?}", result);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user