Add basic tables
This commit is contained in:
parent
d4da1f9184
commit
8e57def387
@ -16,6 +16,8 @@ function min(x, y)
|
|||||||
return m
|
return m
|
||||||
end
|
end
|
||||||
|
|
||||||
|
global sometable = {}
|
||||||
|
|
||||||
print(max(11, 9))
|
print(max(11, 9))
|
||||||
print(add(10)(15))
|
print(add(10)(15))
|
||||||
print(add(10)(15))
|
print(add(10)(15))
|
||||||
|
|||||||
@ -292,6 +292,7 @@ pub enum Expression {
|
|||||||
FunctionDefinition(Vec<Node<String>>, Block),
|
FunctionDefinition(Vec<Node<String>>, Block),
|
||||||
FunctionCall(Box<Node<Expression>>, Node<ExpressionList>),
|
FunctionCall(Box<Node<Expression>>, Node<ExpressionList>),
|
||||||
Literal(Literal),
|
Literal(Literal),
|
||||||
|
TableConstructor,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Expression {
|
impl Parse for Expression {
|
||||||
@ -424,6 +425,10 @@ impl Parse for PrimaryExpression {
|
|||||||
} else if let Some(Token::StringLit(value)) = peeked {
|
} else if let Some(Token::StringLit(value)) = peeked {
|
||||||
stream.next(); // Consume string-literal
|
stream.next(); // Consume string-literal
|
||||||
Expression::Literal(Literal::String(value))
|
Expression::Literal(Literal::String(value))
|
||||||
|
} else if let Some(Token::Symbol('{')) = peeked {
|
||||||
|
stream.next();
|
||||||
|
stream.expect_symbol('}')?;
|
||||||
|
Expression::TableConstructor
|
||||||
} else {
|
} else {
|
||||||
Expression::ValueRef(stream.parse()?)
|
Expression::ValueRef(stream.parse()?)
|
||||||
};
|
};
|
||||||
|
|||||||
@ -324,6 +324,10 @@ impl Expression {
|
|||||||
constants
|
constants
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Expression::TableConstructor => {
|
||||||
|
let constants = HashSet::new();
|
||||||
|
constants
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,6 +544,12 @@ impl Expression {
|
|||||||
));
|
));
|
||||||
(instructions, vec![reg])
|
(instructions, vec![reg])
|
||||||
}
|
}
|
||||||
|
Expression::TableConstructor => {
|
||||||
|
let mut instructions = Vec::new();
|
||||||
|
let reg = scope.register_counter.next();
|
||||||
|
instructions.push(Instruction::NewTable(reg));
|
||||||
|
(instructions, vec![reg])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ mod vm;
|
|||||||
|
|
||||||
static TEST: &str = include_str!("../examples/test.lua");
|
static TEST: &str = include_str!("../examples/test.lua");
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Max;
|
pub struct Max;
|
||||||
impl RustFunction for Max {
|
impl RustFunction for Max {
|
||||||
fn execute(&self, parameters: Vec<vm::Value>) -> Result<Vec<vm::Value>, RuntimeError> {
|
fn execute(&self, parameters: Vec<vm::Value>) -> Result<Vec<vm::Value>, RuntimeError> {
|
||||||
@ -31,7 +31,7 @@ impl RustFunction for Max {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[derive(Debug)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Print;
|
pub struct Print;
|
||||||
impl RustFunction for Print {
|
impl RustFunction for Print {
|
||||||
fn execute(&self, parameters: Vec<vm::Value>) -> Result<Vec<vm::Value>, RuntimeError> {
|
fn execute(&self, parameters: Vec<vm::Value>) -> Result<Vec<vm::Value>, RuntimeError> {
|
||||||
|
|||||||
24
src/vm.rs
24
src/vm.rs
@ -1,6 +1,6 @@
|
|||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
use std::{cell::RefCell, collections::HashMap, fmt::Debug, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, fmt::Debug, hash::Hash, rc::Rc};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{BinaryOperator, LuaNumber, UnaryOperator},
|
ast::{BinaryOperator, LuaNumber, UnaryOperator},
|
||||||
@ -43,6 +43,8 @@ pub enum Instruction {
|
|||||||
GetUpVal(u16, u16),
|
GetUpVal(u16, u16),
|
||||||
/// U[B] := R(A)
|
/// U[B] := R(A)
|
||||||
SetUpVal(u16, u16),
|
SetUpVal(u16, u16),
|
||||||
|
/// R(A) := {}
|
||||||
|
NewTable(u16),
|
||||||
/// R(A) := R(B) + R(C)
|
/// R(A) := R(B) + R(C)
|
||||||
Add(u16, u16, u16),
|
Add(u16, u16, u16),
|
||||||
/// R(A) := -R(B)
|
/// R(A) := -R(B)
|
||||||
@ -81,6 +83,7 @@ impl Debug for Instruction {
|
|||||||
Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1),
|
Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1),
|
||||||
Instruction::GetUpVal(arg0, arg1) => write!(f, "GETUPVAL {} {}", arg0, arg1),
|
Instruction::GetUpVal(arg0, arg1) => write!(f, "GETUPVAL {} {}", arg0, arg1),
|
||||||
Instruction::SetUpVal(arg0, arg1) => write!(f, "SETUPVAL {} {}", arg0, arg1),
|
Instruction::SetUpVal(arg0, arg1) => write!(f, "SETUPVAL {} {}", arg0, arg1),
|
||||||
|
Instruction::NewTable(arg0) => write!(f, "NEWTABLE {}", arg0),
|
||||||
Instruction::Jmp(arg0) => write!(f, "JMP {}", arg0),
|
Instruction::Jmp(arg0) => write!(f, "JMP {}", arg0),
|
||||||
Instruction::Test(arg0, arg1, arg2) => write!(f, "TEST {} {} {}", arg0, arg1, arg2),
|
Instruction::Test(arg0, arg1, arg2) => write!(f, "TEST {} {} {}", arg0, arg1, arg2),
|
||||||
Instruction::Call(arg0, arg1, arg2) => write!(f, "CALL {} {} {}", arg0, arg1, arg2),
|
Instruction::Call(arg0, arg1, arg2) => write!(f, "CALL {} {} {}", arg0, arg1, arg2),
|
||||||
@ -127,6 +130,15 @@ pub enum Value {
|
|||||||
RustFunction(Rc<RefCell<dyn RustFunction>>),
|
RustFunction(Rc<RefCell<dyn RustFunction>>),
|
||||||
Function(Closure),
|
Function(Closure),
|
||||||
Nil,
|
Nil,
|
||||||
|
Table(HashMap<IndexableValue, Value>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
|
||||||
|
pub enum IndexableValue {
|
||||||
|
String(String),
|
||||||
|
Number(VMNumber),
|
||||||
|
RustFunction(String),
|
||||||
|
Function(u32),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
@ -247,6 +259,13 @@ impl Debug for Value {
|
|||||||
.debug_tuple(&format!("Function({})", closure.prototype))
|
.debug_tuple(&format!("Function({})", closure.prototype))
|
||||||
.finish(),
|
.finish(),
|
||||||
Value::Nil => write!(f, "Nil"),
|
Value::Nil => write!(f, "Nil"),
|
||||||
|
Value::Table(hash_map) => {
|
||||||
|
let mut table = f.debug_struct("Table");
|
||||||
|
for (key, value) in hash_map {
|
||||||
|
table.field(&format!("{:?}", key), value);
|
||||||
|
}
|
||||||
|
table.finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -475,6 +494,9 @@ impl ClosureRunner {
|
|||||||
.map(|v| v.borrow().clone())
|
.map(|v| v.borrow().clone())
|
||||||
.unwrap_or(Value::Nil);
|
.unwrap_or(Value::Nil);
|
||||||
}
|
}
|
||||||
|
Instruction::NewTable(reg) => {
|
||||||
|
self.set_stack(*reg, Value::Table(HashMap::new()));
|
||||||
|
}
|
||||||
Instruction::Jmp(b) => {
|
Instruction::Jmp(b) => {
|
||||||
self.program_counter = (self.program_counter as i32 + *b) as usize
|
self.program_counter = (self.program_counter as i32 + *b) as usize
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user