2024-12-10 10:03:11 -05:00
|
|
|
use std::num::{ParseFloatError, ParseIntError};
|
|
|
|
|
|
|
|
use smallvec::{smallvec, SmallVec};
|
|
|
|
|
|
|
|
use crate::{AnnotatedError, LexError, Scope, Span, TokenKind, TokenOwned, Type, TypeConflict};
|
|
|
|
|
|
|
|
/// Compilation errors
|
|
|
|
#[derive(Clone, Debug, PartialEq)]
|
|
|
|
pub enum CompileError {
|
|
|
|
// Token errors
|
|
|
|
ExpectedToken {
|
|
|
|
expected: TokenKind,
|
|
|
|
found: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
ExpectedTokenMultiple {
|
|
|
|
expected: &'static [TokenKind],
|
|
|
|
found: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Parsing errors
|
2024-12-17 16:31:32 -05:00
|
|
|
ComparisonChain {
|
2024-12-10 10:03:11 -05:00
|
|
|
position: Span,
|
|
|
|
},
|
2024-12-10 16:04:36 -05:00
|
|
|
ExpectedBoolean {
|
|
|
|
found: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
2024-12-10 10:03:11 -05:00
|
|
|
ExpectedExpression {
|
|
|
|
found: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
ExpectedFunction {
|
|
|
|
found: TokenOwned,
|
|
|
|
actual_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
ExpectedFunctionType {
|
|
|
|
found: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
InvalidAssignmentTarget {
|
|
|
|
found: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
UnexpectedReturn {
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Variable errors
|
|
|
|
CannotMutateImmutableVariable {
|
|
|
|
identifier: String,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
ExpectedMutableVariable {
|
|
|
|
found: TokenOwned,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
UndeclaredVariable {
|
|
|
|
identifier: String,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
VariableOutOfScope {
|
|
|
|
identifier: String,
|
|
|
|
variable_scope: Scope,
|
|
|
|
access_scope: Scope,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Type errors
|
|
|
|
CannotAddType {
|
|
|
|
argument_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotAddArguments {
|
|
|
|
left_type: Type,
|
|
|
|
left_position: Span,
|
|
|
|
right_type: Type,
|
|
|
|
right_position: Span,
|
|
|
|
},
|
|
|
|
CannotDivideType {
|
|
|
|
argument_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotDivideArguments {
|
|
|
|
left_type: Type,
|
|
|
|
right_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotModuloType {
|
|
|
|
argument_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotModuloArguments {
|
|
|
|
left_type: Type,
|
|
|
|
right_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotMultiplyType {
|
|
|
|
argument_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotMultiplyArguments {
|
|
|
|
left_type: Type,
|
|
|
|
right_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotSubtractType {
|
|
|
|
argument_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotSubtractArguments {
|
|
|
|
left_type: Type,
|
|
|
|
right_type: Type,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotResolveRegisterType {
|
|
|
|
register_index: usize,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
CannotResolveVariableType {
|
|
|
|
identifier: String,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
IfElseBranchMismatch {
|
|
|
|
conflict: TypeConflict,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
IfMissingElse {
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
ListItemTypeConflict {
|
|
|
|
conflict: TypeConflict,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
ReturnTypeConflict {
|
|
|
|
conflict: TypeConflict,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Chunk errors
|
|
|
|
ConstantIndexOutOfBounds {
|
|
|
|
index: usize,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
InstructionIndexOutOfBounds {
|
|
|
|
index: usize,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
LocalIndexOutOfBounds {
|
|
|
|
index: usize,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
|
|
|
|
// Wrappers around foreign errors
|
|
|
|
Lex(LexError),
|
|
|
|
ParseFloatError {
|
|
|
|
error: ParseFloatError,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
ParseIntError {
|
|
|
|
error: ParseIntError,
|
|
|
|
position: Span,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CompileError {}
|
|
|
|
|
|
|
|
impl AnnotatedError for CompileError {
|
|
|
|
fn title() -> &'static str {
|
|
|
|
"Compilation Error"
|
|
|
|
}
|
|
|
|
|
|
|
|
fn description(&self) -> &'static str {
|
|
|
|
match self {
|
|
|
|
Self::CannotAddArguments { .. } => "Cannot add these types",
|
|
|
|
Self::CannotAddType { .. } => "Cannot add to this type",
|
2024-12-17 16:31:32 -05:00
|
|
|
Self::ComparisonChain { .. } => "Cannot chain comparison operations",
|
2024-12-10 10:03:11 -05:00
|
|
|
Self::CannotDivideArguments { .. } => "Cannot divide these types",
|
|
|
|
Self::CannotDivideType { .. } => "Cannot divide this type",
|
|
|
|
Self::CannotModuloArguments { .. } => "Cannot modulo these types",
|
|
|
|
Self::CannotModuloType { .. } => "Cannot modulo this type",
|
|
|
|
Self::CannotMutateImmutableVariable { .. } => "Cannot mutate immutable variable",
|
|
|
|
Self::CannotMultiplyArguments { .. } => "Cannot multiply these types",
|
|
|
|
Self::CannotMultiplyType { .. } => "Cannot multiply this type",
|
|
|
|
Self::CannotResolveRegisterType { .. } => "Cannot resolve register type",
|
|
|
|
Self::CannotResolveVariableType { .. } => "Cannot resolve type",
|
|
|
|
Self::CannotSubtractType { .. } => "Cannot subtract from this type",
|
|
|
|
Self::CannotSubtractArguments { .. } => "Cannot subtract these types",
|
|
|
|
Self::ConstantIndexOutOfBounds { .. } => "Constant index out of bounds",
|
2024-12-10 16:04:36 -05:00
|
|
|
Self::ExpectedBoolean { .. } => "Expected a boolean",
|
2024-12-10 10:03:11 -05:00
|
|
|
Self::ExpectedExpression { .. } => "Expected an expression",
|
|
|
|
Self::ExpectedFunction { .. } => "Expected a function",
|
|
|
|
Self::ExpectedFunctionType { .. } => "Expected a function type",
|
|
|
|
Self::ExpectedMutableVariable { .. } => "Expected a mutable variable",
|
|
|
|
Self::ExpectedToken { .. } => "Expected a specific token",
|
|
|
|
Self::ExpectedTokenMultiple { .. } => "Expected one of multiple tokens",
|
|
|
|
Self::IfElseBranchMismatch { .. } => "Type mismatch in if/else branches",
|
|
|
|
Self::IfMissingElse { .. } => "If statement missing else branch",
|
|
|
|
Self::InstructionIndexOutOfBounds { .. } => "Instruction index out of bounds",
|
|
|
|
Self::InvalidAssignmentTarget { .. } => "Invalid assignment target",
|
|
|
|
Self::Lex(error) => error.description(),
|
|
|
|
Self::ListItemTypeConflict { .. } => "List item type conflict",
|
|
|
|
Self::LocalIndexOutOfBounds { .. } => "Local index out of bounds",
|
|
|
|
Self::ParseFloatError { .. } => "Failed to parse float",
|
|
|
|
Self::ParseIntError { .. } => "Failed to parse integer",
|
|
|
|
Self::ReturnTypeConflict { .. } => "Return type conflict",
|
|
|
|
Self::UndeclaredVariable { .. } => "Undeclared variable",
|
|
|
|
Self::UnexpectedReturn { .. } => "Unexpected return",
|
|
|
|
Self::VariableOutOfScope { .. } => "Variable out of scope",
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn detail_snippets(&self) -> SmallVec<[(String, Span); 2]> {
|
|
|
|
match self {
|
|
|
|
Self::CannotAddArguments {
|
|
|
|
left_type,
|
|
|
|
left_position,
|
|
|
|
right_type,
|
|
|
|
right_position,
|
|
|
|
} => {
|
|
|
|
smallvec![
|
|
|
|
(
|
|
|
|
format!("A value of type \"{left_type}\" was used here."),
|
|
|
|
*left_position
|
|
|
|
),
|
|
|
|
(
|
|
|
|
format!("A value of type \"{right_type}\" was used here."),
|
|
|
|
*right_position
|
|
|
|
)
|
|
|
|
]
|
|
|
|
}
|
2024-12-17 07:10:47 -05:00
|
|
|
_ => SmallVec::new(),
|
2024-12-10 10:03:11 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn help_snippets(&self) -> SmallVec<[(String, Span); 2]> {
|
|
|
|
match self {
|
|
|
|
Self::CannotAddArguments {
|
|
|
|
left_type,
|
|
|
|
left_position,
|
|
|
|
right_type,
|
|
|
|
right_position,
|
|
|
|
} => {
|
|
|
|
smallvec![(
|
|
|
|
format!("Type \"{left_type}\" cannot be added to type \"{right_type}\". Try converting one of the values to the other type."),
|
|
|
|
Span(left_position.0, right_position.1)
|
|
|
|
)]
|
|
|
|
}
|
2024-12-17 07:10:47 -05:00
|
|
|
_ => SmallVec::new(),
|
2024-12-10 10:03:11 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<LexError> for CompileError {
|
|
|
|
fn from(error: LexError) -> Self {
|
|
|
|
Self::Lex(error)
|
|
|
|
}
|
|
|
|
}
|