Add hint.rs in context

This commit is contained in:
Shunsuke Shibayama 2022-09-02 01:20:35 +09:00
parent 0844fb2f7a
commit 3550a0e4b5
7 changed files with 17 additions and 6 deletions

View file

@ -7,12 +7,15 @@ use crate::context::Context;
impl Context { impl Context {
pub(crate) fn get_type_mismatch_hint(&self, expected: &Type, found: &Type) -> Option<Str> { pub(crate) fn get_type_mismatch_hint(&self, expected: &Type, found: &Type) -> Option<Str> {
let expected = if let Type::FreeVar(fv) = expected { let expected = if let Type::FreeVar(fv) = expected {
if fv.is_linked() { fv.crack().clone() } if fv.is_linked() {
else { fv.crack().clone()
} else {
let (_sub, sup) = fv.crack_bound_types().unwrap(); let (_sub, sup) = fv.crack_bound_types().unwrap();
sup sup
} }
} else { expected.clone() }; } else {
expected.clone()
};
match (&expected.name()[..], &found.name()[..]) { match (&expected.name()[..], &found.name()[..]) {
("Eq", "Float") => Some(Str::ever("Float has no equivalence relation defined. you should use `l - r <= Float.EPSILON` instead of `l == r`.")), ("Eq", "Float") => Some(Str::ever("Float has no equivalence relation defined. you should use `l - r <= Float.EPSILON` instead of `l == r`.")),
_ => None, _ => None,

View file

@ -51,6 +51,7 @@ impl Context {
ident.inspect(), ident.inspect(),
&spec_t, &spec_t,
body_t, body_t,
self.get_type_mismatch_hint(&spec_t, body_t),
)); ));
} }
Ok(()) Ok(())
@ -120,6 +121,7 @@ impl Context {
"match", "match",
&class("LambdaFunc"), &class("LambdaFunc"),
t, t,
self.get_type_mismatch_hint(&class("LambdaFunc"), t),
)); ));
} }
} }
@ -616,6 +618,7 @@ impl Context {
&name[..], &name[..],
param_t, param_t,
arg_t, arg_t,
self.get_type_mismatch_hint(param_t, arg_t),
) )
})?; })?;
if let Some(name) = param.name() { if let Some(name) = param.name() {
@ -656,6 +659,7 @@ impl Context {
&name[..], &name[..],
param_t, param_t,
arg_t, arg_t,
self.get_type_mismatch_hint(param_t, arg_t),
) )
}) })
} }
@ -698,6 +702,7 @@ impl Context {
&name[..], &name[..],
pt.typ(), pt.typ(),
arg_t, arg_t,
self.get_type_mismatch_hint(pt.typ(), arg_t),
) )
})?; })?;
} else { } else {

View file

@ -2,6 +2,7 @@
//! `Context` is used for type inference and type checking. //! `Context` is used for type inference and type checking.
pub mod cache; pub mod cache;
pub mod compare; pub mod compare;
pub mod hint;
pub mod initialize; pub mod initialize;
pub mod inquire; pub mod inquire;
pub mod instantiate; pub mod instantiate;

View file

@ -393,6 +393,7 @@ impl Context {
"import::name", "import::name",
&Str, &Str,
mod_name.ref_t(), mod_name.ref_t(),
self.get_type_mismatch_hint(&Str, mod_name.ref_t()),
)); ));
} }
} }

View file

@ -1017,6 +1017,7 @@ impl Context {
param_name.unwrap_or(&Str::ever("_")), param_name.unwrap_or(&Str::ever("_")),
maybe_sup, maybe_sup,
maybe_sub, maybe_sub,
self.get_type_mismatch_hint(maybe_sup, maybe_sub),
)); ));
} }
match (maybe_sub, maybe_sup) { match (maybe_sub, maybe_sup) {

View file

@ -513,6 +513,7 @@ impl TyCheckError {
name: &str, name: &str,
expect: &Type, expect: &Type,
found: &Type, found: &Type,
hint: Option<Str>,
) -> Self { ) -> Self {
Self::new( Self::new(
ErrorCore::new( ErrorCore::new(
@ -525,7 +526,7 @@ impl TyCheckError {
"traditional_chinese" => format!("{name}的類型不匹配:\n預期:{GREEN}{expect}{RESET}\n但找到:{RED}{found}{RESET}"), "traditional_chinese" => format!("{name}的類型不匹配:\n預期:{GREEN}{expect}{RESET}\n但找到:{RED}{found}{RESET}"),
"english" => format!("the type of {name} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"), "english" => format!("the type of {name} is mismatched:\nexpected: {GREEN}{expect}{RESET}\nbut found: {RED}{found}{RESET}"),
), ),
None, hint,
), ),
caused_by, caused_by,
) )

View file

@ -55,6 +55,7 @@ impl ASTLowerer {
name, name,
expect, expect,
found, found,
self.ctx.get_type_mismatch_hint(expect, found),
) )
}) })
} }
@ -336,8 +337,6 @@ impl ASTLowerer {
&hir_args.kw_args, &hir_args.kw_args,
&self.ctx.name, &self.ctx.name,
)?; )?;
log!(err "{}", obj);
log!(err "{:?}", call.method_name);
Ok(hir::Call::new(obj, call.method_name, hir_args, t)) Ok(hir::Call::new(obj, call.method_name, hir_args, t))
} }