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, ...)
local b, c = ...
return x + 5, b, c
function add(x)
return function (y)
x = x + 1
b = b + 1
return x + y, 1, 2, b
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)]
pub struct Function {
pub name: Option<Node<String>>,
pub params: Vec<Node<IdentOrEllipsis>>,
pub params: Vec<Node<String>>,
pub block: Block,
pub _meta: Metadata,
}
@ -176,23 +147,11 @@ impl Parse for Function {
let mut params = Vec::new();
if let Ok(param) = stream.parse::<Node<IdentOrEllipsis>>() {
params.push(param.clone());
match param.kind {
IdentOrEllipsis::Ident(_) => {
if let Ok(param) = stream.parse() {
params.push(param);
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 => {}
params.push(stream.parse()?);
}
}
@ -375,12 +334,11 @@ pub enum Expression {
ValueRef(String),
UnOp(UnaryOperator, 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>),
Literal(Literal),
TableConstructor(Vec<(Option<Node<Expression>>, Node<Expression>)>),
IndexedAccess(Box<Node<Expression>>, Box<Node<Expression>>),
Ellipsis,
}
impl Parse for Expression {
@ -552,8 +510,6 @@ impl Parse for PrimaryExpression {
stream.expect_symbol('}')?;
Expression::TableConstructor(entries)
} else if let Ok(_) = stream.parse::<Ellipsis>() {
Expression::Ellipsis
} else {
Expression::ValueRef(stream.parse()?)
};

View File

@ -1,17 +1,14 @@
use std::collections::{HashMap, HashSet};
use crate::{
ast::{
AccessModifier, BinaryOperator, Block, Expression, IdentOrEllipsis, Literal, Statement,
UnaryOperator,
},
vm::{Constant, Instruction, LuaBool, LuaInteger, Prototype},
ast::{AccessModifier, BinaryOperator, Block, Expression, Literal, Statement, UnaryOperator},
vm::{Constant, Instruction, LuaBool, LuaInteger},
};
#[derive(Clone, Debug)]
pub struct State {
pub constants: Vec<Constant>,
pub prototypes: Vec<Prototype>,
pub prototypes: Vec<Vec<Instruction>>,
}
impl State {
@ -31,7 +28,6 @@ pub struct Scope {
pub register_counter: LocalCounter,
pub highest_upvalue: u16,
pub upvalues: HashMap<String, u16>,
pub is_vararg: bool,
}
#[derive(Clone, Debug, Default)]
@ -47,6 +43,22 @@ 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());
@ -178,19 +190,11 @@ impl Statement {
match access_modifier {
Some(AccessModifier::Local) => {
let mut vararg_applied = false;
for (i, (name, indexes)) in names.iter().enumerate() {
if let Some(expr_reg) = expr_regs.get(i) {
instructions.push(Instruction::Move(
*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 {
todo!()
}
@ -279,21 +283,17 @@ impl Statement {
}
Statement::Return(expr_list) => {
let mut ret_registers = Vec::new();
let mut vararg = false;
for (i, expr) in expr_list.0.iter().enumerate() {
for expr in &expr_list.0 {
let (instr, registers) = expr.kind.compile(
state,
scope,
if i == expr_list.0.len() - 1 {
if expr_list.0.len() == 1 {
None
} else {
Some(1)
},
);
instructions.extend(instr);
if registers.len() == 0 {
vararg = true;
}
ret_registers.extend(registers);
}
@ -310,21 +310,9 @@ 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(
first_ret_register,
if vararg {
0
} else {
*ret_registers.last().unwrap_or(&0)
},
*ret_registers.first().unwrap_or(&scope.register_counter.0),
*ret_registers.last().unwrap_or(&0),
));
}
Statement::If(expr, block) => {
@ -433,7 +421,6 @@ impl Expression {
constants.extend(index.kind.find_constants(scope));
constants
}
Expression::Ellipsis => HashSet::new(),
}
}
@ -546,16 +533,9 @@ impl Expression {
Expression::FunctionDefinition(params, block) => {
let mut inner_scope = Scope::default();
for param in params {
match &param.kind {
IdentOrEllipsis::Ident(name) => {
inner_scope
.locals
.insert(name.clone(), inner_scope.register_counter.next());
}
IdentOrEllipsis::Ellipsis => {
inner_scope.is_vararg = true;
}
}
.insert(param.kind.clone(), inner_scope.register_counter.next());
}
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);
state.prototypes.push(Prototype {
instructions,
parameters: if inner_scope.is_vararg {
params.len() - 1
} else {
params.len()
},
});
state.prototypes.push(instructions);
let mut instructions = Vec::new();
instructions.push(Instruction::Close(scope.register_counter.0));
@ -591,32 +564,26 @@ 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;
for (i, param) in params.kind.0.iter().enumerate() {
for param in params.kind.0.iter() {
let (instr, registers) = param.kind.compile(
state,
&mut param_scope,
if i == params.kind.0.len() - 1 {
if params.kind.0.len() == 1 {
None
} else {
Some(1)
},
);
instructions.extend(instr);
if registers.len() > 0 {
original_param_regs.push(*registers.first().unwrap());
} else {
vararg = true;
}
original_param_regs.extend(registers);
}
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 {
@ -633,11 +600,6 @@ impl Expression {
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 mut return_regs = Vec::new();
@ -654,7 +616,7 @@ impl Expression {
instructions.push(Instruction::Call(
*&function_reg,
if vararg { 0 } else { param_regs.len() as u16 },
param_regs.len() as u16,
if return_regs.len() == 0 {
0
} else {
@ -685,7 +647,7 @@ impl Expression {
instructions.push(Instruction::NewTable(reg));
let mut counter = 1;
for (i, (key, value)) in entries.iter().enumerate() {
for (key, value) in entries {
if let Some(key) = key {
let (instr, key_regs) = key.kind.compile(state, scope, Some(1));
instructions.extend(instr);
@ -700,11 +662,7 @@ impl Expression {
let (instr, value_regs) = value.kind.compile(
state,
scope,
if i == entries.len() - 1 {
None
} else {
Some(1)
},
if entries.len() == 1 { None } else { Some(1) },
);
instructions.extend(instr);
@ -721,7 +679,7 @@ impl Expression {
));
counter += 1;
} else {
instructions.push(Instruction::SetList(reg, counter as u32));
instructions.push(Instruction::SetList(reg));
}
}
}
@ -744,15 +702,6 @@ impl Expression {
(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 {
pub fn with_virtual_machine<'a>(&self, vm: &'a mut VirtualMachine) -> ExecutionUnit<'a> {
let chunk_id = vm.new_prototype(vm::Prototype {
instructions: self.instructions.clone(),
parameters: 0,
});
let chunk_id = vm.new_prototype(self.instructions.clone());
for prototype in &self.state.prototypes {
vm.new_prototype(prototype.clone());
}

View File

@ -110,8 +110,6 @@ impl Debug for Constant {
pub enum Instruction {
/// R(A) := R(B)
Move(u16, u16),
/// R(A) ... R(A + func_register - top) := previous function return values
MoveRetValues(u16),
/// R(A) := K(Bx)
LoadK(u16, u32),
/// R(A), ..., R(B) := nil
@ -126,8 +124,8 @@ pub enum Instruction {
SetUpVal(u16, u16),
/// R(A)[R(B)] := R(C)
SetTable(u16, u16, u16),
/// R(A)[B...] := all values returned from previous function
SetList(u16, u32),
/// R(A) := all values returned from previous function
SetList(u16),
/// R(A) := R(B)[R(C)]
GetTable(u16, u16, u16),
/// R(A) := {}
@ -161,15 +159,12 @@ pub enum Instruction {
Close(u16),
/// R(A) := closure(KPROTO[Bx], R(A), ..., R(A+n))
Closure(u16, u32),
/// R(A), ... := varargs
Vararg(u16),
}
impl Debug for Instruction {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
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::SetGlobal(arg0, arg1) => write!(f, "SETGLOBAL {} {}", arg0, arg1),
Instruction::GetGlobal(arg0, arg1) => write!(f, "GETGLOBAL {} {}", arg0, arg1),
@ -181,7 +176,7 @@ impl Debug for Instruction {
Instruction::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::Jmp(arg0) => write!(f, "JMP {}", arg0),
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::Or(arg0, arg1, arg2) => write!(f, "OR {} {} {}", 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)]
pub struct VirtualMachine {
pub(super) environment: Rc<RefCell<Environment>>,
pub(super) constants: Vec<Constant>,
pub(super) prototypes: HashMap<u32, Prototype>,
pub(super) prototypes: HashMap<u32, Vec<Instruction>>,
pub(super) proto_counter: u32,
}
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;
self.proto_counter += 1;
self.prototypes.insert(proto_id, instructions);
@ -583,7 +571,6 @@ impl Closure {
function_register: 0,
return_registers: Vec::new(),
top: 0,
parameters: params,
}
}
@ -607,7 +594,6 @@ pub struct ClosureRunner {
function_register: u16,
return_registers: Vec<u16>,
top: u16,
parameters: Vec<Value>,
}
#[derive(Clone, Debug)]
@ -662,10 +648,7 @@ impl ClosureRunner {
pub fn execute(&mut self, unit: &CompilationUnit) -> ClosureRunner {
let mut vm = self.closure.vm.clone();
vm.constants = unit.constants.clone();
let proto_id = vm.new_prototype(Prototype {
instructions: unit.instructions.clone(),
parameters: 0,
});
let proto_id = vm.new_prototype(unit.instructions.clone());
for prototype in &unit.state.prototypes {
vm.new_prototype(prototype.clone());
}
@ -710,7 +693,7 @@ impl ClosureRunner {
}
}
let prototype = self
let instructions = self
.closure
.vm
.prototypes
@ -719,26 +702,12 @@ impl ClosureRunner {
.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 {
Instruction::Move(a, b) => {
let b = self.get_stack(*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) => {
self.set_stack(
*reg,
@ -848,13 +817,13 @@ impl ClosureRunner {
self.set_stack(*res, value);
}
Instruction::SetList(reg, start_idx) => {
Instruction::SetList(reg) => {
let table = self.stack.get(reg).cloned();
match table {
Some(value) => {
let mut table = value.borrow_mut();
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 {
let value = self.get_stack(i + 1);
match value {
@ -899,10 +868,14 @@ impl ClosureRunner {
}
}
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 {
self.top - self.top.min(param_start_func_reg + 1)
self.top - self.top.min(param_start_func_reg)
} else {
*param_len
};
@ -977,8 +950,8 @@ impl ClosureRunner {
self.program_counter += 1;
let mut ret_values = Vec::new();
let (reg_start, reg_end) = if *reg_end == 0 {
if self.top > 0 {
(*reg_start, self.top - 1)
if self.function_register > 0 && self.top > 0 {
(self.function_register + 1, self.top)
} else {
(*reg_start, *reg_end)
}
@ -1097,21 +1070,6 @@ impl ClosureRunner {
.unwrap_or(Value::Nil);
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;