Implement numerical for loops
This commit is contained in:
parent
3405f45169
commit
93493ce283
@ -40,6 +40,6 @@ print(true or 0)
|
||||
global value, table = f(10, 11, 12)
|
||||
|
||||
print("hello")
|
||||
for i=1,10 do
|
||||
for i=#table,1,-1 do
|
||||
print(table[i])
|
||||
end
|
||||
@ -380,9 +380,7 @@ impl Statement {
|
||||
scope.locals.insert("_END".to_owned(), *end_reg);
|
||||
scope.locals.insert("_STEP".to_owned(), *step_reg);
|
||||
|
||||
let is_eql = scope.register_counter.next();
|
||||
instructions.push(Instruction::LessThan(is_eql, *end_reg, *init_reg));
|
||||
instructions.push(Instruction::Test(scope.register_counter.next(), is_eql, 1));
|
||||
instructions.push(Instruction::ForTest(*init_reg, *end_reg, *step_reg));
|
||||
|
||||
let mut inner_scope = scope.clone();
|
||||
let instr = block.compile(state, &mut inner_scope);
|
||||
@ -392,7 +390,7 @@ impl Statement {
|
||||
instructions.extend(instr);
|
||||
|
||||
instructions.push(Instruction::Add(*init_reg, *init_reg, *step_reg));
|
||||
instructions.push(Instruction::Jmp(-(instr_len + 5)));
|
||||
instructions.push(Instruction::Jmp(-(instr_len + 4)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
30
src/vm.rs
30
src/vm.rs
@ -152,6 +152,12 @@ pub enum Instruction {
|
||||
Jmp(i32),
|
||||
/// if (R(B) <=> C) then R(A) := R(B) else PC++
|
||||
Test(u16, u16, u16),
|
||||
/// if R(C) >= 0
|
||||
/// then if R(A) < R(B)
|
||||
/// PC ++
|
||||
/// otherwise if R(A) > R(B)
|
||||
/// PC ++
|
||||
ForTest(u16, u16, u16),
|
||||
/// [func] [params.len()] [ret_regs.len()]
|
||||
/// R(A), ... R(A+C-2) := R(A)(R(A+1), ... R(A+B-1))
|
||||
Call(u16, u16, u16),
|
||||
@ -185,6 +191,9 @@ impl Debug for Instruction {
|
||||
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),
|
||||
Instruction::ForTest(arg0, arg1, arg2) => {
|
||||
write!(f, "FORTEST {} {} {}", arg0, arg1, arg2)
|
||||
}
|
||||
Instruction::Call(arg0, arg1, arg2) => write!(f, "CALL {} {} {}", arg0, arg1, arg2),
|
||||
Instruction::Close(arg0) => write!(f, "CLOSE {}", arg0),
|
||||
Instruction::Closure(arg0, arg1) => write!(f, "CLOSURE {} {}", arg0, arg1),
|
||||
@ -898,6 +907,27 @@ impl ClosureRunner {
|
||||
self.program_counter += 1;
|
||||
}
|
||||
}
|
||||
Instruction::ForTest(counter_reg, end_reg, step_reg) => {
|
||||
let step_gte_0 = match self.get_stack(*step_reg) {
|
||||
StackValue::Value(value) => Value::Integer(LuaInteger(0)).lt(&value),
|
||||
};
|
||||
let counter = match self.get_stack(*counter_reg) {
|
||||
StackValue::Value(value) => value,
|
||||
};
|
||||
let end = match self.get_stack(*end_reg) {
|
||||
StackValue::Value(value) => value,
|
||||
};
|
||||
|
||||
if step_gte_0?.is_truthy() {
|
||||
if !end.lt(&counter)?.is_truthy() {
|
||||
self.program_counter += 1;
|
||||
}
|
||||
} else {
|
||||
if !counter.lt(&end)?.is_truthy() {
|
||||
self.program_counter += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Instruction::Call(func_reg, param_len, ret_len) => {
|
||||
let param_start_func_reg = *func_reg;
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user