From e48876266053819680931b8c43fe6c6165e9c739 Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Wed, 24 Nov 2021 11:37:07 +0200 Subject: Fix evaluation problems --- src/builtins.rs | 95 +++++++++++++++++++++++---------------------------------- src/runtime.rs | 88 +++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 101 insertions(+), 82 deletions(-) (limited to 'src') diff --git a/src/builtins.rs b/src/builtins.rs index 20ea19d..087e629 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -10,6 +10,27 @@ pub struct Builtin { pub arguments: Vec, } +impl Builtin { + pub fn new(identifier: &'static str) -> Builtin { + Builtin { + identifier: identifier, + repr_name: identifier, + arguments: vec![], + } + } + + // pub fn bind_arg(self: &Builtin, 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, + // } + // } +} + impl fmt::Display for Builtin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let mut arg_str = String::new(); @@ -21,6 +42,13 @@ impl fmt::Display for Builtin { } } +fn argument_error(builtin_id: &'static str, arg: &Value) -> Result<(Rc, usize), String> { + Err(format!( + "[runtime] cannot apply builtin {} to argument {}", + builtin_id, arg + )) +} + 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"; @@ -49,21 +77,9 @@ pub fn try_ast_symbol_to_builtin_term(symbol: &ast::Symbol) -> Option { "true" => return Some(make_boolean_true_function()), "false" => return Some(make_boolean_false_function()), "id" => return Some(make_identity_function()), - B_INTEGER_EQ => Builtin { - identifier: B_INTEGER_EQ, - repr_name: B_INTEGER_EQ, - 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![], - }, + B_INTEGER_EQ => Builtin::new(B_INTEGER_EQ), + B_INTEGER_INCREMENT => Builtin::new(B_INTEGER_INCREMENT), + B_INTEGER_ADD => Builtin::new(B_INTEGER_ADD), _ => return None, }; @@ -82,12 +98,7 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc) -> Result<(Rc, u }; Term::Builtin(new_builtin) } - other => { - return Err(format!( - "[runtime] cannot apply builtin {} to argument {}", - builtin.identifier, other - )) - } + other => return argument_error(builtin.identifier, other), }, _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, @@ -104,32 +115,17 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc) -> Result<(Rc, u make_boolean_false_function() } } - other => { - return Err(format!( - "[runtime] cannot apply builtin {} to argument {}", - builtin.identifier, other - )) - } + other => return argument_error(builtin.identifier, other), } } - other => { - return Err(format!( - "[runtime] cannot apply builtin {} to argument {}", - builtin.identifier, other - )) - } + other => return argument_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 Err(format!( - "[runtime] cannot apply builtin {} to argument {}", - builtin.identifier, other - )) - } + other => return argument_error(builtin.identifier, other), }, _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, @@ -143,12 +139,7 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc) -> Result<(Rc, u }; Term::Builtin(new_builtin) } - other => { - return Err(format!( - "[runtime] cannot apply builtin {} to argument {}", - builtin.identifier, other - )) - } + other => return argument_error(builtin.identifier, other), }, _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, @@ -161,20 +152,10 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc) -> Result<(Rc, u Value::Integer(summand_value) => { Term::Primitive(Value::Integer(summand_value + value)) } - other => { - return Err(format!( - "[runtime] cannot apply builtin {} to argument {}", - builtin.identifier, other - )) - } + other => return argument_error(builtin.identifier, other), } } - other => { - return Err(format!( - "[runtime] cannot apply builtin {} to argument {}", - builtin.identifier, other - )) - } + other => return argument_error(builtin.identifier, other), }, _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)), }, diff --git a/src/runtime.rs b/src/runtime.rs index 9612659..789d31a 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -111,16 +111,10 @@ pub fn reduce_term( ) -> ReductionResult { let term = &*term_rc; - match term { - Term::Primitive(_) => Ok((term_rc, 0)), - Term::Variable(_) => substitute_var(term_rc, bound_variable_opt), + let (result_term, result_n) = match term { + Term::Primitive(_) => Ok((Rc::clone(&term_rc), 0)), + Term::Variable(_) => substitute_var(Rc::clone(&term_rc), bound_variable_opt), Term::Application(lhs_rc, rhs_rc) => { - let (subst_lhs_rc, lhs_n) = reduce_term( - symbol_table, - Rc::clone(lhs_rc), - bound_variable_opt, - resolve_lazy, - )?; let (subst_rhs_rc, rhs_n) = reduce_term( symbol_table, Rc::clone(rhs_rc), @@ -128,23 +122,55 @@ pub fn reduce_term( resolve_lazy, )?; - let subst_n = lhs_n + rhs_n; - - let (result, app_n) = match &*subst_lhs_rc { - Term::Abstraction(abs_v, abs_body_rc) => reduce_term( - symbol_table, - Rc::clone(abs_body_rc), - &Some((*abs_v, subst_rhs_rc)), - resolve_lazy, - ), - Term::Builtin(builtin) => builtins::evaluate_builtin(builtin, subst_rhs_rc), - _ => Ok(( - Rc::new(Term::Application(subst_lhs_rc, subst_rhs_rc)), - subst_n, - )), + let (result, app_n) = match &**lhs_rc { + Term::Abstraction(abs_v, abs_body_rc) => { + let (reduced_term, reduced_n) = reduce_term( + symbol_table, + Rc::clone(abs_body_rc), + &Some((*abs_v, subst_rhs_rc)), + resolve_lazy, + )?; + + let result: ReductionResult = Ok((reduced_term, reduced_n + 1)); + result + } + Term::Builtin(builtin) => { + let (builtin_evaled_terms, builtin_n) = + builtins::evaluate_builtin(builtin, subst_rhs_rc)?; + + // TODO: think this through + if builtin_n > 0 { + if cfg!(feature = "reduce_debug") { + println!(":: builtin_n: {} > 0", builtin_n); + println!( + ":: returning builtin_evaled_terms:\n{}\n", + builtin_evaled_terms + ); + } + Ok((builtin_evaled_terms, rhs_n + builtin_n)) + } else { + if cfg!(feature = "reduce_debug") { + println!(":: builtin_n: {} < 0", builtin_n); + println!(":: returning application as is:\n{}\n", term); + } + Ok((Rc::clone(&term_rc), rhs_n)) + } + } + _ => { + let (subst_lhs_rc, lhs_n) = reduce_term( + symbol_table, + Rc::clone(lhs_rc), + bound_variable_opt, + resolve_lazy, + )?; + Ok(( + Rc::new(Term::Application(subst_lhs_rc, subst_rhs_rc)), + rhs_n + lhs_n, + )) + } }?; - Ok((result, app_n + subst_n)) + Ok((result, app_n)) } Term::Abstraction(abs_v, body_rc) => { let (subst_body, subst_n) = reduce_term( @@ -155,7 +181,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((Rc::clone(&term_rc), 0)), // Term::Lazy(symbol) => { // if resolve_lazy { // let table_lookup_value = symbol_table.get(symbol); @@ -186,7 +212,19 @@ pub fn reduce_term( // } // } _ => todo!("reduce_term cases"), + }?; + + if cfg!(feature = "reduce_debug") { + println!( + "reduce_term with:\nterm_rc:\n{}\nbound_variable_opt:\n{}\nresolve_lazy:\n{}\n", + Rc::clone(&term_rc), + _bound_variable_opt_to_string(bound_variable_opt), + resolve_lazy + ); + println!("result_term:\n{}\nresult_n: {}\n", result_term, result_n); + println!("\n=========\n"); } + Ok((result_term, result_n)) } const MAX_REDUCTION_ITERATIONS: usize = 1000; -- cgit v1.3