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 })
}
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<u16, ChunkError> {
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",

View File

@ -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,
);

View File

@ -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),],

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> {
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<Value, VmError> {
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 })
}