begin new error system, unfinished

This commit is contained in:
afonya2 2025-06-06 22:01:53 +02:00
parent 32c2a20697
commit 532fffe725
Signed by: afonya
GPG key ID: EBB9C4CAFAAFB2DC
6 changed files with 673 additions and 237 deletions

220
src/errors.rs Normal file
View file

@ -0,0 +1,220 @@
use std::f32::consts::E;
use crate::Context;
pub enum ErrorType {
SyntaxError,
SemanticError,
TypeError,
MathError,
MachineError,
}
pub enum ErrorSubType {
//Syntax errors
UnexpectedEnd,
Expected,
Unexpected,
UnknownOperation,
InvalidTableKeys,
Unclosed,
//Semantic errors
ElseWithoutIf,
BreakContinueWithoutLoop,
UnexpectedOperation,
VariableNotFound,
VariableAlreadyExists,
ArgumentDuplication,
//Machine errors
RegisterNotFound,
MemoryOutOfBounds,
UnknownOPCode,
UnknownFunction,
UnknownString,
UnknownMemoryLocation,
NonFunctionCall,
//Math errors
DivisionByZero,
//Type errors
InvalidType,
WrongType,
NonStringKey,
}
pub struct ASLError {
pub message: String,
pub position: usize,
pub typ: ErrorType,
pub subtype: ErrorSubType,
pub code: String,
}
fn convert_types_to_string(typ: &ErrorType) -> String {
match typ {
ErrorType::SyntaxError => String::from("Syntax Error: "),
ErrorType::TypeError => String::from("Type Error: "),
ErrorType::MathError => String::from("Math Error: "),
ErrorType::SemanticError => String::from("Semantic Error: "),
ErrorType::MachineError => String::from("Machine Error: "),
}
}
fn convert_types_to_short(typ: &ErrorType) -> String {
match typ {
ErrorType::SyntaxError => String::from("ST:"),
ErrorType::TypeError => String::from("TP:"),
ErrorType::MathError => String::from("MT:"),
ErrorType::SemanticError => String::from("SM:"),
ErrorType::MachineError => String::from("MC:"),
}
}
fn convert_subtypes_to_string(stype: &ErrorSubType) -> String {
match stype {
ErrorSubType::UnexpectedEnd => String::from("Unexpected end"),
ErrorSubType::UnexpectedOperation => String::from("Unexpected operation"),
ErrorSubType::Expected => String::from("Expected"),
ErrorSubType::Unexpected => String::from("Unexpected"),
ErrorSubType::InvalidTableKeys => String::from("Invalid table keys"),
ErrorSubType::Unclosed => String::from("Unclosed structure"),
ErrorSubType::ElseWithoutIf => String::from("Else/elseif without if"),
ErrorSubType::BreakContinueWithoutLoop => String::from("Break/continue without loop"),
ErrorSubType::UnknownOperation => String::from("Unknown operation"),
ErrorSubType::VariableNotFound => String::from("Variable not found"),
ErrorSubType::VariableAlreadyExists => String::from("Variable already exists"),
ErrorSubType::ArgumentDuplication => String::from("Argument duplication"),
ErrorSubType::RegisterNotFound => String::from("Register not found"),
ErrorSubType::MemoryOutOfBounds => String::from("Memory out of bounds"),
ErrorSubType::UnknownOPCode => String::from("Unknown OP code"),
ErrorSubType::UnknownFunction => String::from("Unknown function"),
ErrorSubType::UnknownString => String::from("Unknown string"),
ErrorSubType::UnknownMemoryLocation => String::from("Unknown memory location"),
ErrorSubType::NonFunctionCall => String::from("Non-function call"),
ErrorSubType::DivisionByZero => String::from("Division by zero"),
ErrorSubType::InvalidType => String::from("Invalid type"),
ErrorSubType::WrongType => String::from("Wrong type"),
ErrorSubType::NonStringKey => String::from("Non-string key"),
}
}
fn convert_subtypes_to_short(stype: &ErrorSubType) -> String {
match stype {
ErrorSubType::UnexpectedEnd => String::from("UE:"),
ErrorSubType::UnexpectedOperation => String::from("UP:"),
ErrorSubType::Expected => String::from("EX:"),
ErrorSubType::Unexpected => String::from("UN:"),
ErrorSubType::InvalidTableKeys => String::from("IK:"),
ErrorSubType::Unclosed => String::from("UC:"),
ErrorSubType::ElseWithoutIf => String::from("EW:"),
ErrorSubType::BreakContinueWithoutLoop => String::from("BC:"),
ErrorSubType::UnknownOperation => String::from("UO:"),
ErrorSubType::VariableNotFound => String::from("VN:"),
ErrorSubType::VariableAlreadyExists => String::from("VE:"),
ErrorSubType::ArgumentDuplication => String::from("AD:"),
ErrorSubType::RegisterNotFound => String::from("RF:"),
ErrorSubType::MemoryOutOfBounds => String::from("MO:"),
ErrorSubType::UnknownOPCode => String::from("OC:"),
ErrorSubType::UnknownFunction => String::from("UF:"),
ErrorSubType::UnknownString => String::from("US:"),
ErrorSubType::UnknownMemoryLocation => String::from("UM:"),
ErrorSubType::NonFunctionCall => String::from("NF:"),
ErrorSubType::DivisionByZero => String::from("DZ:"),
ErrorSubType::InvalidType => String::from("IT:"),
ErrorSubType::WrongType => String::from("WT:"),
ErrorSubType::NonStringKey => String::from("NS:"),
}
}
pub fn create_error(message: &str, position: usize, typ: ErrorType, stype: ErrorSubType) -> ASLError {
let mut code = convert_types_to_short(&typ);
code.push_str(&convert_subtypes_to_short(&stype));
code.push_str(&position.to_string());
ASLError {
message: String::from(message),
position,
typ,
subtype: stype,
code,
}
}
fn get_exact_pos(file: &String, pos: usize) -> (usize, usize) {
let mut line = 1;
let mut column = 1;
for (i, c) in file.char_indices() {
if i == pos {
return (line, column);
}
if c == '\n' {
line += 1;
column = 1;
} else {
column += 1;
}
}
(line, column)
}
fn get_sorrunding_lines(file: &String, line: usize) -> (String, String, String) {
let lines = file.lines();
let mut before = String::new();
let mut current = String::new();
let mut after = String::new();
let mut current_line = 1;
for l in lines {
if current_line == line - 1 {
before = l.to_string();
} else if current_line == line {
current = l.to_string();
} else if current_line == line + 1 {
after = l.to_string();
break;
}
current_line += 1;
}
(before, current, after)
}
pub fn print_error(error: &ASLError, ctx: &Context) {
let mut out = String::new();
out.push_str(&convert_types_to_string(&error.typ));
if error.message.len() > 0 {
out.push_str(&convert_subtypes_to_string(&error.subtype));
} else {
out.push_str(&error.message);
}
out.push_str(" at position ");
let (line, column) = get_exact_pos(&ctx.raw_file, error.position);
out.push_str(&ctx.file);
out.push_str(":");
out.push_str(&line.to_string());
out.push_str(":");
out.push_str(&column.to_string());
out.push_str("\n");
let (before, current, after) = get_sorrunding_lines(&ctx.raw_file, line);
if line > 1 {
out.push_str(&(line-1).to_string());
out.push_str(" | ");
} else {
out.push_str(" | ");
}
out.push_str(&before);
out.push_str("\n");
out.push_str(&line.to_string());
out.push_str(" | ");
out.push_str(&current);
out.push_str("\n");
out.push_str(" ");
out.push_str(&" ".repeat(column - 1));
out.push_str("^ ");
out.push_str(&error.message);
out.push_str("\n");
out.push_str(&(line+1).to_string());
out.push_str(" | ");
out.push_str(&after);
out.push_str("\n");
out.push_str("Error Code: ");
out.push_str(&error.code);
println!("{}", out);
}