aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2021-11-24 11:37:07 +0200
committerJan Tuomi <jans.tuomi@gmail.com>2021-11-25 09:53:44 +0200
commite48876266053819680931b8c43fe6c6165e9c739 (patch)
tree9a303c3e8c037b1ce049eb090315c3506a5c9602
parentecc88efd10db08afad1027892d44d473839a4b86 (diff)
Fix evaluation problems
-rw-r--r--Cargo.toml3
-rw-r--r--samples/sample1.code12
-rw-r--r--src/builtins.rs95
-rw-r--r--src/runtime.rs86
4 files changed, 110 insertions, 86 deletions
diff --git a/Cargo.toml b/Cargo.toml
index b5a9ba0..0866d42 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -3,6 +3,9 @@ name = "prog-lang-dev1"
version = "0.1.0"
edition = "2021"
+[features]
+reduce_debug = []
+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
diff --git a/samples/sample1.code b/samples/sample1.code
index 1af3984..53e05f6 100644
--- a/samples/sample1.code
+++ b/samples/sample1.code
@@ -1,7 +1,9 @@
-int.eq? 10 20
- "true"
- "false";
+# f a b = int.eq? a b;
+# f 1 2
+# "true"
+# "false";
-int.eq? 30 30
+compare? a b fn = fn b a;
+compare? 2 2 int.eq?
"true"
- "false";
+ "false"; \ No newline at end of file
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<Value>,
}
+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<Term>, 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<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 {
- 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<Term>) -> Result<(Rc<Term>, 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<Term>) -> Result<(Rc<Term>, 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<Term>) -> Result<(Rc<Term>, 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<Term>) -> Result<(Rc<Term>, 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 &**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, 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: 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;