233 lines
6.2 KiB
Rust
233 lines
6.2 KiB
Rust
//! Error types for the semantic analysis phase of the compiler.
|
|
|
|
#![allow(missing_docs)]
|
|
|
|
use std::fmt::Display;
|
|
|
|
use crate::{
|
|
base::{
|
|
log::{Message, Severity, SourceCodeDisplay},
|
|
source_file::{SourceElement as _, Span},
|
|
},
|
|
lexical::token::StringLiteral,
|
|
syntax::syntax_tree::expression::Expression,
|
|
transpile::error::{
|
|
AssignmentError, IllegalIndexing, MismatchedTypes, MissingFunctionDeclaration,
|
|
UnknownIdentifier,
|
|
},
|
|
};
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, thiserror::Error)]
|
|
#[allow(missing_docs)]
|
|
pub enum Error {
|
|
#[error(transparent)]
|
|
MissingFunctionDeclaration(#[from] MissingFunctionDeclaration),
|
|
#[error(transparent)]
|
|
UnexpectedExpression(#[from] UnexpectedExpression),
|
|
#[error(transparent)]
|
|
ConflictingFunctionNames(#[from] ConflictingFunctionNames),
|
|
#[error(transparent)]
|
|
InvalidNamespaceName(#[from] InvalidNamespaceName),
|
|
#[error(transparent)]
|
|
UnresolvedMacroUsage(#[from] UnresolvedMacroUsage),
|
|
#[error(transparent)]
|
|
IncompatibleFunctionAnnotation(#[from] IncompatibleFunctionAnnotation),
|
|
#[error(transparent)]
|
|
IllegalIndexing(#[from] IllegalIndexing),
|
|
#[error(transparent)]
|
|
MismatchedTypes(#[from] MismatchedTypes),
|
|
#[error(transparent)]
|
|
UnknownIdentifier(#[from] UnknownIdentifier),
|
|
#[error(transparent)]
|
|
AssignmentError(#[from] AssignmentError),
|
|
#[error("Lua is disabled, but a Lua function was used.")]
|
|
LuaDisabled,
|
|
#[error("Other: {0}")]
|
|
Other(String),
|
|
}
|
|
|
|
/// An error that occurs when a function declaration is missing.
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct UnexpectedExpression(pub Expression);
|
|
|
|
impl Display for UnexpectedExpression {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
Message::new(Severity::Error, "encountered unexpected expression")
|
|
)?;
|
|
|
|
write!(
|
|
f,
|
|
"\n{}",
|
|
SourceCodeDisplay::new(&self.0.span(), Option::<u8>::None)
|
|
)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for UnexpectedExpression {}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct ConflictingFunctionNames {
|
|
pub definition: Span,
|
|
pub name: String,
|
|
}
|
|
|
|
impl Display for ConflictingFunctionNames {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
Message::new(
|
|
Severity::Error,
|
|
format!("the following function declaration conflicts with an existing function with name `{}`", self.name)
|
|
)
|
|
)?;
|
|
|
|
write!(
|
|
f,
|
|
"\n{}",
|
|
SourceCodeDisplay::new(&self.definition, Option::<u8>::None)
|
|
)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for ConflictingFunctionNames {}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct InvalidNamespaceName {
|
|
pub name: StringLiteral,
|
|
pub invalid_chars: String,
|
|
}
|
|
|
|
impl Display for InvalidNamespaceName {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
Message::new(
|
|
Severity::Error,
|
|
format!(
|
|
"Invalid characters in namespace `{}`. The following characters are not allowed in namespace definitions: `{}`",
|
|
self.name.str_content(),
|
|
self.invalid_chars
|
|
)
|
|
)
|
|
)?;
|
|
|
|
write!(
|
|
f,
|
|
"\n{}",
|
|
SourceCodeDisplay::new(&self.name.span, Option::<u8>::None)
|
|
)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for InvalidNamespaceName {}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct UnresolvedMacroUsage {
|
|
pub span: Span,
|
|
}
|
|
|
|
impl Display for UnresolvedMacroUsage {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
Message::new(
|
|
Severity::Error,
|
|
format!(
|
|
"Macro `{}` was used, but could not be resolved.",
|
|
self.span.str(),
|
|
)
|
|
)
|
|
)?;
|
|
|
|
write!(
|
|
f,
|
|
"\n{}",
|
|
SourceCodeDisplay::new(
|
|
&self.span,
|
|
Some(format!(
|
|
"You might want to add `{}` to the function parameters.",
|
|
self.span.str()
|
|
))
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for UnresolvedMacroUsage {}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct IncompatibleFunctionAnnotation {
|
|
pub span: Span,
|
|
pub reason: String,
|
|
}
|
|
|
|
impl Display for IncompatibleFunctionAnnotation {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
Message::new(
|
|
Severity::Error,
|
|
format!(
|
|
"Annotation `{}` cannot be used here, because {}.",
|
|
self.span.str(),
|
|
self.reason
|
|
)
|
|
)
|
|
)?;
|
|
|
|
write!(f, "\n{}", SourceCodeDisplay::new(&self.span, None::<u8>))
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for IncompatibleFunctionAnnotation {}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
pub struct InvalidFunctionArguments {
|
|
pub span: Span,
|
|
pub expected: usize,
|
|
pub actual: usize,
|
|
}
|
|
|
|
impl Display for InvalidFunctionArguments {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(
|
|
f,
|
|
"{}",
|
|
Message::new(
|
|
Severity::Error,
|
|
format!(
|
|
"Expected {} arguments, but got {}.",
|
|
self.expected, self.actual
|
|
)
|
|
)
|
|
)?;
|
|
|
|
let help_message = if self.expected > self.actual {
|
|
format!(
|
|
"You might want to add {} more arguments.",
|
|
self.expected - self.actual
|
|
)
|
|
} else {
|
|
format!(
|
|
"You might want to remove {} arguments.",
|
|
self.actual - self.expected
|
|
)
|
|
};
|
|
|
|
write!(
|
|
f,
|
|
"\n{}",
|
|
SourceCodeDisplay::new(&self.span, Some(help_message))
|
|
)
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for InvalidFunctionArguments {}
|