diff --git a/dust-lang/src/parser.rs b/dust-lang/src/parser.rs index 4611086..2fe67a2 100644 --- a/dust-lang/src/parser.rs +++ b/dust-lang/src/parser.rs @@ -1003,11 +1003,21 @@ impl<'src> Parser<'src> { if let Token::Else = self.current_token { let else_start = self.chunk.len(); + let if_last_register = self.next_register().saturating_sub(1); self.parse_else(allowed, block_allowed)?; + let else_last_register = self.next_register().saturating_sub(1); let else_end = self.chunk.len(); let jump_distance = (else_end - else_start) as u8; + + if if_last_register < else_last_register { + self.emit_instruction( + Instruction::r#move(else_last_register, if_last_register), + self.current_position, + ); + } + self.current_is_expression = if_block_is_expression && self .chunk diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 04bb99c..4d3fe22 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -65,7 +65,12 @@ impl Vm { ); match instruction.operation() { - Operation::Move => todo!(), + Operation::Move => { + let to_register = instruction.a(); + let from_register = instruction.b(); + + self.set_pointer(to_register, from_register, position)?; + } Operation::Close => { let from_register = instruction.b(); let to_register = instruction.c(); diff --git a/dust-lang/tests/control_flow.rs b/dust-lang/tests/control_flow.rs index 60aa85b..73313c6 100644 --- a/dust-lang/tests/control_flow.rs +++ b/dust-lang/tests/control_flow.rs @@ -60,6 +60,70 @@ fn equality_assignment_short() { assert_eq!(run(source), Ok(Some(Value::boolean(true)))); } +#[test] +fn if_else_assigment() { + let source = r#" + let a = if 4 == 4 { + 1; 2; 3; 4; + 42 + } else { + 1; 2; 3; 4; + panic() + }; + a"#; + + assert_eq!( + parse(source), + Ok(Chunk::with_data( + None, + vec![ + ( + *Instruction::equal(true, 0, 1) + .set_b_is_constant() + .set_c_is_constant(), + Span(22, 24) + ), + (Instruction::jump(5, true), Span(22, 24)), + (Instruction::load_constant(0, 2, false), Span(41, 42)), + (Instruction::load_constant(1, 3, false), Span(44, 45)), + (Instruction::load_constant(2, 4, false), Span(47, 48)), + (Instruction::load_constant(3, 5, false), Span(50, 51)), + (Instruction::load_constant(4, 6, false), Span(65, 67)), + (Instruction::jump(6, true), Span(138, 139)), + (Instruction::jump(5, true), Span(138, 139)), + (Instruction::load_constant(5, 7, false), Span(97, 98)), + (Instruction::load_constant(6, 8, false), Span(100, 101)), + (Instruction::load_constant(7, 9, false), Span(103, 104)), + (Instruction::load_constant(8, 10, false), Span(106, 107)), + ( + Instruction::call_native(9, NativeFunction::Panic, 0), + Span(121, 128) + ), + (Instruction::r#move(8, 4), Span(138, 139)), + (Instruction::define_local(8, 0, false), Span(13, 14)), + (Instruction::get_local(9, 0), Span(148, 149)), + (Instruction::r#return(true), Span(149, 149)), + ], + vec![ + Value::integer(4), + Value::integer(4), + Value::integer(1), + Value::integer(2), + Value::integer(3), + Value::integer(4), + Value::integer(42), + Value::integer(1), + Value::integer(2), + Value::integer(3), + Value::integer(4), + ], + vec![Local::new(Identifier::new("a"), None, false, 0, 0)] + )), + ); + + assert_eq!(run(source), Ok(Some(Value::integer(42)))); +} + #[test] fn if_else_complex() { let source = " @@ -91,6 +155,7 @@ fn if_else_complex() { (Instruction::load_constant(5, 7, false), Span(77, 78)), (Instruction::load_constant(6, 8, false), Span(80, 81)), (Instruction::load_constant(7, 9, false), Span(83, 84)), + (Instruction::r#move(7, 3), Span(95, 95)), (Instruction::r#return(true), Span(95, 95)), ], vec![