diff --git a/dust-lang/src/instruction.rs b/dust-lang/src/instruction.rs index 6c29268..a5ce850 100644 --- a/dust-lang/src/instruction.rs +++ b/dust-lang/src/instruction.rs @@ -15,10 +15,11 @@ impl Instruction { instruction } - pub fn close(to_register: u8) -> Instruction { + pub fn close(from_register: u8, to_register: u8) -> Instruction { let mut instruction = Instruction(Operation::Close as u32); - instruction.set_destination(to_register); + instruction.set_first_argument(from_register); + instruction.set_second_argument(to_register); instruction } @@ -243,7 +244,12 @@ impl Instruction { Operation::Move => { format!("R({}) = R({})", self.destination(), self.first_argument()) } - Operation::Close => format!("R({})", self.destination()), + Operation::Close => { + let from_register = self.first_argument(); + let to_register = self.second_argument().saturating_sub(1); + + format!("R({from_register})..=R({to_register})") + } Operation::LoadConstant => { let constant_index = self.first_argument(); @@ -274,7 +280,7 @@ impl Instruction { let last_index = destination - 1; format!( - "R({}) = [R({})..R({})]", + "R({}) = [R({})..=R({})]", destination, first_index, last_index ) } @@ -556,15 +562,11 @@ mod tests { #[test] fn close() { - let mut instruction = Instruction::close(1); - - instruction.set_first_argument_to_constant(); - instruction.set_second_argument_to_constant(); + let instruction = Instruction::close(1, 2); assert_eq!(instruction.operation(), Operation::Close); - assert_eq!(instruction.destination(), 1); - assert!(instruction.first_argument_is_constant()); - assert!(instruction.second_argument_is_constant()); + assert_eq!(instruction.first_argument(), 1); + assert_eq!(instruction.second_argument(), 2); } #[test] diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index 1e495a8..0d4da5e 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -485,8 +485,17 @@ impl<'src> Parser<'src> { let mut length = 0; while !self.allow(TokenKind::RightSquareBrace)? && !self.is_eof() { + let next_register = self.current_register; + self.parse(Precedence::Assignment)?; // Do not allow assignment + if next_register != self.current_register - 1 { + self.emit_instruction( + Instruction::close(next_register, self.current_register - 1), + self.current_position, + ); + } + length += 1; if !self.allow(TokenKind::Comma)? { diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 95c261b..b71c86d 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -66,7 +66,14 @@ impl Vm { self.insert(value, to, position)?; } - Operation::Close => todo!(), + Operation::Close => { + let from = instruction.first_argument(); + let to = instruction.second_argument(); + + for register_index in from..to { + self.register_stack[register_index as usize] = None; + } + } Operation::LoadConstant => { let to_register = instruction.destination(); let from_constant = instruction.first_argument(); @@ -77,13 +84,17 @@ impl Vm { Operation::LoadList => { let to_register = instruction.destination(); let length = instruction.first_argument(); - let first_register = to_register - length; + let first_register = to_register - length - 1; let last_register = to_register - 1; let mut list = Vec::with_capacity(length as usize); for register_index in first_register..=last_register { - let value = self.clone(register_index, position)?; + let value = match self.clone(register_index, position) { + Ok(value) => value, + Err(VmError::EmptyRegister { .. }) => continue, + Err(error) => return Err(error), + }; list.push(value); }