136 lines
4.0 KiB
Rust
136 lines
4.0 KiB
Rust
use super::parser::Position;
|
|
use std::fmt;
|
|
use std::fmt::Display;
|
|
use std::io;
|
|
use std::num::ParseIntError;
|
|
|
|
use super::vm::VariableType;
|
|
|
|
#[derive(Debug)]
|
|
pub enum GenericError {
|
|
StdIOError(io::Error),
|
|
}
|
|
|
|
impl From<io::Error> for GenericError {
|
|
fn from(error: io::Error) -> Self {
|
|
Self::StdIOError(error)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum SyntaxError {
|
|
#[allow(dead_code)]
|
|
Fatal,
|
|
ExpectedToken(Position, char),
|
|
ExpectedExpression(Position, Option<Box<SyntaxError>>),
|
|
ExpectedIdent(Position),
|
|
ExpectedStatement(Position, Option<Box<SyntaxError>>),
|
|
ExpectedPattern(Position),
|
|
}
|
|
|
|
impl SyntaxError {
|
|
fn from_opt(from: &Option<Box<SyntaxError>>) -> String {
|
|
if let Some(err) = from {
|
|
format!("\n {}", err)
|
|
} else {
|
|
String::new()
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for SyntaxError {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
let text = match self {
|
|
SyntaxError::Fatal => "Fatal error".to_string(),
|
|
SyntaxError::ExpectedToken(pos, c) => format!("Expected token '{}' at {}", c, pos),
|
|
SyntaxError::ExpectedExpression(pos, err) => format!(
|
|
"Expected expression at {}{}",
|
|
pos,
|
|
SyntaxError::from_opt(err)
|
|
),
|
|
SyntaxError::ExpectedIdent(pos) => format!("Expected ident at {}", pos),
|
|
SyntaxError::ExpectedStatement(pos, err) => format!(
|
|
"Expected statement at {}{}",
|
|
pos,
|
|
SyntaxError::from_opt(err)
|
|
),
|
|
SyntaxError::ExpectedPattern(pos) => format!("Expected pattern at {}", pos),
|
|
};
|
|
write!(f, "{}", text)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum CompilerError {
|
|
#[allow(dead_code)]
|
|
Fatal,
|
|
VariableExists(Position, String),
|
|
VariableNotExists(Position, String),
|
|
InvalidScopeExit(Position),
|
|
LetFailed(Position, Box<CompilerError>),
|
|
CanNotAssignVoidType,
|
|
FunctionNotFound(Position, String, Vec<VariableType>),
|
|
ParseIntError(ParseIntError),
|
|
}
|
|
|
|
impl Display for CompilerError {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
let text = match self {
|
|
CompilerError::Fatal => "Fatal error".to_string(),
|
|
CompilerError::VariableExists(pos, name) => {
|
|
format!("Variable '{}' already exists, re-assign at {}", pos, name)
|
|
}
|
|
CompilerError::VariableNotExists(pos, name) => {
|
|
format!("Variable '{}' does not exist, at {}", name, pos)
|
|
}
|
|
CompilerError::InvalidScopeExit(pos) => {
|
|
format!("Attempted to escape a scope invalidly at {}", pos)
|
|
}
|
|
CompilerError::LetFailed(pos, error) => {
|
|
format!("Let statement failed at {}:\n {}", pos, error)
|
|
}
|
|
CompilerError::CanNotAssignVoidType => format!("Can not assign void type here"),
|
|
CompilerError::FunctionNotFound(pos, name, params) => format!(
|
|
"Function with signature {}{} not found at {}",
|
|
name,
|
|
ParamList(params.clone()),
|
|
pos
|
|
),
|
|
CompilerError::ParseIntError(err) => format!("Failed to parse integer value: {}", err),
|
|
};
|
|
write!(f, "{}", text)
|
|
}
|
|
}
|
|
|
|
struct ParamList(Vec<VariableType>);
|
|
|
|
impl Display for ParamList {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
let mut text = String::new();
|
|
text += "(";
|
|
for (idx, vtype) in self.0.iter().enumerate() {
|
|
if idx > 0 {
|
|
text += ", ";
|
|
}
|
|
text += &vtype.to_string();
|
|
}
|
|
text += ")";
|
|
write!(f, "{}", text)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum RuntimePanic {
|
|
#[allow(dead_code)]
|
|
Fatal,
|
|
InvalidCommandIdx(usize),
|
|
ScopeStackUnderflow,
|
|
StackUnderflow,
|
|
StackOverflow,
|
|
RegistryNotDefined,
|
|
InvalidHeapAddress,
|
|
ValueNotInitialized,
|
|
InvalidTypeAssign,
|
|
InvalidFuncAddress,
|
|
}
|