From 855782c37030a8e6978b00304f5e12c3e76527d9 Mon Sep 17 00:00:00 2001 From: Jeff Date: Tue, 24 Sep 2024 11:40:12 -0400 Subject: [PATCH] Pass tests --- dust-lang/src/parser/mod.rs | 25 ++++++++++++++++++++----- dust-lang/src/parser/tests.rs | 35 ++++++++++++++++++++++------------- dust-lang/src/vm.rs | 23 +++++++++-------------- 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index e8dd596..dcd2119 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -731,7 +731,7 @@ impl<'src> Parser<'src> { self.advance()?; self.parse_expression()?; - if matches!( + let jump_position = if matches!( self.chunk.get_last_n_operations(), [ Some(Operation::LoadBoolean), @@ -739,10 +739,22 @@ impl<'src> Parser<'src> { 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.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(); @@ -752,10 +764,13 @@ impl<'src> Parser<'src> { } 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 - .insert_instruction(jump_start, jump_instruction, self.current_position); + self.chunk.insert_instruction( + jump_start, + Instruction::jump(jump_distance as u8, true), + jump_position, + ); if self.allow(TokenKind::Else)? { if let Token::If = self.current_token { diff --git a/dust-lang/src/parser/tests.rs b/dust-lang/src/parser/tests.rs index cedf9cc..3afd8da 100644 --- a/dust-lang/src/parser/tests.rs +++ b/dust-lang/src/parser/tests.rs @@ -204,14 +204,16 @@ fn equality_assignment_long() { .set_second_argument_to_constant(), Span(13, 15) ), - (Instruction::jump(1, true), Span(13, 15)), - (Instruction::load_boolean(0, true, true), Span(13, 15)), - (Instruction::load_boolean(0, false, false), Span(13, 15)), - (Instruction::define_local(0, 0, false), Span(4, 5)), + (Instruction::jump(2, true), Span(13, 15)), + (Instruction::load_boolean(0, true, false), Span(20, 24)), + (Instruction::end(true), Span(25, 26)), + (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)), ], 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(), Span(5, 7) ), - (Instruction::jump(1, true), Span(5, 7)), - (Instruction::load_boolean(0, true, true), Span(5, 7)), - (Instruction::load_boolean(0, false, false), Span(5, 7)), + (Instruction::jump(2, true), Span(5, 7)), + (Instruction::load_constant(0, 2), Span(12, 13)), + (Instruction::end(true), Span(14, 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![] )), ); @@ -281,12 +283,19 @@ fn if_else_expression() { .set_second_argument_to_constant(), Span(5, 7) ), - (Instruction::jump(1, true), Span(5, 7)), - (Instruction::load_boolean(0, true, true), Span(5, 7)), - (Instruction::load_boolean(0, false, false), Span(5, 7)), + (Instruction::jump(2, true), Span(5, 7)), + (Instruction::load_constant(0, 2), Span(12, 13)), + (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)), ], - vec![Value::integer(1), Value::integer(1)], + vec![ + Value::integer(1), + Value::integer(1), + Value::integer(2), + Value::integer(3) + ], vec![] )), ); diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index d83a021..2e067ce 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -1,5 +1,3 @@ -use log::debug; - use crate::{ parse, AnnotatedError, Chunk, ChunkError, DustError, Identifier, Instruction, Local, Operation, Span, Value, ValueError, @@ -254,18 +252,15 @@ impl Vm { Operation::Less => { 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 less = left - .less_than(right) - .map_err(|error| VmError::Value { error, position })?; let boolean = left - .equal(right) + .less_than(right) .map_err(|error| VmError::Value { error, position })? .as_boolean() .ok_or_else(|| VmError::ExpectedBoolean { - found: less, + found: left.clone(), position, })?; let compare_to = instruction.destination_as_boolean(); @@ -285,17 +280,17 @@ impl Vm { } } 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 less_or_equal = left - .less_than_or_equal(right) - .map_err(|error| VmError::Value { error, position })?; let boolean = left - .equal(right) + .less_than_or_equal(right) .map_err(|error| VmError::Value { error, position })? .as_boolean() .ok_or_else(|| VmError::ExpectedBoolean { - found: less_or_equal, + found: left.clone(), position, })?; let compare_to = instruction.destination_as_boolean();