Making eval expression method a bit less complex

by splitting it into submethods
This commit is contained in:
greg 2018-10-17 19:39:48 -07:00
parent 1b60bd38ff
commit 1be6991f55

View File

@ -181,11 +181,7 @@ impl<'a> State<'a> {
obj @ Node::PrimObject { .. } => Ok(obj), obj @ Node::PrimObject { .. } => Ok(obj),
Node::Expr(expr) => match expr { Node::Expr(expr) => match expr {
literal @ Lit(_) => Ok(Node::Expr(literal)), literal @ Lit(_) => Ok(Node::Expr(literal)),
Call { box f, args } => match self.expression(Node::Expr(f))? { Call { box f, args } => self.call_expression(f, args),
Node::Expr(Constructor { type_name, name, tag, arity }) => self.apply_data_constructor(type_name, name, tag, arity, args),
Node::Expr(Func(f)) => self.apply_function(f, args),
other => return Err(format!("Tried to call {:?} which is not a function or data constructor", other)),
},
Val(v) => self.value(v), Val(v) => self.value(v),
Constructor { arity, ref name, tag, .. } if arity == 0 => Ok(Node::PrimObject { name: name.clone(), tag, items: vec![] }), Constructor { arity, ref name, tag, .. } if arity == 0 => Ok(Node::PrimObject { name: name.clone(), tag, items: vec![] }),
constructor @ Constructor { .. } => Ok(Node::Expr(constructor)), constructor @ Constructor { .. } => Ok(Node::Expr(constructor)),
@ -261,6 +257,15 @@ impl<'a> State<'a> {
} }
} }
fn call_expression(&mut self, f: Expr, args: Vec<Expr>) -> EvalResult<Node> {
use self::Expr::*;
match self.expression(Node::Expr(f))? {
Node::Expr(Constructor { type_name, name, tag, arity }) => self.apply_data_constructor(type_name, name, tag, arity, args),
Node::Expr(Func(f)) => self.apply_function(f, args),
other => return Err(format!("Tried to call {:?} which is not a function or data constructor", other)),
}
}
fn apply_data_constructor(&mut self, type_name: Rc<String>, name: Rc<String>, tag: usize, arity: usize, args: Vec<Expr>) -> EvalResult<Node> { fn apply_data_constructor(&mut self, type_name: Rc<String>, name: Rc<String>, tag: usize, arity: usize, args: Vec<Expr>) -> EvalResult<Node> {
if arity != args.len() { if arity != args.len() {
return Err(format!("Data constructor {} requires {} args", name, arity)); return Err(format!("Data constructor {} requires {} args", name, arity));