2024-09-10 02:57:14 +00:00
|
|
|
use std::fmt::{self, Debug, Display, Formatter};
|
2024-09-07 10:38:12 +00:00
|
|
|
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
2024-09-11 07:10:12 +00:00
|
|
|
use crate::{AnnotatedError, Identifier, Instruction, Span, Value};
|
2024-09-07 10:38:12 +00:00
|
|
|
|
2024-09-12 03:07:20 +00:00
|
|
|
#[derive(Clone)]
|
2024-09-07 10:38:12 +00:00
|
|
|
pub struct Chunk {
|
2024-09-12 13:11:49 +00:00
|
|
|
instructions: Vec<(Instruction, Span)>,
|
2024-09-11 08:22:54 +00:00
|
|
|
constants: Vec<Option<Value>>,
|
2024-09-12 13:11:49 +00:00
|
|
|
locals: Vec<Local>,
|
2024-09-11 07:10:12 +00:00
|
|
|
scope_depth: usize,
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Chunk {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
2024-09-12 13:11:49 +00:00
|
|
|
instructions: Vec::new(),
|
2024-09-07 10:38:12 +00:00
|
|
|
constants: Vec::new(),
|
2024-09-12 13:11:49 +00:00
|
|
|
locals: Vec::new(),
|
2024-09-11 07:10:12 +00:00
|
|
|
scope_depth: 0,
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-07 16:15:47 +00:00
|
|
|
pub fn with_data(
|
2024-09-12 13:11:49 +00:00
|
|
|
instructions: Vec<(Instruction, Span)>,
|
2024-09-07 16:15:47 +00:00
|
|
|
constants: Vec<Value>,
|
2024-09-09 23:23:49 +00:00
|
|
|
identifiers: Vec<Local>,
|
2024-09-07 16:15:47 +00:00
|
|
|
) -> Self {
|
|
|
|
Self {
|
2024-09-12 13:11:49 +00:00
|
|
|
instructions,
|
2024-09-11 08:22:54 +00:00
|
|
|
constants: constants.into_iter().map(Some).collect(),
|
2024-09-12 13:11:49 +00:00
|
|
|
locals: identifiers,
|
2024-09-11 07:10:12 +00:00
|
|
|
scope_depth: 0,
|
2024-09-07 16:15:47 +00:00
|
|
|
}
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn len(&self) -> usize {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.instructions.len()
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_empty(&self) -> bool {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.instructions.is_empty()
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-10 22:19:59 +00:00
|
|
|
pub fn scope_depth(&self) -> usize {
|
2024-09-11 07:10:12 +00:00
|
|
|
self.scope_depth
|
2024-09-10 22:19:59 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn get_instruction(
|
2024-09-12 03:07:20 +00:00
|
|
|
&self,
|
|
|
|
offset: usize,
|
|
|
|
position: Span,
|
|
|
|
) -> Result<&(Instruction, Span), ChunkError> {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.instructions
|
2024-09-07 16:15:47 +00:00
|
|
|
.get(offset)
|
2024-09-10 22:19:59 +00:00
|
|
|
.ok_or(ChunkError::CodeIndexOfBounds { offset, position })
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn push_instruction(&mut self, instruction: Instruction, position: Span) {
|
|
|
|
self.instructions.push((instruction, position));
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn pop_instruction(&mut self) -> Option<(Instruction, Span)> {
|
|
|
|
self.instructions.pop()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_constant(&self, index: usize, position: Span) -> Result<&Value, ChunkError> {
|
2024-09-07 10:38:12 +00:00
|
|
|
self.constants
|
2024-09-12 13:11:49 +00:00
|
|
|
.get(index)
|
2024-09-10 22:19:59 +00:00
|
|
|
.ok_or(ChunkError::ConstantIndexOutOfBounds { index, position })
|
2024-09-11 08:22:54 +00:00
|
|
|
.and_then(|value| {
|
|
|
|
value
|
|
|
|
.as_ref()
|
|
|
|
.ok_or(ChunkError::ConstantAlreadyUsed { index, position })
|
|
|
|
})
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn use_constant(&mut self, index: usize, position: Span) -> Result<Value, ChunkError> {
|
2024-09-11 08:22:54 +00:00
|
|
|
self.constants
|
2024-09-12 13:11:49 +00:00
|
|
|
.get_mut(index)
|
2024-09-12 03:07:20 +00:00
|
|
|
.ok_or_else(|| ChunkError::ConstantIndexOutOfBounds { index, position })?
|
2024-09-11 08:22:54 +00:00
|
|
|
.take()
|
2024-09-12 03:07:20 +00:00
|
|
|
.ok_or(ChunkError::ConstantAlreadyUsed { index, position })
|
2024-09-10 07:42:25 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 03:07:20 +00:00
|
|
|
pub fn push_constant(&mut self, value: Value, position: Span) -> Result<u16, ChunkError> {
|
2024-09-07 10:38:12 +00:00
|
|
|
let starting_length = self.constants.len();
|
|
|
|
|
|
|
|
if starting_length + 1 > (u8::MAX as usize) {
|
2024-09-11 07:10:12 +00:00
|
|
|
Err(ChunkError::ConstantOverflow { position })
|
2024-09-07 10:38:12 +00:00
|
|
|
} else {
|
2024-09-11 08:22:54 +00:00
|
|
|
self.constants.push(Some(value));
|
2024-09-07 10:38:12 +00:00
|
|
|
|
2024-09-12 03:07:20 +00:00
|
|
|
Ok(starting_length as u16)
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-09 23:23:49 +00:00
|
|
|
pub fn contains_identifier(&self, identifier: &Identifier) -> bool {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.locals
|
2024-09-11 07:10:12 +00:00
|
|
|
.iter()
|
|
|
|
.any(|local| &local.identifier == identifier)
|
2024-09-09 23:23:49 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn get_local(&self, index: usize, position: Span) -> Result<&Local, ChunkError> {
|
|
|
|
self.locals
|
2024-09-12 17:03:24 +00:00
|
|
|
.get(index)
|
2024-09-12 13:11:49 +00:00
|
|
|
.ok_or(ChunkError::LocalIndexOutOfBounds { index, position })
|
2024-09-10 22:19:59 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 08:22:54 +00:00
|
|
|
pub fn get_identifier(&self, index: u8) -> Option<&Identifier> {
|
2024-09-12 13:11:49 +00:00
|
|
|
if let Some(local) = self.locals.get(index as usize) {
|
2024-09-11 08:22:54 +00:00
|
|
|
Some(&local.identifier)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2024-09-07 16:15:47 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn get_local_index(
|
2024-09-10 22:19:59 +00:00
|
|
|
&self,
|
|
|
|
identifier: &Identifier,
|
|
|
|
position: Span,
|
2024-09-12 03:07:20 +00:00
|
|
|
) -> Result<u16, ChunkError> {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.locals
|
2024-09-11 07:10:12 +00:00
|
|
|
.iter()
|
|
|
|
.rev()
|
2024-09-11 08:22:54 +00:00
|
|
|
.enumerate()
|
2024-09-11 07:10:12 +00:00
|
|
|
.find_map(|(index, local)| {
|
|
|
|
if &local.identifier == identifier {
|
2024-09-12 03:07:20 +00:00
|
|
|
Some(index as u16)
|
2024-09-11 07:10:12 +00:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
2024-09-10 22:19:59 +00:00
|
|
|
.ok_or(ChunkError::IdentifierNotFound {
|
|
|
|
identifier: identifier.clone(),
|
|
|
|
position,
|
|
|
|
})
|
2024-09-09 23:23:49 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn declare_local(
|
2024-09-11 07:10:12 +00:00
|
|
|
&mut self,
|
|
|
|
identifier: Identifier,
|
|
|
|
position: Span,
|
2024-09-12 03:07:20 +00:00
|
|
|
) -> Result<u16, ChunkError> {
|
2024-09-12 13:11:49 +00:00
|
|
|
let starting_length = self.locals.len();
|
2024-09-07 16:15:47 +00:00
|
|
|
|
|
|
|
if starting_length + 1 > (u8::MAX as usize) {
|
2024-09-11 07:10:12 +00:00
|
|
|
Err(ChunkError::IdentifierOverflow { position })
|
2024-09-07 16:15:47 +00:00
|
|
|
} else {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.locals
|
|
|
|
.push(Local::new(identifier, self.scope_depth, None));
|
2024-09-07 16:15:47 +00:00
|
|
|
|
2024-09-12 03:07:20 +00:00
|
|
|
Ok(starting_length as u16)
|
2024-09-07 16:15:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
pub fn define_local(
|
|
|
|
&mut self,
|
|
|
|
index: usize,
|
|
|
|
value: Value,
|
|
|
|
position: Span,
|
|
|
|
) -> Result<(), ChunkError> {
|
|
|
|
let local = self
|
|
|
|
.locals
|
|
|
|
.get_mut(index)
|
|
|
|
.ok_or_else(|| ChunkError::LocalIndexOutOfBounds { index, position })?;
|
|
|
|
|
|
|
|
local.value = Some(value);
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-09-10 14:44:15 +00:00
|
|
|
pub fn begin_scope(&mut self) {
|
2024-09-11 07:10:12 +00:00
|
|
|
self.scope_depth += 1;
|
2024-09-10 14:44:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn end_scope(&mut self) {
|
2024-09-11 07:10:12 +00:00
|
|
|
self.scope_depth -= 1;
|
2024-09-10 14:44:15 +00:00
|
|
|
}
|
|
|
|
|
2024-09-07 10:38:12 +00:00
|
|
|
pub fn clear(&mut self) {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.instructions.clear();
|
2024-09-07 10:38:12 +00:00
|
|
|
self.constants.clear();
|
2024-09-12 13:11:49 +00:00
|
|
|
self.locals.clear();
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-11 07:10:12 +00:00
|
|
|
pub fn identifiers(&self) -> &[Local] {
|
2024-09-12 13:11:49 +00:00
|
|
|
&self.locals
|
2024-09-11 07:10:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pop_identifier(&mut self) -> Option<Local> {
|
2024-09-12 13:11:49 +00:00
|
|
|
self.locals.pop()
|
2024-09-11 07:10:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
pub fn disassemble<'a>(&self, name: &'a str) -> DisassembledChunk<'a> {
|
|
|
|
DisassembledChunk::new(name, self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Chunk {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Chunk {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}", self.disassemble("Chunk Display"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Debug for Chunk {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}", self.disassemble("Chunk Debug Display"))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for Chunk {}
|
|
|
|
|
|
|
|
impl PartialEq for Chunk {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
self.instructions == other.instructions
|
|
|
|
&& self.constants == other.constants
|
|
|
|
&& self.locals == other.locals
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
|
|
|
|
pub struct Local {
|
|
|
|
pub identifier: Identifier,
|
|
|
|
pub depth: usize,
|
|
|
|
pub value: Option<Value>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Local {
|
|
|
|
pub fn new(identifier: Identifier, depth: usize, value: Option<Value>) -> Self {
|
|
|
|
Self {
|
|
|
|
identifier,
|
|
|
|
depth,
|
|
|
|
value,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct DisassembledChunk<'a> {
|
|
|
|
name: &'a str,
|
|
|
|
body: String,
|
|
|
|
}
|
2024-09-07 10:38:12 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
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", " ")
|
|
|
|
};
|
2024-09-10 14:44:15 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
disassembled.push_str(&instruction_display);
|
2024-09-07 10:38:12 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
let line_length = instruction_display.len();
|
2024-09-10 00:55:00 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
if line_length > longest_line {
|
|
|
|
longest_line = line_length;
|
|
|
|
}
|
2024-09-10 00:55:00 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
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);
|
|
|
|
};
|
2024-09-10 00:55:00 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
push_centered("\n");
|
|
|
|
push_centered(&mut DisassembledChunk::constant_header());
|
|
|
|
|
|
|
|
for (index, value_option) in chunk.constants.iter().enumerate() {
|
2024-09-11 08:22:54 +00:00
|
|
|
let value_kind_display = match value_option {
|
|
|
|
Some(Value::Raw(_)) => "RAW ",
|
|
|
|
Some(Value::Reference(_)) => "REF ",
|
|
|
|
Some(Value::Mutable(_)) => "MUT ",
|
|
|
|
None => "EMPTY",
|
2024-09-10 00:55:00 +00:00
|
|
|
};
|
2024-09-11 08:22:54 +00:00
|
|
|
let value_display = value_option
|
|
|
|
.as_ref()
|
|
|
|
.map(|value| value.to_string())
|
|
|
|
.unwrap_or_else(|| "EMPTY".to_string());
|
2024-09-12 17:03:24 +00:00
|
|
|
let constant_display = format!("{index:<5} {value_kind_display:<4} {value_display:<5}");
|
2024-09-10 00:55:00 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
push_centered(&constant_display);
|
2024-09-10 00:55:00 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
push_centered("\n");
|
|
|
|
push_centered(&mut DisassembledChunk::local_header());
|
2024-09-10 13:26:05 +00:00
|
|
|
|
2024-09-12 13:11:49 +00:00
|
|
|
for (
|
|
|
|
index,
|
|
|
|
Local {
|
|
|
|
identifier,
|
|
|
|
depth,
|
|
|
|
value,
|
|
|
|
},
|
2024-09-12 17:03:24 +00:00
|
|
|
) in chunk.locals.iter().enumerate()
|
2024-09-12 13:11:49 +00:00
|
|
|
{
|
2024-09-12 17:03:24 +00:00
|
|
|
let value_kind_display = match value {
|
|
|
|
Some(Value::Raw(_)) => "RAW ",
|
|
|
|
Some(Value::Reference(_)) => "REF ",
|
|
|
|
Some(Value::Mutable(_)) => "MUT ",
|
|
|
|
None => "EMPTY",
|
|
|
|
};
|
2024-09-12 13:11:49 +00:00
|
|
|
let value_display = value
|
|
|
|
.as_ref()
|
|
|
|
.map(|value| value.to_string())
|
|
|
|
.unwrap_or_else(|| "EMPTY".to_string());
|
2024-09-12 17:03:24 +00:00
|
|
|
let identifier_display = identifier.as_str();
|
|
|
|
let local_display =
|
|
|
|
format!("{index:<5} {identifier_display:<10} {depth:<5} {value_kind_display:<4} {value_display:<5}");
|
2024-09-12 13:11:49 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
push_centered(&local_display);
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
DisassembledChunk {
|
|
|
|
name,
|
|
|
|
body: disassembled,
|
|
|
|
}
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
pub fn to_string_with_width(&self, width: usize) -> String {
|
|
|
|
let mut display = String::new();
|
2024-09-07 10:38:12 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
for line in self.to_string().lines() {
|
|
|
|
display.push_str(&format!("{line:^width$}\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
display
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
fn name_header(&self) -> String {
|
|
|
|
format!("{:^50}\n{:^50}", self.name, "==============")
|
2024-09-07 22:48:01 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
fn instructions_header() -> String {
|
|
|
|
format!(
|
|
|
|
"{:^50}\n{:^50}\n{:<6} {:<16} {:<17} {}\n{} {} {} {}",
|
|
|
|
"Instructions",
|
|
|
|
"------------",
|
|
|
|
"OFFSET",
|
|
|
|
"INSTRUCTION",
|
|
|
|
"INFO",
|
|
|
|
"POSITION",
|
|
|
|
"------",
|
|
|
|
"----------------",
|
|
|
|
"-----------------",
|
|
|
|
"--------"
|
|
|
|
)
|
|
|
|
}
|
2024-09-11 08:22:54 +00:00
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
fn constant_header() -> String {
|
|
|
|
format!(
|
|
|
|
"{:^16}\n{:^16}\n{:<5} {:<4} {}\n{} {} {}",
|
|
|
|
"Constants", "---------", "INDEX", "KIND", "VALUE", "-----", "----", "-----"
|
|
|
|
)
|
2024-09-11 08:22:54 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
fn local_header() -> String {
|
|
|
|
format!(
|
|
|
|
"{:^50}\n{:^50}\n{:<5} {:<10} {:<5} {:<5} {:<5}\n{} {} {} {} {}",
|
|
|
|
"Locals",
|
|
|
|
"------",
|
|
|
|
"INDEX",
|
|
|
|
"IDENTIFIER",
|
|
|
|
"DEPTH",
|
|
|
|
"KIND",
|
|
|
|
"VALUE",
|
|
|
|
"-----",
|
|
|
|
"----------",
|
|
|
|
"-----",
|
|
|
|
"-----",
|
|
|
|
"-----"
|
|
|
|
)
|
|
|
|
}
|
2024-09-11 07:10:12 +00:00
|
|
|
}
|
|
|
|
|
2024-09-12 17:03:24 +00:00
|
|
|
impl Display for DisassembledChunk<'_> {
|
|
|
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
|
|
|
write!(f, "{}\n{}", self.name_header(), self.body)
|
2024-09-12 09:08:55 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-09 23:23:49 +00:00
|
|
|
#[derive(Debug, Clone, PartialEq)]
|
2024-09-07 10:38:12 +00:00
|
|
|
pub enum ChunkError {
|
2024-09-10 22:19:59 +00:00
|
|
|
CodeIndexOfBounds {
|
|
|
|
offset: usize,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-09-11 08:22:54 +00:00
|
|
|
ConstantAlreadyUsed {
|
2024-09-12 13:11:49 +00:00
|
|
|
index: usize,
|
2024-09-11 08:22:54 +00:00
|
|
|
position: Span,
|
|
|
|
},
|
2024-09-11 07:10:12 +00:00
|
|
|
ConstantOverflow {
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-09-10 22:19:59 +00:00
|
|
|
ConstantIndexOutOfBounds {
|
2024-09-12 13:11:49 +00:00
|
|
|
index: usize,
|
2024-09-10 22:19:59 +00:00
|
|
|
position: Span,
|
|
|
|
},
|
2024-09-12 13:11:49 +00:00
|
|
|
LocalIndexOutOfBounds {
|
|
|
|
index: usize,
|
2024-09-11 07:10:12 +00:00
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
IdentifierOverflow {
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-09-10 22:19:59 +00:00
|
|
|
IdentifierNotFound {
|
|
|
|
identifier: Identifier,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AnnotatedError for ChunkError {
|
|
|
|
fn title() -> &'static str {
|
|
|
|
"Chunk Error"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn description(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
ChunkError::CodeIndexOfBounds { .. } => "Code index out of bounds",
|
2024-09-11 08:22:54 +00:00
|
|
|
ChunkError::ConstantAlreadyUsed { .. } => "Constant already used",
|
2024-09-11 07:10:12 +00:00
|
|
|
ChunkError::ConstantOverflow { .. } => "Constant overflow",
|
2024-09-10 22:19:59 +00:00
|
|
|
ChunkError::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds",
|
2024-09-12 13:11:49 +00:00
|
|
|
ChunkError::LocalIndexOutOfBounds { .. } => "Identifier index out of bounds",
|
2024-09-11 07:10:12 +00:00
|
|
|
ChunkError::IdentifierOverflow { .. } => "Identifier overflow",
|
2024-09-10 22:19:59 +00:00
|
|
|
ChunkError::IdentifierNotFound { .. } => "Identifier not found",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn details(&self) -> Option<String> {
|
|
|
|
match self {
|
|
|
|
ChunkError::CodeIndexOfBounds { offset, .. } => Some(format!("Code index: {}", offset)),
|
2024-09-11 08:22:54 +00:00
|
|
|
ChunkError::ConstantAlreadyUsed { index, .. } => {
|
|
|
|
Some(format!("Constant index: {}", index))
|
|
|
|
}
|
2024-09-10 22:19:59 +00:00
|
|
|
ChunkError::ConstantIndexOutOfBounds { index, .. } => {
|
|
|
|
Some(format!("Constant index: {}", index))
|
|
|
|
}
|
2024-09-12 13:11:49 +00:00
|
|
|
ChunkError::LocalIndexOutOfBounds { index, .. } => {
|
2024-09-10 22:19:59 +00:00
|
|
|
Some(format!("Identifier index: {}", index))
|
|
|
|
}
|
|
|
|
ChunkError::IdentifierNotFound { identifier, .. } => {
|
|
|
|
Some(format!("Identifier: {}", identifier))
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn position(&self) -> Span {
|
|
|
|
match self {
|
|
|
|
ChunkError::CodeIndexOfBounds { position, .. } => *position,
|
2024-09-11 08:22:54 +00:00
|
|
|
ChunkError::ConstantAlreadyUsed { position, .. } => *position,
|
2024-09-10 22:19:59 +00:00
|
|
|
ChunkError::ConstantIndexOutOfBounds { position, .. } => *position,
|
|
|
|
ChunkError::IdentifierNotFound { position, .. } => *position,
|
|
|
|
_ => todo!(),
|
|
|
|
}
|
|
|
|
}
|
2024-09-07 10:38:12 +00:00
|
|
|
}
|