aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builtins.rs50
-rw-r--r--src/test.rs41
2 files changed, 82 insertions, 9 deletions
diff --git a/src/builtins.rs b/src/builtins.rs
index a24db52..20ea19d 100644
--- a/src/builtins.rs
+++ b/src/builtins.rs
@@ -21,7 +21,8 @@ impl fmt::Display for Builtin {
}
}
-pub const B_INTEGER_EQ0: &str = "int.eq0?";
+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";
@@ -48,9 +49,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_EQ0 => Builtin {
- identifier: B_INTEGER_EQ0,
- repr_name: B_INTEGER_EQ0,
+ B_INTEGER_EQ => Builtin {
+ identifier: B_INTEGER_EQ,
+ repr_name: B_INTEGER_EQ,
arguments: vec![],
},
B_INTEGER_INCREMENT => Builtin {
@@ -71,13 +72,44 @@ pub fn try_ast_symbol_to_builtin_term(symbol: &ast::Symbol) -> Option<Term> {
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 {
+ 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 Err(format!(
+ "[runtime] cannot apply builtin {} to argument {}",
+ 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) => {
- if *value == 0 {
- make_boolean_true_function()
- } else {
- make_boolean_false_function()
+ 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()
+ }
+ }
+ other => {
+ return Err(format!(
+ "[runtime] cannot apply builtin {} to argument {}",
+ builtin.identifier, other
+ ))
+ }
}
}
other => {
diff --git a/src/test.rs b/src/test.rs
index 10d907c..70bfd49 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -195,3 +195,44 @@ fn reduce_builtin_int_add() -> Result<(), String> {
Ok(())
}
+
+#[test]
+#[serial]
+fn reduce_builtin_int_eq() -> Result<(), String> {
+ initialize_before_test();
+ let source = "
+ int.eq? 10 20
+ \"true\"
+ \"false\";
+ int.eq? 30 30
+ \"true\"
+ \"false\";
+ ";
+
+ let (terms, symbol_table) = evaluate_from_source(String::from(source), None)?;
+ assert_eq!(terms.len(), 2);
+ let term1 = &terms[0];
+ let term2 = &terms[1];
+
+ // First expression
+ let (result_term1, _) = repeatedly_reduce_term(&symbol_table, Rc::clone(term1), &None, false)?;
+ let expected1_string = Value::String(String::from("false"));
+ let result_builtin1 = match &*result_term1 {
+ Term::Primitive(p) => p,
+ _ => return Err(format!("{} is not a primitive", result_term1)),
+ };
+
+ assert_eq!(*result_builtin1, expected1_string);
+
+ // Second expression
+ let (result_term2, _) = repeatedly_reduce_term(&symbol_table, Rc::clone(term2), &None, false)?;
+ let expected2_string = Value::String(String::from("true"));
+ let result_builtin2 = match &*result_term2 {
+ Term::Primitive(p) => p,
+ _ => return Err(format!("{} is not a primitive", result_term2)),
+ };
+
+ assert_eq!(*result_builtin2, expected2_string);
+
+ Ok(())
+}