1
0

Begin refactoring jump instructions

This commit is contained in:
Jeff 2024-10-30 14:48:30 -04:00
parent 1f9adfab2f
commit 604962c535
6 changed files with 182 additions and 70 deletions

View File

@ -211,10 +211,11 @@ impl Instruction {
instruction instruction
} }
pub fn jump(jump_to: u8) -> Instruction { pub fn jump(jump_offset: u8, is_positive: bool) -> Instruction {
let mut instruction = Instruction(Operation::Jump as u32); let mut instruction = Instruction(Operation::Jump as u32);
instruction.set_b(jump_to); instruction.set_b(jump_offset);
instruction.set_c_to_boolean(is_positive);
instruction instruction
} }
@ -557,9 +558,14 @@ impl Instruction {
format!("R{to_register} = !{argument}") format!("R{to_register} = !{argument}")
} }
Operation::Jump => { Operation::Jump => {
let jump_to = self.b(); let jump_distance = self.b();
let is_positive = self.c_as_boolean();
format!("JUMP TO {jump_to}") if is_positive {
format!("JUMP +{jump_distance}")
} else {
format!("JUMP -{jump_distance}")
}
} }
Operation::Call => { Operation::Call => {
let to_register = self.a(); let to_register = self.a();
@ -839,10 +845,12 @@ mod tests {
#[test] #[test]
fn jump() { fn jump() {
let instruction = Instruction::jump(4); let instruction = Instruction::jump(4, true);
assert_eq!(instruction.operation(), Operation::Jump); assert_eq!(instruction.operation(), Operation::Jump);
assert_eq!(instruction.b(), 4); assert_eq!(instruction.b(), 4);
assert!(instruction.c_as_boolean());
} }
#[test] #[test]

View File

@ -555,18 +555,37 @@ pub enum NativeFunctionError {
impl AnnotatedError for NativeFunctionError { impl AnnotatedError for NativeFunctionError {
fn title() -> &'static str { fn title() -> &'static str {
todo!() "Native Function Error"
} }
fn description(&self) -> &'static str { fn description(&self) -> &'static str {
todo!() match self {
NativeFunctionError::ExpectedArgumentCount { .. } => {
"Expected a different number of arguments"
}
NativeFunctionError::Panic { .. } => "Explicit panic",
NativeFunctionError::Parse { .. } => "Failed to parse value",
NativeFunctionError::Io { .. } => "I/O error",
}
} }
fn details(&self) -> Option<String> { fn details(&self) -> Option<String> {
todo!() match self {
NativeFunctionError::ExpectedArgumentCount {
expected, found, ..
} => Some(format!("Expected {} arguments, found {}", expected, found)),
NativeFunctionError::Panic { message, .. } => message.clone(),
NativeFunctionError::Parse { error, .. } => Some(format!("{}", error)),
NativeFunctionError::Io { error, .. } => Some(format!("{}", error)),
}
} }
fn position(&self) -> Span { fn position(&self) -> Span {
todo!() match self {
NativeFunctionError::ExpectedArgumentCount { position, .. } => *position,
NativeFunctionError::Panic { position, .. } => *position,
NativeFunctionError::Parse { position, .. } => *position,
NativeFunctionError::Io { position, .. } => *position,
}
} }
} }

View File

@ -228,6 +228,19 @@ impl<'src> Parser<'src> {
}) })
} }
fn get_last_jumpable_mut(&mut self) -> Option<&mut Instruction> {
self.chunk
.instructions_mut()
.iter_mut()
.find_map(|(instruction, _)| {
if let Operation::LoadBoolean | Operation::LoadConstant = instruction.operation() {
Some(instruction)
} else {
None
}
})
}
fn emit_constant(&mut self, value: Value, position: Span) -> Result<(), ParseError> { fn emit_constant(&mut self, value: Value, position: Span) -> Result<(), ParseError> {
let constant_index = self.chunk.push_constant(value, position)?; let constant_index = self.chunk.push_constant(value, position)?;
let register = self.next_register(); let register = self.next_register();
@ -651,7 +664,6 @@ impl<'src> Parser<'src> {
Token::LessEqual => Instruction::less_equal(true, left, right), Token::LessEqual => Instruction::less_equal(true, left, right),
Token::Greater => Instruction::less_equal(false, left, right), Token::Greater => Instruction::less_equal(false, left, right),
Token::GreaterEqual => Instruction::less(false, left, right), Token::GreaterEqual => Instruction::less(false, left, right),
_ => { _ => {
return Err(ParseError::ExpectedTokenMultiple { return Err(ParseError::ExpectedTokenMultiple {
expected: &[ expected: &[
@ -688,9 +700,7 @@ impl<'src> Parser<'src> {
self.emit_instruction(instruction, operator_position); self.emit_instruction(instruction, operator_position);
let jump_to = (self.chunk.len() + 2) as u8; self.emit_instruction(Instruction::jump(1, true), operator_position);
self.emit_instruction(Instruction::jump(jump_to), operator_position);
self.emit_instruction( self.emit_instruction(
Instruction::load_boolean(register, true, true), Instruction::load_boolean(register, true, true),
operator_position, operator_position,
@ -706,6 +716,7 @@ impl<'src> Parser<'src> {
} }
fn parse_logical_binary(&mut self) -> Result<(), ParseError> { fn parse_logical_binary(&mut self) -> Result<(), ParseError> {
let start_length = self.chunk.len();
let (left_instruction, left_position) = let (left_instruction, left_position) =
self.chunk self.chunk
.instructions_mut() .instructions_mut()
@ -719,7 +730,7 @@ impl<'src> Parser<'src> {
let operator_position = self.current_position; let operator_position = self.current_position;
let rule = ParseRule::from(&operator); let rule = ParseRule::from(&operator);
let instruction = match operator { let test_instruction = match operator {
Token::DoubleAmpersand => Instruction::test(left_instruction.a(), false), Token::DoubleAmpersand => Instruction::test(left_instruction.a(), false),
Token::DoublePipe => Instruction::test(left_instruction.a(), true), Token::DoublePipe => Instruction::test(left_instruction.a(), true),
_ => { _ => {
@ -733,11 +744,11 @@ impl<'src> Parser<'src> {
self.advance()?; self.advance()?;
self.emit_instruction(left_instruction, left_position); self.emit_instruction(left_instruction, left_position);
self.emit_instruction(instruction, operator_position); self.emit_instruction(test_instruction, operator_position);
let jump_to = (self.chunk.len() + 2) as u8; let jump_distance = (self.chunk.len() - start_length) as u8;
self.emit_instruction(Instruction::jump(jump_to), operator_position); self.emit_instruction(Instruction::jump(jump_distance, true), operator_position);
self.parse_sub_expression(&rule.precedence)?; self.parse_sub_expression(&rule.precedence)?;
self.current_is_expression = true; self.current_is_expression = true;
@ -956,7 +967,16 @@ impl<'src> Parser<'src> {
}; };
if let Token::LeftCurlyBrace = self.current_token { if let Token::LeftCurlyBrace = self.current_token {
let block_start = self.chunk.len();
self.parse_block(block_allowed)?; self.parse_block(block_allowed)?;
let block_end = self.chunk.len();
let jump_distance = (block_end - block_start) as u8;
if let Some(jump) = self.get_last_jump_mut() {
jump.set_b(jump_distance);
}
} else { } else {
return Err(ParseError::ExpectedToken { return Err(ParseError::ExpectedToken {
expected: TokenKind::LeftCurlyBrace, expected: TokenKind::LeftCurlyBrace,
@ -965,14 +985,57 @@ impl<'src> Parser<'src> {
}); });
} }
let if_block_end = self.chunk.len(); let if_block_is_expression = self
.chunk
if let Some(if_jump) = self.get_last_jump_mut() { .instructions()
if_jump.set_b(if_block_end as u8); .iter()
.find_map(|(instruction, _)| {
if !matches!(instruction.operation(), Operation::Jump) {
Some(true)
} else {
None
} }
})
.unwrap_or(false);
if let Token::Else = self.current_token { if let Token::Else = self.current_token {
let else_start = self.chunk.len();
self.parse_else(allowed, block_allowed)?; self.parse_else(allowed, block_allowed)?;
let else_end = self.chunk.len();
let jump_distance = (else_end - else_start) as u8;
self.current_is_expression = if_block_is_expression
&& self
.chunk
.instructions()
.iter()
.find_map(|(instruction, _)| {
if !matches!(instruction.operation(), Operation::Jump) {
Some(true)
} else {
None
}
})
.unwrap_or(false);
if jump_distance == 1 {
if let Some(skippable) = self.get_last_jumpable_mut() {
skippable.set_c_to_boolean(true);
} else {
self.chunk.insert_instruction(
else_start,
Instruction::jump(jump_distance, true),
self.current_position,
)?;
}
} else {
self.chunk.insert_instruction(
else_start,
Instruction::jump(jump_distance, true),
self.current_position,
)?;
}
} else { } else {
self.current_is_expression = false; self.current_is_expression = false;
} }
@ -987,21 +1050,17 @@ impl<'src> Parser<'src> {
if let Token::If = self.current_token { if let Token::If = self.current_token {
self.parse_if(allowed)?; self.parse_if(allowed)?;
let if_block_end = self.chunk.len() as u8;
if let Some(if_jump) = self.get_last_jump_mut() {
if_jump.set_b(if_block_end + 1);
}
} else if let Token::LeftCurlyBrace = self.current_token { } else if let Token::LeftCurlyBrace = self.current_token {
self.parse_block(block_allowed)?; self.parse_block(block_allowed)?;
let else_end = self.chunk.len(); let else_end = self.chunk.len();
if else_end - if_block_end > 1 { if else_end - if_block_end > 1 {
let jump_distance = (else_end - if_block_end) as u8;
self.chunk.insert_instruction( self.chunk.insert_instruction(
if_block_end, if_block_end,
Instruction::jump((else_end + 1) as u8), Instruction::jump(jump_distance, true),
self.current_position, self.current_position,
)?; )?;
} }
@ -1051,13 +1110,13 @@ impl<'src> Parser<'src> {
implicit_return: false, implicit_return: false,
})?; })?;
let jump_end = self.chunk.len() as u8;
if let Some(jump) = self.get_last_jump_mut() { if let Some(jump) = self.get_last_jump_mut() {
jump.set_b(jump_end + 1); jump.set_b(jump.b() + 1);
} }
let jump_back = Instruction::jump(jump_start); let jump_end = self.chunk.len() as u8;
let jump_distance = jump_end - jump_start;
let jump_back = Instruction::jump(jump_distance, false);
self.emit_instruction(jump_back, self.current_position); self.emit_instruction(jump_back, self.current_position);
self.optimize_statement(); self.optimize_statement();

View File

@ -81,13 +81,13 @@ impl Vm {
Operation::LoadBoolean => { Operation::LoadBoolean => {
let to_register = instruction.a(); let to_register = instruction.a();
let boolean = instruction.b_as_boolean(); let boolean = instruction.b_as_boolean();
let skip = instruction.c_as_boolean(); let jump = instruction.c_as_boolean();
let value = Value::boolean(boolean); let value = Value::boolean(boolean);
self.set(to_register, value, position)?; self.set(to_register, value, position)?;
if skip { if jump {
self.ip += 1; self.jump_to_ip(self.ip + 1);
} }
} }
Operation::LoadConstant => { Operation::LoadConstant => {
@ -98,7 +98,7 @@ impl Vm {
self.set_constant(to_register, from_constant, position)?; self.set_constant(to_register, from_constant, position)?;
if jump { if jump {
self.ip += 1; self.jump_to_ip(self.ip + 1);
} }
} }
Operation::LoadList => { Operation::LoadList => {
@ -247,7 +247,7 @@ impl Vm {
self.ip - jump_distance as usize self.ip - jump_distance as usize
}; };
self.ip = new_ip; self.jump_to_ip(new_ip);
} }
} }
Operation::Less => { Operation::Less => {
@ -283,7 +283,7 @@ impl Vm {
self.ip - jump_distance as usize self.ip - jump_distance as usize
}; };
self.ip = new_ip; self.jump_to_ip(new_ip);
} }
} }
Operation::LessEqual => { Operation::LessEqual => {
@ -320,7 +320,7 @@ impl Vm {
self.ip - jump_distance as usize self.ip - jump_distance as usize
}; };
self.ip = new_ip; self.jump_to_ip(new_ip);
} }
} }
Operation::Negate => { Operation::Negate => {
@ -348,9 +348,15 @@ impl Vm {
self.set(instruction.a(), not, position)?; self.set(instruction.a(), not, position)?;
} }
Operation::Jump => { Operation::Jump => {
let jump_to = instruction.b(); let jump_distance = instruction.b();
let is_positive = instruction.c_as_boolean();
let new_ip = if is_positive {
self.ip + jump_distance as usize
} else {
self.ip - jump_distance as usize
};
self.ip = jump_to as usize; self.jump_to_ip(new_ip);
} }
Operation::Call => { Operation::Call => {
let to_register = instruction.a(); let to_register = instruction.a();
@ -418,6 +424,24 @@ impl Vm {
Ok(None) Ok(None)
} }
fn jump_to_ip(&mut self, new_ip: usize) {
let final_index = self.chunk.len() - 1;
if new_ip > final_index {
let last_operation = self
.chunk
.instructions()
.last()
.map(|(instruction, _)| instruction.operation());
if let Some(Operation::Return) = last_operation {
self.ip = final_index;
}
} else {
self.ip = new_ip;
}
}
fn set(&mut self, to_register: u8, value: Value, position: Span) -> Result<(), VmError> { fn set(&mut self, to_register: u8, value: Value, position: Span) -> Result<(), VmError> {
let length = self.stack.len(); let length = self.stack.len();
self.last_assigned_register = Some(to_register); self.last_assigned_register = Some(to_register);

View File

@ -15,7 +15,7 @@ fn equality_assignment_long() {
.set_c_is_constant(), .set_c_is_constant(),
Span(13, 15) Span(13, 15)
), ),
(Instruction::jump(3), Span(13, 15)), (Instruction::jump(1, true), Span(13, 15)),
(Instruction::load_boolean(0, true, true), Span(20, 24)), (Instruction::load_boolean(0, true, true), Span(20, 24)),
(Instruction::load_boolean(0, false, false), Span(34, 39)), (Instruction::load_boolean(0, false, false), Span(34, 39)),
(Instruction::define_local(0, 0, false), Span(4, 5)), (Instruction::define_local(0, 0, false), Span(4, 5)),
@ -45,7 +45,7 @@ fn equality_assignment_short() {
.set_c_is_constant(), .set_c_is_constant(),
Span(10, 12) Span(10, 12)
), ),
(Instruction::jump(3), Span(10, 12)), (Instruction::jump(1, true), Span(10, 12)),
(Instruction::load_boolean(0, true, true), Span(10, 12)), (Instruction::load_boolean(0, true, true), Span(10, 12)),
(Instruction::load_boolean(0, false, false), Span(10, 12)), (Instruction::load_boolean(0, false, false), Span(10, 12)),
(Instruction::define_local(0, 0, false), Span(4, 5)), (Instruction::define_local(0, 0, false), Span(4, 5)),
@ -80,12 +80,13 @@ fn if_else_complex() {
.set_c_is_constant(), .set_c_is_constant(),
Span(14, 16) Span(14, 16)
), ),
(Instruction::jump(7), Span(14, 16)), (Instruction::jump(5, true), Span(14, 16)),
(Instruction::load_constant(0, 2, false), Span(33, 34)), (Instruction::load_constant(0, 2, false), Span(33, 34)),
(Instruction::load_constant(1, 3, false), Span(36, 37)), (Instruction::load_constant(1, 3, false), Span(36, 37)),
(Instruction::load_constant(2, 4, false), Span(39, 40)), (Instruction::load_constant(2, 4, false), Span(39, 40)),
(Instruction::load_constant(3, 5, false), Span(42, 43)), (Instruction::load_constant(3, 5, false), Span(42, 43)),
(Instruction::jump(11), Span(95, 95)), (Instruction::jump(5, true), Span(95, 95)),
(Instruction::jump(4, true), Span(95, 95)),
(Instruction::load_constant(4, 6, false), Span(74, 75)), (Instruction::load_constant(4, 6, false), Span(74, 75)),
(Instruction::load_constant(5, 7, false), Span(77, 78)), (Instruction::load_constant(5, 7, false), Span(77, 78)),
(Instruction::load_constant(6, 8, false), Span(80, 81)), (Instruction::load_constant(6, 8, false), Span(80, 81)),
@ -137,27 +138,27 @@ fn if_else_complex() {
// .set_c_is_constant(), // .set_c_is_constant(),
// Span(14, 16) // Span(14, 16)
// ), // ),
// (Instruction::jump(7), Span(14, 16)), // (Instruction::jump(7, true), Span(14, 16)),
// ( // (
// *Instruction::equal(true, 0, 2) // *Instruction::equal(true, 0, 2)
// .set_b_is_constant() // .set_b_is_constant()
// .set_c_is_constant(), // .set_c_is_constant(),
// Span(38, 41) // Span(38, 41)
// ), // ),
// (Instruction::jump(3), Span(38, 41)), // (Instruction::jump(3, true), Span(38, 41)),
// (Instruction::load_constant(0, 1, false), Span(61, 62)), // (Instruction::load_constant(0, 1, false), Span(61, 62)),
// (Instruction::jump(11), Span(95, 95)), // (Instruction::jump(1, true1), Span(95, 95)),
// ( // (
// *Instruction::equal(true, 0, 3) // *Instruction::equal(true, 0, 3)
// .set_b_is_constant() // .set_b_is_constant()
// .set_c_is_constant(), // .set_c_is_constant(),
// Span(77, 79) // Span(77, 79)
// ), // ),
// (Instruction::jump(3), Span(77, 79)), // (Instruction::jump(3, true), Span(77, 79)),
// (Instruction::load_constant(0, 2, false), Span(94, 95)), // (Instruction::load_constant(0, 2, false), Span(94, 95)),
// (Instruction::jump(11), Span(95, 95)), // (Instruction::jump(1, true1), Span(95, 95)),
// (Instruction::load_constant(0, 3, false), Span(114, 115)), // (Instruction::load_constant(0, 3, false), Span(114, 115)),
// (Instruction::jump(11), Span(95, 95)), // (Instruction::jump(1, true1), Span(95, 95)),
// (Instruction::load_constant(0, 4, false), Span(134, 135)), // (Instruction::load_constant(0, 4, false), Span(134, 135)),
// (Instruction::r#return(true), Span(146, 146)), // (Instruction::r#return(true), Span(146, 146)),
// ], // ],
@ -194,12 +195,12 @@ fn if_else_false() {
.set_c_is_constant(), .set_c_is_constant(),
Span(5, 7) Span(5, 7)
), ),
(Instruction::jump(3), Span(5, 7)), (Instruction::jump(1, true), Span(5, 7)),
( (
Instruction::call_native(0, NativeFunction::Panic, 0), Instruction::call_native(0, NativeFunction::Panic, 0),
Span(12, 19) Span(12, 19)
), ),
(Instruction::load_constant(0, 2, false), Span(29, 31)), (Instruction::load_constant(0, 2, true), Span(29, 31)),
(Instruction::r#return(true), Span(33, 33)), (Instruction::r#return(true), Span(33, 33)),
], ],
vec![Value::integer(1), Value::integer(2), Value::integer(42)], vec![Value::integer(1), Value::integer(2), Value::integer(42)],
@ -225,19 +226,20 @@ fn if_else_true() {
.set_c_is_constant(), .set_c_is_constant(),
Span(5, 7) Span(5, 7)
), ),
(Instruction::jump(3), Span(5, 7)), (Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2, false), Span(12, 14)), (Instruction::load_constant(0, 2, true), Span(12, 14)),
( (
Instruction::call_native(1, NativeFunction::Panic, 0), Instruction::call_native(1, NativeFunction::Panic, 0),
Span(24, 31) Span(24, 31)
), ),
(Instruction::r#return(true), Span(33, 33))
], ],
vec![Value::integer(1), Value::integer(1), Value::integer(42)], vec![Value::integer(1), Value::integer(1), Value::integer(42)],
vec![] vec![]
)), )),
); );
assert_eq!(run(source), Ok(None)); assert_eq!(run(source), Ok(Some(Value::integer(42))));
} }
#[test] #[test]
@ -255,7 +257,7 @@ fn if_expression_false() {
.set_c_is_constant(), .set_c_is_constant(),
Span(5, 7) Span(5, 7)
), ),
(Instruction::jump(3), Span(5, 7)), (Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2, false), Span(12, 13)), (Instruction::load_constant(0, 2, false), Span(12, 13)),
], ],
vec![Value::integer(1), Value::integer(2), Value::integer(2)], vec![Value::integer(1), Value::integer(2), Value::integer(2)],
@ -281,7 +283,7 @@ fn if_expression_true() {
.set_c_is_constant(), .set_c_is_constant(),
Span(5, 7) Span(5, 7)
), ),
(Instruction::jump(3), Span(5, 7)), (Instruction::jump(1, true), Span(5, 7)),
(Instruction::load_constant(0, 2, false), Span(12, 13)), (Instruction::load_constant(0, 2, false), Span(12, 13)),
], ],
vec![Value::integer(1), Value::integer(1), Value::integer(2)], vec![Value::integer(1), Value::integer(1), Value::integer(2)],

View File

@ -59,7 +59,7 @@ fn and() {
vec![ vec![
(Instruction::load_boolean(0, true, false), Span(0, 4)), (Instruction::load_boolean(0, true, false), Span(0, 4)),
(Instruction::test(0, false), Span(5, 7)), (Instruction::test(0, false), Span(5, 7)),
(Instruction::jump(4), Span(5, 7)), (Instruction::jump(4, true), Span(5, 7)),
(Instruction::load_boolean(1, false, false), Span(8, 13)), (Instruction::load_boolean(1, false, false), Span(8, 13)),
(Instruction::r#return(true), Span(13, 13)), (Instruction::r#return(true), Span(13, 13)),
], ],
@ -258,7 +258,7 @@ fn equal() {
.set_c_is_constant(), .set_c_is_constant(),
Span(2, 4) Span(2, 4)
), ),
(Instruction::jump(3), Span(2, 4)), (Instruction::jump(3, true), Span(2, 4)),
(Instruction::load_boolean(0, true, true), Span(2, 4)), (Instruction::load_boolean(0, true, true), Span(2, 4)),
(Instruction::load_boolean(0, false, false), Span(2, 4)), (Instruction::load_boolean(0, false, false), Span(2, 4)),
(Instruction::r#return(true), Span(6, 6)), (Instruction::r#return(true), Span(6, 6)),
@ -419,7 +419,7 @@ fn greater() {
.set_c_is_constant(), .set_c_is_constant(),
Span(2, 3) Span(2, 3)
), ),
(Instruction::jump(3), Span(2, 3)), (Instruction::jump(3, true), Span(2, 3)),
(Instruction::load_boolean(0, true, true), Span(2, 3)), (Instruction::load_boolean(0, true, true), Span(2, 3)),
(Instruction::load_boolean(0, false, false), Span(2, 3)), (Instruction::load_boolean(0, false, false), Span(2, 3)),
(Instruction::r#return(true), Span(5, 5)), (Instruction::r#return(true), Span(5, 5)),
@ -447,7 +447,7 @@ fn greater_than_or_equal() {
.set_c_is_constant(), .set_c_is_constant(),
Span(2, 4) Span(2, 4)
), ),
(Instruction::jump(3), Span(2, 4)), (Instruction::jump(3, true), Span(2, 4)),
(Instruction::load_boolean(0, true, true), Span(2, 4)), (Instruction::load_boolean(0, true, true), Span(2, 4)),
(Instruction::load_boolean(0, false, false), Span(2, 4)), (Instruction::load_boolean(0, false, false), Span(2, 4)),
(Instruction::r#return(true), Span(6, 6)), (Instruction::r#return(true), Span(6, 6)),
@ -475,7 +475,7 @@ fn less_than() {
.set_c_is_constant(), .set_c_is_constant(),
Span(2, 3) Span(2, 3)
), ),
(Instruction::jump(3), Span(2, 3)), (Instruction::jump(3, true), Span(2, 3)),
(Instruction::load_boolean(0, true, true), Span(2, 3)), (Instruction::load_boolean(0, true, true), Span(2, 3)),
(Instruction::load_boolean(0, false, false), Span(2, 3)), (Instruction::load_boolean(0, false, false), Span(2, 3)),
(Instruction::r#return(true), Span(5, 5)), (Instruction::r#return(true), Span(5, 5)),
@ -503,7 +503,7 @@ fn less_than_or_equal() {
.set_c_is_constant(), .set_c_is_constant(),
Span(2, 4) Span(2, 4)
), ),
(Instruction::jump(3), Span(2, 4)), (Instruction::jump(3, true), Span(2, 4)),
(Instruction::load_boolean(0, true, true), Span(2, 4)), (Instruction::load_boolean(0, true, true), Span(2, 4)),
(Instruction::load_boolean(0, false, false), Span(2, 4)), (Instruction::load_boolean(0, false, false), Span(2, 4)),
(Instruction::r#return(true), Span(6, 6)), (Instruction::r#return(true), Span(6, 6)),
@ -762,7 +762,7 @@ fn not_equal() {
.set_c_is_constant(), .set_c_is_constant(),
Span(2, 4) Span(2, 4)
), ),
(Instruction::jump(3), Span(2, 4)), (Instruction::jump(3, true), Span(2, 4)),
(Instruction::load_boolean(0, true, true), Span(2, 4)), (Instruction::load_boolean(0, true, true), Span(2, 4)),
(Instruction::load_boolean(0, false, false), Span(2, 4)), (Instruction::load_boolean(0, false, false), Span(2, 4)),
(Instruction::r#return(true), Span(6, 6)), (Instruction::r#return(true), Span(6, 6)),
@ -786,7 +786,7 @@ fn or() {
vec![ vec![
(Instruction::load_boolean(0, true, false), Span(0, 4)), (Instruction::load_boolean(0, true, false), Span(0, 4)),
(Instruction::test(0, true), Span(5, 7)), (Instruction::test(0, true), Span(5, 7)),
(Instruction::jump(4), Span(5, 7)), (Instruction::jump(4, true), Span(5, 7)),
(Instruction::load_boolean(1, false, false), Span(8, 13)), (Instruction::load_boolean(1, false, false), Span(8, 13)),
(Instruction::r#return(true), Span(13, 13)), (Instruction::r#return(true), Span(13, 13)),
], ],
@ -917,7 +917,7 @@ fn variable_and() {
(Instruction::define_local(1, 1, false), Span(18, 19)), (Instruction::define_local(1, 1, false), Span(18, 19)),
(Instruction::get_local(2, 0), Span(29, 30)), (Instruction::get_local(2, 0), Span(29, 30)),
(Instruction::test(2, false), Span(31, 33)), (Instruction::test(2, false), Span(31, 33)),
(Instruction::jump(8), Span(31, 33)), (Instruction::jump(8, true), Span(31, 33)),
(Instruction::get_local(3, 1), Span(34, 35)), (Instruction::get_local(3, 1), Span(34, 35)),
(Instruction::r#return(true), Span(35, 35)), (Instruction::r#return(true), Span(35, 35)),
], ],
@ -947,9 +947,9 @@ fn r#while() {
*Instruction::less(true, 0, 1).set_c_is_constant(), *Instruction::less(true, 0, 1).set_c_is_constant(),
Span(23, 24) Span(23, 24)
), ),
(Instruction::jump(7), Span(23, 24)), (Instruction::jump(7, true), Span(23, 24)),
(*Instruction::add(0, 0, 2).set_c_is_constant(), Span(39, 40)), (*Instruction::add(0, 0, 2).set_c_is_constant(), Span(39, 40)),
(Instruction::jump(2), Span(41, 42)), (Instruction::jump(2, true), Span(41, 42)),
(Instruction::get_local(1, 0), Span(41, 42)), (Instruction::get_local(1, 0), Span(41, 42)),
(Instruction::r#return(true), Span(42, 42)), (Instruction::r#return(true), Span(42, 42)),
], ],