Add varargs to parse

This commit is contained in:
Sofia 2026-03-18 19:11:53 +02:00
parent b55c5eb070
commit 17c7432b7b
4 changed files with 95 additions and 71 deletions

View File

@ -1,37 +1,6 @@
global b = 5
function add(x) function f(x, ...)
return function (y) return x + 5
x = x + 1
b = b + 1
return x + y, 1, 2, b
end
end end
function min(x, y) print(123, f(10, 12, 13))
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))

View File

@ -129,10 +129,39 @@ impl Metadata {
} }
} }
#[derive(Debug, Clone)]
pub struct Ellipsis;
impl Parse for Ellipsis {
fn parse(mut stream: TokenStream) -> Result<Self, TokenStreamError> {
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<Self, TokenStreamError> {
if let Ok(ident) = stream.parse() {
Ok(IdentOrEllipsis::Ident(ident))
} else {
stream.parse::<Ellipsis>()?;
Ok(IdentOrEllipsis::Ellipsis)
}
}
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Function { pub struct Function {
pub name: Option<Node<String>>, pub name: Option<Node<String>>,
pub params: Vec<Node<String>>, pub params: Vec<Node<IdentOrEllipsis>>,
pub block: Block, pub block: Block,
pub _meta: Metadata, pub _meta: Metadata,
} }
@ -147,11 +176,23 @@ impl Parse for Function {
let mut params = Vec::new(); let mut params = Vec::new();
if let Ok(param) = stream.parse() { if let Ok(param) = stream.parse::<Node<IdentOrEllipsis>>() {
params.push(param); params.push(param.clone());
match param.kind {
IdentOrEllipsis::Ident(_) => {
while stream.peek() == Some(Token::Symbol(',')) { while stream.peek() == Some(Token::Symbol(',')) {
stream.next(); stream.next();
params.push(stream.parse()?); let param = stream.parse::<Node<IdentOrEllipsis>>()?;
params.push(param.clone());
match param.kind {
IdentOrEllipsis::Ident(_) => {}
IdentOrEllipsis::Ellipsis => {
break;
}
}
}
}
IdentOrEllipsis::Ellipsis => {}
} }
} }
@ -334,11 +375,12 @@ pub enum Expression {
ValueRef(String), ValueRef(String),
UnOp(UnaryOperator, Box<Node<Expression>>), UnOp(UnaryOperator, Box<Node<Expression>>),
BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>), BinOp(BinaryOperator, Box<Node<Expression>>, Box<Node<Expression>>),
FunctionDefinition(Vec<Node<String>>, Block), FunctionDefinition(Vec<Node<IdentOrEllipsis>>, Block),
FunctionCall(Box<Node<Expression>>, Node<ExpressionList>), FunctionCall(Box<Node<Expression>>, Node<ExpressionList>),
Literal(Literal), Literal(Literal),
TableConstructor(Vec<(Option<Node<Expression>>, Node<Expression>)>), TableConstructor(Vec<(Option<Node<Expression>>, Node<Expression>)>),
IndexedAccess(Box<Node<Expression>>, Box<Node<Expression>>), IndexedAccess(Box<Node<Expression>>, Box<Node<Expression>>),
Ellipsis,
} }
impl Parse for Expression { impl Parse for Expression {
@ -510,6 +552,8 @@ impl Parse for PrimaryExpression {
stream.expect_symbol('}')?; stream.expect_symbol('}')?;
Expression::TableConstructor(entries) Expression::TableConstructor(entries)
} else if let Ok(_) = stream.parse::<Ellipsis>() {
Expression::Ellipsis
} else { } else {
Expression::ValueRef(stream.parse()?) Expression::ValueRef(stream.parse()?)
}; };

View File

@ -1,7 +1,10 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use crate::{ use crate::{
ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator}, ast::{
AccessModifier, BinaryOperator, Block, Expression, IdentOrEllipsis, Literal, Statement,
UnaryOperator,
},
vm::{Constant, Instruction, LuaBool, LuaInteger}, vm::{Constant, Instruction, LuaBool, LuaInteger},
}; };
@ -43,22 +46,6 @@ impl LocalCounter {
} }
pub fn consecutive(&mut self, amount: usize) -> Vec<u16> { pub fn consecutive(&mut self, amount: usize) -> Vec<u16> {
'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(); let mut returned = Vec::new();
for _ in 0..amount { for _ in 0..amount {
returned.push(self.new()); returned.push(self.new());
@ -283,17 +270,21 @@ impl Statement {
} }
Statement::Return(expr_list) => { Statement::Return(expr_list) => {
let mut ret_registers = Vec::new(); 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( let (instr, registers) = expr.kind.compile(
state, state,
scope, scope,
if expr_list.0.len() == 1 { if i == expr_list.0.len() - 1 {
None None
} else { } else {
Some(1) Some(1)
}, },
); );
instructions.extend(instr); instructions.extend(instr);
if registers.len() == 0 {
vararg = true;
}
ret_registers.extend(registers); ret_registers.extend(registers);
} }
@ -310,9 +301,21 @@ impl Statement {
*ret_register = new_reg; *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( instructions.push(Instruction::Return(
*ret_registers.first().unwrap_or(&scope.register_counter.0), first_ret_register,
*ret_registers.last().unwrap_or(&0), if vararg {
0
} else {
*ret_registers.last().unwrap_or(&0)
},
)); ));
} }
Statement::If(expr, block) => { Statement::If(expr, block) => {
@ -421,6 +424,7 @@ impl Expression {
constants.extend(index.kind.find_constants(scope)); constants.extend(index.kind.find_constants(scope));
constants constants
} }
Expression::Ellipsis => HashSet::new(),
} }
} }
@ -533,9 +537,14 @@ impl Expression {
Expression::FunctionDefinition(params, block) => { Expression::FunctionDefinition(params, block) => {
let mut inner_scope = Scope::default(); let mut inner_scope = Scope::default();
for param in params { for param in params {
match &param.kind {
IdentOrEllipsis::Ident(name) => {
inner_scope inner_scope
.locals .locals
.insert(param.kind.clone(), inner_scope.register_counter.next()); .insert(name.clone(), inner_scope.register_counter.next());
}
IdentOrEllipsis::Ellipsis => todo!(),
}
} }
inner_scope.highest_upvalue = scope.highest_upvalue + scope.register_counter.0; 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 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 param_scope = scope.clone();
let mut original_param_regs = Vec::new(); let mut original_param_regs = Vec::new();
let mut vararg = false; 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 function_reg = registers.next().unwrap();
let mut param_regs = Vec::new(); let mut param_regs = Vec::new();
for _ in &original_param_regs { for _ in &original_param_regs {
@ -716,6 +726,7 @@ impl Expression {
(instructions, vec![local]) (instructions, vec![local])
} }
Expression::Ellipsis => todo!(),
} }
} }
} }

View File

@ -963,8 +963,8 @@ impl ClosureRunner {
self.program_counter += 1; self.program_counter += 1;
let mut ret_values = Vec::new(); let mut ret_values = Vec::new();
let (reg_start, reg_end) = if *reg_end == 0 { let (reg_start, reg_end) = if *reg_end == 0 {
if self.function_register > 0 && self.top > 0 { if self.top > 0 {
(self.function_register + 1, self.top) (*reg_start, self.top - 1)
} else { } else {
(*reg_start, *reg_end) (*reg_start, *reg_end)
} }