Compare commits

..

No commits in common. "a0108b4fd4f6cf0b032d5659490eea254e309d67" and "73e33444c9e7a33e8db782549690ee232161be2e" have entirely different histories.

6 changed files with 101 additions and 212 deletions

View File

@ -1,7 +1,36 @@
global b = 5
function f(x, ...) function add(x)
local b, c = ... return function (y)
return x + 5, b, c x = x + 1
b = b + 1
return x + y, 1, 2, b
end
end end
print(123, f(10, 11, 12)) function min(x, y)
local m = x
if y < x then
m = y
end
return m
end
function f(x)
return x + 5
end
global sometable = {}
sometable["hello"] = { 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)

BIN
luac.out

Binary file not shown.

View File

@ -129,39 +129,10 @@ 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<IdentOrEllipsis>>, pub params: Vec<Node<String>>,
pub block: Block, pub block: Block,
pub _meta: Metadata, pub _meta: Metadata,
} }
@ -176,23 +147,11 @@ impl Parse for Function {
let mut params = Vec::new(); let mut params = Vec::new();
if let Ok(param) = stream.parse::<Node<IdentOrEllipsis>>() { if let Ok(param) = stream.parse() {
params.push(param.clone()); params.push(param);
match param.kind {
IdentOrEllipsis::Ident(_) => {
while stream.peek() == Some(Token::Symbol(',')) { while stream.peek() == Some(Token::Symbol(',')) {
stream.next(); stream.next();
let param = stream.parse::<Node<IdentOrEllipsis>>()?; params.push(stream.parse()?);
params.push(param.clone());
match param.kind {
IdentOrEllipsis::Ident(_) => {}
IdentOrEllipsis::Ellipsis => {
break;
}
}
}
}
IdentOrEllipsis::Ellipsis => {}
} }
} }
@ -375,12 +334,11 @@ 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<IdentOrEllipsis>>, Block), FunctionDefinition(Vec<Node<String>>, 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 {
@ -552,8 +510,6 @@ 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,17 +1,14 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use crate::{ use crate::{
ast::{ ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator},
AccessModifier, BinaryOperator, Block, Expression, IdentOrEllipsis, Literal, Statement, vm::{Constant, Instruction, LuaBool, LuaInteger},
UnaryOperator,
},
vm::{Constant, Instruction, LuaBool, LuaInteger, Prototype},
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct State { pub struct State {
pub constants: Vec<Constant>, pub constants: Vec<Constant>,
pub prototypes: Vec<Prototype>, pub prototypes: Vec<Vec<Instruction>>,
} }
impl State { impl State {
@ -31,7 +28,6 @@ pub struct Scope {
pub register_counter: LocalCounter, pub register_counter: LocalCounter,
pub highest_upvalue: u16, pub highest_upvalue: u16,
pub upvalues: HashMap<String, u16>, pub upvalues: HashMap<String, u16>,
pub is_vararg: bool,
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
@ -47,6 +43,22 @@ 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());
@ -178,19 +190,11 @@ impl Statement {
match access_modifier { match access_modifier {
Some(AccessModifier::Local) => { Some(AccessModifier::Local) => {
let mut vararg_applied = false;
for (i, (name, indexes)) in names.iter().enumerate() { for (i, (name, indexes)) in names.iter().enumerate() {
if let Some(expr_reg) = expr_regs.get(i) {
instructions.push(Instruction::Move( instructions.push(Instruction::Move(
*new_registers.get(i).unwrap(), *new_registers.get(i).unwrap(),
*expr_reg, expr_regs.get(i).cloned().unwrap(),
)); ));
} else if !vararg_applied {
instructions.push(Instruction::MoveRetValues(
*new_registers.get(i).unwrap(),
));
vararg_applied = true;
}
if indexes.len() > 0 { if indexes.len() > 0 {
todo!() todo!()
} }
@ -279,21 +283,17 @@ impl Statement {
} }
Statement::Return(expr_list) => { Statement::Return(expr_list) => {
let mut ret_registers = Vec::new(); let mut ret_registers = Vec::new();
let mut vararg = false; for expr in &expr_list.0 {
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 i == expr_list.0.len() - 1 { if 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,21 +310,9 @@ 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(
first_ret_register, *ret_registers.first().unwrap_or(&scope.register_counter.0),
if vararg { *ret_registers.last().unwrap_or(&0),
0
} else {
*ret_registers.last().unwrap_or(&0)
},
)); ));
} }
Statement::If(expr, block) => { Statement::If(expr, block) => {
@ -433,7 +421,6 @@ impl Expression {
constants.extend(index.kind.find_constants(scope)); constants.extend(index.kind.find_constants(scope));
constants constants
} }
Expression::Ellipsis => HashSet::new(),
} }
} }
@ -546,16 +533,9 @@ 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(name.clone(), inner_scope.register_counter.next()); .insert(param.kind.clone(), inner_scope.register_counter.next());
}
IdentOrEllipsis::Ellipsis => {
inner_scope.is_vararg = true;
}
}
} }
inner_scope.highest_upvalue = scope.highest_upvalue + scope.register_counter.0; inner_scope.highest_upvalue = scope.highest_upvalue + scope.register_counter.0;
@ -567,14 +547,7 @@ impl Expression {
} }
let instructions = block.compile(state, &mut inner_scope); let instructions = block.compile(state, &mut inner_scope);
state.prototypes.push(Prototype { state.prototypes.push(instructions);
instructions,
parameters: if inner_scope.is_vararg {
params.len() - 1
} else {
params.len()
},
});
let mut instructions = Vec::new(); let mut instructions = Vec::new();
instructions.push(Instruction::Close(scope.register_counter.0)); instructions.push(Instruction::Close(scope.register_counter.0));
@ -591,32 +564,26 @@ 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; for param in params.kind.0.iter() {
for (i, param) in params.kind.0.iter().enumerate() {
let (instr, registers) = param.kind.compile( let (instr, registers) = param.kind.compile(
state, state,
&mut param_scope, &mut param_scope,
if i == params.kind.0.len() - 1 { if params.kind.0.len() == 1 {
None None
} else { } else {
Some(1) Some(1)
}, },
); );
instructions.extend(instr); instructions.extend(instr);
if registers.len() > 0 { original_param_regs.extend(registers);
original_param_regs.push(*registers.first().unwrap());
} else {
vararg = true;
}
} }
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 {
@ -633,11 +600,6 @@ impl Expression {
instructions.push(Instruction::Move(function_reg, *old_function_reg)); instructions.push(Instruction::Move(function_reg, *old_function_reg));
} }
if vararg {
let last_reg = param_regs.last().unwrap_or(&function_reg) + 1;
instructions.push(Instruction::MoveRetValues(last_reg));
}
let last_param_reg = param_regs.last().unwrap_or(&function_reg); let last_param_reg = param_regs.last().unwrap_or(&function_reg);
let mut return_regs = Vec::new(); let mut return_regs = Vec::new();
@ -654,7 +616,7 @@ impl Expression {
instructions.push(Instruction::Call( instructions.push(Instruction::Call(
*&function_reg, *&function_reg,
if vararg { 0 } else { param_regs.len() as u16 }, param_regs.len() as u16,
if return_regs.len() == 0 { if return_regs.len() == 0 {
0 0
} else { } else {
@ -685,7 +647,7 @@ impl Expression {
instructions.push(Instruction::NewTable(reg)); instructions.push(Instruction::NewTable(reg));
let mut counter = 1; let mut counter = 1;
for (i, (key, value)) in entries.iter().enumerate() { for (key, value) in entries {
if let Some(key) = key { if let Some(key) = key {
let (instr, key_regs) = key.kind.compile(state, scope, Some(1)); let (instr, key_regs) = key.kind.compile(state, scope, Some(1));
instructions.extend(instr); instructions.extend(instr);
@ -700,11 +662,7 @@ impl Expression {
let (instr, value_regs) = value.kind.compile( let (instr, value_regs) = value.kind.compile(
state, state,
scope, scope,
if i == entries.len() - 1 { if entries.len() == 1 { None } else { Some(1) },
None
} else {
Some(1)
},
); );
instructions.extend(instr); instructions.extend(instr);
@ -721,7 +679,7 @@ impl Expression {
)); ));
counter += 1; counter += 1;
} else { } else {
instructions.push(Instruction::SetList(reg, counter as u32)); instructions.push(Instruction::SetList(reg));
} }
} }
} }
@ -744,15 +702,6 @@ impl Expression {
(instructions, vec![local]) (instructions, vec![local])
} }
Expression::Ellipsis => {
if !scope.is_vararg {
panic!("Function is not vararg!");
}
let mut instructions = Vec::new();
let new_reg = scope.register_counter.new();
instructions.push(Instruction::Vararg(new_reg));
(instructions, Vec::new())
}
} }
} }
} }

View File

@ -70,10 +70,7 @@ impl Debug for CompilationUnit {
impl CompilationUnit { impl CompilationUnit {
pub fn with_virtual_machine<'a>(&self, vm: &'a mut VirtualMachine) -> ExecutionUnit<'a> { pub fn with_virtual_machine<'a>(&self, vm: &'a mut VirtualMachine) -> ExecutionUnit<'a> {
let chunk_id = vm.new_prototype(vm::Prototype { let chunk_id = vm.new_prototype(self.instructions.clone());
instructions: self.instructions.clone(),
parameters: 0,
});
for prototype in &self.state.prototypes { for prototype in &self.state.prototypes {
vm.new_prototype(prototype.clone()); vm.new_prototype(prototype.clone());
} }

View File

@ -110,8 +110,6 @@ impl Debug for Constant {
pub enum Instruction { pub enum Instruction {
/// R(A) := R(B) /// R(A) := R(B)
Move(u16, u16), Move(u16, u16),
/// R(A) ... R(A + func_register - top) := previous function return values
MoveRetValues(u16),
/// R(A) := K(Bx) /// R(A) := K(Bx)
LoadK(u16, u32), LoadK(u16, u32),
/// R(A), ..., R(B) := nil /// R(A), ..., R(B) := nil
@ -126,8 +124,8 @@ pub enum Instruction {
SetUpVal(u16, u16), SetUpVal(u16, u16),
/// R(A)[R(B)] := R(C) /// R(A)[R(B)] := R(C)
SetTable(u16, u16, u16), SetTable(u16, u16, u16),
/// R(A)[B...] := all values returned from previous function /// R(A) := all values returned from previous function
SetList(u16, u32), SetList(u16),
/// R(A) := R(B)[R(C)] /// R(A) := R(B)[R(C)]
GetTable(u16, u16, u16), GetTable(u16, u16, u16),
/// R(A) := {} /// R(A) := {}
@ -161,15 +159,12 @@ pub enum Instruction {
Close(u16), Close(u16),
/// R(A) := closure(KPROTO[Bx], R(A), ..., R(A+n)) /// R(A) := closure(KPROTO[Bx], R(A), ..., R(A+n))
Closure(u16, u32), Closure(u16, u32),
/// R(A), ... := varargs
Vararg(u16),
} }
impl Debug for Instruction { impl Debug for Instruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
Instruction::Move(arg0, arg1) => write!(f, "MOVE {} {}", arg0, arg1), Instruction::Move(arg0, arg1) => write!(f, "MOVE {} {}", arg0, arg1),
Instruction::MoveRetValues(arg0) => write!(f, "MOVERETVALS {}", arg0),
Instruction::LoadK(arg0, arg1) => write!(f, "LOADK {} {}", arg0, arg1), Instruction::LoadK(arg0, arg1) => write!(f, "LOADK {} {}", arg0, arg1),
Instruction::SetGlobal(arg0, arg1) => write!(f, "SETGLOBAL {} {}", arg0, arg1), Instruction::SetGlobal(arg0, arg1) => write!(f, "SETGLOBAL {} {}", arg0, arg1),
Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1), Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1),
@ -181,7 +176,7 @@ impl Debug for Instruction {
Instruction::GetTable(arg0, arg1, arg2) => { Instruction::GetTable(arg0, arg1, arg2) => {
write!(f, "GETTABLE {} {} {}", arg0, arg1, arg2) write!(f, "GETTABLE {} {} {}", arg0, arg1, arg2)
} }
Instruction::SetList(arg0, arg1) => write!(f, "SETLIST {} {}", arg0, arg1), Instruction::SetList(arg0) => write!(f, "SETLIST {}", arg0),
Instruction::NewTable(arg0) => write!(f, "NEWTABLE {}", arg0), 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),
@ -200,7 +195,6 @@ impl Debug for Instruction {
Instruction::Len(arg0, arg1) => write!(f, "LEN {} {}", arg0, arg1), Instruction::Len(arg0, arg1) => write!(f, "LEN {} {}", arg0, arg1),
Instruction::Or(arg0, arg1, arg2) => write!(f, "OR {} {} {}", arg0, arg1, arg2), Instruction::Or(arg0, arg1, arg2) => write!(f, "OR {} {} {}", arg0, arg1, arg2),
Instruction::And(arg0, arg1, arg2) => write!(f, "AND {} {} {}", arg0, arg1, arg2), Instruction::And(arg0, arg1, arg2) => write!(f, "AND {} {} {}", arg0, arg1, arg2),
Instruction::Vararg(arg0) => write!(f, "VARARG {}", arg0),
} }
} }
} }
@ -512,22 +506,16 @@ impl<T: RustFunction + 'static> From<T> for Value {
} }
} }
#[derive(Debug, Clone, Default)]
pub struct Prototype {
pub instructions: Vec<Instruction>,
pub parameters: usize,
}
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
pub struct VirtualMachine { pub struct VirtualMachine {
pub(super) environment: Rc<RefCell<Environment>>, pub(super) environment: Rc<RefCell<Environment>>,
pub(super) constants: Vec<Constant>, pub(super) constants: Vec<Constant>,
pub(super) prototypes: HashMap<u32, Prototype>, pub(super) prototypes: HashMap<u32, Vec<Instruction>>,
pub(super) proto_counter: u32, pub(super) proto_counter: u32,
} }
impl VirtualMachine { impl VirtualMachine {
pub fn new_prototype(&mut self, instructions: Prototype) -> u32 { pub fn new_prototype(&mut self, instructions: Vec<Instruction>) -> u32 {
let proto_id = self.proto_counter; let proto_id = self.proto_counter;
self.proto_counter += 1; self.proto_counter += 1;
self.prototypes.insert(proto_id, instructions); self.prototypes.insert(proto_id, instructions);
@ -583,7 +571,6 @@ impl Closure {
function_register: 0, function_register: 0,
return_registers: Vec::new(), return_registers: Vec::new(),
top: 0, top: 0,
parameters: params,
} }
} }
@ -607,7 +594,6 @@ pub struct ClosureRunner {
function_register: u16, function_register: u16,
return_registers: Vec<u16>, return_registers: Vec<u16>,
top: u16, top: u16,
parameters: Vec<Value>,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -662,10 +648,7 @@ impl ClosureRunner {
pub fn execute(&mut self, unit: &CompilationUnit) -> ClosureRunner { pub fn execute(&mut self, unit: &CompilationUnit) -> ClosureRunner {
let mut vm = self.closure.vm.clone(); let mut vm = self.closure.vm.clone();
vm.constants = unit.constants.clone(); vm.constants = unit.constants.clone();
let proto_id = vm.new_prototype(Prototype { let proto_id = vm.new_prototype(unit.instructions.clone());
instructions: unit.instructions.clone(),
parameters: 0,
});
for prototype in &unit.state.prototypes { for prototype in &unit.state.prototypes {
vm.new_prototype(prototype.clone()); vm.new_prototype(prototype.clone());
} }
@ -710,7 +693,7 @@ impl ClosureRunner {
} }
} }
let prototype = self let instructions = self
.closure .closure
.vm .vm
.prototypes .prototypes
@ -719,26 +702,12 @@ impl ClosureRunner {
.clone(); .clone();
let constants = self.closure.vm.constants.clone(); let constants = self.closure.vm.constants.clone();
if let Some(instr) = prototype.instructions.get(self.program_counter) { if let Some(instr) = instructions.get(self.program_counter) {
match instr { match instr {
Instruction::Move(a, b) => { Instruction::Move(a, b) => {
let b = self.get_stack(*b); let b = self.get_stack(*b);
self.set_stack(*a, b); self.set_stack(*a, b);
} }
Instruction::MoveRetValues(res) => {
let length = self.top - self.function_register;
let mut values = Vec::new();
for i in 0..length {
let b = self.get_stack(self.function_register + i + 1);
values.push(b);
}
for (i, val) in values.into_iter().enumerate() {
self.set_stack(*res + i as u16, val);
}
self.top = *res + length;
}
Instruction::LoadK(reg, constant) => { Instruction::LoadK(reg, constant) => {
self.set_stack( self.set_stack(
*reg, *reg,
@ -848,13 +817,13 @@ impl ClosureRunner {
self.set_stack(*res, value); self.set_stack(*res, value);
} }
Instruction::SetList(reg, start_idx) => { Instruction::SetList(reg) => {
let table = self.stack.get(reg).cloned(); let table = self.stack.get(reg).cloned();
match table { match table {
Some(value) => { Some(value) => {
let mut table = value.borrow_mut(); let mut table = value.borrow_mut();
if let Value::Table(table) = &mut *table { if let Value::Table(table) = &mut *table {
let mut counter = *start_idx as i64; let mut counter = 1;
for i in self.function_register..self.top { for i in self.function_register..self.top {
let value = self.get_stack(i + 1); let value = self.get_stack(i + 1);
match value { match value {
@ -899,10 +868,14 @@ impl ClosureRunner {
} }
} }
Instruction::Call(func_reg, param_len, ret_len) => { Instruction::Call(func_reg, param_len, ret_len) => {
let param_start_func_reg = *func_reg; let param_start_func_reg = if *param_len == 0 {
self.function_register
} else {
*func_reg
};
let param_len = if *param_len == 0 { let param_len = if *param_len == 0 {
self.top - self.top.min(param_start_func_reg + 1) self.top - self.top.min(param_start_func_reg)
} else { } else {
*param_len *param_len
}; };
@ -977,8 +950,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.top > 0 { if self.function_register > 0 && self.top > 0 {
(*reg_start, self.top - 1) (self.function_register + 1, self.top)
} else { } else {
(*reg_start, *reg_end) (*reg_start, *reg_end)
} }
@ -1097,21 +1070,6 @@ impl ClosureRunner {
.unwrap_or(Value::Nil); .unwrap_or(Value::Nil);
self.set_stack(*res, StackValue::Value(lhs.and(&rhs)?)); self.set_stack(*res, StackValue::Value(lhs.and(&rhs)?));
} }
Instruction::Vararg(reg) => {
self.function_register = reg - 1;
self.top = self.function_register + self.parameters.len() as u16
- prototype.parameters as u16;
for (i, param) in self
.parameters
.clone()
.iter()
.skip(prototype.parameters)
.enumerate()
{
self.set_stack(*reg + i as u16, StackValue::Value(param.clone()));
}
}
}; };
self.program_counter += 1; self.program_counter += 1;