Fix and implement variable getting and setting

This commit is contained in:
Jeff 2024-09-12 14:16:26 -04:00
parent 8b33df3d4a
commit caf59894b6
4 changed files with 43 additions and 31 deletions

View File

@ -108,12 +108,8 @@ impl Chunk {
.ok_or(ChunkError::LocalIndexOutOfBounds { index, position }) .ok_or(ChunkError::LocalIndexOutOfBounds { index, position })
} }
pub fn get_identifier(&self, index: u8) -> Option<&Identifier> { pub fn get_identifier(&self, index: usize) -> Option<&Identifier> {
if let Some(local) = self.locals.get(index as usize) { self.locals.get(index).map(|local| &local.identifier)
Some(&local.identifier)
} else {
None
}
} }
pub fn get_local_index( pub fn get_local_index(
@ -123,8 +119,8 @@ impl Chunk {
) -> Result<u16, ChunkError> { ) -> Result<u16, ChunkError> {
self.locals self.locals
.iter() .iter()
.rev()
.enumerate() .enumerate()
.rev()
.find_map(|(index, local)| { .find_map(|(index, local)| {
if &local.identifier == identifier { if &local.identifier == identifier {
Some(index as u16) Some(index as u16)
@ -262,9 +258,9 @@ impl DisassembledChunk<'_> {
let operation = instruction.operation.to_string(); let operation = instruction.operation.to_string();
let info_option = instruction.disassembly_info(Some(chunk)); let info_option = instruction.disassembly_info(Some(chunk));
let instruction_display = if let Some(info) = info_option { 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 { } else {
format!("{offset:<6} {operation:16} {:17} {position:8}\n", " ") format!("{offset:<6} {operation:16} {:20} {position:8}\n", " ")
}; };
disassembled.push_str(&instruction_display); disassembled.push_str(&instruction_display);
@ -351,12 +347,14 @@ impl DisassembledChunk<'_> {
} }
fn name_header(&self) -> String { 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 { fn instructions_header() -> String {
format!( format!(
"{:^50}\n{:^50}\n{:<6} {:<16} {:<17} {}\n{} {} {} {}", "{:^50}\n{:^50}\n{:<6} {:<16} {:<20} {}\n{} {} {} {}",
"Instructions", "Instructions",
"------------", "------------",
"OFFSET", "OFFSET",
@ -365,21 +363,21 @@ impl DisassembledChunk<'_> {
"POSITION", "POSITION",
"------", "------",
"----------------", "----------------",
"-----------------", "--------------------",
"--------" "--------"
) )
} }
fn constant_header() -> String { fn constant_header() -> String {
format!( format!(
"{:^16}\n{:^16}\n{:<5} {:<4} {}\n{} {} {}", "{}\n{}\n{:<5} {:<4} {}\n{} {} {}",
"Constants", "---------", "INDEX", "KIND", "VALUE", "-----", "----", "-----" "Constants", "---------", "INDEX", "KIND", "VALUE", "-----", "----", "-----"
) )
} }
fn local_header() -> String { fn local_header() -> String {
format!( format!(
"{:^50}\n{:^50}\n{:<5} {:<10} {:<5} {:<5} {:<5}\n{} {} {} {} {}", "{}\n{}\n{:<5} {:<10} {:<5} {:<5} {}\n{} {} {} {} {}",
"Locals", "Locals",
"------", "------",
"INDEX", "INDEX",

View File

@ -138,6 +138,7 @@ impl<'src> Parser<'src> {
Instruction::load_constant(self.current_register, constant_index), Instruction::load_constant(self.current_register, constant_index),
position, position,
); );
self.increment_register()?;
Ok(()) Ok(())
} }
@ -350,6 +351,8 @@ impl<'src> Parser<'src> {
); );
} }
self.increment_register()?;
Ok(()) Ok(())
} }
@ -449,7 +452,7 @@ impl<'src> Parser<'src> {
let local_index = self.chunk.declare_local(identifier, position)?; let local_index = self.chunk.declare_local(identifier, position)?;
self.emit_instruction( self.emit_instruction(
Instruction::declare_local(self.current_register, local_index), Instruction::declare_local(self.current_register - 1, local_index),
position, position,
); );

View File

@ -9,7 +9,7 @@ fn let_statement() {
Ok(Chunk::with_data( Ok(Chunk::with_data(
vec![ vec![
(Instruction::load_constant(0, 0), Span(8, 10)), (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![Value::integer(42),],
vec![Local::new(Identifier::new("x"), 0, None)] vec![Local::new(Identifier::new("x"), 0, None)]
@ -38,9 +38,7 @@ fn add() {
parse("1 + 2"), parse("1 + 2"),
Ok(Chunk::with_data( Ok(Chunk::with_data(
vec![ vec![
(Instruction::load_constant(0, 0), Span(0, 1)), (Instruction::add(0, 0, 1), Span(2, 3)),
(Instruction::load_constant(1, 1), Span(4, 5)),
(Instruction::add(2, 0, 1), Span(2, 3)),
(Instruction::r#return(), Span(0, 5)), (Instruction::r#return(), Span(0, 5)),
], ],
vec![Value::integer(1), Value::integer(2),], vec![Value::integer(1), Value::integer(2),],
@ -55,9 +53,7 @@ fn subtract() {
parse("1 - 2"), parse("1 - 2"),
Ok(Chunk::with_data( Ok(Chunk::with_data(
vec![ vec![
(Instruction::load_constant(0, 0), Span(0, 1)), (Instruction::subtract(0, 0, 1), Span(2, 3)),
(Instruction::load_constant(1, 1), Span(4, 5)),
(Instruction::subtract(2, 0, 1), Span(2, 3)),
(Instruction::r#return(), Span(0, 5)), (Instruction::r#return(), Span(0, 5)),
], ],
vec![Value::integer(1), Value::integer(2),], vec![Value::integer(1), Value::integer(2),],

View File

@ -30,6 +30,10 @@ impl Vm {
} }
} }
pub fn take_chunk(self) -> Chunk {
self.chunk
}
pub fn run(&mut self) -> Result<Option<Value>, VmError> { pub fn run(&mut self) -> Result<Option<Value>, VmError> {
while let Ok((instruction, position)) = self.read(Span(0, 0)).copied() { while let Ok((instruction, position)) = self.read(Span(0, 0)).copied() {
log::trace!("Running instruction {instruction} at {position}"); log::trace!("Running instruction {instruction} at {position}");
@ -51,10 +55,19 @@ impl Vm {
self.chunk.define_local(local_index, value, position)?; self.chunk.define_local(local_index, value, position)?;
} }
Operation::GetLocal => { Operation::GetLocal => {
let identifier_index = u16::from_le_bytes(instruction.arguments) as usize; let register_index = instruction.destination as usize;
let value = self.clone(identifier_index, position)?; 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::SetLocal => todo!(),
Operation::Add => { Operation::Add => {
@ -137,13 +150,15 @@ impl Vm {
fn clone(&mut self, index: usize, position: Span) -> Result<Value, VmError> { fn clone(&mut self, index: usize, position: Span) -> Result<Value, VmError> {
if let Some(register) = self.register_stack.get_mut(index) { if let Some(register) = self.register_stack.get_mut(index) {
let value = register if let Some(mut value) = register.take() {
.take() if value.is_raw() {
.ok_or(VmError::EmptyRegister { index, position })? value = value.into_reference();
.into_reference(); }
let _ = register.insert(value.clone());
Ok(value) Ok(value.clone())
} else {
Err(VmError::EmptyRegister { index, position })
}
} else { } else {
Err(VmError::RegisterIndexOutOfBounds { position }) Err(VmError::RegisterIndexOutOfBounds { position })
} }