Add varargs to parse
This commit is contained in:
parent
b55c5eb070
commit
17c7432b7b
@ -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))
|
||||
print(123, f(10, 12, 13))
|
||||
58
src/ast.rs
58
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<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)]
|
||||
pub struct Function {
|
||||
pub name: Option<Node<String>>,
|
||||
pub params: Vec<Node<String>>,
|
||||
pub params: Vec<Node<IdentOrEllipsis>>,
|
||||
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::<Node<IdentOrEllipsis>>() {
|
||||
params.push(param.clone());
|
||||
match param.kind {
|
||||
IdentOrEllipsis::Ident(_) => {
|
||||
while stream.peek() == Some(Token::Symbol(',')) {
|
||||
stream.next();
|
||||
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),
|
||||
UnOp(UnaryOperator, 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>),
|
||||
Literal(Literal),
|
||||
TableConstructor(Vec<(Option<Node<Expression>>, Node<Expression>)>),
|
||||
IndexedAccess(Box<Node<Expression>>, Box<Node<Expression>>),
|
||||
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::<Ellipsis>() {
|
||||
Expression::Ellipsis
|
||||
} else {
|
||||
Expression::ValueRef(stream.parse()?)
|
||||
};
|
||||
|
||||
@ -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<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();
|
||||
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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user