diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.rs | 121 | ||||
| -rw-r--r-- | src/test.rs | 2 |
2 files changed, 53 insertions, 70 deletions
diff --git a/src/builtins.rs b/src/builtins.rs index 087e629..20ed23b 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -6,29 +6,29 @@ use std::rc::Rc; #[derive(Debug, Clone, PartialEq)] pub struct Builtin { pub identifier: &'static str, - pub repr_name: &'static str, pub arguments: Vec<Value>, + pub n_arguments: usize, } impl Builtin { - pub fn new(identifier: &'static str) -> Builtin { + pub fn new(identifier: &'static str, n_arguments: usize) -> Builtin { Builtin { identifier: identifier, - repr_name: identifier, arguments: vec![], + n_arguments: n_arguments, } } - // pub fn bind_arg(self: &Builtin, arg: &Value) -> Builtin { - // let mut new_args = self.arguments.clone(); - // new_args.push(arg.clone()); + pub fn bind_arg(&self, arg: &Value) -> Builtin { + let mut new_args = self.arguments.clone(); + new_args.push(arg.clone()); - // Builtin { - // identifier: new_identifier, - // repr_name: self.repr_name, - // arguments: new_args, - // } - // } + Builtin { + identifier: self.identifier, + arguments: new_args, + n_arguments: self.n_arguments - 1, + } + } } impl fmt::Display for Builtin { @@ -38,22 +38,27 @@ impl fmt::Display for Builtin { arg_str.push_str(format!(" {}", argument).as_str()); } - write!(f, "Builtin({}){}", self.repr_name, arg_str) + write!(f, "Builtin({}){}", self.identifier, arg_str) } } -fn argument_error(builtin_id: &'static str, arg: &Value) -> Result<(Rc<Term>, usize), String> { +fn argument_type_error(builtin_id: &'static str, arg: &Value) -> Result<(Rc<Term>, usize), String> { Err(format!( "[runtime] cannot apply builtin {} to argument {}", builtin_id, arg )) } +fn argument_n_error(builtin_id: &'static str, n: usize) -> Result<(Rc<Term>, usize), String> { + Err(format!( + "[runtime] builtin {} can not accept an argument with n {}", + builtin_id, n + )) +} + pub const B_INTEGER_EQ: &str = "int.eq?"; -pub const B_INTEGER_EQ_1: &str = "##int.eq?_1"; pub const B_INTEGER_INCREMENT: &str = "int.increment"; pub const B_INTEGER_ADD: &str = "int.add"; -pub const B_INTEGER_ADD_1: &str = "##int.add_1"; pub fn make_boolean_true_function() -> Term { let x = advance_v(); @@ -77,9 +82,9 @@ pub fn try_ast_symbol_to_builtin_term(symbol: &ast::Symbol) -> Option<Term> { "true" => return Some(make_boolean_true_function()), "false" => return Some(make_boolean_false_function()), "id" => return Some(make_identity_function()), - B_INTEGER_EQ => Builtin::new(B_INTEGER_EQ), - B_INTEGER_INCREMENT => Builtin::new(B_INTEGER_INCREMENT), - B_INTEGER_ADD => Builtin::new(B_INTEGER_ADD), + B_INTEGER_EQ => Builtin::new(B_INTEGER_EQ, 2), + B_INTEGER_INCREMENT => Builtin::new(B_INTEGER_INCREMENT, 1), + B_INTEGER_ADD => Builtin::new(B_INTEGER_ADD, 2), _ => return None, }; @@ -90,72 +95,50 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc<Term>) -> Result<(Rc<Term>, u let result_term = match builtin.identifier { B_INTEGER_EQ => match &*rhs { Term::Primitive(primitive) => match primitive { - Value::Integer(_) => { - let new_builtin = Builtin { - identifier: B_INTEGER_EQ_1, - repr_name: builtin.identifier, - arguments: vec![primitive.clone()], - }; - Term::Builtin(new_builtin) - } - other => return argument_error(builtin.identifier, other), - }, - _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), - }, - B_INTEGER_EQ_1 => match &*rhs { - Term::Primitive(primitive) => match primitive { - Value::Integer(value) => { - assert_eq!(builtin.arguments.len(), 1); - let other = &builtin.arguments[0]; - match other { - Value::Integer(other_value) => { - if value == other_value { - make_boolean_true_function() - } else { - make_boolean_false_function() + Value::Integer(value) => match builtin.n_arguments { + 2 => Term::Builtin(builtin.bind_arg(primitive)), + 1 => { + let other = &builtin.arguments[0]; + match other { + Value::Integer(other_value) => { + if value == other_value { + make_boolean_true_function() + } else { + make_boolean_false_function() + } } + other => return argument_type_error(builtin.identifier, other), } - other => return argument_error(builtin.identifier, other), } - } - other => return argument_error(builtin.identifier, other), + _ => return argument_n_error(builtin.identifier, builtin.n_arguments), + }, + other => return argument_type_error(builtin.identifier, other), }, _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, B_INTEGER_INCREMENT => match &*rhs { Term::Primitive(primitive) => match primitive { Value::Integer(value) => Term::Primitive(Value::Integer(value + 1)), - other => return argument_error(builtin.identifier, other), + other => return argument_type_error(builtin.identifier, other), }, _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, B_INTEGER_ADD => match &*rhs { Term::Primitive(primitive) => match primitive { - Value::Integer(_) => { - let new_builtin = Builtin { - identifier: B_INTEGER_ADD_1, - repr_name: builtin.identifier, - arguments: vec![primitive.clone()], - }; - Term::Builtin(new_builtin) - } - other => return argument_error(builtin.identifier, other), - }, - _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), - }, - B_INTEGER_ADD_1 => match &*rhs { - Term::Primitive(primitive) => match primitive { - Value::Integer(value) => { - assert_eq!(builtin.arguments.len(), 1); - let summand = &builtin.arguments[0]; - match summand { - Value::Integer(summand_value) => { - Term::Primitive(Value::Integer(summand_value + value)) + Value::Integer(value) => match builtin.n_arguments { + 2 => Term::Builtin(builtin.bind_arg(primitive)), + 1 => { + let other = &builtin.arguments[0]; + match other { + Value::Integer(other_value) => { + Term::Primitive(Value::Integer(value + other_value)) + } + other => return argument_type_error(builtin.identifier, other), } - other => return argument_error(builtin.identifier, other), } - } - other => return argument_error(builtin.identifier, other), + _ => return argument_n_error(builtin.identifier, builtin.n_arguments), + }, + other => return argument_type_error(builtin.identifier, other), }, _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, diff --git a/src/test.rs b/src/test.rs index 70bfd49..a2dea85 100644 --- a/src/test.rs +++ b/src/test.rs @@ -175,7 +175,7 @@ fn reduce_builtin_int_add() -> Result<(), String> { // Second expression let (result_term2, _) = repeatedly_reduce_term(&symbol_table, Rc::clone(term2), &None, false)?; - let expected2_identifier = builtins::B_INTEGER_ADD_1; + let expected2_identifier = builtins::B_INTEGER_ADD; let result_builtin2 = match &*result_term2 { Term::Builtin(b) => b, _ => return Err(format!("{} is not a builtin", result_term2)), |
