Add Pre-Instructions
This commit is contained in:
parent
93493ce283
commit
c59c4e4e24
@ -40,6 +40,6 @@ print(true or 0)
|
|||||||
global value, table = f(10, 11, 12)
|
global value, table = f(10, 11, 12)
|
||||||
|
|
||||||
print("hello")
|
print("hello")
|
||||||
for i=#table,1,-1 do
|
for i=1,#table do
|
||||||
print(table[i])
|
print(table[i])
|
||||||
end
|
end
|
||||||
209
src/compile.rs
209
src/compile.rs
@ -77,6 +77,23 @@ impl LocalCounter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) enum PreInstr {
|
||||||
|
Instr(Instruction),
|
||||||
|
Break,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn process_pre_instrs(pre_instructions: Vec<PreInstr>) -> Vec<Instruction> {
|
||||||
|
let mut instructions = Vec::new();
|
||||||
|
for pre_instr in pre_instructions {
|
||||||
|
match pre_instr {
|
||||||
|
PreInstr::Instr(instruction) => instructions.push(instruction),
|
||||||
|
PreInstr::Break => panic!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instructions
|
||||||
|
}
|
||||||
|
|
||||||
impl Block {
|
impl Block {
|
||||||
pub(crate) fn find_constants(
|
pub(crate) fn find_constants(
|
||||||
&self,
|
&self,
|
||||||
@ -94,7 +111,7 @@ impl Block {
|
|||||||
constants
|
constants
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn compile(&self, state: &mut State, scope: &mut Scope) -> Vec<Instruction> {
|
pub(crate) fn compile(&self, state: &mut State, scope: &mut Scope) -> Vec<PreInstr> {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
|
|
||||||
let mut inner_scope = scope.clone();
|
let mut inner_scope = scope.clone();
|
||||||
@ -165,7 +182,7 @@ impl Statement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile(&self, state: &mut State, scope: &mut Scope) -> Vec<Instruction> {
|
fn compile(&self, state: &mut State, scope: &mut Scope) -> Vec<PreInstr> {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
@ -173,7 +190,7 @@ impl Statement {
|
|||||||
let new_registers = if *access_modifier == Some(AccessModifier::Local) {
|
let new_registers = if *access_modifier == Some(AccessModifier::Local) {
|
||||||
let min_reg = scope.register_counter.0 + 1;
|
let min_reg = scope.register_counter.0 + 1;
|
||||||
let max_reg = scope.register_counter.0 + names.len() as u16;
|
let max_reg = scope.register_counter.0 + names.len() as u16;
|
||||||
instructions.push(Instruction::LoadNil(min_reg, max_reg));
|
instructions.push(PreInstr::Instr(Instruction::LoadNil(min_reg, max_reg)));
|
||||||
scope.register_counter.0 += names.len() as u16 + 1;
|
scope.register_counter.0 += names.len() as u16 + 1;
|
||||||
|
|
||||||
let mut new_registers = Vec::new();
|
let mut new_registers = Vec::new();
|
||||||
@ -205,14 +222,14 @@ impl Statement {
|
|||||||
let mut vararg_applied = false;
|
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) {
|
if let Some(expr_reg) = expr_regs.get(i) {
|
||||||
instructions.push(Instruction::Move(
|
instructions.push(PreInstr::Instr(Instruction::Move(
|
||||||
*new_registers.get(i).unwrap(),
|
*new_registers.get(i).unwrap(),
|
||||||
*expr_reg,
|
*expr_reg,
|
||||||
));
|
)));
|
||||||
} else if !vararg_applied {
|
} else if !vararg_applied {
|
||||||
instructions.push(Instruction::MoveRetValues(
|
instructions.push(PreInstr::Instr(Instruction::MoveRetValues(
|
||||||
*new_registers.get(i).unwrap(),
|
*new_registers.get(i).unwrap(),
|
||||||
));
|
)));
|
||||||
vararg_applied = true;
|
vararg_applied = true;
|
||||||
}
|
}
|
||||||
if indexes.len() > 0 {
|
if indexes.len() > 0 {
|
||||||
@ -229,10 +246,10 @@ impl Statement {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
let global = state.get_constant(&Constant::String(name.kind.clone()));
|
let global = state.get_constant(&Constant::String(name.kind.clone()));
|
||||||
instructions.push(Instruction::SetGlobal(
|
instructions.push(PreInstr::Instr(Instruction::SetGlobal(
|
||||||
expr_regs.get(i).cloned().unwrap(),
|
expr_regs.get(i).cloned().unwrap(),
|
||||||
global,
|
global,
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -242,13 +259,17 @@ impl Statement {
|
|||||||
*reg
|
*reg
|
||||||
} else if let Some(upval_reg) = scope.upvalues.get(&name.kind) {
|
} else if let Some(upval_reg) = scope.upvalues.get(&name.kind) {
|
||||||
let local = scope.register_counter.next();
|
let local = scope.register_counter.next();
|
||||||
instructions.push(Instruction::GetUpVal(local, *upval_reg));
|
instructions.push(PreInstr::Instr(Instruction::GetUpVal(
|
||||||
|
local, *upval_reg,
|
||||||
|
)));
|
||||||
local
|
local
|
||||||
} else {
|
} else {
|
||||||
let global =
|
let global =
|
||||||
state.get_constant(&Constant::String(name.kind.clone()));
|
state.get_constant(&Constant::String(name.kind.clone()));
|
||||||
let local = scope.register_counter.next();
|
let local = scope.register_counter.next();
|
||||||
instructions.push(Instruction::GetGlobal(local, global));
|
instructions.push(PreInstr::Instr(Instruction::GetGlobal(
|
||||||
|
local, global,
|
||||||
|
)));
|
||||||
local
|
local
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -261,40 +282,40 @@ impl Statement {
|
|||||||
let (instr, index_reg) =
|
let (instr, index_reg) =
|
||||||
index.kind.compile(state, scope, Some(1));
|
index.kind.compile(state, scope, Some(1));
|
||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
instructions.push(Instruction::GetTable(
|
instructions.push(PreInstr::Instr(Instruction::GetTable(
|
||||||
table_reg,
|
table_reg,
|
||||||
table_reg,
|
table_reg,
|
||||||
*index_reg.first().unwrap(),
|
*index_reg.first().unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (instr, index_reg) =
|
let (instr, index_reg) =
|
||||||
indexes.last().unwrap().kind.compile(state, scope, Some(1));
|
indexes.last().unwrap().kind.compile(state, scope, Some(1));
|
||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
instructions.push(Instruction::SetTable(
|
instructions.push(PreInstr::Instr(Instruction::SetTable(
|
||||||
table_reg,
|
table_reg,
|
||||||
*index_reg.first().unwrap(),
|
*index_reg.first().unwrap(),
|
||||||
expr_regs.get(i).cloned().unwrap(),
|
expr_regs.get(i).cloned().unwrap(),
|
||||||
));
|
)));
|
||||||
} else {
|
} else {
|
||||||
if let Some(reg) = scope.locals.get(&name.kind) {
|
if let Some(reg) = scope.locals.get(&name.kind) {
|
||||||
instructions.push(Instruction::Move(
|
instructions.push(PreInstr::Instr(Instruction::Move(
|
||||||
*reg,
|
*reg,
|
||||||
expr_regs.get(i).cloned().unwrap(),
|
expr_regs.get(i).cloned().unwrap(),
|
||||||
));
|
)));
|
||||||
} else if let Some(upval_reg) = scope.upvalues.get(&name.kind) {
|
} else if let Some(upval_reg) = scope.upvalues.get(&name.kind) {
|
||||||
instructions.push(Instruction::SetUpVal(
|
instructions.push(PreInstr::Instr(Instruction::SetUpVal(
|
||||||
*upval_reg,
|
*upval_reg,
|
||||||
expr_regs.get(i).cloned().unwrap(),
|
expr_regs.get(i).cloned().unwrap(),
|
||||||
));
|
)));
|
||||||
} else {
|
} else {
|
||||||
let global =
|
let global =
|
||||||
state.get_constant(&Constant::String(name.kind.clone()));
|
state.get_constant(&Constant::String(name.kind.clone()));
|
||||||
instructions.push(Instruction::SetGlobal(
|
instructions.push(PreInstr::Instr(Instruction::SetGlobal(
|
||||||
expr_regs.get(i).cloned().unwrap(),
|
expr_regs.get(i).cloned().unwrap(),
|
||||||
global,
|
global,
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,35 +350,42 @@ impl Statement {
|
|||||||
for (i, ret_register) in ret_registers.iter_mut().enumerate() {
|
for (i, ret_register) in ret_registers.iter_mut().enumerate() {
|
||||||
let new_reg = first_ret_register + i as u16;
|
let new_reg = first_ret_register + i as u16;
|
||||||
if *ret_register != new_reg {
|
if *ret_register != new_reg {
|
||||||
instructions.push(Instruction::Move(new_reg, *ret_register));
|
instructions
|
||||||
|
.push(PreInstr::Instr(Instruction::Move(new_reg, *ret_register)));
|
||||||
}
|
}
|
||||||
*ret_register = new_reg;
|
*ret_register = new_reg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if vararg {
|
if vararg {
|
||||||
instructions.push(Instruction::MoveRetValues(
|
instructions.push(PreInstr::Instr(Instruction::MoveRetValues(
|
||||||
first_ret_register + ret_registers.len() as u16,
|
first_ret_register + ret_registers.len() as u16,
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
instructions.push(Instruction::Return(
|
instructions.push(PreInstr::Instr(Instruction::Return(
|
||||||
first_ret_register,
|
first_ret_register,
|
||||||
if vararg {
|
if vararg {
|
||||||
0
|
0
|
||||||
} else {
|
} else {
|
||||||
*ret_registers.last().unwrap_or(&0)
|
*ret_registers.last().unwrap_or(&0)
|
||||||
},
|
},
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
Statement::If(expr, block) => {
|
Statement::If(expr, block) => {
|
||||||
let (instr, regs) = expr.kind.compile(state, scope, Some(1));
|
let (instr, regs) = expr.kind.compile(state, scope, Some(1));
|
||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
|
|
||||||
let local = scope.register_counter.next();
|
let local = scope.register_counter.next();
|
||||||
instructions.push(Instruction::Test(local, *regs.first().unwrap(), 0));
|
instructions.push(PreInstr::Instr(Instruction::Test(
|
||||||
|
local,
|
||||||
|
*regs.first().unwrap(),
|
||||||
|
0,
|
||||||
|
)));
|
||||||
|
|
||||||
let block_instructions = block.compile(state, scope);
|
let block_instructions = block.compile(state, scope);
|
||||||
instructions.push(Instruction::Jmp(block_instructions.len() as i32));
|
instructions.push(PreInstr::Instr(Instruction::Jmp(
|
||||||
|
block_instructions.len() as i32
|
||||||
|
)));
|
||||||
instructions.extend(block_instructions);
|
instructions.extend(block_instructions);
|
||||||
}
|
}
|
||||||
Statement::Expression(expr) => {
|
Statement::Expression(expr) => {
|
||||||
@ -380,17 +408,21 @@ impl Statement {
|
|||||||
scope.locals.insert("_END".to_owned(), *end_reg);
|
scope.locals.insert("_END".to_owned(), *end_reg);
|
||||||
scope.locals.insert("_STEP".to_owned(), *step_reg);
|
scope.locals.insert("_STEP".to_owned(), *step_reg);
|
||||||
|
|
||||||
instructions.push(Instruction::ForTest(*init_reg, *end_reg, *step_reg));
|
instructions.push(PreInstr::Instr(Instruction::ForTest(
|
||||||
|
*init_reg, *end_reg, *step_reg,
|
||||||
|
)));
|
||||||
|
|
||||||
let mut inner_scope = scope.clone();
|
let mut inner_scope = scope.clone();
|
||||||
let instr = block.compile(state, &mut inner_scope);
|
let instr = block.compile(state, &mut inner_scope);
|
||||||
let instr_len = instr.len() as i32;
|
let instr_len = instr.len() as i32;
|
||||||
|
|
||||||
instructions.push(Instruction::Jmp(instr_len + 2));
|
instructions.push(PreInstr::Instr(Instruction::Jmp(instr_len + 2)));
|
||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
|
|
||||||
instructions.push(Instruction::Add(*init_reg, *init_reg, *step_reg));
|
instructions.push(PreInstr::Instr(Instruction::Add(
|
||||||
instructions.push(Instruction::Jmp(-(instr_len + 4)));
|
*init_reg, *init_reg, *step_reg,
|
||||||
|
)));
|
||||||
|
instructions.push(PreInstr::Instr(Instruction::Jmp(-(instr_len + 4))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,21 +524,24 @@ impl Expression {
|
|||||||
state: &mut State,
|
state: &mut State,
|
||||||
scope: &mut Scope,
|
scope: &mut Scope,
|
||||||
expected_values: Option<usize>,
|
expected_values: Option<usize>,
|
||||||
) -> (Vec<Instruction>, Vec<u16>) {
|
) -> (Vec<PreInstr>, Vec<u16>) {
|
||||||
match self {
|
match self {
|
||||||
Expression::ValueRef(name) => {
|
Expression::ValueRef(name) => {
|
||||||
if let Some(reg) = scope.locals.get(name) {
|
if let Some(reg) = scope.locals.get(name) {
|
||||||
(Vec::new(), vec![*reg])
|
(Vec::new(), vec![*reg])
|
||||||
} else if let Some(upvalue) = scope.upvalues.get(name) {
|
} else if let Some(upvalue) = scope.upvalues.get(name) {
|
||||||
let local = scope.register_counter.next();
|
let local = scope.register_counter.next();
|
||||||
(vec![Instruction::GetUpVal(local, *upvalue)], vec![local])
|
(
|
||||||
|
vec![PreInstr::Instr(Instruction::GetUpVal(local, *upvalue))],
|
||||||
|
vec![local],
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
let reg = scope.register_counter.next();
|
let reg = scope.register_counter.next();
|
||||||
instructions.push(Instruction::GetGlobal(
|
instructions.push(PreInstr::Instr(Instruction::GetGlobal(
|
||||||
reg,
|
reg,
|
||||||
state.get_constant(&Constant::String(name.clone())),
|
state.get_constant(&Constant::String(name.clone())),
|
||||||
));
|
)));
|
||||||
(instructions, vec![reg])
|
(instructions, vec![reg])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -519,64 +554,69 @@ impl Expression {
|
|||||||
let reg = scope.register_counter.next();
|
let reg = scope.register_counter.next();
|
||||||
match binary_operator {
|
match binary_operator {
|
||||||
BinaryOperator::Equal => {
|
BinaryOperator::Equal => {
|
||||||
instructions.push(Instruction::Equal(
|
instructions.push(PreInstr::Instr(Instruction::Equal(
|
||||||
reg,
|
reg,
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::LessThan => {
|
BinaryOperator::LessThan => {
|
||||||
instructions.push(Instruction::LessThan(
|
instructions.push(PreInstr::Instr(Instruction::LessThan(
|
||||||
reg,
|
reg,
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::LessThanOrEqual => {
|
BinaryOperator::LessThanOrEqual => {
|
||||||
instructions.push(Instruction::LessThanOrEqual(
|
instructions.push(PreInstr::Instr(Instruction::LessThanOrEqual(
|
||||||
reg,
|
reg,
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::GreaterThan => {
|
BinaryOperator::GreaterThan => {
|
||||||
instructions.push(Instruction::LessThan(
|
instructions.push(PreInstr::Instr(Instruction::LessThan(
|
||||||
reg,
|
reg,
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::GreaterThanOrEqual => {
|
BinaryOperator::GreaterThanOrEqual => {
|
||||||
instructions.push(Instruction::LessThanOrEqual(
|
instructions.push(PreInstr::Instr(Instruction::LessThanOrEqual(
|
||||||
reg,
|
reg,
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::Add => {
|
BinaryOperator::Add => {
|
||||||
instructions.push(Instruction::Add(
|
instructions.push(PreInstr::Instr(Instruction::Add(
|
||||||
reg,
|
reg,
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::Sub => {
|
BinaryOperator::Sub => {
|
||||||
instructions.push(Instruction::Unm(reg, *rhs.get(0).unwrap()));
|
instructions
|
||||||
instructions.push(Instruction::Add(reg, *lhs.get(0).unwrap(), reg));
|
.push(PreInstr::Instr(Instruction::Unm(reg, *rhs.get(0).unwrap())));
|
||||||
|
instructions.push(PreInstr::Instr(Instruction::Add(
|
||||||
|
reg,
|
||||||
|
*lhs.get(0).unwrap(),
|
||||||
|
reg,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::And => {
|
BinaryOperator::And => {
|
||||||
instructions.push(Instruction::And(
|
instructions.push(PreInstr::Instr(Instruction::And(
|
||||||
reg,
|
reg,
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
BinaryOperator::Or => {
|
BinaryOperator::Or => {
|
||||||
instructions.push(Instruction::Or(
|
instructions.push(PreInstr::Instr(Instruction::Or(
|
||||||
reg,
|
reg,
|
||||||
*lhs.get(0).unwrap(),
|
*lhs.get(0).unwrap(),
|
||||||
*rhs.get(0).unwrap(),
|
*rhs.get(0).unwrap(),
|
||||||
));
|
)));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(instructions, vec![reg])
|
(instructions, vec![reg])
|
||||||
@ -587,8 +627,12 @@ impl Expression {
|
|||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
for reg in ®isters {
|
for reg in ®isters {
|
||||||
match op {
|
match op {
|
||||||
UnaryOperator::Negation => instructions.push(Instruction::Unm(*reg, *reg)),
|
UnaryOperator::Negation => {
|
||||||
UnaryOperator::Length => instructions.push(Instruction::Len(*reg, *reg)),
|
instructions.push(PreInstr::Instr(Instruction::Unm(*reg, *reg)))
|
||||||
|
}
|
||||||
|
UnaryOperator::Length => {
|
||||||
|
instructions.push(PreInstr::Instr(Instruction::Len(*reg, *reg)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(instructions, registers)
|
(instructions, registers)
|
||||||
@ -618,7 +662,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(Prototype {
|
||||||
instructions,
|
instructions: process_pre_instrs(instructions),
|
||||||
parameters: if inner_scope.is_vararg {
|
parameters: if inner_scope.is_vararg {
|
||||||
params.len() - 1
|
params.len() - 1
|
||||||
} else {
|
} else {
|
||||||
@ -627,9 +671,14 @@ impl Expression {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
instructions.push(Instruction::Close(scope.register_counter.0));
|
instructions.push(PreInstr::Instr(Instruction::Close(
|
||||||
|
scope.register_counter.0,
|
||||||
|
)));
|
||||||
let local = scope.register_counter.next();
|
let local = scope.register_counter.next();
|
||||||
instructions.push(Instruction::Closure(local, state.prototypes.len() as u32));
|
instructions.push(PreInstr::Instr(Instruction::Closure(
|
||||||
|
local,
|
||||||
|
state.prototypes.len() as u32,
|
||||||
|
)));
|
||||||
|
|
||||||
(instructions, vec![local])
|
(instructions, vec![local])
|
||||||
}
|
}
|
||||||
@ -676,16 +725,19 @@ impl Expression {
|
|||||||
for (i, param_reg) in original_param_regs.iter().enumerate().rev() {
|
for (i, param_reg) in original_param_regs.iter().enumerate().rev() {
|
||||||
let new_reg = param_regs.get(i).unwrap();
|
let new_reg = param_regs.get(i).unwrap();
|
||||||
if param_reg != new_reg {
|
if param_reg != new_reg {
|
||||||
instructions.push(Instruction::Move(*new_reg, *param_reg));
|
instructions.push(PreInstr::Instr(Instruction::Move(*new_reg, *param_reg)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if function_reg != *old_function_reg {
|
if function_reg != *old_function_reg {
|
||||||
instructions.push(Instruction::Move(function_reg, *old_function_reg));
|
instructions.push(PreInstr::Instr(Instruction::Move(
|
||||||
|
function_reg,
|
||||||
|
*old_function_reg,
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if vararg {
|
if vararg {
|
||||||
let last_reg = param_regs.last().unwrap_or(&function_reg) + 1;
|
let last_reg = param_regs.last().unwrap_or(&function_reg) + 1;
|
||||||
instructions.push(Instruction::MoveRetValues(last_reg));
|
instructions.push(PreInstr::Instr(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);
|
||||||
@ -702,7 +754,7 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instructions.push(Instruction::Call(
|
instructions.push(PreInstr::Instr(Instruction::Call(
|
||||||
*&function_reg,
|
*&function_reg,
|
||||||
if vararg { 0 } else { param_regs.len() as u16 },
|
if vararg { 0 } else { param_regs.len() as u16 },
|
||||||
if return_regs.len() == 0 {
|
if return_regs.len() == 0 {
|
||||||
@ -710,14 +762,14 @@ impl Expression {
|
|||||||
} else {
|
} else {
|
||||||
return_regs.len() as u16 + 1
|
return_regs.len() as u16 + 1
|
||||||
},
|
},
|
||||||
));
|
)));
|
||||||
|
|
||||||
(instructions, return_regs)
|
(instructions, return_regs)
|
||||||
}
|
}
|
||||||
Expression::Literal(literal) => {
|
Expression::Literal(literal) => {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
let reg = scope.register_counter.next();
|
let reg = scope.register_counter.next();
|
||||||
instructions.push(Instruction::LoadK(
|
instructions.push(PreInstr::Instr(Instruction::LoadK(
|
||||||
reg,
|
reg,
|
||||||
state.get_constant(&match literal {
|
state.get_constant(&match literal {
|
||||||
Literal::Float(value) => Constant::Float(value.vm_number()),
|
Literal::Float(value) => Constant::Float(value.vm_number()),
|
||||||
@ -726,13 +778,13 @@ impl Expression {
|
|||||||
Literal::Bool(value) => Constant::Bool(LuaBool(*value)),
|
Literal::Bool(value) => Constant::Bool(LuaBool(*value)),
|
||||||
Literal::Nil => Constant::Nil,
|
Literal::Nil => Constant::Nil,
|
||||||
}),
|
}),
|
||||||
));
|
)));
|
||||||
(instructions, vec![reg])
|
(instructions, vec![reg])
|
||||||
}
|
}
|
||||||
Expression::TableConstructor(entries) => {
|
Expression::TableConstructor(entries) => {
|
||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
let reg = scope.register_counter.next();
|
let reg = scope.register_counter.next();
|
||||||
instructions.push(Instruction::NewTable(reg));
|
instructions.push(PreInstr::Instr(Instruction::NewTable(reg)));
|
||||||
|
|
||||||
let mut counter = 1;
|
let mut counter = 1;
|
||||||
for (i, (key, value)) in entries.iter().enumerate() {
|
for (i, (key, value)) in entries.iter().enumerate() {
|
||||||
@ -741,11 +793,11 @@ impl Expression {
|
|||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
let (instr, value_regs) = value.kind.compile(state, scope, Some(1));
|
let (instr, value_regs) = value.kind.compile(state, scope, Some(1));
|
||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
instructions.push(Instruction::SetTable(
|
instructions.push(PreInstr::Instr(Instruction::SetTable(
|
||||||
reg,
|
reg,
|
||||||
*key_regs.first().unwrap(),
|
*key_regs.first().unwrap(),
|
||||||
*value_regs.first().unwrap(),
|
*value_regs.first().unwrap(),
|
||||||
));
|
)));
|
||||||
} else {
|
} else {
|
||||||
let (instr, value_regs) = value.kind.compile(
|
let (instr, value_regs) = value.kind.compile(
|
||||||
state,
|
state,
|
||||||
@ -760,18 +812,19 @@ impl Expression {
|
|||||||
|
|
||||||
if value_regs.len() > 0 {
|
if value_regs.len() > 0 {
|
||||||
let key_reg = scope.register_counter.next();
|
let key_reg = scope.register_counter.next();
|
||||||
instructions.push(Instruction::LoadK(
|
instructions.push(PreInstr::Instr(Instruction::LoadK(
|
||||||
key_reg,
|
key_reg,
|
||||||
state.get_constant(&Constant::Integer(LuaInteger(counter))),
|
state.get_constant(&Constant::Integer(LuaInteger(counter))),
|
||||||
));
|
)));
|
||||||
instructions.push(Instruction::SetTable(
|
instructions.push(PreInstr::Instr(Instruction::SetTable(
|
||||||
reg,
|
reg,
|
||||||
key_reg,
|
key_reg,
|
||||||
*value_regs.first().unwrap(),
|
*value_regs.first().unwrap(),
|
||||||
));
|
)));
|
||||||
counter += 1;
|
counter += 1;
|
||||||
} else {
|
} else {
|
||||||
instructions.push(Instruction::SetList(reg, counter as u32));
|
instructions
|
||||||
|
.push(PreInstr::Instr(Instruction::SetList(reg, counter as u32)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -786,11 +839,11 @@ impl Expression {
|
|||||||
instructions.extend(instr);
|
instructions.extend(instr);
|
||||||
|
|
||||||
let local = scope.register_counter.next();
|
let local = scope.register_counter.next();
|
||||||
instructions.push(Instruction::GetTable(
|
instructions.push(PreInstr::Instr(Instruction::GetTable(
|
||||||
local,
|
local,
|
||||||
*expr_regs.first().unwrap(),
|
*expr_regs.first().unwrap(),
|
||||||
*index_regs.first().unwrap(),
|
*index_regs.first().unwrap(),
|
||||||
));
|
)));
|
||||||
|
|
||||||
(instructions, vec![local])
|
(instructions, vec![local])
|
||||||
}
|
}
|
||||||
@ -801,10 +854,10 @@ impl Expression {
|
|||||||
let mut instructions = Vec::new();
|
let mut instructions = Vec::new();
|
||||||
let new_reg = scope.register_counter.new();
|
let new_reg = scope.register_counter.new();
|
||||||
if expected_values == None {
|
if expected_values == None {
|
||||||
instructions.push(Instruction::Vararg(new_reg, 0));
|
instructions.push(PreInstr::Instr(Instruction::Vararg(new_reg, 0)));
|
||||||
(instructions, Vec::new())
|
(instructions, Vec::new())
|
||||||
} else {
|
} else {
|
||||||
instructions.push(Instruction::Vararg(new_reg, 3));
|
instructions.push(PreInstr::Instr(Instruction::Vararg(new_reg, 3)));
|
||||||
(instructions, vec![new_reg])
|
(instructions, vec![new_reg])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ use thiserror::Error;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::Block,
|
ast::Block,
|
||||||
|
compile::process_pre_instrs,
|
||||||
token_stream::{
|
token_stream::{
|
||||||
TokenStream, TokenStreamError,
|
TokenStream, TokenStreamError,
|
||||||
lexer::{Error as TokenizerError, Token, tokenize},
|
lexer::{Error as TokenizerError, Token, tokenize},
|
||||||
@ -139,7 +140,7 @@ pub fn compile(
|
|||||||
// dbg!(&constants);
|
// dbg!(&constants);
|
||||||
|
|
||||||
Ok(CompilationUnit {
|
Ok(CompilationUnit {
|
||||||
instructions,
|
instructions: process_pre_instrs(instructions),
|
||||||
state,
|
state,
|
||||||
constants,
|
constants,
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user