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
This commit is contained in:
parent
588b3b5b2c
commit
21228ff3d7
@ -1,4 +1,4 @@
|
|||||||
use std::{collections::HashMap, fmt::Display, rc::Rc};
|
use std::{fmt::Display, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Ast, BinOpType, Expression, If, Statement, UnOpType},
|
ast::{Ast, BinOpType, Expression, If, Statement, UnOpType},
|
||||||
@ -14,16 +14,32 @@ pub enum Value {
|
|||||||
|
|
||||||
pub struct Interpreter {
|
pub struct Interpreter {
|
||||||
// Variable table stores the runtime values of variables
|
// Variable table stores the runtime values of variables
|
||||||
vartable: HashMap<String, Value>,
|
vartable: Vec<(String, Value)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpreter {
|
impl Interpreter {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
vartable: HashMap::new(),
|
vartable: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_var(&self, name: &str) -> Option<Value> {
|
||||||
|
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) {
|
pub fn run_str(&mut self, code: &str, print_tokens: bool, print_ast: bool) {
|
||||||
let tokens = lex(code).unwrap();
|
let tokens = lex(code).unwrap();
|
||||||
if print_tokens {
|
if print_tokens {
|
||||||
@ -39,6 +55,7 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self, prog: &Ast) {
|
pub fn run(&mut self, prog: &Ast) {
|
||||||
|
let vartable_len = self.vartable.len();
|
||||||
for stmt in &prog.prog {
|
for stmt in &prog.prog {
|
||||||
match stmt {
|
match stmt {
|
||||||
Statement::Expr(expr) => {
|
Statement::Expr(expr) => {
|
||||||
@ -78,6 +95,8 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.vartable.truncate(vartable_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_expr(&mut self, expr: &Expression) -> Value {
|
fn resolve_expr(&mut self, expr: &Expression) -> Value {
|
||||||
@ -91,7 +110,7 @@ impl Interpreter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_var(&mut self, name: &str) -> Value {
|
fn resolve_var(&mut self, name: &str) -> Value {
|
||||||
match self.vartable.get(name) {
|
match self.get_var(name) {
|
||||||
Some(val) => val.clone(),
|
Some(val) => val.clone(),
|
||||||
None => panic!("Variable '{}' used but not declared", name),
|
None => panic!("Variable '{}' used but not declared", name),
|
||||||
}
|
}
|
||||||
@ -113,11 +132,11 @@ impl Interpreter {
|
|||||||
|
|
||||||
match (&bo, &lhs) {
|
match (&bo, &lhs) {
|
||||||
(BinOpType::Declare, Expression::Var(name)) => {
|
(BinOpType::Declare, Expression::Var(name)) => {
|
||||||
self.vartable.insert(name.clone(), rhs.clone());
|
self.vartable.push((name.clone(), rhs.clone()));
|
||||||
return rhs;
|
return rhs;
|
||||||
}
|
}
|
||||||
(BinOpType::Assign, Expression::Var(name)) => {
|
(BinOpType::Assign, Expression::Var(name)) => {
|
||||||
match self.vartable.get_mut(name) {
|
match self.get_var_mut(name) {
|
||||||
Some(val) => *val = rhs.clone(),
|
Some(val) => *val = rhs.clone(),
|
||||||
None => panic!("Runtime Error: Trying to assign value to undeclared variable"),
|
None => panic!("Runtime Error: Trying to assign value to undeclared variable"),
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user