Make environment a true table

This commit is contained in:
Sofia 2026-03-20 18:27:04 +02:00
parent 56943d612a
commit f12f3b629b
2 changed files with 52 additions and 60 deletions

View File

@ -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<Constant, Rc<RefCell<Value>>>,
}
impl Environment {
fn get_global(&mut self, key: &Constant) -> Option<StackValue> {
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<Instruction>,
@ -181,7 +151,7 @@ pub struct Prototype {
#[derive(Debug, Clone, Default)]
pub struct VirtualMachine {
pub(super) environment: Rc<RefCell<Environment>>,
pub(super) environment: Table,
pub(super) constants: Vec<Constant>,
pub(super) prototypes: HashMap<u32, Prototype>,
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<Constant, Value> {
pub fn get_globals(&self) -> HashMap<IndexableValue, Value> {
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<RefCell<Environment>>,
environment: Table,
upvalues: HashMap<u16, Rc<RefCell<Value>>>,
}
@ -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(),

View File

@ -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<RefCell<HashMap<IndexableValue, Value>>>;
#[derive(Clone)]
pub enum Value {
String(String),
@ -123,7 +131,7 @@ pub enum Value {
RustFunction(Rc<RefCell<dyn RustFunction>>),
Function(Closure),
Nil,
Table(Rc<RefCell<HashMap<IndexableValue, Value>>>),
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),
}