Add comparison tests for lists; Edit README.md; Add benches to Cargo.toml
This commit is contained in:
parent
4c019410e8
commit
a53e0018cf
@ -29,6 +29,10 @@ fn fib (n: int) -> int {
|
||||
write_line(fib(25))
|
||||
```
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Dust is still experimental. Currently, development is more focused on exploring ideas for
|
||||
> optimization and performance than on stability or feature completeness. This will change as the
|
||||
> project matures.
|
||||
|
||||
## Highlights
|
||||
|
||||
|
@ -31,6 +31,18 @@ criterion = { version = "0.5.1", features = ["html_reports"] }
|
||||
name = "addictive_addition"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "addictive_subtraction"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "addictive_multiplication"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "addictive_division"
|
||||
harness = false
|
||||
|
||||
[[bench]]
|
||||
name = "fibonacci"
|
||||
harness = false
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use criterion::{Criterion, black_box, criterion_group, criterion_main};
|
||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||
use dust_lang::run;
|
||||
|
||||
const SOURCE: &str = r#"
|
||||
@ -9,9 +9,13 @@ const SOURCE: &str = r#"
|
||||
while i < 1_000 {
|
||||
i += 1
|
||||
|
||||
spawn(
|
||||
fn () { random_int(0, 10); }
|
||||
)
|
||||
spawn(fn () {
|
||||
let mut j = 0
|
||||
|
||||
while j < 5_000_000 {
|
||||
j += 1
|
||||
}
|
||||
})
|
||||
}
|
||||
"#;
|
||||
|
||||
|
@ -855,6 +855,7 @@ impl<'src> Compiler<'src> {
|
||||
let operand = instruction.as_operand();
|
||||
let push_back = match instruction.operation() {
|
||||
Operation::LOAD_ENCODED
|
||||
| Operation::LOAD_LIST
|
||||
| Operation::LOAD_SELF
|
||||
| Operation::ADD
|
||||
| Operation::SUBTRACT
|
||||
@ -997,6 +998,22 @@ impl<'src> Compiler<'src> {
|
||||
position: self.current_position,
|
||||
});
|
||||
}
|
||||
let (left_instruction, left_type, left_position) =
|
||||
self.instructions
|
||||
.pop()
|
||||
.ok_or_else(|| CompileError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
|
||||
// TODO: Check if the left type is a valid type for comparison
|
||||
|
||||
let (left, push_back_left) = self.handle_binary_argument(&left_instruction);
|
||||
|
||||
if push_back_left {
|
||||
self.instructions
|
||||
.push((left_instruction, left_type, left_position));
|
||||
}
|
||||
|
||||
let operator = self.current_token;
|
||||
let operator_position = self.current_position;
|
||||
@ -1012,30 +1029,18 @@ impl<'src> Compiler<'src> {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
let (left_instruction, left_type, left_position) =
|
||||
self.instructions
|
||||
.pop()
|
||||
.ok_or_else(|| CompileError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
let (left, push_back_left) = self.handle_binary_argument(&left_instruction);
|
||||
let (right, push_back_right) = self.handle_binary_argument(&right_instruction);
|
||||
|
||||
// TODO: Check if the left type is a valid type for comparison
|
||||
// TODO: Check if the right type is a valid type for comparison
|
||||
// TODO: Check if the left and right types are compatible
|
||||
|
||||
if push_back_left {
|
||||
self.instructions
|
||||
.push((left_instruction, left_type, left_position));
|
||||
}
|
||||
let (right, push_back_right) = self.handle_binary_argument(&right_instruction);
|
||||
|
||||
if push_back_right {
|
||||
self.instructions
|
||||
.push((right_instruction, right_type, right_position));
|
||||
}
|
||||
|
||||
// TODO: Check if the left and right types are compatible
|
||||
|
||||
let comparison = match operator {
|
||||
Token::DoubleEqual => Instruction::equal(true, left, right),
|
||||
Token::BangEqual => Instruction::equal(false, left, right),
|
||||
@ -1074,9 +1079,6 @@ impl<'src> Compiler<'src> {
|
||||
}
|
||||
|
||||
fn parse_logical_binary(&mut self) -> Result<(), CompileError> {
|
||||
let operator = self.current_token;
|
||||
let operator_position = self.current_position;
|
||||
let rule = ParseRule::from(&operator);
|
||||
let (left_instruction, left_type, left_position) =
|
||||
self.instructions
|
||||
.pop()
|
||||
@ -1084,42 +1086,19 @@ impl<'src> Compiler<'src> {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
let operand_register = if left_instruction.operation() == Operation::MOVE {
|
||||
let Move { operand: to, .. } = Move::from(&left_instruction);
|
||||
let local = self.get_local(to.index())?;
|
||||
|
||||
local.register_index
|
||||
} else if left_instruction.yields_value() {
|
||||
let register = left_instruction.a_field();
|
||||
|
||||
self.instructions
|
||||
.push((left_instruction, left_type, left_position));
|
||||
|
||||
register
|
||||
} else {
|
||||
return Err(CompileError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: Check if the left type is boolean
|
||||
|
||||
self.advance()?;
|
||||
self.parse_sub_expression(&rule.precedence)?;
|
||||
let (left, push_back_left) = self.handle_binary_argument(&left_instruction);
|
||||
|
||||
let (mut right_instruction, right_type, right_position) = self
|
||||
.instructions
|
||||
.pop()
|
||||
.ok_or_else(|| CompileError::ExpectedExpression {
|
||||
found: self.previous_token.to_owned(),
|
||||
position: self.previous_position,
|
||||
})?;
|
||||
|
||||
// TODO: Check if the right type is boolean
|
||||
|
||||
right_instruction.set_a_field(operand_register);
|
||||
if push_back_left {
|
||||
self.instructions
|
||||
.push((left_instruction, left_type.clone(), left_position));
|
||||
}
|
||||
|
||||
let operator = self.current_token;
|
||||
let operator_position = self.current_position;
|
||||
let rule = ParseRule::from(&operator);
|
||||
let test_boolean = match operator {
|
||||
Token::DoubleAmpersand => true,
|
||||
Token::DoublePipe => false,
|
||||
@ -1131,13 +1110,35 @@ impl<'src> Compiler<'src> {
|
||||
});
|
||||
}
|
||||
};
|
||||
let test = Instruction::test(operand_register, test_boolean);
|
||||
let test = Instruction::test(left.index(), test_boolean);
|
||||
let jump = Instruction::jump(1, true);
|
||||
|
||||
self.emit_instruction(test, Type::None, operator_position);
|
||||
self.emit_instruction(jump, Type::None, operator_position);
|
||||
self.instructions
|
||||
.push((right_instruction, right_type, right_position));
|
||||
|
||||
self.advance()?;
|
||||
self.parse_sub_expression(&rule.precedence)?;
|
||||
|
||||
// TODO: Check if the right type is boolean
|
||||
|
||||
if matches!(
|
||||
self.get_last_operations(),
|
||||
Some([
|
||||
Operation::EQUAL | Operation::LESS | Operation::LESS_EQUAL,
|
||||
Operation::JUMP,
|
||||
Operation::LOAD_ENCODED | Operation::LOAD_CONSTANT,
|
||||
Operation::LOAD_ENCODED | Operation::LOAD_CONSTANT,
|
||||
])
|
||||
) {
|
||||
let instruction_count = self.instructions.len();
|
||||
let loaders = self
|
||||
.instructions
|
||||
.get_many_mut([instruction_count - 1, instruction_count - 2])
|
||||
.unwrap(); // Safe because the indices in bounds and do not overlap
|
||||
|
||||
loaders[0].0.set_a_field(left.index());
|
||||
loaders[1].0.set_a_field(left.index());
|
||||
}
|
||||
|
||||
let instructions_length = self.instructions.len();
|
||||
|
||||
|
@ -660,7 +660,7 @@ impl Instruction {
|
||||
Operation::EQUAL => Equal::from(*self).to_string(),
|
||||
Operation::LESS => Less::from(*self).to_string(),
|
||||
Operation::LESS_EQUAL => LessEqual::from(*self).to_string(),
|
||||
Operation::TEST => Test::from(*self).to_string(),
|
||||
Operation::TEST => Test::from(self).to_string(),
|
||||
Operation::TEST_SET => TestSet::from(*self).to_string(),
|
||||
Operation::CALL => Call::from(*self).to_string(),
|
||||
Operation::CALL_NATIVE => CallNative::from(*self).to_string(),
|
||||
|
@ -11,7 +11,7 @@ pub struct Operation(pub u8);
|
||||
impl Operation {
|
||||
pub const NO_OP: Operation = Operation(0);
|
||||
|
||||
// Stack manipulation
|
||||
// Register manipulation
|
||||
pub const MOVE: Operation = Operation(1);
|
||||
pub const CLOSE: Operation = Operation(2);
|
||||
|
||||
|
@ -9,8 +9,8 @@ pub struct Test {
|
||||
pub test_value: bool,
|
||||
}
|
||||
|
||||
impl From<Instruction> for Test {
|
||||
fn from(instruction: Instruction) -> Self {
|
||||
impl From<&Instruction> for Test {
|
||||
fn from(instruction: &Instruction) -> Self {
|
||||
let operand_register = instruction.b_field();
|
||||
let test_value = instruction.c_field() != 0;
|
||||
|
||||
|
@ -51,7 +51,7 @@ impl Thread {
|
||||
|
||||
let instruction = &instructions[ip];
|
||||
|
||||
info!("Run instruction {}", instruction.operation());
|
||||
info!("IP = {ip} Run {}", instruction.operation());
|
||||
|
||||
match instruction.operation() {
|
||||
Operation::MOVE => {
|
||||
@ -1334,7 +1334,19 @@ impl Thread {
|
||||
}
|
||||
_ => unreachable!("Invalid LESS_EQUAL instruction"),
|
||||
},
|
||||
Operation::TEST => {
|
||||
let operand_register_index = instruction.b_field() as usize;
|
||||
let test_value = instruction.c_field() != 0;
|
||||
let operand_boolean = current_frame
|
||||
.registers
|
||||
.booleans
|
||||
.get(operand_register_index)
|
||||
.copy_value();
|
||||
|
||||
if operand_boolean == test_value {
|
||||
current_frame.ip += 1;
|
||||
}
|
||||
}
|
||||
Operation::JUMP => {
|
||||
let offset = instruction.b_field() as usize;
|
||||
let is_positive = instruction.c_field() != 0;
|
||||
|
@ -159,3 +159,51 @@ fn equal_strings() {
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn equal_lists() {
|
||||
let source = "[1, 2, 3] == [4, 5, 6]";
|
||||
let chunk = Chunk {
|
||||
r#type: FunctionType::new([], [], Type::Boolean),
|
||||
instructions: vec![
|
||||
Instruction::load_constant(0, 0, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(1, 1, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(2, 2, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(0, TypeCode::INTEGER, 0, 2, false),
|
||||
Instruction::load_constant(3, 3, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(4, 4, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(5, 5, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(1, TypeCode::INTEGER, 3, 5, false),
|
||||
Instruction::equal(
|
||||
true,
|
||||
Operand::Register(0, TypeCode::LIST),
|
||||
Operand::Register(1, TypeCode::LIST),
|
||||
),
|
||||
Instruction::jump(1, true),
|
||||
Instruction::load_encoded(0, true as u8, TypeCode::BOOLEAN, true),
|
||||
Instruction::load_encoded(0, false as u8, TypeCode::BOOLEAN, false),
|
||||
Instruction::r#return(true, 0, TypeCode::BOOLEAN),
|
||||
],
|
||||
positions: vec![
|
||||
Span(1, 2),
|
||||
Span(4, 5),
|
||||
Span(7, 8),
|
||||
Span(0, 9),
|
||||
Span(14, 15),
|
||||
Span(17, 18),
|
||||
Span(20, 21),
|
||||
Span(13, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(22, 22),
|
||||
],
|
||||
integer_constants: vec![1, 2, 3, 4, 5, 6],
|
||||
..Chunk::default()
|
||||
};
|
||||
let return_value = Some(Value::boolean(false));
|
||||
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
@ -153,3 +153,51 @@ fn greater_strings() {
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn greater_lists() {
|
||||
let source = "[1, 2, 3] > [4, 5, 6]";
|
||||
let chunk = Chunk {
|
||||
r#type: FunctionType::new([], [], Type::Boolean),
|
||||
instructions: vec![
|
||||
Instruction::load_constant(0, 0, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(1, 1, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(2, 2, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(0, TypeCode::INTEGER, 0, 2, false),
|
||||
Instruction::load_constant(3, 3, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(4, 4, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(5, 5, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(1, TypeCode::INTEGER, 3, 5, false),
|
||||
Instruction::less_equal(
|
||||
false,
|
||||
Operand::Register(0, TypeCode::LIST),
|
||||
Operand::Register(1, TypeCode::LIST),
|
||||
),
|
||||
Instruction::jump(1, true),
|
||||
Instruction::load_encoded(0, true as u8, TypeCode::BOOLEAN, true),
|
||||
Instruction::load_encoded(0, false as u8, TypeCode::BOOLEAN, false),
|
||||
Instruction::r#return(true, 0, TypeCode::BOOLEAN),
|
||||
],
|
||||
positions: vec![
|
||||
Span(1, 2),
|
||||
Span(4, 5),
|
||||
Span(7, 8),
|
||||
Span(0, 9),
|
||||
Span(13, 14),
|
||||
Span(16, 17),
|
||||
Span(19, 20),
|
||||
Span(12, 21),
|
||||
Span(0, 21),
|
||||
Span(0, 21),
|
||||
Span(0, 21),
|
||||
Span(0, 21),
|
||||
Span(21, 21),
|
||||
],
|
||||
integer_constants: vec![1, 2, 3, 4, 5, 6],
|
||||
..Chunk::default()
|
||||
};
|
||||
let return_value = Some(Value::boolean(false));
|
||||
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
@ -194,3 +194,51 @@ fn greater_equal_strings() {
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn greater_equal_lists() {
|
||||
let source = "[1, 2, 3] >= [4, 5, 6]";
|
||||
let chunk = Chunk {
|
||||
r#type: FunctionType::new([], [], Type::Boolean),
|
||||
instructions: vec![
|
||||
Instruction::load_constant(0, 0, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(1, 1, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(2, 2, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(0, TypeCode::INTEGER, 0, 2, false),
|
||||
Instruction::load_constant(3, 3, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(4, 4, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(5, 5, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(1, TypeCode::INTEGER, 3, 5, false),
|
||||
Instruction::less(
|
||||
false,
|
||||
Operand::Register(0, TypeCode::LIST),
|
||||
Operand::Register(1, TypeCode::LIST),
|
||||
),
|
||||
Instruction::jump(1, true),
|
||||
Instruction::load_encoded(0, true as u8, TypeCode::BOOLEAN, true),
|
||||
Instruction::load_encoded(0, false as u8, TypeCode::BOOLEAN, false),
|
||||
Instruction::r#return(true, 0, TypeCode::BOOLEAN),
|
||||
],
|
||||
positions: vec![
|
||||
Span(1, 2),
|
||||
Span(4, 5),
|
||||
Span(7, 8),
|
||||
Span(0, 9),
|
||||
Span(14, 15),
|
||||
Span(17, 18),
|
||||
Span(20, 21),
|
||||
Span(13, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(22, 22),
|
||||
],
|
||||
integer_constants: vec![1, 2, 3, 4, 5, 6],
|
||||
..Chunk::default()
|
||||
};
|
||||
let return_value = Some(Value::boolean(false));
|
||||
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
@ -188,3 +188,51 @@ fn less_strings() {
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn less_lists() {
|
||||
let source = "[1, 2, 3] < [4, 5, 6]";
|
||||
let chunk = Chunk {
|
||||
r#type: FunctionType::new([], [], Type::Boolean),
|
||||
instructions: vec![
|
||||
Instruction::load_constant(0, 0, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(1, 1, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(2, 2, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(0, TypeCode::INTEGER, 0, 2, false),
|
||||
Instruction::load_constant(3, 3, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(4, 4, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(5, 5, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(1, TypeCode::INTEGER, 3, 5, false),
|
||||
Instruction::less(
|
||||
true,
|
||||
Operand::Register(0, TypeCode::LIST),
|
||||
Operand::Register(1, TypeCode::LIST),
|
||||
),
|
||||
Instruction::jump(1, true),
|
||||
Instruction::load_encoded(0, true as u8, TypeCode::BOOLEAN, true),
|
||||
Instruction::load_encoded(0, false as u8, TypeCode::BOOLEAN, false),
|
||||
Instruction::r#return(true, 0, TypeCode::BOOLEAN),
|
||||
],
|
||||
positions: vec![
|
||||
Span(1, 2),
|
||||
Span(4, 5),
|
||||
Span(7, 8),
|
||||
Span(0, 9),
|
||||
Span(13, 14),
|
||||
Span(16, 17),
|
||||
Span(19, 20),
|
||||
Span(12, 21),
|
||||
Span(0, 21),
|
||||
Span(0, 21),
|
||||
Span(0, 21),
|
||||
Span(0, 21),
|
||||
Span(21, 21),
|
||||
],
|
||||
integer_constants: vec![1, 2, 3, 4, 5, 6],
|
||||
..Chunk::default()
|
||||
};
|
||||
let return_value = Some(Value::boolean(true));
|
||||
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
@ -194,3 +194,51 @@ fn less_equal_strings() {
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn less_equal_lists() {
|
||||
let source = "[1, 2, 3] <= [4, 5, 6]";
|
||||
let chunk = Chunk {
|
||||
r#type: FunctionType::new([], [], Type::Boolean),
|
||||
instructions: vec![
|
||||
Instruction::load_constant(0, 0, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(1, 1, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(2, 2, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(0, TypeCode::INTEGER, 0, 2, false),
|
||||
Instruction::load_constant(3, 3, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(4, 4, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(5, 5, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(1, TypeCode::INTEGER, 3, 5, false),
|
||||
Instruction::less_equal(
|
||||
true,
|
||||
Operand::Register(0, TypeCode::LIST),
|
||||
Operand::Register(1, TypeCode::LIST),
|
||||
),
|
||||
Instruction::jump(1, true),
|
||||
Instruction::load_encoded(0, true as u8, TypeCode::BOOLEAN, true),
|
||||
Instruction::load_encoded(0, false as u8, TypeCode::BOOLEAN, false),
|
||||
Instruction::r#return(true, 0, TypeCode::BOOLEAN),
|
||||
],
|
||||
positions: vec![
|
||||
Span(1, 2),
|
||||
Span(4, 5),
|
||||
Span(7, 8),
|
||||
Span(0, 9),
|
||||
Span(14, 15),
|
||||
Span(17, 18),
|
||||
Span(20, 21),
|
||||
Span(13, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(22, 22),
|
||||
],
|
||||
integer_constants: vec![1, 2, 3, 4, 5, 6],
|
||||
..Chunk::default()
|
||||
};
|
||||
let return_value = Some(Value::boolean(true));
|
||||
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
@ -194,3 +194,51 @@ fn not_equal_strings() {
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_equal_lists() {
|
||||
let source = "[1, 2, 3] != [4, 5, 6]";
|
||||
let chunk = Chunk {
|
||||
r#type: FunctionType::new([], [], Type::Boolean),
|
||||
instructions: vec![
|
||||
Instruction::load_constant(0, 0, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(1, 1, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(2, 2, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(0, TypeCode::INTEGER, 0, 2, false),
|
||||
Instruction::load_constant(3, 3, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(4, 4, TypeCode::INTEGER, false),
|
||||
Instruction::load_constant(5, 5, TypeCode::INTEGER, false),
|
||||
Instruction::load_list(1, TypeCode::INTEGER, 3, 5, false),
|
||||
Instruction::equal(
|
||||
false,
|
||||
Operand::Register(0, TypeCode::LIST),
|
||||
Operand::Register(1, TypeCode::LIST),
|
||||
),
|
||||
Instruction::jump(1, true),
|
||||
Instruction::load_encoded(0, true as u8, TypeCode::BOOLEAN, true),
|
||||
Instruction::load_encoded(0, false as u8, TypeCode::BOOLEAN, false),
|
||||
Instruction::r#return(true, 0, TypeCode::BOOLEAN),
|
||||
],
|
||||
positions: vec![
|
||||
Span(1, 2),
|
||||
Span(4, 5),
|
||||
Span(7, 8),
|
||||
Span(0, 9),
|
||||
Span(14, 15),
|
||||
Span(17, 18),
|
||||
Span(20, 21),
|
||||
Span(13, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(0, 22),
|
||||
Span(22, 22),
|
||||
],
|
||||
integer_constants: vec![1, 2, 3, 4, 5, 6],
|
||||
..Chunk::default()
|
||||
};
|
||||
let return_value = Some(Value::boolean(true));
|
||||
|
||||
assert_eq!(chunk, compile(source).unwrap());
|
||||
assert_eq!(return_value, run(source).unwrap());
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user