Store types in locals; Fix local disassembly
This commit is contained in:
parent
25b4230aa4
commit
820ead0c02
@ -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)?;
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user