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

View File

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