From 21228ff3d7e64fbfd9bac6a3ccb632eceeaf3d04 Mon Sep 17 00:00:00 2001 From: Daniel M Date: Thu, 3 Feb 2022 22:09:58 +0100 Subject: [PATCH] Implement vec based scopes - Replaced vartable hashmap with vec - Use linear search in reverse to find the variables by name - This is really fast with a small number of variables but tanks fast with more vars due to O(n) lookup times - Implemented scopes by dropping all elements from the vartable at the end of a scope --- src/interpreter.rs | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/interpreter.rs b/src/interpreter.rs index f02e93e..a1d2d75 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, fmt::Display, rc::Rc}; +use std::{fmt::Display, rc::Rc}; use crate::{ ast::{Ast, BinOpType, Expression, If, Statement, UnOpType}, @@ -14,16 +14,32 @@ pub enum Value { pub struct Interpreter { // Variable table stores the runtime values of variables - vartable: HashMap, + vartable: Vec<(String, Value)>, } impl Interpreter { pub fn new() -> Self { Self { - vartable: HashMap::new(), + vartable: Vec::new(), } } + fn get_var(&self, name: &str) -> Option { + self.vartable + .iter() + .rev() + .find(|it| it.0 == name) + .map(|it| it.1.clone()) + } + + fn get_var_mut(&mut self, name: &str) -> Option<&mut Value> { + self.vartable + .iter_mut() + .rev() + .find(|it| it.0 == name) + .map(|it| &mut it.1) + } + pub fn run_str(&mut self, code: &str, print_tokens: bool, print_ast: bool) { let tokens = lex(code).unwrap(); if print_tokens { @@ -39,6 +55,7 @@ impl Interpreter { } pub fn run(&mut self, prog: &Ast) { + let vartable_len = self.vartable.len(); for stmt in &prog.prog { match stmt { Statement::Expr(expr) => { @@ -78,6 +95,8 @@ impl Interpreter { } } } + + self.vartable.truncate(vartable_len); } fn resolve_expr(&mut self, expr: &Expression) -> Value { @@ -91,7 +110,7 @@ impl Interpreter { } fn resolve_var(&mut self, name: &str) -> Value { - match self.vartable.get(name) { + match self.get_var(name) { Some(val) => val.clone(), None => panic!("Variable '{}' used but not declared", name), } @@ -113,11 +132,11 @@ impl Interpreter { match (&bo, &lhs) { (BinOpType::Declare, Expression::Var(name)) => { - self.vartable.insert(name.clone(), rhs.clone()); + self.vartable.push((name.clone(), rhs.clone())); return rhs; } (BinOpType::Assign, Expression::Var(name)) => { - match self.vartable.get_mut(name) { + match self.get_var_mut(name) { Some(val) => *val = rhs.clone(), None => panic!("Runtime Error: Trying to assign value to undeclared variable"), }