diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-21 11:05:14 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-21 11:05:14 +0200 |
| commit | 787d7fe08d018abb6c12b11d8e00af9e3e0653ec (patch) | |
| tree | 479da3ea1c642119ceb4b243b74104b36e487232 | |
| parent | fe12f80810b2c2e9fa57e9a9a8ad21b410aa9c68 (diff) | |
Get evaluation working
| -rw-r--r-- | samples/sample1.code | 3 | ||||
| -rw-r--r-- | src/grammar.pest | 6 | ||||
| -rw-r--r-- | src/main.rs | 110 |
3 files changed, 71 insertions, 48 deletions
diff --git a/samples/sample1.code b/samples/sample1.code index 4d70215..a507c24 100644 --- a/samples/sample1.code +++ b/samples/sample1.code @@ -1,2 +1 @@ -id; -id;
\ No newline at end of file +(id id) (id 1);
\ No newline at end of file diff --git a/src/grammar.pest b/src/grammar.pest index 4fce017..2b6cbfe 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -1,9 +1,9 @@ COMMENT = _{ "#" ~ (!("#" | NEWLINE) ~ ANY)* ~ NEWLINE* } WHITESPACE = _{ " " | "\t" | NEWLINE } program = { SOI ~ statement+ ~ EOI } -statement = { (definition | expression) } -definition = { symbol ~ "=" ~ expression ~ ";"+ } -expression = { (symbol | integer_literal | string_literal | ("(" ~ expression ~ ")"))+ ~ ";" } +statement = { (definition | expression) ~ ";"+ } +definition = { symbol ~ "=" ~ expression } +expression = { (symbol | integer_literal | string_literal | ("(" ~ expression ~ ")"))+ } integer_literal = @{ "-"? ~ ASCII_DIGIT+ } string_literal = { QUOTATION_MARK ~ (!QUOTATION_MARK ~ ANY)* ~ QUOTATION_MARK } symbol = @{ (ASCII_ALPHA | "_.") ~ (ASCII_ALPHANUMERIC | "-" | "." | "?" | "!")* } diff --git a/src/main.rs b/src/main.rs index 0685cb0..d7aaee4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -166,6 +166,10 @@ mod runtime { } fn try_apply_function(func_rc: Rc<Value>, arg: Rc<Value>, bound_v: Option<usize>) -> Rc<Value> { + // println!( + // "[runtime] evaluating func {:#?}, arg {:#?}, bound_v: {:#?}", + // func_rc, arg, bound_v + // ); let func = &*func_rc; match func { Value::Function(func_v, body_rc) => { @@ -187,57 +191,77 @@ mod runtime { } } - fn evaluate_expr( + fn evaluate_expr_inner_unary( symbol_table: &HashMap<String, Rc<Value>>, - expression: &ast::Expression, + inner: &ast::ExpressionInner, ) -> Rc<Value> { - match expression { - ast::Expression::Unary(inner) => match inner { - 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_evaluate_builtin(value); - if builtin_value.is_some() { - return Rc::new(builtin_value.unwrap()); - } + match inner { + 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_evaluate_builtin(value); + if builtin_value.is_some() { + return Rc::new(builtin_value.unwrap()); + } - let table_lookup_value = symbol_table.get(value); - if table_lookup_value.is_some() { - let lookup_rc = table_lookup_value.unwrap(); - return lookup_rc.clone(); - } + let table_lookup_value = symbol_table.get(value); + if table_lookup_value.is_some() { + let lookup_rc = table_lookup_value.unwrap(); + return lookup_rc.clone(); + } + + panic!("[runtime] symbol not defined: {:#?}", value); + } + ast::ExpressionInner::Expression(value_rc) => { + let sub_expr = &**value_rc; + evaluate_expr(symbol_table, sub_expr) + } + } + } + + fn evaluate_expr_inner_binary( + symbol_table: &HashMap<String, Rc<Value>>, + lhs: &ast::ExpressionInner, + rhs: &ast::ExpressionInner, + ) -> Rc<Value> { + match lhs { + ast::ExpressionInner::Expression(value_rc) => { + let sub_expr = &**value_rc; + let evaled_lhs = evaluate_expr(symbol_table, sub_expr); + let evaled_rhs = evaluate_expr_inner_unary(symbol_table, rhs); + try_apply_function(evaled_lhs, evaled_rhs, None) + } + ast::ExpressionInner::Symbol(value) => { + let lhs_value_rc: Rc<Value>; + + if let Some(builtin) = try_evaluate_builtin(value) { + lhs_value_rc = Rc::new(builtin); + } else if let Some(lookup) = symbol_table.get(value) { + lhs_value_rc = (*lookup).clone(); + } else { panic!("[runtime] symbol not defined: {:#?}", value); } - ast::ExpressionInner::Expression(value_rc) => { - let sub_expr = &**value_rc; - evaluate_expr(symbol_table, sub_expr) - } - }, - ast::Expression::Binary(inner1, inner2) => match inner1 { - ast::ExpressionInner::Expression(value_rc) => { - let sub_expr = &**value_rc; - evaluate_expr(symbol_table, sub_expr) - } - ast::ExpressionInner::Symbol(value) => { - let mut lhs_value_rc: Rc<Value>; - if let Some(builtin) = try_evaluate_builtin(value) { - lhs_value_rc = Rc::new(builtin); - } else if let Some(lookup) = symbol_table.get(value) { - lhs_value_rc = *lookup; - } else { - panic!("[runtime] symbol not defined: {:#?}", value); - } + let evaled_rhs = evaluate_expr_inner_unary(symbol_table, rhs); + try_apply_function(lhs_value_rc, evaled_rhs, None) + } + other => unreachable!( + "[runtime] this should not be on the left side of a binary expression: {:#?}", + other + ), + } + } - let evaled_arg = evaluate_expr_inner(inner2); - try_apply_function(lhs_value_rc, evaled_arg, None) - } - other => unreachable!( - "[runtime] this should not be on the left side of a binary expression: {:#?}", - other - ), - }, + fn evaluate_expr( + symbol_table: &HashMap<String, Rc<Value>>, + expression: &ast::Expression, + ) -> Rc<Value> { + match expression { + ast::Expression::Unary(inner) => evaluate_expr_inner_unary(symbol_table, inner), + ast::Expression::Binary(inner1, inner2) => { + evaluate_expr_inner_binary(symbol_table, inner1, inner2) + } } // println!("[runtime] evaluating expression"); |
