Begin refactoring jump instructions
This commit is contained in:
parent
1f9adfab2f
commit
604962c535
@ -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]
|
||||||
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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)],
|
||||||
|
@ -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)),
|
||||||
],
|
],
|
||||||
|
Loading…
Reference in New Issue
Block a user