1
0

Add jump incrementing when emitting return instructions

This commit is contained in:
Jeff 2024-12-30 20:34:06 -05:00
parent 86bdf0bc37
commit 10c66b3f95
5 changed files with 111 additions and 45 deletions

View File

@ -938,7 +938,7 @@ impl<'src> Compiler<'src> {
self.instructions
.push((last_instruction, last_type, last_position));
self.next_register() - 1
self.next_register().saturating_sub(1)
};
let operator = self.current_token;
let operator_position = self.current_position;
@ -962,11 +962,17 @@ impl<'src> Compiler<'src> {
self.advance()?;
self.parse_sub_expression(&rule.precedence)?;
let instructions_length = self.instructions.len() - 1;
let instructions_length = self.instructions.len();
for (group_index, instructions) in self.instructions.rchunks_mut(3).enumerate().rev() {
if instructions[0].0.operation() != Operation::TEST
|| instructions[1].0.operation() != Operation::JUMP
if instructions.len() < 3 {
continue;
}
if !matches!(
instructions[0].0.operation(),
Operation::TEST | Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL
) || !matches!(instructions[1].0.operation(), Operation::JUMP)
{
continue;
}
@ -1152,10 +1158,29 @@ impl<'src> Compiler<'src> {
self.advance()?;
self.parse_expression()?;
let emit_test_and_jump = if matches!(
self.get_last_operations(),
Some([
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
Operation::JUMP,
Operation::LOAD_BOOLEAN,
Operation::LOAD_BOOLEAN
]),
) {
self.instructions.pop();
self.instructions.pop();
false
} else {
true
};
if emit_test_and_jump {
let operand_register = self.next_register() - 1;
let test = Instruction::test(operand_register, true);
self.emit_instruction(test, Type::None, self.current_position);
}
let if_block_start = self.instructions.len();
let if_block_start_position = self.current_position;
@ -1173,7 +1198,7 @@ impl<'src> Compiler<'src> {
let if_block_end = self.instructions.len();
let mut if_block_distance = (if_block_end - if_block_start) as u8;
let if_block_type = self.get_last_instruction_type();
let if_last_register = self.next_register().saturating_sub(1);
// let if_last_register = self.next_register().saturating_sub(1);
if let Token::Else = self.current_token {
self.advance()?;
@ -1236,19 +1261,21 @@ impl<'src> Compiler<'src> {
}
}
if emit_test_and_jump {
let jump = Instruction::jump(if_block_distance, true);
self.instructions
.insert(if_block_start, (jump, Type::None, if_block_start_position));
}
control_flow_register_consolidation(self);
let else_last_register = self.next_register().saturating_sub(1);
let point = Instruction::point(else_last_register, if_last_register);
// let else_last_register = self.next_register().saturating_sub(1);
// let point = Instruction::point(else_last_register, if_last_register);
if if_last_register < else_last_register {
self.emit_instruction(point, else_block_type, self.current_position);
}
// if if_last_register < else_last_register {
// self.emit_instruction(point, else_block_type, self.current_position);
// }
Ok(())
}
@ -1406,6 +1433,22 @@ impl<'src> Compiler<'src> {
self.emit_instruction(r#return, Type::None, Span(start, end));
let instruction_length = self.instructions.len();
for (index, (instruction, _, _)) in self.instructions.iter_mut().enumerate() {
if instruction.operation() == Operation::JUMP {
let Jump {
offset,
is_positive,
} = Jump::from(&*instruction);
let offset = offset as usize;
if is_positive && offset + index == instruction_length - 2 {
*instruction = Instruction::jump((offset + 1) as u8, true);
}
}
}
Ok(())
}
@ -1432,6 +1475,22 @@ impl<'src> Compiler<'src> {
self.emit_instruction(r#return, Type::None, self.current_position);
}
let instruction_length = self.instructions.len();
for (index, (instruction, _, _)) in self.instructions.iter_mut().enumerate() {
if instruction.operation() == Operation::JUMP {
let Jump {
offset,
is_positive,
} = Jump::from(&*instruction);
let offset = offset as usize;
if is_positive && offset + index == instruction_length - 2 {
*instruction = Instruction::jump((offset + 1) as u8, true);
}
}
}
Ok(())
}

View File

@ -41,7 +41,7 @@ pub fn write(
let mut stdout = stdout();
for register_index in argument_range {
let value = record.open_register(register_index);
if let Some(value) = record.open_register_allow_empty(register_index) {
let string = value.display(record);
stdout
@ -51,6 +51,7 @@ pub fn write(
position: record.current_position(),
})?;
}
}
stdout.flush().map_err(|io_error| NativeFunctionError::Io {
error: io_error.kind(),
@ -68,7 +69,7 @@ pub fn write_line(
let mut stdout = stdout().lock();
for register_index in argument_range {
let value = record.open_register(register_index);
if let Some(value) = record.open_register_allow_empty(register_index) {
let string = value.display(record);
stdout
@ -84,6 +85,7 @@ pub fn write_line(
position: record.current_position(),
})?;
}
}
stdout.flush().map_err(|io_error| NativeFunctionError::Io {
error: io_error.kind(),

View File

@ -38,6 +38,10 @@ impl CallStack {
self.calls.last()
}
pub fn last_mut(&mut self) -> Option<&mut FunctionCall> {
self.calls.last_mut()
}
pub fn pop_or_panic(&mut self) -> FunctionCall {
assert!(!self.is_empty(), "{}", VmError::CallStackUnderflow);

View File

@ -82,7 +82,10 @@ impl Thread {
if record_index == active.index() as usize {
trace!("Recursion detected");
self.call_stack.last_mut_or_panic().ip = active.ip;
if let Some(record) = self.call_stack.last_mut() {
record.ip = active.ip;
}
active.ip = 0;
}
@ -133,10 +136,8 @@ impl Thread {
}
}
};
let outer_call = self.call_stack.last_or_panic();
let record_index = outer_call.record_index as usize;
trace!("Return from {returning_call} to {outer_call}");
let outer_call = self.call_stack.last();
let record_index = outer_call.map_or(0, |call| call.record_index as usize);
if should_return_value {
let return_register = active
@ -153,7 +154,7 @@ impl Thread {
);
} else {
active = &mut self.records[record_index];
active.ip = outer_call.ip;
active.ip = record_index;
}
}
}

View File

@ -5,4 +5,4 @@ fn fib (n: int) -> int {
fib(n - 1) + fib(n - 2)
}
write_line(fib(1))
write_line(fib(0))