From caf59894b645de2aea9cca5f50bc20e206099055 Mon Sep 17 00:00:00 2001 From: Jeff Date: Thu, 12 Sep 2024 14:16:26 -0400 Subject: [PATCH] Fix and implement variable getting and setting --- dust-lang/src/chunk.rs | 26 ++++++++++++-------------- dust-lang/src/parser/mod.rs | 5 ++++- dust-lang/src/parser/tests.rs | 10 +++------- dust-lang/src/vm.rs | 33 ++++++++++++++++++++++++--------- 4 files changed, 43 insertions(+), 31 deletions(-) diff --git a/dust-lang/src/chunk.rs b/dust-lang/src/chunk.rs index 36876ac..a3014f7 100644 --- a/dust-lang/src/chunk.rs +++ b/dust-lang/src/chunk.rs @@ -108,12 +108,8 @@ impl Chunk { .ok_or(ChunkError::LocalIndexOutOfBounds { index, position }) } - pub fn get_identifier(&self, index: u8) -> Option<&Identifier> { - if let Some(local) = self.locals.get(index as usize) { - Some(&local.identifier) - } else { - None - } + pub fn get_identifier(&self, index: usize) -> Option<&Identifier> { + self.locals.get(index).map(|local| &local.identifier) } pub fn get_local_index( @@ -123,8 +119,8 @@ impl Chunk { ) -> Result { self.locals .iter() - .rev() .enumerate() + .rev() .find_map(|(index, local)| { if &local.identifier == identifier { Some(index as u16) @@ -262,9 +258,9 @@ impl DisassembledChunk<'_> { let operation = instruction.operation.to_string(); let info_option = instruction.disassembly_info(Some(chunk)); let instruction_display = if let Some(info) = info_option { - format!("{offset:<6} {operation:16} {info:17} {position:8}\n") + format!("{offset:<6} {operation:16} {info:20} {position:8}\n") } else { - format!("{offset:<6} {operation:16} {:17} {position:8}\n", " ") + format!("{offset:<6} {operation:16} {:20} {position:8}\n", " ") }; disassembled.push_str(&instruction_display); @@ -351,12 +347,14 @@ impl DisassembledChunk<'_> { } fn name_header(&self) -> String { - format!("{:^50}\n{:^50}", self.name, "==============") + let name_length = self.name.len(); + + format!("{:^50}\n{:^50}", self.name, "=".repeat(name_length)) } fn instructions_header() -> String { format!( - "{:^50}\n{:^50}\n{:<6} {:<16} {:<17} {}\n{} {} {} {}", + "{:^50}\n{:^50}\n{:<6} {:<16} {:<20} {}\n{} {} {} {}", "Instructions", "------------", "OFFSET", @@ -365,21 +363,21 @@ impl DisassembledChunk<'_> { "POSITION", "------", "----------------", - "-----------------", + "--------------------", "--------" ) } fn constant_header() -> String { format!( - "{:^16}\n{:^16}\n{:<5} {:<4} {}\n{} {} {}", + "{}\n{}\n{:<5} {:<4} {}\n{} {} {}", "Constants", "---------", "INDEX", "KIND", "VALUE", "-----", "----", "-----" ) } fn local_header() -> String { format!( - "{:^50}\n{:^50}\n{:<5} {:<10} {:<5} {:<5} {:<5}\n{} {} {} {} {}", + "{}\n{}\n{:<5} {:<10} {:<5} {:<5} {}\n{} {} {} {} {}", "Locals", "------", "INDEX", diff --git a/dust-lang/src/parser/mod.rs b/dust-lang/src/parser/mod.rs index d974b87..ea76032 100644 --- a/dust-lang/src/parser/mod.rs +++ b/dust-lang/src/parser/mod.rs @@ -138,6 +138,7 @@ impl<'src> Parser<'src> { Instruction::load_constant(self.current_register, constant_index), position, ); + self.increment_register()?; Ok(()) } @@ -350,6 +351,8 @@ impl<'src> Parser<'src> { ); } + self.increment_register()?; + Ok(()) } @@ -449,7 +452,7 @@ impl<'src> Parser<'src> { let local_index = self.chunk.declare_local(identifier, position)?; self.emit_instruction( - Instruction::declare_local(self.current_register, local_index), + Instruction::declare_local(self.current_register - 1, local_index), position, ); diff --git a/dust-lang/src/parser/tests.rs b/dust-lang/src/parser/tests.rs index b3861c8..4b19171 100644 --- a/dust-lang/src/parser/tests.rs +++ b/dust-lang/src/parser/tests.rs @@ -9,7 +9,7 @@ fn let_statement() { Ok(Chunk::with_data( vec![ (Instruction::load_constant(0, 0), Span(8, 10)), - (Instruction::declare_local(1, 0), Span(4, 5)), + (Instruction::declare_local(0, 0), Span(4, 5)), ], vec![Value::integer(42),], vec![Local::new(Identifier::new("x"), 0, None)] @@ -38,9 +38,7 @@ fn add() { parse("1 + 2"), Ok(Chunk::with_data( vec![ - (Instruction::load_constant(0, 0), Span(0, 1)), - (Instruction::load_constant(1, 1), Span(4, 5)), - (Instruction::add(2, 0, 1), Span(2, 3)), + (Instruction::add(0, 0, 1), Span(2, 3)), (Instruction::r#return(), Span(0, 5)), ], vec![Value::integer(1), Value::integer(2),], @@ -55,9 +53,7 @@ fn subtract() { parse("1 - 2"), Ok(Chunk::with_data( vec![ - (Instruction::load_constant(0, 0), Span(0, 1)), - (Instruction::load_constant(1, 1), Span(4, 5)), - (Instruction::subtract(2, 0, 1), Span(2, 3)), + (Instruction::subtract(0, 0, 1), Span(2, 3)), (Instruction::r#return(), Span(0, 5)), ], vec![Value::integer(1), Value::integer(2),], diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index 51373ff..327301c 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -30,6 +30,10 @@ impl Vm { } } + pub fn take_chunk(self) -> Chunk { + self.chunk + } + pub fn run(&mut self) -> Result, VmError> { while let Ok((instruction, position)) = self.read(Span(0, 0)).copied() { log::trace!("Running instruction {instruction} at {position}"); @@ -51,10 +55,19 @@ impl Vm { self.chunk.define_local(local_index, value, position)?; } Operation::GetLocal => { - let identifier_index = u16::from_le_bytes(instruction.arguments) as usize; - let value = self.clone(identifier_index, position)?; + let register_index = instruction.destination as usize; + let local_index = u16::from_le_bytes(instruction.arguments) as usize; + let local = self.chunk.get_local(local_index, position)?; + let value = if let Some(value) = &local.value { + value.clone() + } else { + return Err(VmError::UndefinedVariable { + identifier: local.identifier.clone(), + position, + }); + }; - self.insert(value, identifier_index, position)?; + self.insert(value, register_index, position)?; } Operation::SetLocal => todo!(), Operation::Add => { @@ -137,13 +150,15 @@ impl Vm { fn clone(&mut self, index: usize, position: Span) -> Result { if let Some(register) = self.register_stack.get_mut(index) { - let value = register - .take() - .ok_or(VmError::EmptyRegister { index, position })? - .into_reference(); - let _ = register.insert(value.clone()); + if let Some(mut value) = register.take() { + if value.is_raw() { + value = value.into_reference(); + } - Ok(value) + Ok(value.clone()) + } else { + Err(VmError::EmptyRegister { index, position }) + } } else { Err(VmError::RegisterIndexOutOfBounds { position }) }