Bring back chunk errors
This commit is contained in:
parent
c0b998c0d8
commit
78840cf3e7
@ -37,7 +37,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
env::current_exe,
|
env::current_exe,
|
||||||
fmt::{self, Debug, Display},
|
fmt::{self, Debug, Display, Formatter},
|
||||||
};
|
};
|
||||||
|
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
@ -127,6 +127,12 @@ impl Chunk {
|
|||||||
&mut self.instructions
|
&mut self.instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_instruction(&self, index: usize) -> Result<&(Instruction, Span), ChunkError> {
|
||||||
|
self.instructions
|
||||||
|
.get(index)
|
||||||
|
.ok_or(ChunkError::InstructionIndexOutOfBounds { index })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn locals(&self) -> &Vec<Local> {
|
pub fn locals(&self) -> &Vec<Local> {
|
||||||
&self.locals
|
&self.locals
|
||||||
}
|
}
|
||||||
@ -135,12 +141,32 @@ impl Chunk {
|
|||||||
&mut self.locals
|
&mut self.locals
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_local(&self, index: u8) -> Result<&Local, ChunkError> {
|
||||||
|
self.locals
|
||||||
|
.get(index as usize)
|
||||||
|
.ok_or(ChunkError::LocalIndexOutOfBounds {
|
||||||
|
index: index as usize,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_local_mut(&mut self, index: u8) -> Result<&mut Local, ChunkError> {
|
||||||
|
self.locals
|
||||||
|
.get_mut(index as usize)
|
||||||
|
.ok_or(ChunkError::LocalIndexOutOfBounds {
|
||||||
|
index: index as usize,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn current_scope(&self) -> Scope {
|
pub fn current_scope(&self) -> Scope {
|
||||||
self.current_scope
|
self.current_scope
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_constant(&self, index: u8) -> Option<&Value> {
|
pub fn get_constant(&self, index: u8) -> Result<&Value, ChunkError> {
|
||||||
self.constants.get(index as usize)
|
self.constants
|
||||||
|
.get(index as usize)
|
||||||
|
.ok_or(ChunkError::ConstantIndexOutOfBounds {
|
||||||
|
index: index as usize,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push_or_get_constant(&mut self, value: Value) -> u8 {
|
pub fn push_or_get_constant(&mut self, value: Value) -> u8 {
|
||||||
@ -181,6 +207,14 @@ impl Chunk {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expect_not_poisoned(&self) -> Result<(), ChunkError> {
|
||||||
|
if self.is_poisoned {
|
||||||
|
Err(ChunkError::PoisonedChunk)
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_constant_type(&self, constant_index: u8) -> Option<Type> {
|
pub fn get_constant_type(&self, constant_index: u8) -> Option<Type> {
|
||||||
self.constants
|
self.constants
|
||||||
.get(constant_index as usize)
|
.get(constant_index as usize)
|
||||||
@ -652,3 +686,28 @@ impl<'a> ChunkDisassembler<'a> {
|
|||||||
self.output
|
self.output
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum ChunkError {
|
||||||
|
ConstantIndexOutOfBounds { index: usize },
|
||||||
|
InstructionIndexOutOfBounds { index: usize },
|
||||||
|
LocalIndexOutOfBounds { index: usize },
|
||||||
|
PoisonedChunk,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ChunkError {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
ChunkError::ConstantIndexOutOfBounds { index } => {
|
||||||
|
write!(f, "Constant index {} out of bounds", index)
|
||||||
|
}
|
||||||
|
ChunkError::InstructionIndexOutOfBounds { index } => {
|
||||||
|
write!(f, "Instruction index {} out of bounds", index)
|
||||||
|
}
|
||||||
|
ChunkError::LocalIndexOutOfBounds { index } => {
|
||||||
|
write!(f, "Local index {} out of bounds", index)
|
||||||
|
}
|
||||||
|
ChunkError::PoisonedChunk => write!(f, "Chunk is poisoned"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,7 +14,7 @@ pub mod r#type;
|
|||||||
pub mod value;
|
pub mod value;
|
||||||
pub mod vm;
|
pub mod vm;
|
||||||
|
|
||||||
pub use crate::chunk::{Chunk, ChunkDisassembler, Local, Scope};
|
pub use crate::chunk::{Chunk, ChunkDisassembler, ChunkError, Local, Scope};
|
||||||
pub use crate::dust_error::{AnnotatedError, DustError};
|
pub use crate::dust_error::{AnnotatedError, DustError};
|
||||||
pub use crate::formatter::{format, Formatter};
|
pub use crate::formatter::{format, Formatter};
|
||||||
pub use crate::instruction::Instruction;
|
pub use crate::instruction::Instruction;
|
||||||
|
@ -13,8 +13,9 @@ use std::{
|
|||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
optimize, AnnotatedError, Chunk, DustError, FunctionType, Instruction, LexError, Lexer, Local,
|
optimize, AnnotatedError, Chunk, ChunkError, DustError, FunctionType, Instruction, LexError,
|
||||||
NativeFunction, Operation, Scope, Span, Token, TokenKind, TokenOwned, Type, Value,
|
Lexer, Local, NativeFunction, Operation, Scope, Span, Token, TokenKind, TokenOwned, Type,
|
||||||
|
Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Parses the input and returns a chunk.
|
/// Parses the input and returns a chunk.
|
||||||
@ -127,13 +128,10 @@ impl<'src> Parser<'src> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_local(&self, index: u8) -> Result<&Local, ParseError> {
|
fn get_local(&self, index: u8) -> Result<&Local, ParseError> {
|
||||||
let index = index as usize;
|
|
||||||
|
|
||||||
self.chunk
|
self.chunk
|
||||||
.locals()
|
.get_local(index)
|
||||||
.get(index)
|
.map_err(|error| ParseError::Chunk {
|
||||||
.ok_or(ParseError::LocalIndexOutOfBounds {
|
error,
|
||||||
index,
|
|
||||||
position: self.current_position,
|
position: self.current_position,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1882,7 +1880,7 @@ impl From<&Token<'_>> for ParseRule<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum ParseError {
|
pub enum ParseError {
|
||||||
// Token errors
|
// Token errors
|
||||||
ExpectedToken {
|
ExpectedToken {
|
||||||
@ -1934,19 +1932,11 @@ pub enum ParseError {
|
|||||||
position: Span,
|
position: Span,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Chunk errors
|
|
||||||
LocalIndexOutOfBounds {
|
|
||||||
index: usize,
|
|
||||||
position: Span,
|
|
||||||
},
|
|
||||||
RegisterOverflow {
|
|
||||||
position: Span,
|
|
||||||
},
|
|
||||||
RegisterUnderflow {
|
|
||||||
position: Span,
|
|
||||||
},
|
|
||||||
|
|
||||||
// Wrappers around foreign errors
|
// Wrappers around foreign errors
|
||||||
|
Chunk {
|
||||||
|
error: ChunkError,
|
||||||
|
position: Span,
|
||||||
|
},
|
||||||
Lex(LexError),
|
Lex(LexError),
|
||||||
ParseFloatError {
|
ParseFloatError {
|
||||||
error: ParseFloatError,
|
error: ParseFloatError,
|
||||||
@ -1967,17 +1957,15 @@ impl AnnotatedError for ParseError {
|
|||||||
match self {
|
match self {
|
||||||
Self::CannotChainComparison { .. } => "Cannot chain comparison",
|
Self::CannotChainComparison { .. } => "Cannot chain comparison",
|
||||||
Self::CannotMutateImmutableVariable { .. } => "Cannot mutate immutable variable",
|
Self::CannotMutateImmutableVariable { .. } => "Cannot mutate immutable variable",
|
||||||
|
Self::Chunk { .. } => "Chunk error",
|
||||||
Self::ExpectedExpression { .. } => "Expected an expression",
|
Self::ExpectedExpression { .. } => "Expected an expression",
|
||||||
Self::ExpectedMutableVariable { .. } => "Expected a mutable variable",
|
Self::ExpectedMutableVariable { .. } => "Expected a mutable variable",
|
||||||
Self::ExpectedToken { .. } => "Expected a specific token",
|
Self::ExpectedToken { .. } => "Expected a specific token",
|
||||||
Self::ExpectedTokenMultiple { .. } => "Expected one of multiple tokens",
|
Self::ExpectedTokenMultiple { .. } => "Expected one of multiple tokens",
|
||||||
Self::InvalidAssignmentTarget { .. } => "Invalid assignment target",
|
Self::InvalidAssignmentTarget { .. } => "Invalid assignment target",
|
||||||
Self::Lex(error) => error.description(),
|
Self::Lex(error) => error.description(),
|
||||||
Self::LocalIndexOutOfBounds { .. } => "Local index out of bounds",
|
|
||||||
Self::ParseFloatError { .. } => "Failed to parse float",
|
Self::ParseFloatError { .. } => "Failed to parse float",
|
||||||
Self::ParseIntError { .. } => "Failed to parse integer",
|
Self::ParseIntError { .. } => "Failed to parse integer",
|
||||||
Self::RegisterOverflow { .. } => "Register overflow",
|
|
||||||
Self::RegisterUnderflow { .. } => "Register underflow",
|
|
||||||
Self::UndeclaredVariable { .. } => "Undeclared variable",
|
Self::UndeclaredVariable { .. } => "Undeclared variable",
|
||||||
Self::UnexpectedReturn { .. } => "Unexpected return",
|
Self::UnexpectedReturn { .. } => "Unexpected return",
|
||||||
Self::VariableOutOfScope { .. } => "Variable out of scope",
|
Self::VariableOutOfScope { .. } => "Variable out of scope",
|
||||||
@ -1992,6 +1980,7 @@ impl AnnotatedError for ParseError {
|
|||||||
Self::CannotMutateImmutableVariable { identifier, .. } => {
|
Self::CannotMutateImmutableVariable { identifier, .. } => {
|
||||||
Some(format!("Cannot mutate immutable variable {identifier}"))
|
Some(format!("Cannot mutate immutable variable {identifier}"))
|
||||||
}
|
}
|
||||||
|
Self::Chunk { error, .. } => Some(error.to_string()),
|
||||||
Self::ExpectedExpression { found, .. } => Some(format!("Found {found}")),
|
Self::ExpectedExpression { found, .. } => Some(format!("Found {found}")),
|
||||||
Self::ExpectedToken {
|
Self::ExpectedToken {
|
||||||
expected, found, ..
|
expected, found, ..
|
||||||
@ -2024,13 +2013,9 @@ impl AnnotatedError for ParseError {
|
|||||||
Some(format!("Invalid assignment target, found {found}"))
|
Some(format!("Invalid assignment target, found {found}"))
|
||||||
}
|
}
|
||||||
Self::Lex(error) => error.details(),
|
Self::Lex(error) => error.details(),
|
||||||
Self::LocalIndexOutOfBounds { index, .. } => {
|
|
||||||
Some(format!("Local index {index} out of bounds"))
|
|
||||||
}
|
|
||||||
Self::ParseFloatError { error, .. } => Some(error.to_string()),
|
Self::ParseFloatError { error, .. } => Some(error.to_string()),
|
||||||
Self::ParseIntError { error, .. } => Some(error.to_string()),
|
Self::ParseIntError { error, .. } => Some(error.to_string()),
|
||||||
Self::RegisterOverflow { .. } => None,
|
|
||||||
Self::RegisterUnderflow { .. } => None,
|
|
||||||
Self::UndeclaredVariable { identifier, .. } => {
|
Self::UndeclaredVariable { identifier, .. } => {
|
||||||
Some(format!("Undeclared variable {identifier}"))
|
Some(format!("Undeclared variable {identifier}"))
|
||||||
}
|
}
|
||||||
@ -2045,17 +2030,15 @@ impl AnnotatedError for ParseError {
|
|||||||
match self {
|
match self {
|
||||||
Self::CannotChainComparison { position } => *position,
|
Self::CannotChainComparison { position } => *position,
|
||||||
Self::CannotMutateImmutableVariable { position, .. } => *position,
|
Self::CannotMutateImmutableVariable { position, .. } => *position,
|
||||||
|
Self::Chunk { position, .. } => *position,
|
||||||
Self::ExpectedExpression { position, .. } => *position,
|
Self::ExpectedExpression { position, .. } => *position,
|
||||||
Self::ExpectedMutableVariable { position, .. } => *position,
|
Self::ExpectedMutableVariable { position, .. } => *position,
|
||||||
Self::ExpectedToken { position, .. } => *position,
|
Self::ExpectedToken { position, .. } => *position,
|
||||||
Self::ExpectedTokenMultiple { position, .. } => *position,
|
Self::ExpectedTokenMultiple { position, .. } => *position,
|
||||||
Self::InvalidAssignmentTarget { position, .. } => *position,
|
Self::InvalidAssignmentTarget { position, .. } => *position,
|
||||||
Self::Lex(error) => error.position(),
|
Self::Lex(error) => error.position(),
|
||||||
Self::LocalIndexOutOfBounds { position, .. } => *position,
|
|
||||||
Self::ParseFloatError { position, .. } => *position,
|
Self::ParseFloatError { position, .. } => *position,
|
||||||
Self::ParseIntError { position, .. } => *position,
|
Self::ParseIntError { position, .. } => *position,
|
||||||
Self::RegisterOverflow { position } => *position,
|
|
||||||
Self::RegisterUnderflow { position } => *position,
|
|
||||||
Self::UndeclaredVariable { position, .. } => *position,
|
Self::UndeclaredVariable { position, .. } => *position,
|
||||||
Self::UnexpectedReturn { position } => *position,
|
Self::UnexpectedReturn { position } => *position,
|
||||||
Self::VariableOutOfScope { position, .. } => *position,
|
Self::VariableOutOfScope { position, .. } => *position,
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
use std::{cmp::Ordering, mem::replace};
|
use std::{cmp::Ordering, mem::replace};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parse, value::ConcreteValue, AnnotatedError, Chunk, DustError, FunctionType, Instruction,
|
parse, value::ConcreteValue, AnnotatedError, Chunk, ChunkError, DustError, FunctionType,
|
||||||
Local, NativeFunction, NativeFunctionError, Operation, Span, Type, Value, ValueError,
|
Instruction, Local, NativeFunction, NativeFunctionError, Operation, Span, Type, Value,
|
||||||
|
ValueError,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
pub fn run(source: &str) -> Result<Option<Value>, DustError> {
|
||||||
@ -45,22 +46,12 @@ impl Vm {
|
|||||||
position: Span,
|
position: Span,
|
||||||
) -> Result<(&Value, &Value), VmError> {
|
) -> Result<(&Value, &Value), VmError> {
|
||||||
let left = if instruction.b_is_constant() {
|
let left = if instruction.b_is_constant() {
|
||||||
vm.chunk.get_constant(instruction.b()).ok_or_else(|| {
|
vm.get_constant(instruction.b(), position)?
|
||||||
VmError::ConstantIndexOutOfBounds {
|
|
||||||
index: instruction.b() as usize,
|
|
||||||
position,
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
} else {
|
} else {
|
||||||
vm.get_register(instruction.b(), position)?
|
vm.get_register(instruction.b(), position)?
|
||||||
};
|
};
|
||||||
let right = if instruction.c_is_constant() {
|
let right = if instruction.c_is_constant() {
|
||||||
vm.chunk.get_constant(instruction.c()).ok_or_else(|| {
|
vm.get_constant(instruction.c(), position)?
|
||||||
VmError::ConstantIndexOutOfBounds {
|
|
||||||
index: instruction.c() as usize,
|
|
||||||
position,
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
} else {
|
} else {
|
||||||
vm.get_register(instruction.c(), position)?
|
vm.get_register(instruction.c(), position)?
|
||||||
};
|
};
|
||||||
@ -336,12 +327,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
Operation::Negate => {
|
Operation::Negate => {
|
||||||
let value = if instruction.b_is_constant() {
|
let value = if instruction.b_is_constant() {
|
||||||
self.chunk.get_constant(instruction.b()).ok_or_else(|| {
|
self.get_constant(instruction.b(), position)?
|
||||||
VmError::ConstantIndexOutOfBounds {
|
|
||||||
index: instruction.b() as usize,
|
|
||||||
position,
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
} else {
|
} else {
|
||||||
self.get_register(instruction.b(), position)?
|
self.get_register(instruction.b(), position)?
|
||||||
};
|
};
|
||||||
@ -353,12 +339,7 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
Operation::Not => {
|
Operation::Not => {
|
||||||
let value = if instruction.b_is_constant() {
|
let value = if instruction.b_is_constant() {
|
||||||
self.chunk.get_constant(instruction.b()).ok_or_else(|| {
|
self.get_constant(instruction.b(), position)?
|
||||||
VmError::ConstantIndexOutOfBounds {
|
|
||||||
index: instruction.b() as usize,
|
|
||||||
position,
|
|
||||||
}
|
|
||||||
})?
|
|
||||||
} else {
|
} else {
|
||||||
self.get_register(instruction.b(), position)?
|
self.get_register(instruction.b(), position)?
|
||||||
};
|
};
|
||||||
@ -588,6 +569,12 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_constant(&self, index: u8, position: Span) -> Result<&Value, VmError> {
|
||||||
|
self.chunk
|
||||||
|
.get_constant(index)
|
||||||
|
.map_err(|error| VmError::Chunk { error, position })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_register(&self, index: u8, position: Span) -> Result<&Value, VmError> {
|
pub fn get_register(&self, index: u8, position: Span) -> Result<&Value, VmError> {
|
||||||
let index = index as usize;
|
let index = index as usize;
|
||||||
let register = self
|
let register = self
|
||||||
@ -598,13 +585,7 @@ impl Vm {
|
|||||||
match register {
|
match register {
|
||||||
Register::Value(value) => Ok(value),
|
Register::Value(value) => Ok(value),
|
||||||
Register::Pointer(register_index) => self.get_register(*register_index, position),
|
Register::Pointer(register_index) => self.get_register(*register_index, position),
|
||||||
Register::Constant(constant_index) => self
|
Register::Constant(constant_index) => self.get_constant(*constant_index, position),
|
||||||
.chunk
|
|
||||||
.get_constant(*constant_index)
|
|
||||||
.ok_or_else(|| VmError::ConstantIndexOutOfBounds {
|
|
||||||
index: *constant_index as usize,
|
|
||||||
position,
|
|
||||||
}),
|
|
||||||
Register::Empty => Err(VmError::EmptyRegister { index, position }),
|
Register::Empty => Err(VmError::EmptyRegister { index, position }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -640,24 +621,19 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn read(&mut self, position: Span) -> Result<&(Instruction, Span), VmError> {
|
fn read(&mut self, position: Span) -> Result<&(Instruction, Span), VmError> {
|
||||||
if self.chunk.is_poisoned {
|
self.chunk
|
||||||
return Err(VmError::PoisonedChunk { position });
|
.expect_not_poisoned()
|
||||||
}
|
.map_err(|error| VmError::Chunk { error, position })?;
|
||||||
|
|
||||||
if self.ip >= self.chunk.len() {
|
let max_ip = self.chunk.len() - 1;
|
||||||
self.ip = self.chunk.len() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let current = self.chunk.instructions().get(self.ip).ok_or_else(|| {
|
|
||||||
VmError::InstructionIndexOutOfBounds {
|
|
||||||
index: self.ip,
|
|
||||||
position,
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
|
if self.ip > max_ip {
|
||||||
|
return self.get_instruction(max_ip, position);
|
||||||
|
} else {
|
||||||
self.ip += 1;
|
self.ip += 1;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(current)
|
self.get_instruction(self.ip - 1, position)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn define_local(
|
fn define_local(
|
||||||
@ -668,12 +644,8 @@ impl Vm {
|
|||||||
) -> Result<(), VmError> {
|
) -> Result<(), VmError> {
|
||||||
let local = self
|
let local = self
|
||||||
.chunk
|
.chunk
|
||||||
.locals_mut()
|
.get_local_mut(local_index)
|
||||||
.get_mut(local_index as usize)
|
.map_err(|error| VmError::Chunk { error, position })?;
|
||||||
.ok_or_else(|| VmError::LocalIndexOutOfBounds {
|
|
||||||
index: local_index as usize,
|
|
||||||
position,
|
|
||||||
})?;
|
|
||||||
|
|
||||||
log::debug!("Define local L{}", local_index);
|
log::debug!("Define local L{}", local_index);
|
||||||
|
|
||||||
@ -683,15 +655,9 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_local(&self, local_index: u8, position: Span) -> Result<&Local, VmError> {
|
fn get_local(&self, local_index: u8, position: Span) -> Result<&Local, VmError> {
|
||||||
let local_index = local_index as usize;
|
|
||||||
|
|
||||||
self.chunk
|
self.chunk
|
||||||
.locals()
|
.get_local(local_index)
|
||||||
.get(local_index)
|
.map_err(|error| VmError::Chunk { error, position })
|
||||||
.ok_or_else(|| VmError::LocalIndexOutOfBounds {
|
|
||||||
index: local_index,
|
|
||||||
position,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_instruction(
|
fn get_instruction(
|
||||||
@ -700,9 +666,8 @@ impl Vm {
|
|||||||
position: Span,
|
position: Span,
|
||||||
) -> Result<&(Instruction, Span), VmError> {
|
) -> Result<&(Instruction, Span), VmError> {
|
||||||
self.chunk
|
self.chunk
|
||||||
.instructions()
|
.get_instruction(index)
|
||||||
.get(index)
|
.map_err(|error| VmError::Chunk { error, position })
|
||||||
.ok_or_else(|| VmError::InstructionIndexOutOfBounds { index, position })
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -714,7 +679,7 @@ enum Register {
|
|||||||
Constant(u8),
|
Constant(u8),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub enum VmError {
|
pub enum VmError {
|
||||||
// Stack errors
|
// Stack errors
|
||||||
StackOverflow { position: Span },
|
StackOverflow { position: Span },
|
||||||
@ -724,17 +689,12 @@ pub enum VmError {
|
|||||||
EmptyRegister { index: usize, position: Span },
|
EmptyRegister { index: usize, position: Span },
|
||||||
RegisterIndexOutOfBounds { index: usize, position: Span },
|
RegisterIndexOutOfBounds { index: usize, position: Span },
|
||||||
|
|
||||||
// Chunk errors
|
|
||||||
ConstantIndexOutOfBounds { index: usize, position: Span },
|
|
||||||
InstructionIndexOutOfBounds { index: usize, position: Span },
|
|
||||||
LocalIndexOutOfBounds { index: usize, position: Span },
|
|
||||||
PoisonedChunk { position: Span },
|
|
||||||
|
|
||||||
// Execution errors
|
// Execution errors
|
||||||
ExpectedBoolean { found: Value, position: Span },
|
ExpectedBoolean { found: Value, position: Span },
|
||||||
ExpectedFunction { found: Value, position: Span },
|
ExpectedFunction { found: Value, position: Span },
|
||||||
|
|
||||||
// Wrappers for foreign errors
|
// Wrappers for foreign errors
|
||||||
|
Chunk { error: ChunkError, position: Span },
|
||||||
NativeFunction(NativeFunctionError),
|
NativeFunction(NativeFunctionError),
|
||||||
Value { error: ValueError, position: Span },
|
Value { error: ValueError, position: Span },
|
||||||
}
|
}
|
||||||
@ -746,14 +706,11 @@ impl AnnotatedError for VmError {
|
|||||||
|
|
||||||
fn description(&self) -> &'static str {
|
fn description(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
Self::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds",
|
Self::Chunk { .. } => "Chunk error",
|
||||||
Self::EmptyRegister { .. } => "Empty register",
|
Self::EmptyRegister { .. } => "Empty register",
|
||||||
Self::ExpectedBoolean { .. } => "Expected boolean",
|
Self::ExpectedBoolean { .. } => "Expected boolean",
|
||||||
Self::ExpectedFunction { .. } => "Expected function",
|
Self::ExpectedFunction { .. } => "Expected function",
|
||||||
Self::InstructionIndexOutOfBounds { .. } => "Instruction index out of bounds",
|
|
||||||
Self::LocalIndexOutOfBounds { .. } => "Local index out of bounds",
|
|
||||||
Self::NativeFunction(error) => error.description(),
|
Self::NativeFunction(error) => error.description(),
|
||||||
Self::PoisonedChunk { .. } => "Poisoned chunk",
|
|
||||||
Self::RegisterIndexOutOfBounds { .. } => "Register index out of bounds",
|
Self::RegisterIndexOutOfBounds { .. } => "Register index out of bounds",
|
||||||
Self::StackOverflow { .. } => "Stack overflow",
|
Self::StackOverflow { .. } => "Stack overflow",
|
||||||
Self::StackUnderflow { .. } => "Stack underflow",
|
Self::StackUnderflow { .. } => "Stack underflow",
|
||||||
@ -763,20 +720,12 @@ impl AnnotatedError for VmError {
|
|||||||
|
|
||||||
fn details(&self) -> Option<String> {
|
fn details(&self) -> Option<String> {
|
||||||
match self {
|
match self {
|
||||||
Self::ConstantIndexOutOfBounds { index, .. } => {
|
Self::Chunk { error, .. } => Some(error.to_string()),
|
||||||
Some(format!("Constant C{index} does not exist"))
|
|
||||||
}
|
|
||||||
Self::EmptyRegister { index, .. } => Some(format!("Register R{index} is empty")),
|
Self::EmptyRegister { index, .. } => Some(format!("Register R{index} is empty")),
|
||||||
Self::ExpectedFunction { found, .. } => Some(format!("{found} is not a function")),
|
Self::ExpectedFunction { found, .. } => Some(format!("{found} is not a function")),
|
||||||
Self::RegisterIndexOutOfBounds { index, .. } => {
|
Self::RegisterIndexOutOfBounds { index, .. } => {
|
||||||
Some(format!("Register {index} does not exist"))
|
Some(format!("Register {index} does not exist"))
|
||||||
}
|
}
|
||||||
Self::InstructionIndexOutOfBounds { index, .. } => {
|
|
||||||
Some(format!("Instruction {index} does not exist"))
|
|
||||||
}
|
|
||||||
Self::LocalIndexOutOfBounds { index, .. } => {
|
|
||||||
Some(format!("Local L{index} does not exist"))
|
|
||||||
}
|
|
||||||
Self::NativeFunction(error) => error.details(),
|
Self::NativeFunction(error) => error.details(),
|
||||||
Self::Value { error, .. } => Some(error.to_string()),
|
Self::Value { error, .. } => Some(error.to_string()),
|
||||||
_ => None,
|
_ => None,
|
||||||
@ -785,14 +734,11 @@ impl AnnotatedError for VmError {
|
|||||||
|
|
||||||
fn position(&self) -> Span {
|
fn position(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Self::ConstantIndexOutOfBounds { position, .. } => *position,
|
Self::Chunk { position, .. } => *position,
|
||||||
Self::EmptyRegister { position, .. } => *position,
|
Self::EmptyRegister { position, .. } => *position,
|
||||||
Self::ExpectedBoolean { position, .. } => *position,
|
Self::ExpectedBoolean { position, .. } => *position,
|
||||||
Self::ExpectedFunction { position, .. } => *position,
|
Self::ExpectedFunction { position, .. } => *position,
|
||||||
Self::InstructionIndexOutOfBounds { position, .. } => *position,
|
|
||||||
Self::LocalIndexOutOfBounds { position, .. } => *position,
|
|
||||||
Self::NativeFunction(error) => error.position(),
|
Self::NativeFunction(error) => error.position(),
|
||||||
Self::PoisonedChunk { position } => *position,
|
|
||||||
Self::RegisterIndexOutOfBounds { position, .. } => *position,
|
Self::RegisterIndexOutOfBounds { position, .. } => *position,
|
||||||
Self::StackOverflow { position } => *position,
|
Self::StackOverflow { position } => *position,
|
||||||
Self::StackUnderflow { position } => *position,
|
Self::StackUnderflow { position } => *position,
|
||||||
|
Loading…
Reference in New Issue
Block a user