Fix and implement variable getting and setting
This commit is contained in:
parent
8b33df3d4a
commit
caf59894b6
@ -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",
|
||||
|
@ -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,
|
||||
);
|
||||
|
||||
|
@ -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),],
|
||||
|
@ -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 })
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user