mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-02 21:44:34 +00:00
Fixed to define subroutine as Type::Failure
even if type checking fails
This commit is contained in:
parent
2c15b057de
commit
3147dfb1d8
3 changed files with 104 additions and 30 deletions
|
@ -388,6 +388,7 @@ impl Context {
|
|||
sig: &ast::SubrSignature,
|
||||
mode: RegistrationMode,
|
||||
) -> TyCheckResult<Type> {
|
||||
// -> Result<Type, (Type, TyCheckErrors)> {
|
||||
let opt_decl_sig_t = self
|
||||
.rec_get_var_t(&sig.ident, &self.cfg.input, &self.name)
|
||||
.ok()
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::path::PathBuf;
|
|||
|
||||
use erg_common::config::{ErgConfig, Input};
|
||||
use erg_common::levenshtein::get_similar_name;
|
||||
use erg_common::set::Set;
|
||||
use erg_common::traits::{Locational, Stream};
|
||||
use erg_common::vis::Visibility;
|
||||
use erg_common::Str;
|
||||
|
@ -98,7 +99,6 @@ impl Context {
|
|||
let vis = sig.ident.vis();
|
||||
let muty = Mutability::from(&name[..]);
|
||||
let kind = id.map_or(VarKind::Declared, VarKind::Defined);
|
||||
let t = self.instantiate_sub_sig_t(sig, PreRegister)?;
|
||||
let comptime_decos = sig
|
||||
.decorators
|
||||
.iter()
|
||||
|
@ -108,7 +108,18 @@ impl Context {
|
|||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
.collect::<Set<_>>();
|
||||
let t = self.instantiate_sub_sig_t(sig, PreRegister).map_err(|e| {
|
||||
let vi = VarInfo::new(
|
||||
Type::Failure,
|
||||
muty,
|
||||
vis,
|
||||
kind.clone(),
|
||||
Some(comptime_decos.clone()),
|
||||
);
|
||||
self.decls.insert(sig.ident.name.clone(), vi);
|
||||
e
|
||||
})?;
|
||||
let vi = VarInfo::new(t, muty, vis, kind, Some(comptime_decos));
|
||||
if let Some(_decl) = self.decls.remove(name) {
|
||||
Err(TyCheckErrors::from(TyCheckError::duplicate_decl_error(
|
||||
|
@ -455,6 +466,40 @@ impl Context {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn fake_subr_assign(&mut self, sig: &ast::SubrSignature, failure_t: Type) {
|
||||
// already defined as const
|
||||
if sig.is_const() {
|
||||
let vi = self.decls.remove(sig.ident.inspect()).unwrap();
|
||||
self.locals.insert(sig.ident.name.clone(), vi);
|
||||
}
|
||||
let muty = if sig.ident.is_const() {
|
||||
Mutability::Const
|
||||
} else {
|
||||
Mutability::Immutable
|
||||
};
|
||||
let name = &sig.ident.name;
|
||||
self.decls.remove(name);
|
||||
let comptime_decos = sig
|
||||
.decorators
|
||||
.iter()
|
||||
.filter_map(|deco| match &deco.0 {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(local)) if local.is_const() => {
|
||||
Some(local.inspect().clone())
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
let vi = VarInfo::new(
|
||||
failure_t,
|
||||
muty,
|
||||
sig.ident.vis(),
|
||||
VarKind::DoesNotExist,
|
||||
Some(comptime_decos),
|
||||
);
|
||||
log!(info "Registered {}::{name}: {}", self.name, &vi.t);
|
||||
self.locals.insert(name.clone(), vi);
|
||||
}
|
||||
|
||||
// To allow forward references and recursive definitions
|
||||
pub(crate) fn preregister(&mut self, block: &ast::Block) -> TyCheckResult<()> {
|
||||
let mut total_errs = TyCheckErrors::empty();
|
||||
|
|
|
@ -660,36 +660,64 @@ impl ASTLowerer {
|
|||
.unwrap()
|
||||
.t
|
||||
.clone();
|
||||
let t = enum_unwrap!(t, Type::Subr);
|
||||
if let Err(errs) = self.ctx.assign_params(&sig.params, Some(t.clone())) {
|
||||
self.errs.extend(errs.into_iter());
|
||||
}
|
||||
if let Err(errs) = self.ctx.preregister(&body.block) {
|
||||
self.errs.extend(errs.into_iter());
|
||||
}
|
||||
let block = self.lower_block(body.block).map_err(|e| {
|
||||
self.pop_append_errs();
|
||||
e
|
||||
})?;
|
||||
let found_body_t = block.ref_t();
|
||||
let expect_body_t = t.return_t.as_ref();
|
||||
if !sig.is_const() {
|
||||
if let Err(e) =
|
||||
self.return_t_check(sig.loc(), sig.ident.inspect(), expect_body_t, found_body_t)
|
||||
{
|
||||
self.errs.push(e);
|
||||
match t {
|
||||
Type::Subr(t) => {
|
||||
if let Err(errs) = self.ctx.assign_params(&sig.params, Some(t.clone())) {
|
||||
self.errs.extend(errs.into_iter());
|
||||
}
|
||||
if let Err(errs) = self.ctx.preregister(&body.block) {
|
||||
self.errs.extend(errs.into_iter());
|
||||
}
|
||||
let block = self.lower_block(body.block).map_err(|e| {
|
||||
self.pop_append_errs();
|
||||
e
|
||||
})?;
|
||||
let found_body_t = block.ref_t();
|
||||
let expect_body_t = t.return_t.as_ref();
|
||||
if !sig.is_const() {
|
||||
if let Err(e) = self.return_t_check(
|
||||
sig.loc(),
|
||||
sig.ident.inspect(),
|
||||
expect_body_t,
|
||||
found_body_t,
|
||||
) {
|
||||
self.errs.push(e);
|
||||
}
|
||||
}
|
||||
let id = body.id;
|
||||
self.ctx
|
||||
.outer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.assign_subr(&sig, id, found_body_t)?;
|
||||
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
||||
let sig = hir::SubrSignature::new(ident, sig.params, Type::Subr(t));
|
||||
let body = hir::DefBody::new(body.op, block, body.id);
|
||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||
}
|
||||
Type::Failure => {
|
||||
if let Err(errs) = self.ctx.assign_params(&sig.params, None) {
|
||||
self.errs.extend(errs.into_iter());
|
||||
}
|
||||
if let Err(errs) = self.ctx.preregister(&body.block) {
|
||||
self.errs.extend(errs.into_iter());
|
||||
}
|
||||
let block = self.lower_block(body.block).map_err(|e| {
|
||||
self.pop_append_errs();
|
||||
e
|
||||
})?;
|
||||
self.ctx
|
||||
.outer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.fake_subr_assign(&sig, Type::Failure);
|
||||
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
||||
let sig = hir::SubrSignature::new(ident, sig.params, Type::Failure);
|
||||
let body = hir::DefBody::new(body.op, block, body.id);
|
||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
let id = body.id;
|
||||
self.ctx
|
||||
.outer
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.assign_subr(&sig, id, found_body_t)?;
|
||||
let ident = hir::Identifier::bare(sig.ident.dot, sig.ident.name);
|
||||
let sig = hir::SubrSignature::new(ident, sig.params, Type::Subr(t));
|
||||
let body = hir::DefBody::new(body.op, block, body.id);
|
||||
Ok(hir::Def::new(hir::Signature::Subr(sig), body))
|
||||
}
|
||||
|
||||
fn lower_class_def(&mut self, class_def: ast::ClassDef) -> LowerResult<hir::ClassDef> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue