Add basic tables

This commit is contained in:
Sofia 2026-03-17 18:18:31 +02:00
parent d4da1f9184
commit 8e57def387
5 changed files with 42 additions and 3 deletions

View File

@ -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))

View File

@ -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()?)
}; };

View File

@ -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])
}
} }
} }
} }

View File

@ -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> {

View File

@ -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
} }