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 })
|
.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",
|
||||||
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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),],
|
||||||
|
@ -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 })
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user