Make environment a true table
This commit is contained in:
parent
56943d612a
commit
f12f3b629b
@ -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(),
|
||||||
|
|||||||
@ -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),
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user