diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-21 21:33:45 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-21 21:33:45 +0200 |
| commit | cf3e54525f0b63adf9ab086bf03751ed232fb0b5 (patch) | |
| tree | 002de85a97a34364e4732eafba810e8eca057260 /src | |
| parent | 4b845f566fabcab20992aa75dee5b6bf64f39573 (diff) | |
Prepare ast for parameterized functions
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast.rs | 29 | ||||
| -rw-r--r-- | src/builtins.rs | 107 | ||||
| -rw-r--r-- | src/grammar.pest | 2 | ||||
| -rw-r--r-- | src/main.rs | 1 | ||||
| -rw-r--r-- | src/runtime.rs | 120 |
5 files changed, 147 insertions, 112 deletions
@@ -25,6 +25,7 @@ pub type Program = Vec<Statement>; pub enum Statement { Definition { symbol: Symbol, + parameters: Vec<Symbol>, expression: Rc<Expression>, }, Expression(Rc<Expression>), @@ -37,15 +38,31 @@ impl Statement { fn definition_from_pair(pair: pest::iterators::Pair<Rule>) -> Statement { let mut inner = pair.into_inner(); let symbol = inner.next().unwrap().as_span().as_str(); - let expression = inner.next().unwrap(); - let expression_inners: Vec<ExpressionInner> = expression - .into_inner() - .map(ExpressionInner::from_pair) - .collect(); + let mut parameters: Vec<Symbol> = vec![]; + let mut expression_opt: Option<Rc<Expression>> = None; + + while let Some(p) = inner.next() { + match p.as_rule() { + Rule::symbol => parameters.push(String::from(p.as_span().as_str())), + Rule::expression => { + let expression_inners: Vec<ExpressionInner> = + p.into_inner().map(ExpressionInner::from_pair).collect(); + expression_opt = Some(expression_vec_to_tuple(&expression_inners)); + } + _ => panic!( + "[ast] illegal rule {:#?} as child of definition", + p.as_rule() + ), + } + } + + let expression = + expression_opt.expect("[ast] no expression found as child of definition"); Statement::Definition { symbol: String::from(symbol), - expression: expression_vec_to_tuple(&expression_inners), + parameters: parameters, + expression: expression, } } diff --git a/src/builtins.rs b/src/builtins.rs new file mode 100644 index 0000000..351a652 --- /dev/null +++ b/src/builtins.rs @@ -0,0 +1,107 @@ +use super::ast; +use super::runtime; +use super::runtime::Value; +use std::rc::Rc; + +pub const B_INTEGER_INCREMENT: &str = "int.increment"; +pub const B_INTEGER_DECREMENT: &str = "int.decrement"; +pub const B_INTEGER_ADD: &str = "int.add"; +pub const B_INTEGER_MULTIPLY: &str = "int.multiply"; +pub const B_INTEGER_EQ: &str = "int.eq?"; + +#[derive(Debug, Clone)] +pub enum BuiltinFunction { + IntegerIncrement, + IntegerDecrement, + IntegerAdd, + IntegerAdd1(i64), + IntegerMultiply, + IntegerMultiply1(i64), + IntegerEq, + IntegerEq1(i64), +} + +pub fn try_builtin_symbol_to_value(symbol: &ast::Symbol) -> Option<Value> { + match symbol.as_str() { + "true" => Some(runtime::make_boolean_true_function()), + "false" => Some(runtime::make_boolean_false_function()), + "id" => Some(runtime::make_identity_function()), + B_INTEGER_INCREMENT => Some(Value::BuiltinFunction(BuiltinFunction::IntegerIncrement)), + B_INTEGER_DECREMENT => Some(Value::BuiltinFunction(BuiltinFunction::IntegerDecrement)), + B_INTEGER_ADD => Some(Value::BuiltinFunction(BuiltinFunction::IntegerAdd)), + B_INTEGER_MULTIPLY => Some(Value::BuiltinFunction(BuiltinFunction::IntegerMultiply)), + B_INTEGER_EQ => Some(Value::BuiltinFunction(BuiltinFunction::IntegerEq)), + _ => None, + } +} + +pub fn apply_builtin(builtin: &BuiltinFunction, arg: &Value) -> Rc<Value> { + match builtin { + BuiltinFunction::IntegerIncrement => match arg { + Value::Integer(value) => Rc::new(Value::Integer(value + 1)), + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_INCREMENT + ), + }, + BuiltinFunction::IntegerDecrement => match arg { + Value::Integer(value) => Rc::new(Value::Integer(value - 1)), + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_DECREMENT + ), + }, + BuiltinFunction::IntegerAdd => match arg { + Value::Integer(value) => { + Rc::new(Value::BuiltinFunction(BuiltinFunction::IntegerAdd1(*value))) + } + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_ADD + ), + }, + BuiltinFunction::IntegerAdd1(other) => match arg { + Value::Integer(value) => Rc::new(Value::Integer(other + value)), + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_ADD + ), + }, + BuiltinFunction::IntegerMultiply => match arg { + Value::Integer(value) => Rc::new(Value::BuiltinFunction( + BuiltinFunction::IntegerMultiply1(*value), + )), + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_MULTIPLY + ), + }, + BuiltinFunction::IntegerMultiply1(other) => match arg { + Value::Integer(value) => Rc::new(Value::Integer(other * value)), + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_MULTIPLY + ), + }, + BuiltinFunction::IntegerEq => match arg { + Value::Integer(value) => { + Rc::new(Value::BuiltinFunction(BuiltinFunction::IntegerEq1(*value))) + } + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_EQ + ), + }, + BuiltinFunction::IntegerEq1(other) => match arg { + Value::Integer(value) => Rc::new(if other == value { + runtime::make_boolean_true_function() + } else { + runtime::make_boolean_false_function() + }), + _ => panic!( + "[runtime] tried to apply non-integer value to {}", + B_INTEGER_EQ + ), + }, + } +} diff --git a/src/grammar.pest b/src/grammar.pest index 2b6cbfe..3db5519 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -2,7 +2,7 @@ COMMENT = _{ "#" ~ (!("#" | NEWLINE) ~ ANY)* ~ NEWLINE* } WHITESPACE = _{ " " | "\t" | NEWLINE } program = { SOI ~ statement+ ~ EOI } statement = { (definition | expression) ~ ";"+ } -definition = { symbol ~ "=" ~ expression } +definition = { symbol+ ~ "=" ~ expression } expression = { (symbol | integer_literal | string_literal | ("(" ~ expression ~ ")"))+ } integer_literal = @{ "-"? ~ ASCII_DIGIT+ } string_literal = { QUOTATION_MARK ~ (!QUOTATION_MARK ~ ANY)* ~ QUOTATION_MARK } diff --git a/src/main.rs b/src/main.rs index 98be9ea..59e91df 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,7 @@ extern crate pest_derive; extern crate pest; mod ast; +mod builtins; mod lparser; mod runtime; diff --git a/src/runtime.rs b/src/runtime.rs index 3a16567..9a5b4b4 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -1,22 +1,12 @@ use super::ast; +use super::builtins; +use super::builtins::BuiltinFunction; use std::collections::HashMap; use std::fmt; use std::rc::Rc; use std::sync::atomic::{AtomicUsize, Ordering}; #[derive(Debug, Clone)] -pub enum BuiltinFunction { - IntegerIncrement, - IntegerDecrement, - IntegerAdd, - IntegerAdd1(i64), - IntegerMultiply, - IntegerMultiply1(i64), - IntegerEq, - IntegerEq1(i64), -} - -#[derive(Debug, Clone)] pub enum Value { Integer(i64), String(String), @@ -40,11 +30,6 @@ impl fmt::Display for Value { } static VAR_ID_INC: AtomicUsize = AtomicUsize::new(0); -const B_INTEGER_INCREMENT: &str = "int.increment"; -const B_INTEGER_DECREMENT: &str = "int.decrement"; -const B_INTEGER_ADD: &str = "int.add"; -const B_INTEGER_MULTIPLY: &str = "int.multiply"; -const B_INTEGER_EQ: &str = "int.eq?"; fn advance_v() -> usize { let v = VAR_ID_INC.load(Ordering::Relaxed); @@ -52,33 +37,21 @@ fn advance_v() -> usize { v } -fn make_boolean_true_function() -> Value { +pub fn make_boolean_true_function() -> Value { let x = advance_v(); let y = advance_v(); Value::Function(x, Rc::new(Value::Function(y, Rc::new(Value::Var(x))))) } -fn make_boolean_false_function() -> Value { +pub fn make_boolean_false_function() -> Value { let x = advance_v(); let y = advance_v(); Value::Function(x, Rc::new(Value::Function(y, Rc::new(Value::Var(y))))) } -fn try_builtin_symbol_to_value(symbol: &ast::Symbol) -> Option<Value> { - match symbol.as_str() { - "true" => Some(make_boolean_true_function()), - "false" => Some(make_boolean_false_function()), - "id" => { - let v = advance_v(); - Some(Value::Function(v, Rc::new(Value::Var(v)))) - } - B_INTEGER_INCREMENT => Some(Value::BuiltinFunction(BuiltinFunction::IntegerIncrement)), - B_INTEGER_DECREMENT => Some(Value::BuiltinFunction(BuiltinFunction::IntegerDecrement)), - B_INTEGER_ADD => Some(Value::BuiltinFunction(BuiltinFunction::IntegerAdd)), - B_INTEGER_MULTIPLY => Some(Value::BuiltinFunction(BuiltinFunction::IntegerMultiply)), - B_INTEGER_EQ => Some(Value::BuiltinFunction(BuiltinFunction::IntegerEq)), - _ => None, - } +pub fn make_identity_function() -> Value { + let v = advance_v(); + Value::Function(v, Rc::new(Value::Var(v))) } fn try_apply_function(func_rc: Rc<Value>, arg_rc: Rc<Value>, bound_v: Option<usize>) -> Rc<Value> { @@ -103,74 +76,7 @@ fn try_apply_function(func_rc: Rc<Value>, arg_rc: Rc<Value>, bound_v: Option<usi _ => Rc::clone(body_rc), } } - Value::BuiltinFunction(builtin) => match builtin { - BuiltinFunction::IntegerIncrement => match arg { - Value::Integer(value) => Rc::new(Value::Integer(value + 1)), - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_INCREMENT - ), - }, - BuiltinFunction::IntegerDecrement => match arg { - Value::Integer(value) => Rc::new(Value::Integer(value - 1)), - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_DECREMENT - ), - }, - BuiltinFunction::IntegerAdd => match arg { - Value::Integer(value) => { - Rc::new(Value::BuiltinFunction(BuiltinFunction::IntegerAdd1(*value))) - } - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_ADD - ), - }, - BuiltinFunction::IntegerAdd1(other) => match arg { - Value::Integer(value) => Rc::new(Value::Integer(other + value)), - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_ADD - ), - }, - BuiltinFunction::IntegerMultiply => match arg { - Value::Integer(value) => Rc::new(Value::BuiltinFunction( - BuiltinFunction::IntegerMultiply1(*value), - )), - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_MULTIPLY - ), - }, - BuiltinFunction::IntegerMultiply1(other) => match arg { - Value::Integer(value) => Rc::new(Value::Integer(other * value)), - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_MULTIPLY - ), - }, - BuiltinFunction::IntegerEq => match arg { - Value::Integer(value) => { - Rc::new(Value::BuiltinFunction(BuiltinFunction::IntegerEq1(*value))) - } - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_EQ - ), - }, - BuiltinFunction::IntegerEq1(other) => match arg { - Value::Integer(value) => Rc::new(if other == value { - make_boolean_true_function() - } else { - make_boolean_false_function() - }), - _ => panic!( - "[runtime] tried to apply non-integer value to {}", - B_INTEGER_EQ - ), - }, - }, + Value::BuiltinFunction(builtin) => builtins::apply_builtin(builtin, arg), _ => func_rc, } } @@ -183,7 +89,7 @@ fn evaluate_expr_inner_unary( ast::ExpressionInner::IntegerLiteral(value) => Rc::new(Value::Integer(*value)), ast::ExpressionInner::StringLiteral(value) => Rc::new(Value::String(value.clone())), ast::ExpressionInner::Symbol(value) => { - let builtin_value = try_builtin_symbol_to_value(value); + let builtin_value = builtins::try_builtin_symbol_to_value(value); if builtin_value.is_some() { return Rc::new(builtin_value.unwrap()); } @@ -219,7 +125,7 @@ fn evaluate_expr_inner_binary( ast::ExpressionInner::Symbol(value) => { let lhs_value_rc: Rc<Value>; - if let Some(builtin) = try_builtin_symbol_to_value(value) { + if let Some(builtin) = builtins::try_builtin_symbol_to_value(value) { lhs_value_rc = Rc::new(builtin); } else if let Some(lookup) = symbol_table.get(value) { lhs_value_rc = Rc::clone(lookup); @@ -254,7 +160,11 @@ pub fn evaluate(program: &ast::Program) { for statement in program { match statement { - ast::Statement::Definition { symbol, expression } => { + ast::Statement::Definition { + symbol, + parameters, + expression, + } => { println!("[runtime] defining symbol: {:#?}", symbol); let value = evaluate_expr(&symbol_table, expression); symbol_table.insert(symbol.clone(), value); |
