diff --git a/src/vm/mod.rs b/src/vm/mod.rs index c008112..4c8d005 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -5,7 +5,7 @@ use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc}; use crate::{ CompilationUnit, ast::{BinaryOperator, UnaryOperator}, - vm::value::{Constant, IndexableValue, LuaInteger, Value}, + vm::value::{Constant, IndexableValue, LuaInteger, Table, Value}, }; pub mod value; @@ -143,36 +143,6 @@ pub enum RuntimeError { Custom(String), } -#[derive(Debug, Clone, Default)] -pub(crate) struct Environment { - pub globals: HashMap>>, -} - -impl Environment { - fn get_global(&mut self, key: &Constant) -> Option { - let value = self.globals.get_mut(key)?; - Some(match &*value.borrow() { - _ => StackValue::Value(value.borrow().clone()), - }) - } - - fn set_global(&mut self, key: Constant, value: StackValue) { - if let Some(existing) = self.globals.get_mut(&key) { - match value { - StackValue::Value(value) => { - *existing.borrow_mut() = value; - } - } - } else { - match value { - StackValue::Value(value) => { - self.globals.insert(key, Rc::new(RefCell::new(value))); - } - } - } - } -} - #[derive(Debug, Clone, Default)] pub struct Prototype { pub instructions: Vec, @@ -181,7 +151,7 @@ pub struct Prototype { #[derive(Debug, Clone, Default)] pub struct VirtualMachine { - pub(super) environment: Rc>, + pub(super) environment: Table, pub(super) constants: Vec, pub(super) prototypes: HashMap, pub(super) proto_counter: u32, @@ -206,16 +176,17 @@ impl VirtualMachine { } } - pub fn set_global(&mut self, key: Constant, value: Value) { + pub fn set_global(&mut self, key: Value, value: Value) -> Result<(), RuntimeError> { self.environment .borrow_mut() - .set_global(key, StackValue::Value(value)); + .insert(key.as_indexable()?, value); + Ok(()) } - pub fn get_globals(&self) -> HashMap { + pub fn get_globals(&self) -> HashMap { let mut values = HashMap::new(); - for (key, value) in &self.environment.borrow().globals { - values.insert(key.clone(), value.borrow().clone()); + for (key, value) in self.environment.borrow().iter() { + values.insert(key.clone(), value.clone()); } values @@ -226,7 +197,7 @@ impl VirtualMachine { pub struct Closure { vm: VirtualMachine, pub(crate) prototype: u32, - environment: Rc>, + environment: Table, upvalues: HashMap>>, } @@ -424,19 +395,26 @@ impl ClosureRunner { } Instruction::SetGlobal(reg, global) => { let value = self.get_stack(*reg); - self.closure - .environment - .borrow_mut() - .set_global(constants.get(*global as usize).unwrap().clone(), value); + self.closure.environment.borrow_mut().insert( + constants + .get(*global as usize) + .unwrap() + .clone() + .as_value() + .as_indexable()?, + match value { + StackValue::Value(value) => value, + }, + ); } Instruction::GetGlobal(reg, global) => { - let glob = self - .closure - .environment - .borrow_mut() - .get_global(constants.get(*global as usize).unwrap()); + let constant = constants.get(*global as usize).unwrap().clone(); + let environment = self.closure.environment.borrow_mut().clone(); + let glob = environment + .get(&constant.as_value().as_indexable()?) + .cloned(); if let Some(global) = glob { - self.set_stack(*reg, global); + self.set_stack(*reg, StackValue::Value(global)); } else { return Err(RuntimeError::GlobalNotFound( constants.get(*global as usize).cloned(), diff --git a/src/vm/value.rs b/src/vm/value.rs index 70ba33f..7eebeb7 100644 --- a/src/vm/value.rs +++ b/src/vm/value.rs @@ -96,9 +96,15 @@ pub enum Constant { Nil, } -impl From<&str> for Constant { - fn from(value: &str) -> Self { - Constant::String(value.to_owned()) +impl Constant { + pub fn as_value(self) -> Value { + match self { + Constant::String(value) => Value::String(value), + Constant::Float(vmfloat) => Value::Float(vmfloat), + Constant::Integer(lua_integer) => Value::Integer(lua_integer), + Constant::Bool(lua_bool) => Value::Boolean(lua_bool), + Constant::Nil => Value::Nil, + } } } @@ -114,6 +120,8 @@ impl Debug for Constant { } } +pub type Table = Rc>>; + #[derive(Clone)] pub enum Value { String(String), @@ -123,7 +131,7 @@ pub enum Value { RustFunction(Rc>), Function(Closure), Nil, - Table(Rc>>), + Table(Table), } impl Value { @@ -160,14 +168,10 @@ impl Value { } } -#[derive(Debug, PartialEq, Eq, Hash, Clone, Ord, PartialOrd)] -pub enum IndexableValue { - String(String), - Float(VMFloat), - Integer(LuaInteger), - Bool(LuaBool), - RustFunction(String), - Function(u32), +impl From<&str> for Value { + fn from(value: &str) -> Self { + Value::String(value.to_owned()) + } } impl Value { @@ -357,3 +361,13 @@ impl Debug for Value { } } } + +#[derive(Debug, PartialEq, Eq, Hash, Clone, Ord, PartialOrd)] +pub enum IndexableValue { + String(String), + Float(VMFloat), + Integer(LuaInteger), + Bool(LuaBool), + RustFunction(String), + Function(u32), +}