Prettify the hell out of chunk disassembly
This commit is contained in:
parent
78c9ed97e2
commit
8b33df3d4a
@ -104,7 +104,7 @@ impl Chunk {
|
||||
|
||||
pub fn get_local(&self, index: usize, position: Span) -> Result<&Local, ChunkError> {
|
||||
self.locals
|
||||
.get(index as usize)
|
||||
.get(index)
|
||||
.ok_or(ChunkError::LocalIndexOutOfBounds { index, position })
|
||||
}
|
||||
|
||||
@ -193,78 +193,8 @@ impl Chunk {
|
||||
self.locals.pop()
|
||||
}
|
||||
|
||||
pub fn disassemble(&self, name: &str) -> String {
|
||||
let mut output = String::new();
|
||||
|
||||
let name_length = name.len();
|
||||
let buffer_length = 51_usize.saturating_sub(name_length);
|
||||
let name_buffer = " ".repeat(buffer_length / 2);
|
||||
let underline = "-".repeat(name_length);
|
||||
|
||||
output.push_str(&format!("{name_buffer}{name}{name_buffer}\n"));
|
||||
output.push_str(&format!("{name_buffer}{underline}{name_buffer}\n",));
|
||||
output.push_str(" Code \n");
|
||||
output.push_str("------ ---------------- -------------------- --------\n");
|
||||
output.push_str("OFFSET INSTRUCTION INFO POSITION\n");
|
||||
output.push_str("------ ---------------- -------------------- --------\n");
|
||||
|
||||
for (offset, (instruction, position)) in self.instructions.iter().enumerate() {
|
||||
let display = format!(
|
||||
"{offset:^6} {:37} {position}\n",
|
||||
instruction.disassemble(self)
|
||||
);
|
||||
|
||||
output.push_str(&display);
|
||||
}
|
||||
|
||||
output.push_str("\n Constants\n");
|
||||
output.push_str("----- ---- -----\n");
|
||||
output.push_str("INDEX KIND VALUE\n");
|
||||
output.push_str("----- ---- -----\n");
|
||||
|
||||
for (index, value_option) in self.constants.iter().enumerate() {
|
||||
let value_kind_display = match value_option {
|
||||
Some(Value::Raw(_)) => "RAW ",
|
||||
Some(Value::Reference(_)) => "REF ",
|
||||
Some(Value::Mutable(_)) => "MUT ",
|
||||
None => "EMPTY",
|
||||
};
|
||||
let value_display = value_option
|
||||
.as_ref()
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or_else(|| "EMPTY".to_string());
|
||||
let display = format!("{index:3} {value_kind_display} {value_display}\n",);
|
||||
|
||||
output.push_str(&display);
|
||||
}
|
||||
|
||||
output.push_str("\n Locals\n");
|
||||
output.push_str("----- ---------- ----- -----\n");
|
||||
output.push_str("INDEX NAME DEPTH VALUE\n");
|
||||
output.push_str("----- ---------- ----- -----\n");
|
||||
|
||||
for (
|
||||
index,
|
||||
Local {
|
||||
identifier,
|
||||
depth,
|
||||
value,
|
||||
},
|
||||
) in self.locals.iter().enumerate()
|
||||
{
|
||||
let value_display = value
|
||||
.as_ref()
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or_else(|| "EMPTY".to_string());
|
||||
|
||||
let display = format!(
|
||||
"{index:3} {:10} {depth:<5} {value_display}\n",
|
||||
identifier.as_str()
|
||||
);
|
||||
output.push_str(&display);
|
||||
}
|
||||
|
||||
output
|
||||
pub fn disassemble<'a>(&self, name: &'a str) -> DisassembledChunk<'a> {
|
||||
DisassembledChunk::new(name, self)
|
||||
}
|
||||
}
|
||||
|
||||
@ -313,6 +243,165 @@ impl Local {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DisassembledChunk<'a> {
|
||||
name: &'a str,
|
||||
body: String,
|
||||
}
|
||||
|
||||
impl DisassembledChunk<'_> {
|
||||
pub fn new<'a>(name: &'a str, chunk: &Chunk) -> DisassembledChunk<'a> {
|
||||
let mut disassembled = String::new();
|
||||
let mut longest_line = 0;
|
||||
|
||||
disassembled.push('\n');
|
||||
disassembled.push_str(&DisassembledChunk::instructions_header());
|
||||
disassembled.push('\n');
|
||||
|
||||
for (offset, (instruction, position)) in chunk.instructions.iter().enumerate() {
|
||||
let position = position.to_string();
|
||||
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")
|
||||
} else {
|
||||
format!("{offset:<6} {operation:16} {:17} {position:8}\n", " ")
|
||||
};
|
||||
|
||||
disassembled.push_str(&instruction_display);
|
||||
|
||||
let line_length = instruction_display.len();
|
||||
|
||||
if line_length > longest_line {
|
||||
longest_line = line_length;
|
||||
}
|
||||
}
|
||||
|
||||
let mut push_centered = |section: &str| {
|
||||
let mut centered = String::new();
|
||||
|
||||
for line in section.lines() {
|
||||
centered.push_str(&format!("{line:^longest_line$}\n"));
|
||||
}
|
||||
|
||||
disassembled.push_str(¢ered);
|
||||
};
|
||||
|
||||
push_centered("\n");
|
||||
push_centered(&mut DisassembledChunk::constant_header());
|
||||
|
||||
for (index, value_option) in chunk.constants.iter().enumerate() {
|
||||
let value_kind_display = match value_option {
|
||||
Some(Value::Raw(_)) => "RAW ",
|
||||
Some(Value::Reference(_)) => "REF ",
|
||||
Some(Value::Mutable(_)) => "MUT ",
|
||||
None => "EMPTY",
|
||||
};
|
||||
let value_display = value_option
|
||||
.as_ref()
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or_else(|| "EMPTY".to_string());
|
||||
let constant_display = format!("{index:<5} {value_kind_display:<4} {value_display:<5}");
|
||||
|
||||
push_centered(&constant_display);
|
||||
}
|
||||
|
||||
push_centered("\n");
|
||||
push_centered(&mut DisassembledChunk::local_header());
|
||||
|
||||
for (
|
||||
index,
|
||||
Local {
|
||||
identifier,
|
||||
depth,
|
||||
value,
|
||||
},
|
||||
) in chunk.locals.iter().enumerate()
|
||||
{
|
||||
let value_kind_display = match value {
|
||||
Some(Value::Raw(_)) => "RAW ",
|
||||
Some(Value::Reference(_)) => "REF ",
|
||||
Some(Value::Mutable(_)) => "MUT ",
|
||||
None => "EMPTY",
|
||||
};
|
||||
let value_display = value
|
||||
.as_ref()
|
||||
.map(|value| value.to_string())
|
||||
.unwrap_or_else(|| "EMPTY".to_string());
|
||||
let identifier_display = identifier.as_str();
|
||||
let local_display =
|
||||
format!("{index:<5} {identifier_display:<10} {depth:<5} {value_kind_display:<4} {value_display:<5}");
|
||||
|
||||
push_centered(&local_display);
|
||||
}
|
||||
|
||||
DisassembledChunk {
|
||||
name,
|
||||
body: disassembled,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_string_with_width(&self, width: usize) -> String {
|
||||
let mut display = String::new();
|
||||
|
||||
for line in self.to_string().lines() {
|
||||
display.push_str(&format!("{line:^width$}\n"));
|
||||
}
|
||||
|
||||
display
|
||||
}
|
||||
|
||||
fn name_header(&self) -> String {
|
||||
format!("{:^50}\n{:^50}", self.name, "==============")
|
||||
}
|
||||
|
||||
fn instructions_header() -> String {
|
||||
format!(
|
||||
"{:^50}\n{:^50}\n{:<6} {:<16} {:<17} {}\n{} {} {} {}",
|
||||
"Instructions",
|
||||
"------------",
|
||||
"OFFSET",
|
||||
"INSTRUCTION",
|
||||
"INFO",
|
||||
"POSITION",
|
||||
"------",
|
||||
"----------------",
|
||||
"-----------------",
|
||||
"--------"
|
||||
)
|
||||
}
|
||||
|
||||
fn constant_header() -> String {
|
||||
format!(
|
||||
"{:^16}\n{:^16}\n{:<5} {:<4} {}\n{} {} {}",
|
||||
"Constants", "---------", "INDEX", "KIND", "VALUE", "-----", "----", "-----"
|
||||
)
|
||||
}
|
||||
|
||||
fn local_header() -> String {
|
||||
format!(
|
||||
"{:^50}\n{:^50}\n{:<5} {:<10} {:<5} {:<5} {:<5}\n{} {} {} {} {}",
|
||||
"Locals",
|
||||
"------",
|
||||
"INDEX",
|
||||
"IDENTIFIER",
|
||||
"DEPTH",
|
||||
"KIND",
|
||||
"VALUE",
|
||||
"-----",
|
||||
"----------",
|
||||
"-----",
|
||||
"-----",
|
||||
"-----"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for DisassembledChunk<'_> {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}\n{}", self.name_header(), self.body)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum ChunkError {
|
||||
CodeIndexOfBounds {
|
||||
|
@ -54,17 +54,17 @@ impl Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn declare_variable(to_register: u8, variable_index: u16) -> Instruction {
|
||||
pub fn declare_local(to_register: u8, variable_index: u16) -> Instruction {
|
||||
Instruction {
|
||||
operation: Operation::DeclareVariable,
|
||||
operation: Operation::DeclareLocal,
|
||||
destination: to_register,
|
||||
arguments: variable_index.to_le_bytes(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_variable(to_register: u8, variable_index: u16) -> Instruction {
|
||||
pub fn get_local(to_register: u8, variable_index: u16) -> Instruction {
|
||||
Instruction {
|
||||
operation: Operation::GetVariable,
|
||||
operation: Operation::GetLocal,
|
||||
destination: to_register,
|
||||
arguments: variable_index.to_le_bytes(),
|
||||
}
|
||||
@ -72,7 +72,7 @@ impl Instruction {
|
||||
|
||||
pub fn set_local(from_register: u8, variable_index: u16) -> Instruction {
|
||||
Instruction {
|
||||
operation: Operation::SetVariable,
|
||||
operation: Operation::SetLocal,
|
||||
destination: from_register,
|
||||
arguments: variable_index.to_le_bytes(),
|
||||
}
|
||||
@ -127,200 +127,96 @@ impl Instruction {
|
||||
}
|
||||
|
||||
pub fn disassemble(&self, chunk: &Chunk) -> String {
|
||||
match self.operation {
|
||||
Operation::Move => {
|
||||
format!(
|
||||
"{:16} R({}) R({})",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
self.arguments[0]
|
||||
)
|
||||
let mut disassembled = format!("{:16} ", self.operation.to_string());
|
||||
|
||||
if let Some(info) = self.disassembly_info(Some(chunk)) {
|
||||
disassembled.push_str(&info);
|
||||
}
|
||||
Operation::Close => format!("{:16} R({})", self.operation, self.destination),
|
||||
|
||||
disassembled
|
||||
}
|
||||
|
||||
pub fn disassembly_info(&self, chunk: Option<&Chunk>) -> Option<String> {
|
||||
let info = match self.operation {
|
||||
Operation::Move => {
|
||||
format!("R({}) R({})", self.destination, self.arguments[0])
|
||||
}
|
||||
Operation::Close => format!("R({})", self.destination),
|
||||
Operation::LoadConstant => {
|
||||
let constant_index = u16::from_le_bytes(self.arguments) as usize;
|
||||
let constant_display = match chunk.get_constant(constant_index, Span(0, 0)) {
|
||||
Ok(value) => value.to_string(),
|
||||
Err(error) => format!("{:?}", error),
|
||||
};
|
||||
|
||||
format!(
|
||||
"{:16} R({}) = C({}) {}",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
constant_index,
|
||||
constant_display
|
||||
)
|
||||
if let Some(chunk) = chunk {
|
||||
match chunk.get_constant(constant_index, Span(0, 0)) {
|
||||
Ok(value) => {
|
||||
format!("R({}) = C({}) {}", self.destination, constant_index, value)
|
||||
}
|
||||
Operation::DeclareVariable => {
|
||||
Err(error) => format!(
|
||||
"R({}) = C({}) {:?}",
|
||||
self.destination, constant_index, error
|
||||
),
|
||||
}
|
||||
} else {
|
||||
format!("R({}) = C({})", self.destination, constant_index)
|
||||
}
|
||||
}
|
||||
Operation::DeclareLocal => {
|
||||
let local_index = u16::from_le_bytes([self.arguments[0], self.arguments[1]]);
|
||||
|
||||
format!(
|
||||
"{:16} L({}) = R({})",
|
||||
self.operation.to_string(),
|
||||
local_index,
|
||||
self.destination
|
||||
)
|
||||
format!("L({}) = R({})", local_index, self.destination)
|
||||
}
|
||||
Operation::GetVariable => {
|
||||
Operation::GetLocal => {
|
||||
let local_index = u16::from_le_bytes([self.arguments[0], self.arguments[1]]);
|
||||
|
||||
format!("R({}) = L({})", self.destination, local_index)
|
||||
}
|
||||
Operation::SetLocal => {
|
||||
let identifier_index = u16::from_le_bytes([self.arguments[0], self.arguments[1]]);
|
||||
|
||||
format!(
|
||||
"{:16} R{} = R[I({})]",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
identifier_index
|
||||
)
|
||||
}
|
||||
Operation::SetVariable => {
|
||||
let identifier_index = u16::from_le_bytes([self.arguments[0], self.arguments[1]]);
|
||||
|
||||
format!(
|
||||
"{:16} R[C({})] = R({})",
|
||||
self.operation.to_string(),
|
||||
identifier_index,
|
||||
self.destination
|
||||
)
|
||||
format!("L({}) = R({})", identifier_index, self.destination)
|
||||
}
|
||||
Operation::Add => {
|
||||
format!(
|
||||
"{:16} R({}) = RC({}) + RC({})",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
self.arguments[0],
|
||||
self.arguments[1]
|
||||
"R({}) = RC({}) + RC({})",
|
||||
self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Subtract => {
|
||||
format!(
|
||||
"{:16} R({}) = RC({}) - RC({})",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
self.arguments[0],
|
||||
self.arguments[1]
|
||||
"R({}) = RC({}) - RC({})",
|
||||
self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Multiply => {
|
||||
format!(
|
||||
"{:16} R({}) = RC({}) * RC({})",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
self.arguments[0],
|
||||
self.arguments[1]
|
||||
"R({}) = RC({}) * RC({})",
|
||||
self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Divide => {
|
||||
format!(
|
||||
"{:16} R({}) = RC({}) / RC({})",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
self.arguments[0],
|
||||
self.arguments[1]
|
||||
"R({}) = RC({}) / RC({})",
|
||||
self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Negate => {
|
||||
format!(
|
||||
"{:16} R({}) = -RC({})",
|
||||
self.operation.to_string(),
|
||||
self.destination,
|
||||
self.arguments[0]
|
||||
)
|
||||
}
|
||||
Operation::Return => {
|
||||
format!("{:16}", self.operation.to_string())
|
||||
}
|
||||
format!("R({}) = -RC({})", self.destination, self.arguments[0])
|
||||
}
|
||||
Operation::Return => return None,
|
||||
};
|
||||
|
||||
Some(info)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Instruction {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
match self.operation {
|
||||
Operation::Move => {
|
||||
write!(
|
||||
f,
|
||||
"{} R({}) R({})",
|
||||
self.operation, self.destination, self.arguments[0]
|
||||
)
|
||||
}
|
||||
Operation::Close => write!(f, "{} R({})", self.operation, self.destination),
|
||||
Operation::LoadConstant => {
|
||||
let constant_index = u16::from_le_bytes(self.arguments);
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{} R({}) = C({})",
|
||||
self.operation, self.destination, constant_index
|
||||
)
|
||||
}
|
||||
Operation::DeclareVariable => {
|
||||
let identifier_index = u16::from_le_bytes([self.arguments[0], self.arguments[1]]);
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{} L({}) = R({})",
|
||||
self.operation, identifier_index, self.destination
|
||||
)
|
||||
}
|
||||
Operation::GetVariable => {
|
||||
let identifier_index = u16::from_le_bytes([self.arguments[0], self.arguments[1]]);
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{} R{} = R[I({})]",
|
||||
self.operation, self.destination, identifier_index
|
||||
)
|
||||
}
|
||||
Operation::SetVariable => {
|
||||
let identifier_index = u16::from_le_bytes([self.arguments[0], self.arguments[1]]);
|
||||
|
||||
write!(
|
||||
f,
|
||||
"{} R[C({})] = R({})",
|
||||
self.operation, identifier_index, self.destination
|
||||
)
|
||||
}
|
||||
Operation::Add => {
|
||||
write!(
|
||||
f,
|
||||
"{} R({}) = RC({}) + RC({})",
|
||||
self.operation, self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Subtract => {
|
||||
write!(
|
||||
f,
|
||||
"{} R({}) = RC({}) - RC({})",
|
||||
self.operation, self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Multiply => {
|
||||
write!(
|
||||
f,
|
||||
"{} R({}) = RC({}) * RC({})",
|
||||
self.operation, self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Divide => {
|
||||
write!(
|
||||
f,
|
||||
"{} R({}) = RC({}) / RC({})",
|
||||
self.operation, self.destination, self.arguments[0], self.arguments[1]
|
||||
)
|
||||
}
|
||||
Operation::Negate => {
|
||||
write!(
|
||||
f,
|
||||
"{} R({}) = -RC({})",
|
||||
self.operation, self.destination, self.arguments[0]
|
||||
)
|
||||
}
|
||||
Operation::Return => {
|
||||
if let Some(info) = self.disassembly_info(None) {
|
||||
write!(f, "{} {}", self.operation, info)
|
||||
} else {
|
||||
write!(f, "{}", self.operation)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub enum Operation {
|
||||
@ -332,9 +228,9 @@ pub enum Operation {
|
||||
LoadConstant = 2,
|
||||
|
||||
// Variables
|
||||
DeclareVariable = 3,
|
||||
GetVariable = 4,
|
||||
SetVariable = 5,
|
||||
DeclareLocal = 3,
|
||||
GetLocal = 4,
|
||||
SetLocal = 5,
|
||||
|
||||
// Binary operations
|
||||
Add = 6,
|
||||
@ -355,9 +251,9 @@ impl From<u8> for Operation {
|
||||
0 => Operation::Move,
|
||||
1 => Operation::Close,
|
||||
2 => Operation::LoadConstant,
|
||||
3 => Operation::DeclareVariable,
|
||||
4 => Operation::GetVariable,
|
||||
5 => Operation::SetVariable,
|
||||
3 => Operation::DeclareLocal,
|
||||
4 => Operation::GetLocal,
|
||||
5 => Operation::SetLocal,
|
||||
6 => Operation::Add,
|
||||
7 => Operation::Subtract,
|
||||
8 => Operation::Multiply,
|
||||
@ -374,9 +270,9 @@ impl Display for Operation {
|
||||
Operation::Move => write!(f, "MOVE"),
|
||||
Operation::Close => write!(f, "CLOSE"),
|
||||
Operation::LoadConstant => write!(f, "LOAD_CONSTANT"),
|
||||
Operation::DeclareVariable => write!(f, "DECLARE_VARIABLE"),
|
||||
Operation::GetVariable => write!(f, "GET_VARIABLE"),
|
||||
Operation::SetVariable => write!(f, "SET_VARIABLE"),
|
||||
Operation::DeclareLocal => write!(f, "DECLARE_LOCAL"),
|
||||
Operation::GetLocal => write!(f, "GET_LOCAL"),
|
||||
Operation::SetLocal => write!(f, "SET_LOCAL"),
|
||||
Operation::Add => write!(f, "ADD"),
|
||||
Operation::Subtract => write!(f, "SUBTRACT"),
|
||||
Operation::Multiply => write!(f, "MULTIPLY"),
|
||||
|
@ -138,7 +138,6 @@ impl<'src> Parser<'src> {
|
||||
Instruction::load_constant(self.current_register, constant_index),
|
||||
position,
|
||||
);
|
||||
self.increment_register()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -276,8 +275,8 @@ impl<'src> Parser<'src> {
|
||||
}
|
||||
_ => self.current_register - 1,
|
||||
};
|
||||
let last_instruction = self.chunk.pop_instruction();
|
||||
let left_register = match last_instruction {
|
||||
let previous_instruction = self.chunk.pop_instruction();
|
||||
let left_register = match previous_instruction {
|
||||
Some((
|
||||
Instruction {
|
||||
operation: Operation::LoadConstant,
|
||||
@ -340,12 +339,15 @@ impl<'src> Parser<'src> {
|
||||
|
||||
if allow_assignment && self.allow(TokenKind::Equal)? {
|
||||
self.parse_expression()?;
|
||||
|
||||
self.emit_instruction(
|
||||
Instruction::set_local(self.current_register, local_index),
|
||||
self.previous_position,
|
||||
);
|
||||
self.increment_register()?;
|
||||
} else {
|
||||
self.emit_instruction(
|
||||
Instruction::get_local(self.current_register, local_index),
|
||||
self.previous_position,
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -447,7 +449,7 @@ impl<'src> Parser<'src> {
|
||||
let local_index = self.chunk.declare_local(identifier, position)?;
|
||||
|
||||
self.emit_instruction(
|
||||
Instruction::declare_variable(self.current_register - 1, local_index),
|
||||
Instruction::declare_local(self.current_register, 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_variable(1, 0), Span(4, 5)),
|
||||
(Instruction::declare_local(1, 0), Span(4, 5)),
|
||||
],
|
||||
vec![Value::integer(42),],
|
||||
vec![Local::new(Identifier::new("x"), 0, None)]
|
||||
|
@ -43,20 +43,20 @@ impl Vm {
|
||||
|
||||
self.insert(value, instruction.destination as usize, position)?;
|
||||
}
|
||||
Operation::DeclareVariable => {
|
||||
Operation::DeclareLocal => {
|
||||
let register_index = instruction.destination as usize;
|
||||
let local_index = u16::from_le_bytes(instruction.arguments) as usize;
|
||||
let value = self.clone(register_index, position)?;
|
||||
|
||||
self.chunk.define_local(local_index, value, position)?;
|
||||
}
|
||||
Operation::GetVariable => {
|
||||
Operation::GetLocal => {
|
||||
let identifier_index = u16::from_le_bytes(instruction.arguments) as usize;
|
||||
let value = self.clone(identifier_index, position)?;
|
||||
|
||||
self.insert(value, identifier_index, position)?;
|
||||
}
|
||||
Operation::SetVariable => todo!(),
|
||||
Operation::SetLocal => todo!(),
|
||||
Operation::Add => {
|
||||
let left =
|
||||
self.take_or_use_constant(instruction.arguments[0] as usize, position)?;
|
||||
|
Loading…
Reference in New Issue
Block a user