diff options
| author | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-19 10:39:01 +0200 |
|---|---|---|
| committer | Jan Tuomi <jans.tuomi@gmail.com> | 2021-11-19 10:39:01 +0200 |
| commit | b14b453e593d611594cb9f1569503615d64465ac (patch) | |
| tree | b66a3dc28760f8f2d2a2f6b9e3386d10bca8eb55 /src/main.rs | |
| parent | 7a5d8e0727f15e02047548c6fc8878f766b3c25d (diff) | |
Some progress
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 84 |
1 files changed, 67 insertions, 17 deletions
diff --git a/src/main.rs b/src/main.rs index f8e18cb..72b60e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -127,53 +127,100 @@ mod ast { mod runtime { use super::ast; use std::collections::HashMap; + use std::rc::Rc; + use std::sync::atomic::{AtomicUsize, Ordering}; #[derive(Debug, Clone)] pub enum Value { Integer(i64), String(String), + Var(usize), + Function(usize, Rc<Value>), } + static VAR_ID_INC: AtomicUsize = AtomicUsize::new(0); + fn try_evaluate_builtin(symbol: &ast::Symbol) -> Option<Value> { match symbol.as_str() { "int.zero" => Some(Value::Integer(0)), + "id" => { + let v = VAR_ID_INC.load(Ordering::Relaxed); + VAR_ID_INC.store(v + 1, Ordering::Relaxed); + Some(Value::Function(v, Rc::new(Value::Var(v)))) + } _ => None, } } - fn evaluate_expr(symbol_table: &HashMap<String, Value>, expression: &ast::Expression) -> Value { + fn try_apply_function(func_rc: Rc<Value>, arg: Rc<Value>, bound_v: Option<usize>) -> Rc<Value> { + let func = &*func_rc; + match func { + Value::Function(func_v, body_rc) => { + let v1 = bound_v.unwrap_or(*func_v); + let body = &**body_rc; + match body { + Value::Var(v2) => { + if v1 == *v2 { + arg + } else { + (*body_rc).clone() + } + } + Value::Function(_, _) => try_apply_function((*body_rc).clone(), arg, Some(v1)), + _ => (*body_rc).clone(), + } + } + _ => func_rc, + } + } + + fn evaluate_expr( + symbol_table: &HashMap<String, Rc<Value>>, + expression: &ast::Expression, + ) -> Rc<Value> { // println!("[runtime] evaluating expression"); let head = &expression[0]; let tail = &expression[1..]; let arity = tail.len(); match head { ast::ExpressionInner::IntegerLiteral(value) => match arity { - 0 => Value::Integer(*value), + 0 => Rc::new(Value::Integer(*value)), _ => panic!("[runtime] cannot apply integer: {}", value), }, ast::ExpressionInner::StringLiteral(value) => match arity { - 0 => Value::String(value.clone()), + 0 => Rc::new(Value::String(value.clone())), _ => panic!("[runtime] cannot apply string: {}", value), }, - ast::ExpressionInner::Symbol(value) => { - let builtin_value = try_evaluate_builtin(value); - if builtin_value.is_some() { - return builtin_value.unwrap(); - } + ast::ExpressionInner::Symbol(value) => match arity { + 0 => { + 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() { - return table_lookup_value.unwrap().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(); + } - Value::String(String::from("dummy value")) - } + Rc::new(Value::String(String::from("dummy value"))) + } + 1 => { + // let arg = &tail[0]; + // let applied = try_apply_function(value, arg, None); + panic!("should apply function here!") + } + _ => unreachable!( + "[runtime] expression arity >= 2! there must be an error in AST generation" + ), + }, ast::ExpressionInner::Expression(expression) => evaluate_expr(symbol_table, expression), } } pub fn evaluate(program: &ast::Program) { - let mut symbol_table: HashMap<String, Value> = HashMap::new(); + let mut symbol_table: HashMap<String, Rc<Value>> = HashMap::new(); for statement in program { match statement { @@ -200,9 +247,12 @@ mod runtime { fn main() { use ast::Program; use pest::Parser; + use std::env; use std::fs; - let unparsed_file = fs::read_to_string("samples/sample1.code").expect("cannot read file"); + let script_path = env::args().nth(1).expect("no script file specified"); + + let unparsed_file = fs::read_to_string(script_path).expect("cannot read file"); let parse_tree_result = parser::Parser::parse(parser::Rule::program, &unparsed_file); if parse_tree_result.is_err() { @@ -212,7 +262,7 @@ fn main() { let mut parse_tree = parse_tree_result.unwrap(); - // println!("parse tree = {:#?}", parse_tree); + println!("parse tree = {:#?}", parse_tree); let syntax_tree: Program = ast::from_parse_tree(&mut parse_tree); println!("syntax tree = {:#?}", syntax_tree); |
