1
0

Store types in locals; Fix local disassembly

This commit is contained in:
Jeff 2025-02-07 10:39:33 -05:00
parent 25b4230aa4
commit 820ead0c02
3 changed files with 55 additions and 44 deletions

View File

@ -43,7 +43,7 @@ use std::io::{self, Write};
use colored::{ColoredString, Colorize};
use crate::{Chunk, Local};
use crate::{Chunk, Local, Type};
const INSTRUCTION_COLUMNS: [(&str, usize); 4] =
[("i", 5), ("POSITION", 12), ("OPERATION", 17), ("INFO", 41)];
@ -53,17 +53,18 @@ const INSTRUCTION_BORDERS: [&str; 3] = [
"╰─────┴────────────┴─────────────────┴─────────────────────────────────────────╯",
];
const LOCAL_COLUMNS: [(&str, usize); 5] = [
const LOCAL_COLUMNS: [(&str, usize); 6] = [
("i", 5),
("IDENTIFIER", 16),
("TYPE", 26),
("REGISTER", 10),
("SCOPE", 7),
("MUTABLE", 7),
];
const LOCAL_BORDERS: [&str; 3] = [
"╭─────┬────────────────┬──────────┬───────┬───────╮",
"├─────┼────────────────┼──────────┼───────┼───────┤",
"╰─────┴────────────────┴──────────┴───────┴───────╯",
"╭─────┬────────────────┬──────────────────────────┬──────────┬───────┬───────╮",
"├─────┼────────────────┼──────────────────────────┼──────────┼───────┼───────┤",
"╰─────┴────────────────┴──────────────────────────┴──────────┴───────┴───────╯",
];
const CONSTANT_COLUMNS: [(&str, usize); 3] = [("i", 5), ("TYPE", 26), ("VALUE", 26)];
@ -314,6 +315,7 @@ impl<'a, W: Write> Disassembler<'a, W> {
Local {
identifier_index,
register_index,
r#type,
scope,
is_mutable,
},
@ -325,10 +327,12 @@ impl<'a, W: Write> Disassembler<'a, W> {
.get(*identifier_index as usize)
.map(|value| value.to_string())
.unwrap_or_else(|| "unknown".to_string());
let register_display = format!("R{register_index}");
let type_display = r#type.to_string();
let type_caps = type_display.to_uppercase();
let register_display = format!("R_{type_caps}_{register_index}");
let scope = scope.to_string();
let row = format!(
"│{index:^5}│{identifier_display:^16}│{register_display:^10}│{scope:^7}│{is_mutable:^7}│"
"│{index:^5}│{identifier_display:^16}│{type_display:^26}│{register_display:^10}│{scope:^7}│{is_mutable:^7}│"
);
self.write_center_border(&row)?;

View File

@ -2,7 +2,7 @@
use serde::{Deserialize, Serialize};
use crate::Scope;
use crate::{Scope, Type};
/// Scoped variable.
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
@ -13,6 +13,9 @@ pub struct Local {
/// Index of the register where the variable's value is stored.
pub register_index: u16,
/// Type of the variable's value.
pub r#type: Type,
/// Whether the local is mutable.
pub is_mutable: bool,
@ -22,10 +25,17 @@ pub struct Local {
impl Local {
/// Creates a new Local instance.
pub fn new(identifier_index: u16, register_index: u16, is_mutable: bool, scope: Scope) -> Self {
pub fn new(
identifier_index: u16,
register_index: u16,
r#type: Type,
is_mutable: bool,
scope: Scope,
) -> Self {
Self {
identifier_index,
register_index,
r#type,
is_mutable,
scope,
}

View File

@ -89,7 +89,7 @@ pub struct Compiler<'src> {
/// Block-local variables and their types. The locals are assigned to the chunk when
/// [`Compiler::finish`] is called. The types are discarded after compilation.
locals: Vec<(Local, Type)>,
locals: Vec<Local>,
/// Prototypes that have been compiled. These are assigned to the chunk when
/// [`Compiler::finish`] is called.
@ -239,11 +239,6 @@ impl<'src> Compiler<'src> {
.into_iter()
.map(|(instruction, _, position)| (instruction, position))
.unzip();
let locals = self
.locals
.into_iter()
.map(|(local, _)| local)
.collect::<Vec<Local>>();
Chunk {
name: self.function_name,
@ -251,7 +246,7 @@ impl<'src> Compiler<'src> {
instructions,
positions,
constants: self.constants,
locals,
locals: self.locals,
prototypes: self.prototypes,
boolean_register_count,
byte_register_count,
@ -402,7 +397,7 @@ impl<'src> Compiler<'src> {
Ok(())
}
fn get_local(&self, index: u16) -> Result<&(Local, Type), CompileError> {
fn get_local(&self, index: u16) -> Result<&Local, CompileError> {
self.locals
.get(index as usize)
.ok_or(CompileError::UndeclaredVariable {
@ -416,7 +411,7 @@ impl<'src> Compiler<'src> {
.iter()
.enumerate()
.rev()
.find_map(|(index, (local, _))| {
.find_map(|(index, local)| {
let constant = self.constants.get(local.identifier_index as usize)?;
let identifier = if let ConcreteValue::String(identifier) = constant {
identifier
@ -450,22 +445,23 @@ impl<'src> Compiler<'src> {
let identifier_index = self.push_or_get_constant(identifier);
let local_index = self.locals.len() as u16;
self.locals.push((
Local::new(identifier_index, register_index, is_mutable, scope),
self.locals.push(Local::new(
identifier_index,
register_index,
r#type,
is_mutable,
scope,
));
(local_index, identifier_index)
}
fn get_identifier(&self, local_index: u16) -> Option<String> {
self.locals
.get(local_index as usize)
.and_then(|(local, _)| {
self.constants
.get(local.identifier_index as usize)
.map(|value| value.to_string())
})
self.locals.get(local_index as usize).and_then(|local| {
self.constants
.get(local.identifier_index as usize)
.map(|value| value.to_string())
})
}
fn push_or_get_constant(&mut self, value: ConcreteValue) -> u16 {
@ -535,12 +531,14 @@ impl<'src> Compiler<'src> {
}
fn get_register_type(&self, register_index: u16) -> Result<Type, CompileError> {
if let Some((_, r#type)) = self
.locals
.iter()
.find(|(local, _)| local.register_index == register_index)
{
return Ok(r#type.clone());
if let Some(r#type) = self.locals.iter().find_map(|local| {
if local.register_index == register_index {
Some(local.r#type.clone())
} else {
None
}
}) {
return Ok(r#type);
}
for (instruction, r#type, _) in &self.instructions {
@ -852,7 +850,7 @@ impl<'src> Compiler<'src> {
self.locals
.get(to.index() as usize)
.map(|(local, _)| local.is_mutable)
.map(|local| local.is_mutable)
.unwrap_or(false)
} else {
false
@ -1052,7 +1050,7 @@ impl<'src> Compiler<'src> {
})?;
let operand_register = if last_instruction.operation() == Operation::POINT {
let Point { to, .. } = Point::from(last_instruction);
let (local, _) = self.get_local(to.index())?;
let local = self.get_local(to.index())?;
local.register_index
} else if last_instruction.yields_value() {
@ -1156,9 +1154,8 @@ impl<'src> Compiler<'src> {
});
};
let (local, r#type) = self
.get_local(local_index)
.map(|(local, r#type)| (local, r#type.clone()))?;
let local = self.get_local(local_index)?;
let local_type = local.r#type.clone();
let is_mutable = local.is_mutable;
let local_register_index = local.register_index;
@ -1190,7 +1187,7 @@ impl<'src> Compiler<'src> {
math_instruction.set_a_field(local_register_index);
} else {
let register = match r#type {
let register = match local_type {
Type::Boolean => self.next_boolean_register(),
Type::Byte => self.next_byte_register(),
Type::Character => self.next_character_register(),
@ -1201,16 +1198,16 @@ impl<'src> Compiler<'src> {
};
let point = Instruction::point(
local_register_index,
Operand::Register(register, r#type.type_code()),
Operand::Register(register, local_type.type_code()),
);
self.emit_instruction(point, r#type, start_position);
self.emit_instruction(point, local_type, start_position);
}
return Ok(());
}
let destination = match r#type {
let destination = match local_type {
Type::Boolean => self.next_boolean_register(),
Type::Byte => self.next_byte_register(),
Type::Character => self.next_character_register(),
@ -1221,10 +1218,10 @@ impl<'src> Compiler<'src> {
};
let point = Instruction::point(
destination,
Operand::Register(local_register_index, r#type.type_code()),
Operand::Register(local_register_index, local_type.type_code()),
);
self.emit_instruction(point, r#type, self.previous_position);
self.emit_instruction(point, local_type, self.previous_position);
Ok(())
}