aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jans.tuomi@gmail.com>2021-11-25 14:33:33 +0200
committerJan Tuomi <jans.tuomi@gmail.com>2021-11-25 19:01:31 +0200
commitf311e49a45935a55e55ab9045243a23b17d53557 (patch)
treec87963cbc4fd96b7d3042e033994806fea8aef48
parent9a71e6a806563e5ee9aa7eef0c5c9fdc58a9c1c9 (diff)
Add rudimentary support for Commands
-rw-r--r--src/builtins.rs31
-rw-r--r--src/runtime.rs11
2 files changed, 41 insertions, 1 deletions
diff --git a/src/builtins.rs b/src/builtins.rs
index 7b06864..2d82f96 100644
--- a/src/builtins.rs
+++ b/src/builtins.rs
@@ -38,10 +38,16 @@ impl fmt::Display for Builtin {
arg_str.push_str(format!(" {}", argument).as_str());
}
- write!(f, "Builtin({}){}", self.identifier, arg_str)
+ write!(f, "Builtin({}{})", self.identifier, arg_str)
}
}
+#[derive(Debug, Clone, PartialEq)]
+pub struct Command {
+ pub identifier: &'static str,
+ pub term: Rc<Term>,
+}
+
fn argument_type_error(builtin_id: &'static str, arg: &Term) -> Result<(Rc<Term>, usize), String> {
Err(format!(
"[runtime] cannot apply builtin {} to argument {}",
@@ -90,6 +96,9 @@ pub const B_INTEGER_MULTIPLY: &str = "int.mul";
pub const B_INTEGER_DIVIDE: &str = "int.div";
pub const B_STRING_EQ: &str = "string.eq?";
pub const B_BOOL_TO_STRING: &str = "bool.to-string";
+pub const B_COMMAND_PRINTLN: &str = "cmd.println!";
+
+pub const C_PRINTLN: &str = "PrintLn";
pub fn try_ast_symbol_to_builtin_term(symbol: &str) -> Option<Term> {
let builtin = match symbol {
@@ -104,6 +113,7 @@ pub fn try_ast_symbol_to_builtin_term(symbol: &str) -> Option<Term> {
B_INTEGER_DIVIDE => Builtin::new(B_INTEGER_DIVIDE, 2),
B_STRING_EQ => Builtin::new(B_STRING_EQ, 2),
B_BOOL_TO_STRING => Builtin::new(B_BOOL_TO_STRING, 1),
+ B_COMMAND_PRINTLN => Builtin::new(B_COMMAND_PRINTLN, 1),
_ => return None,
};
@@ -200,6 +210,14 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc<Term>) -> Result<(Rc<Term>, u
let inner = Rc::new(Term::Application(rhs, true_str_rc));
Term::Application(inner, false_str_rc)
}
+ B_COMMAND_PRINTLN => match &*rhs {
+ Term::Primitive(Value::String(_)) => match builtin.n_arguments {
+ 1 => Term::Command(C_PRINTLN, rhs),
+ _ => return argument_n_error(builtin.identifier, builtin.n_arguments),
+ },
+ Term::Primitive(_) => return argument_type_error(builtin.identifier, &*rhs),
+ _ => return Ok((Rc::new(Term::Builtin(builtin.clone())), 0)),
+ },
_ => {
return Err(format!(
"[runtime] invalid builtin evaluated: {}",
@@ -210,3 +228,14 @@ pub fn evaluate_builtin(builtin: &Builtin, rhs: Rc<Term>) -> Result<(Rc<Term>, u
Ok((Rc::new(result_term), 1))
}
+
+pub fn perform_command(command_term: &Term) -> Result<(), String> {
+ let (command, term) = extract_enum_value!(command_term, Term::Command(c, t) => (c, t));
+
+ match (*command, &**term) {
+ (builtins::C_PRINTLN, Term::Primitive(Value::String(str_val))) => println!("{}", str_val),
+ _ => return Err(format!("[runtime] invalid command: {}", command)),
+ }
+
+ Ok(())
+}
diff --git a/src/runtime.rs b/src/runtime.rs
index 71947fe..f810320 100644
--- a/src/runtime.rs
+++ b/src/runtime.rs
@@ -28,6 +28,7 @@ pub enum Term {
Primitive(Value),
Lazy(String),
Builtin(builtins::Builtin),
+ Command(&'static str, Rc<Term>),
}
impl Term {
@@ -38,6 +39,9 @@ impl Term {
Term::Variable(v) => format!("{}Variable({})", indent_str, v),
Term::Primitive(value) => format!("{}{}", indent_str, value),
Term::Builtin(builtin) => format!("{}{}", indent_str, builtin),
+ Term::Command(command, term_rc) => {
+ format!("{}Command({}, {})", indent_str, command, term_rc)
+ }
Term::Abstraction(v, body) => format!(
"{}Abstraction({})\n{}",
indent_str,
@@ -110,6 +114,7 @@ pub fn reduce_term(
let (result_term, result_n) = match term {
Term::Primitive(_) => Ok((Rc::clone(&term_rc), 0)),
+ Term::Command(_, _) => 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_rhs_rc, rhs_n) = reduce_term(
@@ -389,6 +394,12 @@ pub fn process(
let result_term = repeatedly_reduce_term(symbol_table, term, &None)?;
println!("[{}]: {}", index, result_term);
+
+ match &*result_term {
+ Term::Command(_, _) => builtins::perform_command(&result_term),
+ _ => Ok(()),
+ }?;
+
output_terms.push(result_term);
}
}