misc: Chesterton's Fence

Everything is a list in lisp for a reason 🙃
This commit is contained in:
Roman Godmaire 2024-05-12 08:11:12 -04:00
parent 047db2b188
commit 02463197c3
13 changed files with 245 additions and 486 deletions

View file

@ -54,6 +54,13 @@ macro_rules! ordering {
pub(super) fn core() -> HashMap<String, Value> { pub(super) fn core() -> HashMap<String, Value> {
[ [
(
"dbg",
NativeFunc(|args| {
dbg!(args);
Node::Void
}),
),
// Arithmetic operations // Arithmetic operations
("+", arithmetic!(+)), ("+", arithmetic!(+)),
("-", arithmetic!(-)), ("-", arithmetic!(-)),

View file

@ -26,6 +26,8 @@ pub enum Error {
#[error("system error {0}")] #[error("system error {0}")]
SystemError(String), SystemError(String),
#[error("INTERNAL: Incorrect macro expansion, please file a bug report")]
MacroExpansion,
#[error("please file a bug report")] #[error("please file a bug report")]
Unreachable, Unreachable,
} }

View file

@ -6,7 +6,29 @@ use mute_parser::Node;
pub fn eval(env: &Environment, ast: Vec<Node>) -> Result<Vec<Node>> { pub fn eval(env: &Environment, ast: Vec<Node>) -> Result<Vec<Node>> {
let mut exprs = Vec::new(); let mut exprs = Vec::new();
for node in ast { let mut ast = ast.into_iter();
loop {
let node = match ast.next() {
Some(node) => node,
None => break,
};
if let Node::List(list) = &node {
if let Some(Node::Macro(body)) = list.first() {
let mut body = body.iter();
let parameters = body.next().ok_or_else(|| todo!())?;
let parameters = read_parameters(parameters.clone())?;
let args = list.clone().into_iter().skip(1).collect::<Vec<Node>>();
ast = expand_macro(env, parameters.to_owned(), args, body.cloned().collect())?
.into_iter()
.chain(ast)
.collect::<Vec<Node>>()
.into_iter();
continue;
}
}
let res = eval_node(env, node)?; let res = eval_node(env, node)?;
if let Node::Void = res { if let Node::Void = res {
continue; continue;
@ -31,7 +53,11 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
let operator = eval_node(env, list.next().ok_or(Error::InvalidOperator)?)?; let operator = eval_node(env, list.next().ok_or(Error::InvalidOperator)?)?;
match operator.borrow() { match operator.borrow() {
Node::Function { parameters, body } => { Node::Function(body) => {
let mut body = body.iter();
let parameters = body.next().ok_or_else(|| todo!())?;
let parameters = read_parameters(parameters.clone())?;
let args = list; let args = list;
if args.len() != parameters.len() { if args.len() != parameters.len() {
Err(Error::MismatchedArgCount(parameters.len(), args.len()))? Err(Error::MismatchedArgCount(parameters.len(), args.len()))?
@ -44,13 +70,30 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
let records = parameters.iter().map(|k| k.to_owned()).zip(args).collect(); let records = parameters.iter().map(|k| k.to_owned()).zip(args).collect();
let env = env.wrap(records); let env = env.wrap(records);
let res = eval(&env, (*body).clone())?; let res = eval(&env, body.cloned().collect::<Vec<Node>>())?;
match res.last() { match res.last() {
Some(node) => node.to_owned(), Some(node) => node.to_owned(),
None => Node::Void, None => Node::Void,
} }
} }
Node::Macro(body) => {
let mut body = body.iter();
let parameters = body.next().ok_or_else(|| todo!())?;
let parameters = read_parameters(parameters.clone())?;
let args = list;
match expand_macro(
env,
parameters.clone(),
args.collect(),
body.cloned().collect::<Vec<Node>>(),
)? {
nodes if nodes.len() == 1 => nodes[0].to_owned(),
_ => Err(Error::MacroExpansion)?,
}
}
// HACK: This feels sooooooo wrong but it works // HACK: This feels sooooooo wrong but it works
// Native Functions /should/ be their own type, but they're not. // Native Functions /should/ be their own type, but they're not.
Node::Symbol(sym) => { Node::Symbol(sym) => {
@ -71,35 +114,68 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
} }
} }
Node::Define { args } => { Node::Define(body) => {
args.into_iter() body.into_iter()
.map(|(k, v)| Ok((k.to_owned(), eval_node(env, v)?))) .map(|n| match n {
Node::List(list) if list.len() == 2 => Ok((list[0].clone(), list[1].clone())),
Node::List(list) => Err(Error::MismatchedArgCount(2, list.len()))?,
_ => todo!(),
})
.map(|n| match n {
Ok((Node::Symbol(k), v)) => Ok((k.to_owned(), eval_node(env, v)?)),
Ok(_) => todo!(),
Err(e) => Err(e),
})
.collect::<Result<Vec<(String, Node)>>>()? .collect::<Result<Vec<(String, Node)>>>()?
.into_iter() .into_iter()
.for_each(|(k, v)| env.set(k, v)); .for_each(|(k, v)| env.set(k, v));
Node::Void Node::Void
} }
Node::Let { args, body } => { Node::Let(body) => {
let args = args let mut body = body.into_iter();
.into_iter() let args = match body.next().ok_or_else(|| todo!())? {
.map(|(k, v)| Ok((k.to_owned(), eval_node(env, v)?))) Node::List(list) => list
.collect::<Result<Vec<(String, Node)>>>()?; .into_iter()
.map(|n| match n {
Node::List(list) if list.len() == 2 => {
Ok((list[0].clone(), list[1].clone()))
}
Node::List(list) => Err(Error::MismatchedArgCount(2, list.len()))?,
_ => todo!(),
})
.map(|n| match n {
Ok((Node::Symbol(k), v)) => Ok((k.to_owned(), eval_node(env, v)?)),
Ok(_) => todo!(),
Err(e) => Err(e),
})
.collect::<Result<Vec<(String, Node)>>>()?,
_ => Err(Error::MismatchedArgCount(1, 1))?,
};
let body = body.collect();
let env = env.wrap(args); let env = env.wrap(args);
eval(&env, body)?.last().unwrap().to_owned() eval(&env, body)?.last().unwrap().to_owned()
} }
Node::If { Node::If(body) => {
cond, if body.len() != 2 && body.len() != 3 {
consequence, Err(Error::MismatchedArgCount(3, body.len()))?
alternative, }
} => {
let cond = eval_node(env, *cond)?; let mut body = body.iter();
let cond = body.next().expect("arg count verified above").clone();
let consequence = body.next().expect("arg count verified above").clone();
let alternative = match body.next() {
Some(node) => node.clone(),
None => Node::Nil,
};
let cond = eval_node(env, cond)?;
match cond { match cond {
Node::Boolean(true) => eval_node(env, *consequence)?, Node::Boolean(true) => eval_node(env, consequence)?,
Node::Boolean(false) => eval_node(env, *alternative)?, Node::Boolean(false) => eval_node(env, alternative)?,
_ => Err(Error::ExpectedBoolean)?, _ => Err(Error::ExpectedBoolean)?,
} }
} }
@ -124,16 +200,25 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
} }
Node::Unquote(node) => eval_node(env, *node)?, Node::Unquote(node) => eval_node(env, *node)?,
Node::Do { body } => eval(env, body)?.last().unwrap().to_owned(), Node::Do(body) => eval(env, body)?.last().unwrap().to_owned(),
Node::Eval { body } => eval_node(env, eval_node(env, *body)?)?, // FIXME: check for empty body
Node::Apply { func, args } => { Node::Eval(body) => eval_node(env, eval_node(env, body[0].clone())?)?,
let mut list = vec![*func]; Node::Apply(body) => {
match eval_node(env, *args)? { let mut body = body.into_iter();
Node::List(args) => list.extend(args), let operator = eval_node(env, body.next().ok_or(Error::InvalidOperator)?)?;
_ => Err(Error::ExpectedList)?,
}
eval_node(env, Node::List(list))? let args = match body.next() {
Some(node) => match eval_node(env, node)? {
Node::List(list) => list,
_ => todo!(),
},
None => return Err(Error::MismatchedArgCount(2, 1)),
};
let mut nodes = vec![operator];
nodes.extend(args);
eval_node(env, Node::List(nodes))?
} }
Node::Symbol(sym) => match env Node::Symbol(sym) => match env
@ -163,6 +248,39 @@ pub fn eval_node(env: &Environment, ast_node: Node) -> Result<Node> {
Ok(expr) Ok(expr)
} }
fn read_parameters(node: Node) -> Result<Vec<String>> {
match node {
Node::List(parameters) => parameters
.iter()
.map(|node| match node {
Node::Symbol(name) => Ok(name.clone()),
_ => todo!(),
})
.collect::<Result<Vec<String>>>(),
_ => todo!(),
}
}
fn expand_macro(
env: &Environment,
parameters: Vec<String>,
args: Vec<Node>,
body: Vec<Node>,
) -> Result<Vec<Node>> {
if args.len() != parameters.len() {
Err(Error::MismatchedArgCount(parameters.len(), args.len()))?
}
let args = parameters
.into_iter()
.map(|param| param.to_owned())
.zip(args)
.collect::<Vec<(String, Node)>>();
let env = env.wrap(args);
eval(&env, body)
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use mute_parser::parse_str; use mute_parser::parse_str;
@ -194,6 +312,8 @@ mod test {
#[case("(quote (1 2 (4 5) 6 7))", "(1 2 (4 5) 6 7)")] #[case("(quote (1 2 (4 5) 6 7))", "(1 2 (4 5) 6 7)")]
#[case("(quasiquote (1 2 (+ 3 4) 5 6))", "(1 2 (+ 3 4) 5 6)")] #[case("(quasiquote (1 2 (+ 3 4) 5 6))", "(1 2 (+ 3 4) 5 6)")]
#[case("(quasiquote (1 2 (unquote(+ 3 4)) 5 6))", "(1 2 7 5 6)")] #[case("(quasiquote (1 2 (unquote(+ 3 4)) 5 6))", "(1 2 7 5 6)")]
// Macros
#[case("((macro* (var) `(str ,var)) 2)", "2")]
// Arithmetic // Arithmetic
#[case("(+ 1 2)", "3")] #[case("(+ 1 2)", "3")]
#[case("(- 5 1)", "4")] #[case("(- 5 1)", "4")]
@ -289,6 +409,7 @@ mod test {
#[case("(str (list 1 2 3))", "(1 2 3)")] #[case("(str (list 1 2 3))", "(1 2 3)")]
fn test_evaluator(#[case] input: &str, #[case] expected: &str) { fn test_evaluator(#[case] input: &str, #[case] expected: &str) {
dbg!(input); dbg!(input);
let env = Environment::default(); let env = Environment::default();
let ast = parse_str(input).unwrap(); let ast = parse_str(input).unwrap();
let res = crate::eval(&env, ast) let res = crate::eval(&env, ast)

View file

@ -18,15 +18,7 @@ pub fn inline(input: TokenStream) -> TokenStream {
fn format_node(node: Node) -> String { fn format_node(node: Node) -> String {
match node { match node {
Node::List(v) => { Node::List(v) => format!("Node::List({})", reduce_list(v)),
let vec = v
.into_iter()
.map(format_node)
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
format!("Node::List(vec![{vec}])")
}
Node::Symbol(s) => format!("Node::Symbol(\"{s}\".to_string())"), Node::Symbol(s) => format!("Node::Symbol(\"{s}\".to_string())"),
Node::Keyword(k) => format!("Node::Keyword(\"{k}\".to_string())"), Node::Keyword(k) => format!("Node::Keyword(\"{k}\".to_string())"),
@ -39,103 +31,36 @@ fn format_node(node: Node) -> String {
Node::Error(e) => format!("Node::Error(\"{e}\".to_string())"), Node::Error(e) => format!("Node::Error(\"{e}\".to_string())"),
Node::Vector(v) => { Node::Vector(_) => todo!(),
let vec = v Node::Map(_) => todo!(),
.into_iter()
.map(format_node)
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
format!("Node::Vector(vec![{vec}])")
}
Node::Map(v) => {
let vec = v
.into_iter()
.map(|(k, v)| (k, format_node(v)))
.map(|(k, v)| format!("({k}, {v})"))
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
format!("Node::Hashmap(vec![{vec}].into())")
}
Node::Define { args } => {
let args = args
.into_iter()
.map(|(k, v)| format!("(\"{}\".to_string(), {})", k, format_node(v)))
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
format!("Node::Define(vec![{args}])")
}
Node::Let { args, body } => {
let args = args
.into_iter()
.map(|(k, v)| (k, format_node(v)))
.fold(String::new(), |lhs, (k, v)| {
format!("{lhs}, ({k}.to_string(), {v})")
});
let body = body
.into_iter()
.map(format_node)
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
format!("Node::Let(vec![{}], vec![{}]", args, body)
}
Node::Function { parameters, body } => {
let parameters = parameters
.into_iter()
.map(|param| format!("\"{}\".to_string()", param))
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
let body = body
.into_iter()
.map(format_node)
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
format!(
"Node::Function {{ parameters: vec![{}], body: vec![{}] }}",
parameters, body
)
}
Node::Macro { .. } => todo!(),
Node::If {
cond,
consequence,
alternative,
} => format!(
"Node::If(Box::new({}), Box::new({}), Box::new({}))",
format_node(*cond),
format_node(*consequence),
format_node(*alternative)
),
// Quoting
Node::Quote(node) => format!("Node::Quote(Box::new({}))", format_node(*node)), Node::Quote(node) => format!("Node::Quote(Box::new({}))", format_node(*node)),
Node::Quasiquote(node) => format!("Node::Quasiquote(Box::new({}))", format_node(*node)), Node::Quasiquote(node) => format!("Node::Quasiquote(Box::new({}))", format_node(*node)),
Node::Unquote(node) => format!("Node::Unquote(Box::new({}))", format_node(*node)), Node::Unquote(node) => format!("Node::Unquote(Box::new({}))", format_node(*node)),
Node::Do { body } => { // Specials
let vec = body Node::Define(body) => format!("Node::Define({})", reduce_list(body)),
.into_iter() Node::Let(body) => format!("Node::Let({})", reduce_list(body)),
.map(format_node) Node::Function(body) => format!("Node::Function({})", reduce_list(body)),
.reduce(|lhs, rhs| format!("{lhs}, {rhs}")) Node::Macro(body) => format!("Node::Macro({})", reduce_list(body)),
.unwrap_or_default(); Node::If(body) => format!("Node::If({})", reduce_list(body)),
Node::Do(body) => format!("Node::Do({})", reduce_list(body)),
format!("Node::Do(vec![{vec}])") Node::Eval(body) => format!("Node::Eval({})", reduce_list(body)),
} Node::Apply(body) => format!("Node::Apply({})", reduce_list(body),),
Node::Eval { body } => format!("Node::Eval(Box::new({}))", format_node(*body)),
Node::Apply { func, args } => format!(
"Node::Apply(Box::new({}), Box::new({}))",
format_node(*func),
format_node(*args)
),
} }
} }
fn reduce_list(node: Vec<Node>) -> String {
let vec = node
.into_iter()
.map(format_node)
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
format!("vec![{vec}]")
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

View file

@ -2,4 +2,4 @@
source: mute-macros/src/lib.rs source: mute-macros/src/lib.rs
expression: res expression: res
--- ---
Node::Define(vec![("a".to_string(), Node::Int(1)), ("b".to_string(), Node::Int(2))]) Node::Define(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Int(1)]), Node::List(vec![Node::Symbol("b".to_string()), Node::Int(2)])])

View file

@ -2,4 +2,4 @@
source: mute-macros/src/lib.rs source: mute-macros/src/lib.rs
expression: res expression: res
--- ---
Node::Define(vec![("a".to_string(), Node::Int(1))]) Node::Define(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Int(1)])])

View file

@ -2,4 +2,4 @@
source: mute-macros/src/lib.rs source: mute-macros/src/lib.rs
expression: res expression: res
--- ---
Node::Function { parameters: vec![], body: vec![Node::List(vec![Node::Symbol("+".to_string()), Node::Int(1), Node::Int(1)])] } Node::Function(vec![Node::List(vec![]), Node::List(vec![Node::Symbol("+".to_string()), Node::Int(1), Node::Int(1)])])

View file

@ -2,4 +2,4 @@
source: mute-macros/src/lib.rs source: mute-macros/src/lib.rs
expression: res expression: res
--- ---
Node::Function { parameters: vec!["a".to_string(), "b".to_string()], body: vec![Node::List(vec![Node::Symbol("+".to_string()), Node::Symbol("a".to_string()), Node::Symbol("b".to_string())])] } Node::Function(vec![Node::List(vec![Node::Symbol("a".to_string()), Node::Symbol("b".to_string())]), Node::List(vec![Node::Symbol("+".to_string()), Node::Symbol("a".to_string()), Node::Symbol("b".to_string())])])

View file

@ -2,4 +2,4 @@
source: mute-macros/src/lib.rs source: mute-macros/src/lib.rs
expression: res expression: res
--- ---
Node::If(Box::new(Node::Bool(true)), Box::new(Node::Int(1)), Box::new(Node::Int(2))) Node::If(vec![Node::Bool(true), Node::Int(1), Node::Int(2)])

View file

@ -35,6 +35,7 @@ pub enum Token {
Nil, Nil,
// Specials // Specials
Macro,
Function, Function,
Define, Define,
Let, Let,
@ -209,6 +210,7 @@ fn read_ident(input: &mut Peekable<Chars>, first: char) -> Token {
"false" => Token::False, "false" => Token::False,
"nil" => Token::Nil, "nil" => Token::Nil,
"fn*" => Token::Function, "fn*" => Token::Function,
"macro*" => Token::Macro,
"define" => Token::Define, "define" => Token::Define,
"let*" => Token::Let, "let*" => Token::Let,
"eval" => Token::Eval, "eval" => Token::Eval,

View file

@ -30,33 +30,30 @@ fn next_statement(tokens: &mut TokenIter) -> Result<Option<Node>> {
None => return Ok(None), None => return Ok(None),
}; };
macro_rules! read_quote_operator {
($type:expr) => {{
tokens.next(); // Munch opened
let quote = read_quote(tokens, $type)?;
tokens.next(); // Munch closed
quote
}};
}
let node = match tok { let node = match tok {
Token::LeftParen => match tokens.peek().ok_or(Error::UnclosedParenthesis)? { Token::LeftParen => match tokens.peek().ok_or(Error::UnclosedParenthesis)? {
Token::Function => read_function(tokens)?, Token::Function => Node::Function(read_body(tokens)?),
Token::Define => read_define(tokens)?, Token::Macro => Node::Macro(read_body(tokens)?),
Token::Let => read_let(tokens)?, Token::Define => Node::Define(read_body(tokens)?),
Token::Eval => read_eval(tokens)?, Token::Let => Node::Let(read_body(tokens)?),
Token::Apply => read_apply(tokens)?, Token::Eval => Node::Eval(read_body(tokens)?),
Token::If => read_if(tokens)?, Token::Apply => Node::Apply(read_body(tokens)?),
Token::Do => read_do(tokens)?, Token::If => Node::If(read_body(tokens)?),
Token::Quote => { Token::Do => Node::Do(read_body(tokens)?),
tokens.next(); // Munch (
let quote = read_quote(tokens, "quote")?; Token::Quote => read_quote_operator!("quote"),
tokens.next(); // Munch ) Token::Quasiquote => read_quote_operator!("quasiquote"),
quote Token::Unquote => read_quote_operator!("unquote"),
}
Token::Quasiquote => {
tokens.next(); // Munch (
let quote = read_quote(tokens, "quasiquote")?;
tokens.next(); // Munch )
quote
}
Token::Unquote => {
tokens.next(); // Munch (
let quote = read_quote(tokens, "unquote")?;
tokens.next(); // Munch )
quote
}
_ => read_list(tokens, Token::RightParen)?, _ => read_list(tokens, Token::RightParen)?,
}, },
@ -92,6 +89,7 @@ fn next_statement(tokens: &mut TokenIter) -> Result<Option<Node>> {
Token::Unquote => read_quote(tokens, "unquote")?, Token::Unquote => read_quote(tokens, "unquote")?,
Token::Function Token::Function
| Token::Macro
| Token::Define | Token::Define
| Token::Let | Token::Let
| Token::Eval | Token::Eval
@ -152,216 +150,10 @@ fn read_quote(tokens: &mut TokenIter, quote_type: &str) -> Result<Node> {
Ok(node) Ok(node)
} }
fn read_define(tokens: &mut TokenIter) -> Result<Node> {
tokens.next(); // Munch special
let mut args = Vec::new();
if tokens.peek() == Some(&Token::RightParen) {
return Err(Error::EmptyDefine);
}
while tokens.peek() != Some(&Token::RightParen) {
let values = match next_statement(tokens)? {
Some(Node::List(list)) => list,
Some(node) => Err(Error::ExpectedList(node.get_type()))?,
None => Err(Error::UnexpectedEof)?,
};
if values.len() != 2 {
return Err(Error::MismatchedValueCount(2, values.len()));
}
let mut values = values.into_iter();
let name = match values.next().unwrap() {
Node::Symbol(name) => name,
val => Err(Error::ExpectedSymbol(val.get_type()))?,
};
let value = values.next().unwrap();
args.push((name.to_owned(), value.to_owned()))
}
tokens.next(); // Munch closer
Ok(Node::Define { args })
}
fn read_let(tokens: &mut TokenIter) -> Result<Node> {
tokens.next(); // Munch special
let raw_args = match next_statement(tokens)? {
Some(Node::List(list)) => list,
Some(node) => Err(Error::ExpectedList(node.get_type()))?,
None => Err(Error::UnexpectedEof)?,
};
let mut args = Vec::new();
for node in raw_args.iter() {
match node {
Node::List(list) => {
if list.len() != 2 {
return Err(Error::MismatchedValueCount(2, list.len()));
}
let mut list = list.iter();
let name = match list.next().unwrap() {
Node::Symbol(name) => name,
val => Err(Error::ExpectedSymbol(val.get_type()))?,
};
let value = list.next().unwrap();
args.push((name.to_owned(), value.to_owned()))
}
_ => return Err(Error::ExpectedList(node.get_type()))?,
}
}
let body = read_body(tokens)?;
tokens.next(); // Munch closer
Ok(Node::Let { args, body })
}
fn read_function(tokens: &mut TokenIter) -> Result<Node> {
tokens.next(); // Munch special
let parameters = match next_statement(tokens)? {
Some(Node::List(args)) => args,
Some(Node::Nil) => vec![],
Some(node) => Err(Error::ExpectedList(node.get_type()))?,
None => Err(Error::EmptyFunctionArgs)?,
};
// Ensure all parameters are symbols then extract their names
let parameters = parameters
.into_iter()
.map(|node| match node {
Node::Symbol(name) => Ok(name),
_ => Err(Error::ExpectedSymbol(node.get_type()))?,
})
.collect::<Result<Vec<_>>>()?;
if tokens.peek() == Some(&Token::RightParen) {
return Err(Error::EmptyFunctionBody);
}
let body = read_body(tokens)?;
tokens.next(); // Munch closer
Ok(Node::Function { parameters, body })
}
fn read_eval(tokens: &mut TokenIter) -> Result<Node> {
tokens.next(); // Munch special
let node = match next_statement(tokens)? {
Some(node) => node,
None => Err(Error::UnexpectedEof)?,
};
if tokens.peek() != Some(&Token::RightParen) {
// FIXME: This should not say expected is 0
return Err(Error::MismatchedValueCount(1, 0));
}
tokens.next(); // Munch closer
Ok(Node::Eval {
body: Box::new(node),
})
}
fn read_apply(tokens: &mut TokenIter) -> Result<Node> {
tokens.next(); // Munch special
if tokens.peek() == Some(&Token::RightParen) {
return Err(Error::EmptyApplyOperator);
}
let func = match next_statement(tokens)? {
Some(node) => node,
None => Err(Error::UnexpectedEof)?,
};
if tokens.peek() == Some(&Token::RightParen) {
return Err(Error::EmptyApplyBody);
}
let args = match next_statement(tokens)? {
Some(node) => node,
None => Err(Error::UnexpectedEof)?,
};
tokens.next(); // Munch closer
Ok(Node::Apply {
func: Box::new(func),
args: Box::new(args),
})
}
fn read_if(tokens: &mut TokenIter) -> Result<Node> {
tokens.next(); // Munch special
if tokens.peek() == Some(&Token::RightParen) {
return Err(Error::EmptyIfCondition);
}
let cond = match next_statement(tokens)? {
Some(node) => node,
None => Err(Error::UnexpectedEof)?,
};
if tokens.peek() == Some(&Token::RightParen) {
return Err(Error::EmptyIfConsequence);
}
let consequence = match next_statement(tokens)? {
Some(node) => node,
None => Err(Error::UnexpectedEof)?,
};
let alternative = match tokens.peek() {
Some(&Token::RightParen) => Node::Nil,
Some(_) => match next_statement(tokens)? {
Some(node) => node,
None => Err(Error::UnexpectedEof)?,
},
None => Err(Error::UnexpectedEof)?,
};
tokens.next(); // Munch closer
Ok(Node::If {
cond: Box::new(cond),
consequence: Box::new(consequence),
alternative: Box::new(alternative),
})
}
fn read_do(tokens: &mut TokenIter) -> Result<Node> {
tokens.next(); // Munch special
if tokens.peek() == Some(&Token::RightParen) {
return Err(Error::EmptyDo);
}
let body = read_body(tokens)?;
tokens.next(); // Munch closer
Ok(Node::Do { body })
}
fn read_body(tokens: &mut TokenIter) -> Result<Vec<Node>> { fn read_body(tokens: &mut TokenIter) -> Result<Vec<Node>> {
let mut body = Vec::new(); let mut body = Vec::new();
tokens.next(); // Munch special
while tokens.peek() != Some(&Token::RightParen) { while tokens.peek() != Some(&Token::RightParen) {
if let Some(node) = next_statement(tokens)? { if let Some(node) = next_statement(tokens)? {
body.push(node); body.push(node);
@ -373,6 +165,7 @@ fn read_body(tokens: &mut TokenIter) -> Result<Vec<Node>> {
None => Err(Error::UnclosedParenthesis)?, None => Err(Error::UnclosedParenthesis)?,
} }
} }
tokens.next(); // Munch closing parenthesis
Ok(body) Ok(body)
} }

View file

@ -19,41 +19,20 @@ pub enum Node {
Map(HashMap<String, Node>), Map(HashMap<String, Node>),
// Specials // Specials
Define { // TODO: Specials should point to a LinkedList
args: Vec<(String, Node)>, Define(Vec<Node>),
}, Let(Vec<Node>),
Let { Function(Vec<Node>),
args: Vec<(String, Node)>, Macro(Vec<Node>),
body: Vec<Node>, If(Vec<Node>),
},
Function {
parameters: Vec<String>,
body: Vec<Node>,
},
Macro {
parameters: Vec<String>,
body: Vec<Node>,
},
If {
cond: Box<Node>,
consequence: Box<Node>,
alternative: Box<Node>,
},
Quote(Box<Node>), Quote(Box<Node>),
Quasiquote(Box<Node>), Quasiquote(Box<Node>),
Unquote(Box<Node>), Unquote(Box<Node>),
Do { Do(Vec<Node>),
body: Vec<Node>, Eval(Vec<Node>),
}, Apply(Vec<Node>),
Eval {
body: Box<Node>,
},
Apply {
func: Box<Node>,
args: Box<Node>,
},
} }
impl Node { impl Node {
@ -111,106 +90,36 @@ impl std::fmt::Display for Node {
Node::Error(val) => write!(f, "error: {}", val), Node::Error(val) => write!(f, "error: {}", val),
Node::Vector(vec) => { Node::Vector(body) => write!(f, "[{}]", reduce_list(body)),
let s = vec Node::Map(body) => write!(
.iter() f,
.map(|elem| elem.to_string()) "{{{}}}",
.reduce(|lhs, rhs| format!("{lhs} {rhs}")) body.iter()
.unwrap_or_default();
write!(f, "[{s}]")
}
Node::Map(map) => {
let res = map
.iter()
.map(|(k, v)| format!("{k}: {v}")) .map(|(k, v)| format!("{k}: {v}"))
.reduce(|lhs, rhs| format!("{lhs}, {rhs}"))
.unwrap_or_default();
write!(f, "{{{res}}}")
}
Node::Define { args } => {
let res = args
.iter()
.map(|(k, v)| format!("({k} {v})"))
.reduce(|lhs, rhs| format!("{lhs} {rhs}")) .reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.expect("parser does not allow empty define statements"); .unwrap_or_default()
),
write!(f, "(define {res})") Node::Define(body) => write!(f, "(define! {})", reduce_list(body)),
} Node::Let(body) => write!(f, "(let* {})", reduce_list(body)),
Node::Macro(body) => write!(f, "(macro* {})", reduce_list(body)),
Node::Let { args, body } => { Node::Function(body) => write!(f, "(fn* {})", reduce_list(body)),
let args = args Node::If(body) => write!(f, "(if {})", reduce_list(body)),
.iter()
.map(|(k, v)| format!("({k} {v})"))
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.expect("parser does not allow empty let statements");
let body = body
.iter()
.map(|node| node.to_string())
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.expect("parser does not allow empty let bodies");
write!(f, "(let ({args}) {body})")
}
Node::Macro {
parameters: args,
body,
} => {
let args = args
.iter()
.map(|node| node.to_string())
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.unwrap_or_default();
let body = body
.iter()
.map(|node| node.to_string())
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.expect("parser does not allow empty function bodies");
write!(f, "(fn ({args}) {body})")
}
Node::Function {
parameters: args,
body,
} => {
let args = args
.iter()
.map(|node| node.to_string())
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.unwrap_or_default();
let body = body
.iter()
.map(|node| node.to_string())
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.expect("parser does not allow empty function bodies");
write!(f, "(defmacro ({args}) {body})")
}
Node::If {
cond,
consequence,
alternative,
} => write!(f, "(if {cond} {consequence} {alternative})"),
Node::Quote(node) => write!(f, "'{node}"), Node::Quote(node) => write!(f, "'{node}"),
Node::Quasiquote(node) => write!(f, "`{node}"), Node::Quasiquote(node) => write!(f, "`{node}"),
Node::Unquote(node) => write!(f, ",{node}"), Node::Unquote(node) => write!(f, ",{node}"),
Node::Do { body } => { Node::Do(body) => write!(f, "(do {})", reduce_list(body)),
let body = body Node::Eval(body) => write!(f, "(eval {})", reduce_list(body)),
.iter() Node::Apply(body) => write!(f, "(apply {})", reduce_list(body)),
.map(|node| node.to_string())
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.expect("parser does not allow empty do statements");
write!(f, "(do {body})")
}
Node::Eval { body } => write!(f, "(eval {body})"),
Node::Apply { func, args } => write!(f, "(apply {func} {args})"),
} }
} }
} }
fn reduce_list(list: &Vec<Node>) -> String {
list.iter()
.map(|n| n.to_string())
.reduce(|lhs, rhs| format!("{lhs} {rhs}"))
.unwrap_or_default()
}

View file

@ -79,7 +79,7 @@ fn repl() {
Ok(ast) => ast, Ok(ast) => ast,
Err(err) => { Err(err) => {
println!("error: {}", err); println!("error: {}", err);
return; continue;
} }
}; };
let res = eval(&env, ast); let res = eval(&env, ast);