Pass tests
This commit is contained in:
parent
a6da34a79c
commit
855782c370
@ -731,7 +731,7 @@ impl<'src> Parser<'src> {
|
|||||||
self.advance()?;
|
self.advance()?;
|
||||||
self.parse_expression()?;
|
self.parse_expression()?;
|
||||||
|
|
||||||
if matches!(
|
let jump_position = if matches!(
|
||||||
self.chunk.get_last_n_operations(),
|
self.chunk.get_last_n_operations(),
|
||||||
[
|
[
|
||||||
Some(Operation::LoadBoolean),
|
Some(Operation::LoadBoolean),
|
||||||
@ -739,10 +739,22 @@ impl<'src> Parser<'src> {
|
|||||||
Some(Operation::Jump)
|
Some(Operation::Jump)
|
||||||
]
|
]
|
||||||
) {
|
) {
|
||||||
self.chunk.pop_instruction(self.current_position)?;
|
|
||||||
self.chunk.pop_instruction(self.current_position)?;
|
self.chunk.pop_instruction(self.current_position)?;
|
||||||
self.chunk.pop_instruction(self.current_position)?;
|
self.chunk.pop_instruction(self.current_position)?;
|
||||||
self.decrement_register()?;
|
self.decrement_register()?;
|
||||||
|
self.chunk.pop_instruction(self.current_position)?.1
|
||||||
|
} else {
|
||||||
|
self.current_position
|
||||||
|
};
|
||||||
|
|
||||||
|
if let [Some(Operation::LoadBoolean)] = self.chunk.get_last_n_operations() {
|
||||||
|
let (mut load_boolean, load_boolean_position) =
|
||||||
|
self.chunk.pop_instruction(self.current_position)?;
|
||||||
|
|
||||||
|
load_boolean.set_second_argument_to_boolean(true);
|
||||||
|
|
||||||
|
self.emit_instruction(load_boolean, load_boolean_position);
|
||||||
|
self.increment_register()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let jump_start = self.chunk.len();
|
let jump_start = self.chunk.len();
|
||||||
@ -752,10 +764,13 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let jump_end = self.chunk.len();
|
let jump_end = self.chunk.len();
|
||||||
let jump_instruction = Instruction::jump((jump_end - jump_start) as u8, true);
|
let jump_distance = jump_end - jump_start;
|
||||||
|
|
||||||
self.chunk
|
self.chunk.insert_instruction(
|
||||||
.insert_instruction(jump_start, jump_instruction, self.current_position);
|
jump_start,
|
||||||
|
Instruction::jump(jump_distance as u8, true),
|
||||||
|
jump_position,
|
||||||
|
);
|
||||||
|
|
||||||
if self.allow(TokenKind::Else)? {
|
if self.allow(TokenKind::Else)? {
|
||||||
if let Token::If = self.current_token {
|
if let Token::If = self.current_token {
|
||||||
|
@ -204,14 +204,16 @@ fn equality_assignment_long() {
|
|||||||
.set_second_argument_to_constant(),
|
.set_second_argument_to_constant(),
|
||||||
Span(13, 15)
|
Span(13, 15)
|
||||||
),
|
),
|
||||||
(Instruction::jump(1, true), Span(13, 15)),
|
(Instruction::jump(2, true), Span(13, 15)),
|
||||||
(Instruction::load_boolean(0, true, true), Span(13, 15)),
|
(Instruction::load_boolean(0, true, false), Span(20, 24)),
|
||||||
(Instruction::load_boolean(0, false, false), Span(13, 15)),
|
(Instruction::end(true), Span(25, 26)),
|
||||||
(Instruction::define_local(0, 0, false), Span(4, 5)),
|
(Instruction::load_boolean(0, false, false), Span(34, 39)),
|
||||||
|
(Instruction::end(true), Span(40, 41)),
|
||||||
|
(Instruction::define_local(1, 0, false), Span(4, 5)),
|
||||||
(Instruction::end(false), Span(42, 42)),
|
(Instruction::end(false), Span(42, 42)),
|
||||||
],
|
],
|
||||||
vec![Value::integer(4), Value::integer(4)],
|
vec![Value::integer(4), Value::integer(4)],
|
||||||
vec![Local::new(Identifier::new("a"), false, 0, Some(0))]
|
vec![Local::new(Identifier::new("a"), false, 0, Some(1))]
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -256,12 +258,12 @@ fn if_expression() {
|
|||||||
.set_second_argument_to_constant(),
|
.set_second_argument_to_constant(),
|
||||||
Span(5, 7)
|
Span(5, 7)
|
||||||
),
|
),
|
||||||
(Instruction::jump(1, true), Span(5, 7)),
|
(Instruction::jump(2, true), Span(5, 7)),
|
||||||
(Instruction::load_boolean(0, true, true), Span(5, 7)),
|
(Instruction::load_constant(0, 2), Span(12, 13)),
|
||||||
(Instruction::load_boolean(0, false, false), Span(5, 7)),
|
(Instruction::end(true), Span(14, 15)),
|
||||||
(Instruction::end(true), Span(15, 15)),
|
(Instruction::end(true), Span(15, 15)),
|
||||||
],
|
],
|
||||||
vec![Value::integer(1), Value::integer(1)],
|
vec![Value::integer(1), Value::integer(1), Value::integer(2)],
|
||||||
vec![]
|
vec![]
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
@ -281,12 +283,19 @@ fn if_else_expression() {
|
|||||||
.set_second_argument_to_constant(),
|
.set_second_argument_to_constant(),
|
||||||
Span(5, 7)
|
Span(5, 7)
|
||||||
),
|
),
|
||||||
(Instruction::jump(1, true), Span(5, 7)),
|
(Instruction::jump(2, true), Span(5, 7)),
|
||||||
(Instruction::load_boolean(0, true, true), Span(5, 7)),
|
(Instruction::load_constant(0, 2), Span(12, 13)),
|
||||||
(Instruction::load_boolean(0, false, false), Span(5, 7)),
|
(Instruction::end(true), Span(14, 15)),
|
||||||
|
(Instruction::load_constant(0, 3), Span(23, 24)),
|
||||||
|
(Instruction::end(true), Span(25, 26)),
|
||||||
(Instruction::end(true), Span(26, 26)),
|
(Instruction::end(true), Span(26, 26)),
|
||||||
],
|
],
|
||||||
vec![Value::integer(1), Value::integer(1)],
|
vec![
|
||||||
|
Value::integer(1),
|
||||||
|
Value::integer(1),
|
||||||
|
Value::integer(2),
|
||||||
|
Value::integer(3)
|
||||||
|
],
|
||||||
vec![]
|
vec![]
|
||||||
)),
|
)),
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use log::debug;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parse, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, Local, Operation,
|
parse, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, Local, Operation,
|
||||||
Span, Value, ValueError,
|
Span, Value, ValueError,
|
||||||
@ -254,18 +252,15 @@ impl Vm {
|
|||||||
Operation::Less => {
|
Operation::Less => {
|
||||||
let (jump, _) = *self.chunk.get_instruction(self.ip, position)?;
|
let (jump, _) = *self.chunk.get_instruction(self.ip, position)?;
|
||||||
|
|
||||||
assert_eq!(jump.operation(), Operation::Jump);
|
debug_assert_eq!(jump.operation(), Operation::Jump);
|
||||||
|
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
let less = left
|
|
||||||
.less_than(right)
|
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
|
||||||
let boolean = left
|
let boolean = left
|
||||||
.equal(right)
|
.less_than(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?
|
.map_err(|error| VmError::Value { error, position })?
|
||||||
.as_boolean()
|
.as_boolean()
|
||||||
.ok_or_else(|| VmError::ExpectedBoolean {
|
.ok_or_else(|| VmError::ExpectedBoolean {
|
||||||
found: less,
|
found: left.clone(),
|
||||||
position,
|
position,
|
||||||
})?;
|
})?;
|
||||||
let compare_to = instruction.destination_as_boolean();
|
let compare_to = instruction.destination_as_boolean();
|
||||||
@ -285,17 +280,17 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operation::LessEqual => {
|
Operation::LessEqual => {
|
||||||
let (jump, _) = *self.read(position)?;
|
let (jump, _) = *self.chunk.get_instruction(self.ip, position)?;
|
||||||
|
|
||||||
|
debug_assert_eq!(jump.operation(), Operation::Jump);
|
||||||
|
|
||||||
let (left, right) = get_arguments(self, instruction, position)?;
|
let (left, right) = get_arguments(self, instruction, position)?;
|
||||||
let less_or_equal = left
|
|
||||||
.less_than_or_equal(right)
|
|
||||||
.map_err(|error| VmError::Value { error, position })?;
|
|
||||||
let boolean = left
|
let boolean = left
|
||||||
.equal(right)
|
.less_than_or_equal(right)
|
||||||
.map_err(|error| VmError::Value { error, position })?
|
.map_err(|error| VmError::Value { error, position })?
|
||||||
.as_boolean()
|
.as_boolean()
|
||||||
.ok_or_else(|| VmError::ExpectedBoolean {
|
.ok_or_else(|| VmError::ExpectedBoolean {
|
||||||
found: less_or_equal,
|
found: left.clone(),
|
||||||
position,
|
position,
|
||||||
})?;
|
})?;
|
||||||
let compare_to = instruction.destination_as_boolean();
|
let compare_to = instruction.destination_as_boolean();
|
||||||
|
Loading…
Reference in New Issue
Block a user