mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
Readable error messages
This commit is contained in:
parent
6593bf9e2e
commit
615d7937d9
4 changed files with 58 additions and 3 deletions
|
@ -593,11 +593,13 @@ impl Context {
|
|||
}
|
||||
}
|
||||
}
|
||||
let proj = mono_proj(*lhs, rhs);
|
||||
Err(EvalError::no_candidate_error(
|
||||
line!() as usize,
|
||||
&mono_proj(*lhs, rhs),
|
||||
&proj,
|
||||
t_loc,
|
||||
self.caused_by(),
|
||||
self.get_no_candidate_hint(&proj),
|
||||
))
|
||||
}
|
||||
Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level, t_loc)?)),
|
||||
|
|
|
@ -1,10 +1,31 @@
|
|||
use erg_common::astr::AtomicStr;
|
||||
use erg_common::enum_unwrap;
|
||||
|
||||
use erg_type::typaram::TyParam;
|
||||
use erg_type::Type;
|
||||
|
||||
use crate::context::Context;
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Sequence {
|
||||
Forward,
|
||||
Backward,
|
||||
}
|
||||
|
||||
impl Context {
|
||||
fn readable_type(&self, typ: &Type) -> Type {
|
||||
match typ {
|
||||
Type::FreeVar(fv) if fv.constraint_is_sandwiched() => {
|
||||
let (sub, sup) = fv.get_bound_types().unwrap();
|
||||
if sup == Type::Obj {
|
||||
return sub;
|
||||
}
|
||||
Type::FreeVar(fv.clone())
|
||||
}
|
||||
other => other.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_type_mismatch_hint(
|
||||
&self,
|
||||
expected: &Type,
|
||||
|
@ -25,4 +46,35 @@ impl Context {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_no_candidate_hint(&self, proj: &Type) -> Option<AtomicStr> {
|
||||
match proj {
|
||||
Type::MonoProj { lhs, rhs: _ } => {
|
||||
if let Type::FreeVar(fv) = lhs.as_ref() {
|
||||
let (sub, sup) = fv.get_bound_types()?;
|
||||
// TODO: automating
|
||||
let (verb, preposition, sequence) = match &sup.name()[..] {
|
||||
"Add" => Some(("add", "and", Sequence::Forward)),
|
||||
"Sub" => Some(("subtract", "from", Sequence::Backward)),
|
||||
"Mul" => Some(("multiply", "and", Sequence::Forward)),
|
||||
"Div" => Some(("divide", "by", Sequence::Forward)),
|
||||
_ => None,
|
||||
}?;
|
||||
let sup = enum_unwrap!(sup.typarams().remove(0), TyParam::Type);
|
||||
let sup = self.readable_type(&sup);
|
||||
let (l, r) = if sequence == Sequence::Forward {
|
||||
(sub, sup)
|
||||
} else {
|
||||
(sup, sub)
|
||||
};
|
||||
Some(AtomicStr::from(format!(
|
||||
"cannot {verb} {l} {preposition} {r}"
|
||||
)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1594,7 +1594,7 @@ impl Context {
|
|||
op_t,
|
||||
set! {
|
||||
static_instance("R", Type),
|
||||
subtypeof(l, poly("Mul", params))
|
||||
subtypeof(l, poly("Div", params))
|
||||
},
|
||||
);
|
||||
self.register_builtin_impl("__div__", op_t, Const, Private);
|
||||
|
|
|
@ -1145,6 +1145,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
|||
proj: &Type,
|
||||
loc: Location,
|
||||
caused_by: AtomicStr,
|
||||
hint: Option<AtomicStr>,
|
||||
) -> Self {
|
||||
Self::new(
|
||||
ErrorCore::new(
|
||||
|
@ -1157,7 +1158,7 @@ passed keyword args: {RED}{kw_args_len}{RESET}"
|
|||
"traditional_chinese" => format!("{proj}沒有候選項"),
|
||||
"english" => format!("no candidate for {proj}"),
|
||||
),
|
||||
None,
|
||||
hint,
|
||||
),
|
||||
caused_by,
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue