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::{ use crate::{
CompilationUnit, CompilationUnit,
ast::{BinaryOperator, UnaryOperator}, ast::{BinaryOperator, UnaryOperator},
vm::value::{Constant, IndexableValue, LuaInteger, Value}, vm::value::{Constant, IndexableValue, LuaInteger, Table, Value},
}; };
pub mod value; pub mod value;
@ -143,36 +143,6 @@ pub enum RuntimeError {
Custom(String), 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)] #[derive(Debug, Clone, Default)]
pub struct Prototype { pub struct Prototype {
pub instructions: Vec<Instruction>, pub instructions: Vec<Instruction>,
@ -181,7 +151,7 @@ pub struct Prototype {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct VirtualMachine { pub struct VirtualMachine {
pub(super) environment: Rc<RefCell<Environment>>, pub(super) environment: Table,
pub(super) constants: Vec<Constant>, pub(super) constants: Vec<Constant>,
pub(super) prototypes: HashMap<u32, Prototype>, pub(super) prototypes: HashMap<u32, Prototype>,
pub(super) proto_counter: u32, 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 self.environment
.borrow_mut() .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(); let mut values = HashMap::new();
for (key, value) in &self.environment.borrow().globals { for (key, value) in self.environment.borrow().iter() {
values.insert(key.clone(), value.borrow().clone()); values.insert(key.clone(), value.clone());
} }
values values
@ -226,7 +197,7 @@ impl VirtualMachine {
pub struct Closure { pub struct Closure {
vm: VirtualMachine, vm: VirtualMachine,
pub(crate) prototype: u32, pub(crate) prototype: u32,
environment: Rc<RefCell<Environment>>, environment: Table,
upvalues: HashMap<u16, Rc<RefCell<Value>>>, upvalues: HashMap<u16, Rc<RefCell<Value>>>,
} }
@ -424,19 +395,26 @@ impl ClosureRunner {
} }
Instruction::SetGlobal(reg, global) => { Instruction::SetGlobal(reg, global) => {
let value = self.get_stack(*reg); let value = self.get_stack(*reg);
self.closure self.closure.environment.borrow_mut().insert(
.environment constants
.borrow_mut() .get(*global as usize)
.set_global(constants.get(*global as usize).unwrap().clone(), value); .unwrap()
.clone()
.as_value()
.as_indexable()?,
match value {
StackValue::Value(value) => value,
},
);
} }
Instruction::GetGlobal(reg, global) => { Instruction::GetGlobal(reg, global) => {
let glob = self let constant = constants.get(*global as usize).unwrap().clone();
.closure let environment = self.closure.environment.borrow_mut().clone();
.environment let glob = environment
.borrow_mut() .get(&constant.as_value().as_indexable()?)
.get_global(constants.get(*global as usize).unwrap()); .cloned();
if let Some(global) = glob { if let Some(global) = glob {
self.set_stack(*reg, global); self.set_stack(*reg, StackValue::Value(global));
} else { } else {
return Err(RuntimeError::GlobalNotFound( return Err(RuntimeError::GlobalNotFound(
constants.get(*global as usize).cloned(), constants.get(*global as usize).cloned(),

View File

@ -96,9 +96,15 @@ pub enum Constant {
Nil, Nil,
} }
impl From<&str> for Constant { impl Constant {
fn from(value: &str) -> Self { pub fn as_value(self) -> Value {
Constant::String(value.to_owned()) 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)] #[derive(Clone)]
pub enum Value { pub enum Value {
String(String), String(String),
@ -123,7 +131,7 @@ pub enum Value {
RustFunction(Rc<RefCell<dyn RustFunction>>), RustFunction(Rc<RefCell<dyn RustFunction>>),
Function(Closure), Function(Closure),
Nil, Nil,
Table(Rc<RefCell<HashMap<IndexableValue, Value>>>), Table(Table),
} }
impl Value { impl Value {
@ -160,14 +168,10 @@ impl Value {
} }
} }
#[derive(Debug, PartialEq, Eq, Hash, Clone, Ord, PartialOrd)] impl From<&str> for Value {
pub enum IndexableValue { fn from(value: &str) -> Self {
String(String), Value::String(value.to_owned())
Float(VMFloat), }
Integer(LuaInteger),
Bool(LuaBool),
RustFunction(String),
Function(u32),
} }
impl Value { 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),
}