Files
lang/src/ir/upper/error.rs
T
2025-05-06 23:27:30 -04:00

212 lines
5.9 KiB
Rust

use crate::common::{CompilerMsg, CompilerOutput};
use super::{
IdentStatus, KindTy, MemRes, MemberTy, Origin, Res, ResBase, StructID, Type, TypeID, UProgram
};
pub fn report_errs(p: &UProgram, output: &mut CompilerOutput, mut errs: Vec<ResErr>) {
for ident in &p.idents {
match &ident.status {
IdentStatus::Unres { path, base } => {
let mem = path.last().unwrap();
errs.push(ResErr::UnknownMember {
ty: mem.ty,
name: mem.name.clone(),
origin: mem.origin,
parent: base.clone(),
})
}
IdentStatus::Failed(err) => errs.push(err.clone()),
_ => (),
}
}
for err in errs {
match err {
ResErr::Type {
dst,
src,
errs,
origin,
} => {
let mut msg = type_assign_err(p, dst, src);
for inner in errs {
if inner.dst != dst && inner.src != src {
msg.push_str("\n ");
msg.push_str(&type_assign_err(p, inner.dst, inner.src));
}
}
output.err(CompilerMsg::new(msg, origin));
}
ResErr::NotCallable { origin, ty } => {
output.err(CompilerMsg::new(
format!("Cannot call type '{}'", p.type_name(ty)),
origin,
));
}
ResErr::CannotDeref { origin, ty } => {
output.err(CompilerMsg::new(
format!("Cannot dereference type '{}'", p.type_name(ty)),
origin,
));
}
ResErr::CondType { origin, ty } => {
output.err(CompilerMsg::new(
format!("Condition types must be '64'; found '{}'", p.type_name(ty)),
origin,
));
}
ResErr::BadControlFlow { origin, op } => {
output.err(CompilerMsg::new(
format!("Cannot {} here (outside of loop)", op.str()),
origin,
));
}
ResErr::MissingField { origin, id, name } => {
output.err(CompilerMsg::new(
format!(
"Missing field '{name}' in creation of struct '{}'",
p.structs[id].name
),
origin,
));
}
ResErr::UnknownStructField { origin, id, name } => {
output.err(CompilerMsg::new(
format!("Unknown field '{name}' in struct '{}'", p.structs[id].name),
origin,
));
}
ResErr::NoReturn { fid } => output.err(CompilerMsg::new(
format!("Function must return a value"),
p.fns[fid].origin,
)),
ResErr::GenericCount {
origin,
expected,
found,
} => output.err(CompilerMsg::new(
if expected == 0 {
format!("No generic arguments expected")
} else {
format!("Expected {expected} generic arguments, found {found}")
},
origin,
)),
ResErr::KindMismatch {
origin,
found,
expected,
} => output.err(CompilerMsg::new(
format!("Expected {expected}, found {}", found.display_str(p)),
origin,
)),
ResErr::UnknownMember {
origin,
ty,
name,
parent,
} => output.err(CompilerMsg::new(
format!("Unknown {ty} {name} of {}", parent.display_str(p)),
origin,
)),
}
}
for var in &p.vars {
match &p.types[var.ty] {
Type::Error => output.err(CompilerMsg::new(
format!("Var {:?} is error type!", var.name),
var.origin,
)),
Type::Infer => output.err(CompilerMsg::new(
format!("Type of {:?} cannot be inferred", var.name),
var.origin,
)),
_ => (),
}
}
}
#[derive(Clone)]
pub enum ResErr {
UnknownMember {
origin: Origin,
ty: MemberTy,
name: String,
parent: ResBase,
},
KindMismatch {
origin: Origin,
expected: KindTy,
found: Res,
},
GenericCount {
origin: Origin,
expected: usize,
found: usize,
},
NotCallable {
origin: Origin,
ty: TypeID,
},
CannotDeref {
origin: Origin,
ty: TypeID,
},
CondType {
origin: Origin,
ty: TypeID,
},
NoReturn {
fid: usize,
},
BadControlFlow {
op: ControlFlowOp,
origin: Origin,
},
MissingField {
origin: Origin,
id: StructID,
name: String,
},
UnknownStructField {
origin: Origin,
id: StructID,
name: String,
},
Type {
dst: TypeID,
src: TypeID,
errs: Vec<TypeMismatch>,
origin: Origin,
},
}
#[derive(Debug, Clone)]
pub enum ControlFlowOp {
Break,
Continue,
}
impl ControlFlowOp {
pub fn str(&self) -> &'static str {
match self {
ControlFlowOp::Break => "break",
ControlFlowOp::Continue => "continue",
}
}
}
#[derive(Debug, Clone)]
pub struct TypeMismatch {
pub dst: TypeID,
pub src: TypeID,
}
pub fn type_assign_err(p: &UProgram, dst: TypeID, src: TypeID) -> String {
format!(
"Cannot assign type {} to {}",
p.type_name(src),
p.type_name(dst)
)
}