diff --git a/examples/test.lua b/examples/test.lua index d839ae2..c9904ca 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -16,6 +16,8 @@ function min(x, y) return m end +global sometable = {} + print(max(11, 9)) print(add(10)(15)) print(add(10)(15)) diff --git a/src/ast.rs b/src/ast.rs index dd2a524..0b8a650 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -292,6 +292,7 @@ pub enum Expression { FunctionDefinition(Vec>, Block), FunctionCall(Box>, Node), Literal(Literal), + TableConstructor, } impl Parse for Expression { @@ -424,6 +425,10 @@ impl Parse for PrimaryExpression { } else if let Some(Token::StringLit(value)) = peeked { stream.next(); // Consume string-literal Expression::Literal(Literal::String(value)) + } else if let Some(Token::Symbol('{')) = peeked { + stream.next(); + stream.expect_symbol('}')?; + Expression::TableConstructor } else { Expression::ValueRef(stream.parse()?) }; diff --git a/src/compile.rs b/src/compile.rs index 1820e5c..1dd2227 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -324,6 +324,10 @@ impl Expression { constants } }, + Expression::TableConstructor => { + let constants = HashSet::new(); + constants + } } } @@ -540,6 +544,12 @@ impl Expression { )); (instructions, vec![reg]) } + Expression::TableConstructor => { + let mut instructions = Vec::new(); + let reg = scope.register_counter.next(); + instructions.push(Instruction::NewTable(reg)); + (instructions, vec![reg]) + } } } } diff --git a/src/main.rs b/src/main.rs index b7641c3..94ac853 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,7 @@ mod vm; static TEST: &str = include_str!("../examples/test.lua"); -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub struct Max; impl RustFunction for Max { fn execute(&self, parameters: Vec) -> Result, RuntimeError> { @@ -31,7 +31,7 @@ impl RustFunction for Max { } } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub struct Print; impl RustFunction for Print { fn execute(&self, parameters: Vec) -> Result, RuntimeError> { diff --git a/src/vm.rs b/src/vm.rs index 9b9ed28..1f37124 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,6 +1,6 @@ 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::{ ast::{BinaryOperator, LuaNumber, UnaryOperator}, @@ -43,6 +43,8 @@ pub enum Instruction { GetUpVal(u16, u16), /// U[B] := R(A) SetUpVal(u16, u16), + /// R(A) := {} + NewTable(u16), /// R(A) := R(B) + R(C) Add(u16, u16, u16), /// R(A) := -R(B) @@ -81,6 +83,7 @@ impl Debug for Instruction { Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1), Instruction::GetUpVal(arg0, arg1) => write!(f, "GETUPVAL {} {}", 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::Test(arg0, arg1, arg2) => write!(f, "TEST {} {} {}", arg0, arg1, arg2), Instruction::Call(arg0, arg1, arg2) => write!(f, "CALL {} {} {}", arg0, arg1, arg2), @@ -127,6 +130,15 @@ pub enum Value { RustFunction(Rc>), Function(Closure), Nil, + Table(HashMap), +} + +#[derive(Debug, PartialEq, Eq, Hash, Clone)] +pub enum IndexableValue { + String(String), + Number(VMNumber), + RustFunction(String), + Function(u32), } impl Value { @@ -247,6 +259,13 @@ impl Debug for Value { .debug_tuple(&format!("Function({})", closure.prototype)) .finish(), 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()) .unwrap_or(Value::Nil); } + Instruction::NewTable(reg) => { + self.set_stack(*reg, Value::Table(HashMap::new())); + } Instruction::Jmp(b) => { self.program_counter = (self.program_counter as i32 + *b) as usize }