aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--samples/sample1.code4
-rw-r--r--src/builtins.rs121
-rw-r--r--src/test.rs2
3 files changed, 56 insertions, 71 deletions
diff --git a/samples/sample1.code b/samples/sample1.code
index 53e05f6..6ac6847 100644
--- a/samples/sample1.code
+++ b/samples/sample1.code
@@ -6,4 +6,6 @@
compare? a b fn = fn b a;
compare? 2 2 int.eq?
"true"
- "false"; \ No newline at end of file
+ "false";
+
+int.eq? "foobar"; \ No newline at end of file
diff --git a/src/builtins.rs b/src/builtins.rs
index 087e629..20ed23b 100644
--- a/src/builtins.rs
+++ b/src/builtins.rs
@@ -6,29 +6,29 @@ use std::rc::Rc;
#[derive(Debug, Clone, PartialEq)]
pub struct Builtin {
pub identifier: &'static str,
- pub repr_name: &'static str,
pub arguments: Vec<Value>,
+ pub n_arguments: usize,
}
impl Builtin {
- pub fn new(identifier: &'static str) -> Builtin {
+ pub fn new(identifier: &'static str, n_arguments: usize) -> Builtin {
Builtin {
identifier: identifier,
- repr_name: identifier,
arguments: vec![],
+ n_arguments: n_arguments,
}
}
- // pub fn bind_arg(self: &Builtin, arg: &Value) -> Builtin {
- // let mut new_args = self.arguments.clone();
- // new_args.push(arg.clone());
+ pub fn bind_arg(&self, 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,
- // }
- // }
+ Builtin {
+ identifier: self.identifier,
+ arguments: new_args,
+ n_arguments: self.n_arguments - 1,
+ }
+ }
}
impl fmt::Display for Builtin {
@@ -38,22 +38,27 @@ impl fmt::Display for Builtin {
arg_str.push_str(format!(" {}", argument).as_str());
}
- write!(f, "Builtin({}){}", self.repr_name, arg_str)
+ write!(f, "Builtin({}){}", self.identifier, arg_str)
}
}
-fn argument_error(builtin_id: &'static str, arg: &Value) -> Result<(Rc<Term>, usize), String> {
+fn argument_type_error(builtin_id: &'static str, arg: &Value) -> Result<(Rc<Term>, usize), String> {
Err(format!(
"[runtime] cannot apply builtin {} to argument {}",
builtin_id, arg
))
}
+fn argument_n_error(builtin_id: &'static str, n: usize) -> Result<(Rc<Term>, usize), String> {
+ Err(format!(
+ "[runtime] builtin {} can not accept an argument with n {}",
+ builtin_id, n
+ ))
+}
+
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";
pub fn make_boolean_true_function() -> Term {
let x = advance_v();
@@ -77,9 +82,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::new(B_INTEGER_EQ),
- B_INTEGER_INCREMENT => Builtin::new(B_INTEGER_INCREMENT),
- B_INTEGER_ADD => Builtin::new(B_INTEGER_ADD),
+ B_INTEGER_EQ => Builtin::new(B_INTEGER_EQ, 2),
+ B_INTEGER_INCREMENT => Builtin::new(B_INTEGER_INCREMENT, 1),
+ B_INTEGER_ADD => Builtin::new(B_INTEGER_ADD, 2),
_ => return None,
};
@@ -90,72 +95,50 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc<Term>) -> Result<(Rc<Term>, u
let result_term = match builtin.identifier {
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 argument_error(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) => {
- 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()
+ Value::Integer(value) => match builtin.n_arguments {
+ 2 => Term::Builtin(builtin.bind_arg(primitive)),
+ 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 argument_type_error(builtin.identifier, other),
}
- other => return argument_error(builtin.identifier, other),
}
- }
- other => return argument_error(builtin.identifier, other),
+ _ => return argument_n_error(builtin.identifier, builtin.n_arguments),
+ },
+ other => return argument_type_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 argument_error(builtin.identifier, other),
+ other => return argument_type_error(builtin.identifier, other),
},
_ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)),
},
B_INTEGER_ADD => match &*rhs {
Term::Primitive(primitive) => match primitive {
- Value::Integer(_) => {
- let new_builtin = Builtin {
- identifier: B_INTEGER_ADD_1,
- repr_name: builtin.identifier,
- arguments: vec![primitive.clone()],
- };
- Term::Builtin(new_builtin)
- }
- other => return argument_error(builtin.identifier, other),
- },
- _ => 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!(builtin.arguments.len(), 1);
- let summand = &builtin.arguments[0];
- match summand {
- Value::Integer(summand_value) => {
- Term::Primitive(Value::Integer(summand_value + value))
+ Value::Integer(value) => match builtin.n_arguments {
+ 2 => Term::Builtin(builtin.bind_arg(primitive)),
+ 1 => {
+ let other = &builtin.arguments[0];
+ match other {
+ Value::Integer(other_value) => {
+ Term::Primitive(Value::Integer(value + other_value))
+ }
+ other => return argument_type_error(builtin.identifier, other),
}
- other => return argument_error(builtin.identifier, other),
}
- }
- other => return argument_error(builtin.identifier, other),
+ _ => return argument_n_error(builtin.identifier, builtin.n_arguments),
+ },
+ other => return argument_type_error(builtin.identifier, other),
},
_ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)),
},
diff --git a/src/test.rs b/src/test.rs
index 70bfd49..a2dea85 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -175,7 +175,7 @@ fn reduce_builtin_int_add() -> Result<(), String> {
// Second expression
let (result_term2, _) = repeatedly_reduce_term(&symbol_table, Rc::clone(term2), &None, false)?;
- let expected2_identifier = builtins::B_INTEGER_ADD_1;
+ let expected2_identifier = builtins::B_INTEGER_ADD;
let result_builtin2 = match &*result_term2 {
Term::Builtin(b) => b,
_ => return Err(format!("{} is not a builtin", result_term2)),