From c1f50fea93ad308f215e2d2878d773b55a370edb Mon Sep 17 00:00:00 2001 From: Jan Tuomi Date: Tue, 23 Nov 2021 23:27:01 +0200 Subject: Builtins of one parameter working --- samples/sample1.code | 10 ++-------- src/builtins.rs | 45 +++++++++++++++++++++++++++++++++++++++++++-- src/runtime.rs | 12 ++++++++---- 3 files changed, 53 insertions(+), 14 deletions(-) diff --git a/samples/sample1.code b/samples/sample1.code index 5eb4cc3..22412a7 100644 --- a/samples/sample1.code +++ b/samples/sample1.code @@ -1,8 +1,2 @@ -# factorial = int.eq? n 1 -# 1 -# int.multiply n (factorial (int.decrement n)); - -# factorial 10; - -f a b = b a; -f 10 id; +int.increment 1; +int.increment 10; \ No newline at end of file diff --git a/src/builtins.rs b/src/builtins.rs index fa029a9..dbc17eb 100644 --- a/src/builtins.rs +++ b/src/builtins.rs @@ -1,7 +1,8 @@ use super::ast; -use super::runtime::{advance_v, Term}; +use super::runtime::{advance_v, Term, Value}; use std::rc::Rc; +pub const B_INTEGER_EQ0: &str = "int.eq0?"; pub const B_INTEGER_INCREMENT: &str = "int.increment"; pub fn make_boolean_true_function() -> Term { @@ -21,11 +22,51 @@ pub fn make_identity_function() -> Term { Term::Abstraction(v, Rc::new(Term::Variable(v))) } -pub fn try_builtin_symbol_to_term(symbol: &ast::Symbol) -> Option { +pub fn try_ast_symbol_to_builtin_term(symbol: &ast::Symbol) -> Option { 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))), + B_INTEGER_INCREMENT => Some(Term::Builtin(String::from(B_INTEGER_INCREMENT))), _ => None, } } + +pub fn evaluate_builtin(symbol: &String, rhs: Rc) -> Result<(Rc, usize), String> { + let result_term = match symbol.as_str() { + B_INTEGER_EQ0 => match &*rhs { + Term::Primitive(primitive) => match primitive { + Value::Integer(value) => { + if *value == 0 { + make_boolean_true_function() + } else { + make_boolean_false_function() + } + } + other => { + return Err(format!( + "[runtime] cannot apply builtin {} to argument type {}", + symbol, other + )) + } + }, + _ => return Ok((Rc::new(Term::Builtin(symbol.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 type {}", + symbol, other + )) + } + }, + _ => return Ok((Rc::new(Term::Builtin(symbol.clone())), 0)), + }, + _ => return Err(format!("[runtime] invalid builtin evaluated: {}", symbol)), + }; + + Ok((Rc::new(result_term), 1)) +} diff --git a/src/runtime.rs b/src/runtime.rs index f059709..7e4e6f4 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -27,6 +27,7 @@ pub enum Term { Application(Rc, Rc), Primitive(Value), Lazy(String), + Builtin(String), } impl Term { @@ -39,6 +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::Abstraction(v, body) => format!( "{}Abstraction({})\n{}", indent_str, @@ -135,6 +137,7 @@ pub fn reduce_term( &Some((*abs_v, subst_rhs_rc)), resolve_lazy, ), + Term::Builtin(symbol) => builtins::evaluate_builtin(symbol, subst_rhs_rc), _ => Ok(( Rc::new(Term::Application(subst_lhs_rc, subst_rhs_rc)), subst_n, @@ -152,6 +155,7 @@ pub fn reduce_term( )?; Ok((Rc::new(Term::Abstraction(*abs_v, subst_body)), subst_n)) } + Term::Builtin(_) => Ok((term_rc, 0)), // Term::Lazy(symbol) => { // if resolve_lazy { // let table_lookup_value = symbol_table.get(symbol); @@ -243,7 +247,7 @@ fn process_expr_inner_unary( return Rc::clone(lookup_rc); } - let builtin_value = builtins::try_builtin_symbol_to_term(value); + let builtin_value = builtins::try_ast_symbol_to_builtin_term(value); if builtin_value.is_some() { return Rc::new(builtin_value.unwrap()); } @@ -281,7 +285,7 @@ fn process_expr_inner_binary( lhs_term = Rc::new(Term::Variable(bound_symbol.1)); } else if let Some(lookup) = symbol_table.get(value) { lhs_term = Rc::clone(lookup); - } else if let Some(builtin) = builtins::try_builtin_symbol_to_term(value) { + } else if let Some(builtin) = builtins::try_ast_symbol_to_builtin_term(value) { lhs_term = Rc::new(builtin); } else { lhs_term = Rc::new(Term::Lazy(value.clone())); @@ -323,7 +327,7 @@ pub fn process( let mut output_terms: Vec> = vec![]; - for (_index, statement) in program.iter().enumerate() { + for (index, statement) in program.iter().enumerate() { match statement { ast::Statement::Definition { symbol, @@ -350,7 +354,7 @@ pub fn process( let term = process_expr(&symbol_table, expression, &vec![]); let (result_term, _) = repeatedly_reduce_term(&symbol_table, term, &None, false)?; - // println!("Reduction terminated, result:\n{}", term); + println!("[{}]: {}", index, result_term); output_terms.push(result_term); } } -- cgit v1.3