diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/builtins.rs | 100 | ||||
| -rw-r--r-- | src/runtime.rs | 10 |
2 files changed, 71 insertions, 39 deletions
diff --git a/src/builtins.rs b/src/builtins.rs index b8b789f..51ea699 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -1,7 +1,26 @@ use super::ast; use super::runtime::{advance_v, Term, Value}; +use std::fmt; use std::rc::Rc; +#[derive(Debug, Clone, PartialEq)] +pub struct Builtin { + identifier: &'static str, + repr_name: &'static str, + arguments: Vec<Value>, +} + +impl fmt::Display for Builtin { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut arg_str = String::new(); + for argument in &self.arguments { + arg_str.push_str(format!(" {}", argument).as_str()); + } + + write!(f, "Builtin({}){}", self.repr_name, arg_str) + } +} + pub const B_INTEGER_EQ0: &str = "int.eq0?"; pub const B_INTEGER_INCREMENT: &str = "int.increment"; pub const B_INTEGER_ADD: &str = "int.add"; @@ -25,23 +44,33 @@ pub fn make_identity_function() -> Term { } pub fn try_ast_symbol_to_builtin_term(symbol: &ast::Symbol) -> Option<Term> { - match symbol.as_str() { - "true" => Some(make_boolean_true_function()), - "false" => Some(make_boolean_false_function()), - "id" => Some(make_identity_function()), - B_INTEGER_EQ0 => Some(Term::Builtin(String::from(B_INTEGER_EQ0), vec![])), - B_INTEGER_INCREMENT => Some(Term::Builtin(String::from(B_INTEGER_INCREMENT), vec![])), - B_INTEGER_ADD => Some(Term::Builtin(String::from(B_INTEGER_ADD), vec![])), - _ => None, - } + let builtin = match symbol.as_str() { + "true" => return Some(make_boolean_true_function()), + "false" => return Some(make_boolean_false_function()), + "id" => return Some(make_identity_function()), + B_INTEGER_EQ0 => Builtin { + identifier: B_INTEGER_EQ0, + repr_name: B_INTEGER_EQ0, + arguments: vec![], + }, + B_INTEGER_INCREMENT => Builtin { + identifier: B_INTEGER_INCREMENT, + repr_name: B_INTEGER_INCREMENT, + arguments: vec![], + }, + B_INTEGER_ADD => Builtin { + identifier: B_INTEGER_ADD, + repr_name: B_INTEGER_ADD, + arguments: vec![], + }, + _ => return None, + }; + + Some(Term::Builtin(builtin)) } -pub fn evaluate_builtin( - symbol: &String, - bound_arguments: &Vec<Value>, - rhs: Rc<Term>, -) -> Result<(Rc<Term>, usize), String> { - let result_term = match symbol.as_str() { +pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc<Term>) -> Result<(Rc<Term>, usize), String> { + let result_term = match builtin.identifier { B_INTEGER_EQ0 => match &*rhs { Term::Primitive(primitive) => match primitive { Value::Integer(value) => { @@ -54,11 +83,11 @@ pub fn evaluate_builtin( other => { return Err(format!( "[runtime] cannot apply builtin {} to argument {}", - symbol, other + builtin.identifier, other )) } }, - _ => return Ok((Rc::new(Term::Builtin(symbol.clone(), vec![])), 0)), + _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, B_INTEGER_INCREMENT => match &*rhs { Term::Primitive(primitive) => match primitive { @@ -66,31 +95,36 @@ pub fn evaluate_builtin( other => { return Err(format!( "[runtime] cannot apply builtin {} to argument {}", - symbol, other + builtin.identifier, other )) } }, - _ => return Ok((Rc::new(Term::Builtin(symbol.clone(), vec![])), 0)), + _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, B_INTEGER_ADD => match &*rhs { Term::Primitive(primitive) => match primitive { Value::Integer(_) => { - Term::Builtin(String::from(B_INTEGER_ADD_1), vec![primitive.clone()]) + let new_builtin = Builtin { + identifier: B_INTEGER_ADD_1, + repr_name: builtin.identifier, + arguments: vec![primitive.clone()], + }; + Term::Builtin(new_builtin) } other => { return Err(format!( "[runtime] cannot apply builtin {} to argument {}", - symbol, other + builtin.identifier, other )) } }, - _ => return Ok((Rc::new(Term::Builtin(symbol.clone(), vec![])), 0)), + _ => 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!(bound_arguments.len(), 1); - let summand = &bound_arguments[0]; + assert_eq!(builtin.arguments.len(), 1); + let summand = &builtin.arguments[0]; match summand { Value::Integer(summand_value) => { Term::Primitive(Value::Integer(summand_value + value)) @@ -98,7 +132,7 @@ pub fn evaluate_builtin( other => { return Err(format!( "[runtime] cannot apply builtin {} to argument {}", - symbol, other + builtin.identifier, other )) } } @@ -106,18 +140,18 @@ pub fn evaluate_builtin( other => { return Err(format!( "[runtime] cannot apply builtin {} to argument {}", - symbol, other + builtin.identifier, other )) } }, - _ => { - return Ok(( - Rc::new(Term::Builtin(symbol.clone(), bound_arguments.clone())), - 0, - )) - } + _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, - _ => return Err(format!("[runtime] invalid builtin evaluated: {}", symbol)), + _ => { + return Err(format!( + "[runtime] invalid builtin evaluated: {}", + builtin.identifier + )) + } }; Ok((Rc::new(result_term), 1)) diff --git a/src/runtime.rs b/src/runtime.rs index 84f1820..9612659 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -27,7 +27,7 @@ pub enum Term { Application(Rc<Term>, Rc<Term>), Primitive(Value), Lazy(String), - Builtin(String, Vec<Value>), + Builtin(builtins::Builtin), } impl Term { @@ -40,7 +40,7 @@ impl Term { Value::Integer(int_val) => format!("{}Integer({})", indent_str, int_val), Value::String(str_val) => format!("{}String({})", indent_str, str_val), }, - Term::Builtin(symbol, _) => format!("{}Builtin({})", indent_str, symbol), + Term::Builtin(builtin) => format!("{}{}", indent_str, builtin), Term::Abstraction(v, body) => format!( "{}Abstraction({})\n{}", indent_str, @@ -137,9 +137,7 @@ pub fn reduce_term( &Some((*abs_v, subst_rhs_rc)), resolve_lazy, ), - Term::Builtin(symbol, bound_arguments) => { - builtins::evaluate_builtin(symbol, bound_arguments, subst_rhs_rc) - } + Term::Builtin(builtin) => builtins::evaluate_builtin(builtin, subst_rhs_rc), _ => Ok(( Rc::new(Term::Application(subst_lhs_rc, subst_rhs_rc)), subst_n, @@ -157,7 +155,7 @@ pub fn reduce_term( )?; Ok((Rc::new(Term::Abstraction(*abs_v, subst_body)), subst_n)) } - Term::Builtin(_, _) => Ok((term_rc, 0)), + Term::Builtin(_) => Ok((term_rc, 0)), // Term::Lazy(symbol) => { // if resolve_lazy { // let table_lookup_value = symbol_table.get(symbol); |
