From c0742005ee7d1a387cf246e83a97e02302569dda Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sun, 11 Sep 2022 23:19:48 +0900 Subject: [PATCH] Fix #72 --- compiler/erg_compiler/context/register.rs | 142 ++++++++++------------ compiler/erg_compiler/error.rs | 8 +- compiler/erg_compiler/lower.rs | 8 ++ 3 files changed, 74 insertions(+), 84 deletions(-) diff --git a/compiler/erg_compiler/context/register.rs b/compiler/erg_compiler/context/register.rs index 5eef79c9..9e3dbae0 100644 --- a/compiler/erg_compiler/context/register.rs +++ b/compiler/erg_compiler/context/register.rs @@ -25,11 +25,11 @@ use Visibility::*; impl Context { /// If it is a constant that is defined, there must be no variable of the same name defined across all scopes - fn registered(&self, name: &Str, is_const: bool) -> bool { + pub(crate) fn registered(&self, name: &str, is_const: bool) -> bool { if self.params.iter().any(|(maybe_name, _)| { maybe_name .as_ref() - .map(|n| n.inspect() == name) + .map(|n| &n.inspect()[..] == name) .unwrap_or(false) }) || self.locals.contains_key(name) { @@ -87,7 +87,7 @@ impl Context { let muty = Mutability::from(&name[..]); let kind = id.map_or(VarKind::Declared, VarKind::Defined); if self.registered(name, sig.is_const()) { - return Err(TyCheckError::duplicate_decl_error( + return Err(TyCheckError::reassign_error( line!() as usize, sig.loc(), self.caused_by(), @@ -136,22 +136,13 @@ impl Context { self.validate_var_sig_t(ident, sig.t_spec.as_ref(), body_t, Normal)?; let muty = Mutability::from(&ident.inspect()[..]); let generalized = self.generalize_t(body_t.clone()); - if self.registered(ident.inspect(), ident.is_const()) { - Err(TyCheckError::reassign_error( - line!() as usize, - ident.loc(), - self.caused_by(), - ident.inspect(), - )) - } else { - if self.decls.remove(ident.inspect()).is_some() { - // something to do? - } - let vis = ident.vis(); - let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id), None); - self.locals.insert(ident.name.clone(), vi); - Ok(()) + if self.decls.remove(ident.inspect()).is_some() { + // something to do? } + let vis = ident.vis(); + let vi = VarInfo::new(generalized, muty, vis, VarKind::Defined(id), None); + self.locals.insert(ident.name.clone(), vi); + Ok(()) } /// 宣言が既にある場合、opt_decl_tに宣言の型を渡す @@ -370,71 +361,62 @@ impl Context { ) })?; } - if self.registered(name.inspect(), name.is_const()) { - Err(TyCheckError::reassign_error( - line!() as usize, - name.loc(), - self.caused_by(), - name.inspect(), - )) + let sub_t = if sig.ident.is_procedural() { + proc( + non_default_params.clone(), + var_args.cloned(), + default_params.clone(), + body_t.clone(), + ) } else { - let sub_t = if sig.ident.is_procedural() { - proc( - non_default_params.clone(), - var_args.cloned(), - default_params.clone(), - body_t.clone(), - ) - } else { - func( - non_default_params.clone(), - var_args.cloned(), - default_params.clone(), - body_t.clone(), - ) - }; - sub_t.lift(); - let found_t = self.generalize_t(sub_t); - if let Some(mut vi) = self.decls.remove(name) { - if vi.t.has_unbound_var() { - vi.t.lift(); - vi.t = self.generalize_t(vi.t.clone()); - } - self.decls.insert(name.clone(), vi); + func( + non_default_params.clone(), + var_args.cloned(), + default_params.clone(), + body_t.clone(), + ) + }; + sub_t.lift(); + let found_t = self.generalize_t(sub_t); + if let Some(mut vi) = self.decls.remove(name) { + if vi.t.has_unbound_var() { + vi.t.lift(); + vi.t = self.generalize_t(vi.t.clone()); } - if let Some(vi) = self.decls.remove(name) { - if !self.rec_supertype_of(&vi.t, &found_t) { - return Err(TyCheckError::violate_decl_error( - line!() as usize, - sig.loc(), - self.caused_by(), - name.inspect(), - &vi.t, - &found_t, - )); - } - } - 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( - found_t, - muty, - sig.ident.vis(), - VarKind::Defined(id), - Some(comptime_decos), - ); - log!(info "Registered {}::{name}: {}", self.name, &vi.t); - self.locals.insert(name.clone(), vi); - Ok(()) + self.decls.insert(name.clone(), vi); } + if let Some(vi) = self.decls.remove(name) { + if !self.rec_supertype_of(&vi.t, &found_t) { + return Err(TyCheckError::violate_decl_error( + line!() as usize, + sig.loc(), + self.caused_by(), + name.inspect(), + &vi.t, + &found_t, + )); + } + } + 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( + found_t, + muty, + sig.ident.vis(), + VarKind::Defined(id), + Some(comptime_decos), + ); + log!(info "Registered {}::{name}: {}", self.name, &vi.t); + self.locals.insert(name.clone(), vi); + Ok(()) } // To allow forward references and recursive definitions diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 87c6a8c9..9da4202d 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -685,10 +685,10 @@ impl TyCheckError { AssignError, loc, switch_lang!( - "japanese" => format!("変数{name}に再代入されています"), - "simplified_chinese" => format!("不能为变量{name}分配两次"), - "traditional_chinese" => format!("不能為變量{name}分配兩次"), - "english" => format!("cannot assign twice to the variable {name}"), + "japanese" => format!("変数{YELLOW}{name}{RESET}に再代入されています"), + "simplified_chinese" => format!("不能为变量{YELLOW}{name}{RESET}分配两次"), + "traditional_chinese" => format!("不能為變量{YELLOW}{name}{RESET}分配兩次"), + "english" => format!("cannot assign twice to the variable {YELLOW}{name}{RESET}"), ), None, ), diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index dec97bd1..2515307b 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -577,6 +577,14 @@ impl ASTLowerer { } else { "" }; + if self.ctx.registered(name, def.sig.is_const()) { + return Err(LowerError::reassign_error( + line!() as usize, + def.sig.loc(), + self.ctx.caused_by(), + name, + )); + } self.ctx.grow(name, ContextKind::Instant, def.sig.vis())?; let res = match def.sig { ast::Signature::Subr(sig) => self.lower_subr_def(sig, def.body),