Add rudamentary metatables
This commit is contained in:
parent
5c4dbacaa7
commit
c919f3a6ea
@ -1,97 +1,9 @@
|
||||
global b = 5
|
||||
|
||||
function add(x)
|
||||
return function (y)
|
||||
x = x + 1
|
||||
b = b + 1
|
||||
return x + y, 1, 2, b
|
||||
table = { 1, 2, 3 }
|
||||
SETMETATABLE(table, {
|
||||
__add = function ()
|
||||
return 1
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
function min(x, y)
|
||||
local m = x
|
||||
if y < x then
|
||||
m = y
|
||||
end
|
||||
return m
|
||||
end
|
||||
|
||||
|
||||
function f(x, ...)
|
||||
local b = {10, ..., add(10)(15)}
|
||||
return x + 5, b
|
||||
end
|
||||
|
||||
global sometable = {}
|
||||
sometable["hello"] = { 100, 150, add(10)(15) }
|
||||
print(#sometable["hello"])
|
||||
sometable["hello"].there = "my dude"
|
||||
print(sometable.hello.there)
|
||||
|
||||
print(max(11.12345, 9))
|
||||
print(add(10)(15))
|
||||
print(add(10)(15))
|
||||
print(b)
|
||||
print(min(11, 9))
|
||||
print(10 - 15)
|
||||
print("hello there!")
|
||||
print(true or 0)
|
||||
|
||||
global value, table = f(10, 11, 12)
|
||||
|
||||
print("hello")
|
||||
for i=1,#table do
|
||||
print(table[i])
|
||||
if i > 2 then
|
||||
goto test
|
||||
end
|
||||
end
|
||||
::test::
|
||||
|
||||
local test = table[1]
|
||||
if test == 10 then
|
||||
print("first")
|
||||
elseif test == 11 then
|
||||
print("second")
|
||||
else
|
||||
print("third")
|
||||
end
|
||||
print("after if/elseif/else")
|
||||
|
||||
|
||||
local i = 0
|
||||
print("before")
|
||||
while i < 10 do
|
||||
i = i + 1
|
||||
print(i)
|
||||
end
|
||||
print("after while")
|
||||
|
||||
|
||||
local i = 0
|
||||
print("before")
|
||||
repeat
|
||||
i = i + 1
|
||||
print(i)
|
||||
until i >= 10
|
||||
print("after repeat")
|
||||
|
||||
|
||||
function ipairs(t)
|
||||
print("inside!")
|
||||
local i = 0
|
||||
return function (state, control)
|
||||
print(state, control)
|
||||
i = i + 1
|
||||
if i > #table then
|
||||
return nil, nil
|
||||
end
|
||||
return i, t[i]
|
||||
end, "otus", "potus"
|
||||
end
|
||||
|
||||
for k, v in (ipairs(table)) do
|
||||
print(k, v)
|
||||
end
|
||||
|
||||
print("hello " .. "there")
|
||||
print(table + 5);
|
||||
@ -889,6 +889,7 @@ impl Parse for TableConstructorEntry {
|
||||
(stream.peek(), stream.peek2())
|
||||
{
|
||||
let key = stream.parse::<Node<String>>()?;
|
||||
dbg!(&key);
|
||||
let key = key.with(Expression::Literal(Literal::String(key.kind.clone())));
|
||||
if let Some(Token::Symbol('=')) = stream.peek() {
|
||||
stream.next();
|
||||
|
||||
112
src/vm/mod.rs
112
src/vm/mod.rs
@ -5,11 +5,44 @@ use std::{cell::RefCell, collections::HashMap, fmt::Debug, i64, rc::Rc};
|
||||
use crate::{
|
||||
CompilationUnit,
|
||||
ast::{BinaryOperator, UnaryOperator},
|
||||
vm::value::{Constant, IndexableValue, LuaInteger, Table, Value},
|
||||
vm::value::{Constant, IndexableValue, LuaInteger, RustFunction, Table, Value},
|
||||
};
|
||||
|
||||
pub mod value;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SetMetatable;
|
||||
impl RustFunction for SetMetatable {
|
||||
fn execute(&self, parameters: Vec<Value>) -> Result<Vec<Value>, RuntimeError> {
|
||||
let table = parameters
|
||||
.get(0)
|
||||
.ok_or(RuntimeError::NotTable(Value::Nil))?;
|
||||
let metatable = parameters
|
||||
.get(1)
|
||||
.ok_or(RuntimeError::NotTable(Value::Nil))?;
|
||||
|
||||
match table {
|
||||
Value::Table {
|
||||
metatable: inner, ..
|
||||
} => match metatable {
|
||||
Value::Table {
|
||||
contents: metatable,
|
||||
..
|
||||
} => {
|
||||
*inner.borrow_mut() = metatable.borrow().clone();
|
||||
Ok(Vec::new())
|
||||
}
|
||||
_ => Err(RuntimeError::NotTable(metatable.clone())),
|
||||
},
|
||||
_ => Err(RuntimeError::NotTable(table.clone())),
|
||||
}
|
||||
}
|
||||
|
||||
fn as_indexable(&self) -> String {
|
||||
"SETMETATABLE".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Instruction {
|
||||
/// R(A) := R(B)
|
||||
@ -216,7 +249,7 @@ pub struct Prototype {
|
||||
pub parameters: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct VirtualMachine {
|
||||
pub(super) environment: Table,
|
||||
pub(super) constants: Vec<Constant>,
|
||||
@ -224,6 +257,22 @@ pub struct VirtualMachine {
|
||||
pub(super) proto_counter: u32,
|
||||
}
|
||||
|
||||
impl Default for VirtualMachine {
|
||||
fn default() -> Self {
|
||||
let environment: Table = Default::default();
|
||||
environment.borrow_mut().insert(
|
||||
IndexableValue::String("SETMETATABLE".into()),
|
||||
SetMetatable.into(),
|
||||
);
|
||||
Self {
|
||||
environment,
|
||||
constants: Default::default(),
|
||||
prototypes: Default::default(),
|
||||
proto_counter: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
pub fn new_prototype(&mut self, instructions: Prototype) -> u32 {
|
||||
let proto_id = self.proto_counter;
|
||||
@ -231,9 +280,7 @@ impl VirtualMachine {
|
||||
self.prototypes.insert(proto_id, instructions);
|
||||
proto_id
|
||||
}
|
||||
}
|
||||
|
||||
impl VirtualMachine {
|
||||
pub(crate) fn create_closure(&self, prototype: u32) -> Closure {
|
||||
Closure {
|
||||
vm: self.clone(),
|
||||
@ -484,7 +531,7 @@ impl ClosureRunner {
|
||||
*reg,
|
||||
StackValue::Value(Value::Table {
|
||||
contents: self.closure.environment.clone(),
|
||||
metatable: Box::new(Value::Nil),
|
||||
metatable: Rc::new(RefCell::new(HashMap::new())),
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
@ -602,7 +649,7 @@ impl ClosureRunner {
|
||||
*reg,
|
||||
StackValue::Value(Value::Table {
|
||||
contents: Rc::new(RefCell::new(HashMap::new())),
|
||||
metatable: Box::new(Value::Nil),
|
||||
metatable: Rc::new(RefCell::new(HashMap::new())),
|
||||
}),
|
||||
);
|
||||
}
|
||||
@ -936,10 +983,10 @@ impl ClosureRunner {
|
||||
Ok(value) => Ok(value),
|
||||
Err(_) => match (&lhs, &rhs) {
|
||||
(Value::Table { metatable, .. }, _) => {
|
||||
self.call_metamethod(*metatable.clone(), metamethod, vec![lhs, rhs])
|
||||
self.call_metamethod(metatable, metamethod, vec![lhs.clone(), rhs.clone()])
|
||||
}
|
||||
(_, Value::Table { metatable, .. }) => {
|
||||
self.call_metamethod(*metatable.clone(), metamethod, vec![rhs, lhs])
|
||||
self.call_metamethod(metatable, metamethod, vec![lhs.clone(), rhs.clone()])
|
||||
}
|
||||
_ => Err(RuntimeError::InvalidOperation(
|
||||
metamethod.to_owned(),
|
||||
@ -952,38 +999,33 @@ impl ClosureRunner {
|
||||
|
||||
fn call_metamethod(
|
||||
&self,
|
||||
metatable: Value,
|
||||
metatable: &Table,
|
||||
metamethod: &str,
|
||||
params: Vec<Value>,
|
||||
) -> Result<Value, RuntimeError> {
|
||||
match metatable {
|
||||
Value::Table { contents, .. } => {
|
||||
if let Some(value) = contents
|
||||
.borrow()
|
||||
.get(&IndexableValue::String(metamethod.to_owned()))
|
||||
{
|
||||
match value {
|
||||
Value::RustFunction(function) => {
|
||||
let result = function.borrow_mut().execute(params)?;
|
||||
Ok(result.into_iter().next().unwrap())
|
||||
}
|
||||
Value::Function(closure) => {
|
||||
let mut runnable = closure.run(params);
|
||||
#[allow(unused_assignments)]
|
||||
let mut return_value = None;
|
||||
while {
|
||||
return_value = runnable.next()?;
|
||||
return_value.is_none()
|
||||
} {}
|
||||
Ok(return_value.unwrap().into_iter().next().unwrap())
|
||||
}
|
||||
_ => Err(RuntimeError::MetafunctionNotCallable(value.clone())),
|
||||
}
|
||||
} else {
|
||||
Err(RuntimeError::MetafunctionNotFound(metamethod.to_owned()))
|
||||
if let Some(value) = metatable
|
||||
.borrow()
|
||||
.get(&IndexableValue::String(metamethod.to_owned()))
|
||||
{
|
||||
match value {
|
||||
Value::RustFunction(function) => {
|
||||
let result = function.borrow_mut().execute(params)?;
|
||||
Ok(result.into_iter().next().unwrap())
|
||||
}
|
||||
Value::Function(closure) => {
|
||||
let mut runnable = closure.run(params);
|
||||
#[allow(unused_assignments)]
|
||||
let mut return_value = None;
|
||||
while {
|
||||
return_value = runnable.next()?;
|
||||
return_value.is_none()
|
||||
} {}
|
||||
Ok(return_value.unwrap().into_iter().next().unwrap())
|
||||
}
|
||||
_ => Err(RuntimeError::MetafunctionNotCallable(value.clone())),
|
||||
}
|
||||
_ => Err(RuntimeError::MetatableNotTable(metatable)),
|
||||
} else {
|
||||
Err(RuntimeError::MetafunctionNotFound(metamethod.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -136,10 +136,7 @@ pub enum Value {
|
||||
RustFunction(Rc<RefCell<dyn RustFunction>>),
|
||||
Function(Closure),
|
||||
Nil,
|
||||
Table {
|
||||
contents: Table,
|
||||
metatable: Box<Value>,
|
||||
},
|
||||
Table { contents: Table, metatable: Table },
|
||||
}
|
||||
|
||||
impl Value {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user