From 17c7432b7b8dc8733e71532e14f0d09958c6b381 Mon Sep 17 00:00:00 2001 From: Sofia Date: Wed, 18 Mar 2026 19:11:53 +0200 Subject: [PATCH] Add varargs to parse --- examples/test.lua | 37 +++----------------------- src/ast.rs | 58 +++++++++++++++++++++++++++++++++++----- src/compile.rs | 67 +++++++++++++++++++++++++++-------------------- src/vm.rs | 4 +-- 4 files changed, 95 insertions(+), 71 deletions(-) diff --git a/examples/test.lua b/examples/test.lua index 3d52d95..b3aca55 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -1,37 +1,6 @@ -global b = 5 -function add(x) - return function (y) - x = x + 1 - b = b + 1 - return x + y, 1, 2, b - end +function f(x, ...) + return x + 5 end -function min(x, y) - local m = x - if y < x then - m = y - end - return m -end - -function f(x) - return x + 5, add(10)(15) -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) -print(f(10)) \ No newline at end of file +print(123, f(10, 12, 13)) \ No newline at end of file diff --git a/src/ast.rs b/src/ast.rs index 3918799..3c900a3 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -129,10 +129,39 @@ impl Metadata { } } +#[derive(Debug, Clone)] +pub struct Ellipsis; + +impl Parse for Ellipsis { + fn parse(mut stream: TokenStream) -> Result { + stream.expect_symbol('.')?; + stream.expect_symbol('.')?; + stream.expect_symbol('.')?; + Ok(Ellipsis) + } +} + +#[derive(Debug, Clone)] +pub enum IdentOrEllipsis { + Ident(String), + Ellipsis, +} + +impl Parse for IdentOrEllipsis { + fn parse(mut stream: TokenStream) -> Result { + if let Ok(ident) = stream.parse() { + Ok(IdentOrEllipsis::Ident(ident)) + } else { + stream.parse::()?; + Ok(IdentOrEllipsis::Ellipsis) + } + } +} + #[derive(Debug, Clone)] pub struct Function { pub name: Option>, - pub params: Vec>, + pub params: Vec>, pub block: Block, pub _meta: Metadata, } @@ -147,11 +176,23 @@ impl Parse for Function { let mut params = Vec::new(); - if let Ok(param) = stream.parse() { - params.push(param); - while stream.peek() == Some(Token::Symbol(',')) { - stream.next(); - params.push(stream.parse()?); + if let Ok(param) = stream.parse::>() { + params.push(param.clone()); + match param.kind { + IdentOrEllipsis::Ident(_) => { + while stream.peek() == Some(Token::Symbol(',')) { + stream.next(); + let param = stream.parse::>()?; + params.push(param.clone()); + match param.kind { + IdentOrEllipsis::Ident(_) => {} + IdentOrEllipsis::Ellipsis => { + break; + } + } + } + } + IdentOrEllipsis::Ellipsis => {} } } @@ -334,11 +375,12 @@ pub enum Expression { ValueRef(String), UnOp(UnaryOperator, Box>), BinOp(BinaryOperator, Box>, Box>), - FunctionDefinition(Vec>, Block), + FunctionDefinition(Vec>, Block), FunctionCall(Box>, Node), Literal(Literal), TableConstructor(Vec<(Option>, Node)>), IndexedAccess(Box>, Box>), + Ellipsis, } impl Parse for Expression { @@ -510,6 +552,8 @@ impl Parse for PrimaryExpression { stream.expect_symbol('}')?; Expression::TableConstructor(entries) + } else if let Ok(_) = stream.parse::() { + Expression::Ellipsis } else { Expression::ValueRef(stream.parse()?) }; diff --git a/src/compile.rs b/src/compile.rs index a7a7a12..7317f9a 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -1,7 +1,10 @@ use std::collections::{HashMap, HashSet}; use crate::{ - ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator}, + ast::{ + AccessModifier, BinaryOperator, Block, Expression, IdentOrEllipsis, Literal, Statement, + UnaryOperator, + }, vm::{Constant, Instruction, LuaBool, LuaInteger}, }; @@ -43,22 +46,6 @@ impl LocalCounter { } pub fn consecutive(&mut self, amount: usize) -> Vec { - 'outer: for free_num in self.1.clone() { - let mut potentials = vec![free_num]; - let mut curr = free_num; - for _ in 0..amount { - if let Some(next) = self.1.iter().find(|v| **v == curr + 1) { - potentials.push(*next); - curr = *next; - } else { - continue 'outer; - } - } - - self.1 - .retain_mut(|v| potentials.iter().find(|p| v != *p).is_none()); - return potentials; - } let mut returned = Vec::new(); for _ in 0..amount { returned.push(self.new()); @@ -283,17 +270,21 @@ impl Statement { } Statement::Return(expr_list) => { let mut ret_registers = Vec::new(); - for expr in &expr_list.0 { + let mut vararg = false; + for (i, expr) in expr_list.0.iter().enumerate() { let (instr, registers) = expr.kind.compile( state, scope, - if expr_list.0.len() == 1 { + if i == expr_list.0.len() - 1 { None } else { Some(1) }, ); instructions.extend(instr); + if registers.len() == 0 { + vararg = true; + } ret_registers.extend(registers); } @@ -310,9 +301,21 @@ impl Statement { *ret_register = new_reg; } + if vararg { + instructions.push(Instruction::MoveRetValues( + first_ret_register + ret_registers.len() as u16, + )); + } + + dbg!(&first_ret_register); + instructions.push(Instruction::Return( - *ret_registers.first().unwrap_or(&scope.register_counter.0), - *ret_registers.last().unwrap_or(&0), + first_ret_register, + if vararg { + 0 + } else { + *ret_registers.last().unwrap_or(&0) + }, )); } Statement::If(expr, block) => { @@ -421,6 +424,7 @@ impl Expression { constants.extend(index.kind.find_constants(scope)); constants } + Expression::Ellipsis => HashSet::new(), } } @@ -533,9 +537,14 @@ impl Expression { Expression::FunctionDefinition(params, block) => { let mut inner_scope = Scope::default(); for param in params { - inner_scope - .locals - .insert(param.kind.clone(), inner_scope.register_counter.next()); + match ¶m.kind { + IdentOrEllipsis::Ident(name) => { + inner_scope + .locals + .insert(name.clone(), inner_scope.register_counter.next()); + } + IdentOrEllipsis::Ellipsis => todo!(), + } } inner_scope.highest_upvalue = scope.highest_upvalue + scope.register_counter.0; @@ -564,6 +573,11 @@ impl Expression { let old_function_reg = registers.first().unwrap(); + let mut registers = scope + .register_counter + .consecutive(params.kind.0.len() + 1) + .into_iter(); + let mut param_scope = scope.clone(); let mut original_param_regs = Vec::new(); let mut vararg = false; @@ -585,10 +599,6 @@ impl Expression { } } - let mut registers = scope - .register_counter - .consecutive(original_param_regs.len() + 1) - .into_iter(); let function_reg = registers.next().unwrap(); let mut param_regs = Vec::new(); for _ in &original_param_regs { @@ -716,6 +726,7 @@ impl Expression { (instructions, vec![local]) } + Expression::Ellipsis => todo!(), } } } diff --git a/src/vm.rs b/src/vm.rs index cd437ba..5f576ed 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -963,8 +963,8 @@ impl ClosureRunner { self.program_counter += 1; let mut ret_values = Vec::new(); let (reg_start, reg_end) = if *reg_end == 0 { - if self.function_register > 0 && self.top > 0 { - (self.function_register + 1, self.top) + if self.top > 0 { + (*reg_start, self.top - 1) } else { (*reg_start, *reg_end) }