diff --git a/compiler/erg_compiler/context/instantiate.rs b/compiler/erg_compiler/context/instantiate.rs index eaa6af6f..727c9710 100644 --- a/compiler/erg_compiler/context/instantiate.rs +++ b/compiler/erg_compiler/context/instantiate.rs @@ -388,6 +388,7 @@ impl Context { sig: &ast::SubrSignature, mode: RegistrationMode, ) -> TyCheckResult { + // -> Result { let opt_decl_sig_t = self .rec_get_var_t(&sig.ident, &self.cfg.input, &self.name) .ok() diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 5045335f..9f9e9815 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -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::>(); + 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(); diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index e3619902..34def455 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -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 {