From 99dfc331bbe3587e2e775ca505f2686d1e8866fe Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Mon, 19 Dec 2022 08:50:54 +0900 Subject: [PATCH] Fix #301 --- compiler/erg_compiler/codegen.rs | 53 +++++++++++++++++----------- compiler/erg_compiler/effectcheck.rs | 42 ++++++++++++++++++++-- compiler/erg_compiler/error.rs | 13 +++---- compiler/erg_compiler/ty/mod.rs | 11 +++++- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index f93f3ef7..7bd658d6 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -18,6 +18,7 @@ use erg_common::opcode311::{BinOpCode, Opcode311}; use erg_common::option_enum_unwrap; use erg_common::python_util::{env_python_version, PythonVersion}; use erg_common::traits::{Locational, Stream}; +use erg_common::vis::Visibility; use erg_common::Str; use erg_common::{ debug_power_assert, enum_unwrap, fn_name, fn_name_full, impl_stream_for_wrapper, log, @@ -59,19 +60,22 @@ fn debind(ident: &Identifier) -> Option { } } -fn escape_name(ident: Identifier) -> Str { +fn escape_name(name: &str, vis: Visibility) -> Str { + let name = name.replace('!', "__erg_proc__"); + let name = name.replace('$', "__erg_shared__"); + if vis.is_private() { + Str::from("::".to_string() + &name) + } else { + Str::from(name) + } +} + +fn escape_ident(ident: Identifier) -> Str { let vis = ident.vis(); if let Some(py_name) = ident.vi.py_name { py_name } else { - let name = ident.name.into_token().content.to_string(); - let name = name.replace('!', "__erg_proc__"); - let name = name.replace('$', "__erg_shared__"); - if vis.is_private() { - Str::from("::".to_string() + &name) - } else { - Str::from(name) - } + escape_name(ident.inspect(), vis) } } @@ -642,7 +646,7 @@ impl PyCodeGenerator { fn emit_load_name_instr(&mut self, ident: Identifier) { log!(info "entered {}({ident})", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); match &escaped[..] { "if__" | "for__" | "while__" | "with__" | "discard__" => { self.load_control(); @@ -675,7 +679,7 @@ impl PyCodeGenerator { fn emit_load_global_instr(&mut self, ident: Identifier) { log!(info "entered {} ({ident})", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Name) .unwrap_or_else(|| self.register_name(escaped)); @@ -687,7 +691,7 @@ impl PyCodeGenerator { fn emit_import_name_instr(&mut self, ident: Identifier, items_len: usize) { log!(info "entered {}({ident})", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Name) .unwrap_or_else(|| self.register_name(escaped)); @@ -699,7 +703,7 @@ impl PyCodeGenerator { fn emit_import_from_instr(&mut self, ident: Identifier) { log!(info "entered {}", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Name) .unwrap_or_else(|| self.register_name(escaped)); @@ -712,7 +716,7 @@ impl PyCodeGenerator { log!(info "entered {}", fn_name!()); self.emit_load_const(0i32); // escaping to call access `Nat` before importing `Nat` self.emit_load_const([Str::ever("*")]); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Name) .unwrap_or_else(|| self.register_name(escaped)); @@ -752,7 +756,7 @@ impl PyCodeGenerator { fn emit_load_attr_instr(&mut self, ident: Identifier) { log!(info "entered {} ({ident})", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Attr) .unwrap_or_else(|| self.register_attr(escaped)); @@ -769,7 +773,7 @@ impl PyCodeGenerator { if &ident.inspect()[..] == "__new__" { log!("{:?}", ident.vi); } - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Method) .unwrap_or_else(|| self.register_method(escaped)); @@ -784,7 +788,7 @@ impl PyCodeGenerator { fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) { log!(info "entered {} ({ident})", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self.local_search(&escaped, acc_kind).unwrap_or_else(|| { if acc_kind.is_local() { self.register_name(escaped) @@ -808,7 +812,7 @@ impl PyCodeGenerator { // Ergの組み込みオブジェクトをimportするときなどに使う、通常は使わない fn emit_store_global_instr(&mut self, ident: Identifier) { log!(info "entered {} ({ident})", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Name) .unwrap_or_else(|| self.register_name(escaped)); @@ -879,7 +883,14 @@ impl PyCodeGenerator { .iter() .map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")), ) - .map(|s| format!("::{s}")) + .enumerate() + .map(|(i, s)| { + if s == "_" { + format!("_{i}") + } else { + escape_name(s, Visibility::Private).to_string() + } + }) .map(|s| self.get_cached(&s)) .collect() } @@ -1555,7 +1566,7 @@ impl PyCodeGenerator { fn emit_del_instr(&mut self, mut args: Args) { let ident = enum_unwrap!(args.remove_left_or_key("obj").unwrap(), Expr::Accessor:(Accessor::Ident:(_))); log!(info "entered {} ({ident})", fn_name!()); - let escaped = escape_name(ident); + let escaped = escape_ident(ident); let name = self .local_search(&escaped, Name) .unwrap_or_else(|| self.register_name(escaped)); @@ -2233,7 +2244,7 @@ impl PyCodeGenerator { let kw = if is_py_api { arg.keyword.content } else { - Str::from(format!("::{}", arg.keyword.content)) + escape_name(&arg.keyword.content, Visibility::Private) }; kws.push(ValueObj::Str(kw)); self.emit_expr(arg.expr); diff --git a/compiler/erg_compiler/effectcheck.rs b/compiler/erg_compiler/effectcheck.rs index 44ab931d..60d6fbc4 100644 --- a/compiler/erg_compiler/effectcheck.rs +++ b/compiler/erg_compiler/effectcheck.rs @@ -4,7 +4,7 @@ use erg_common::config::ErgConfig; use erg_common::log; -use erg_common::traits::Stream; +use erg_common::traits::{Locational, Stream}; use erg_common::vis::Visibility; use erg_common::Str; use Visibility::*; @@ -235,6 +235,44 @@ impl SideEffectChecker { self.block_stack.push(ConstInstant); } } + if let Signature::Subr(sig) = &def.sig { + let t = sig.ident.ref_t(); + for (nd_param, nd_type) in sig + .params + .non_defaults + .iter() + .zip(t.non_default_params().unwrap()) + { + if nd_type.typ().is_procedure() && !nd_param.inspect().unwrap().ends_with('!') { + self.errs.push(EffectError::proc_assign_error( + self.cfg.input.clone(), + line!() as usize, + nd_param.pat.loc(), + self.full_path(), + )); + } + } + if let Some((var_arg, va_type)) = sig.params.var_args.as_ref().zip(t.var_args()) { + if va_type.typ().is_procedure() && !var_arg.inspect().unwrap().ends_with('!') { + self.errs.push(EffectError::proc_assign_error( + self.cfg.input.clone(), + line!() as usize, + var_arg.pat.loc(), + self.full_path(), + )); + } + } + for (d_param, d_type) in sig.params.defaults.iter().zip(t.default_params().unwrap()) { + if d_type.typ().is_procedure() && !d_param.inspect().unwrap().ends_with('!') { + self.errs.push(EffectError::proc_assign_error( + self.cfg.input.clone(), + line!() as usize, + d_param.sig.pat.loc(), + self.full_path(), + )); + } + } + } let last_idx = def.body.block.len() - 1; for (i, chunk) in def.body.block.iter().enumerate() { self.check_expr(chunk); @@ -247,7 +285,7 @@ impl SideEffectChecker { self.errs.push(EffectError::proc_assign_error( self.cfg.input.clone(), line!() as usize, - &def.sig, + def.sig.loc(), self.full_path(), )); } diff --git a/compiler/erg_compiler/error.rs b/compiler/erg_compiler/error.rs index 81de17bb..a6932678 100644 --- a/compiler/erg_compiler/error.rs +++ b/compiler/erg_compiler/error.rs @@ -17,7 +17,7 @@ use erg_common::{ use erg_parser::error::{ParserRunnerError, ParserRunnerErrors}; use crate::context::Context; -use crate::hir::{Expr, Identifier, Signature}; +use crate::hir::{Expr, Identifier}; use crate::ty::{HasType, Predicate, Type}; /// `unreachable!(self: Context)` @@ -1450,12 +1450,7 @@ impl EffectError { ) } - pub fn proc_assign_error( - input: Input, - errno: usize, - sig: &Signature, - caused_by: String, - ) -> Self { + pub fn proc_assign_error(input: Input, errno: usize, loc: Location, caused_by: String) -> Self { let hint = Some( switch_lang!( "japanese" => { @@ -1490,7 +1485,7 @@ impl EffectError { ); Self::new( ErrorCore::new( - vec![SubMessage::ambiguous_new(sig.loc(), vec![], hint)], + vec![SubMessage::ambiguous_new(loc, vec![], hint)], switch_lang!( "japanese" => "プロシージャを通常の変数に代入することはできません", "simplified_chinese" => "不能将过程赋值给普通变量", @@ -1499,7 +1494,7 @@ impl EffectError { ), errno, HasEffect, - sig.loc(), + loc, ), input, caused_by, diff --git a/compiler/erg_compiler/ty/mod.rs b/compiler/erg_compiler/ty/mod.rs index aabd272b..740ace4c 100644 --- a/compiler/erg_compiler/ty/mod.rs +++ b/compiler/erg_compiler/ty/mod.rs @@ -2127,6 +2127,7 @@ impl Type { vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())] } Self::Subr(subr) => subr.typarams(), + Self::Quantified(quant) => quant.typarams(), Self::Callable { param_ts: _, .. } => todo!(), Self::Poly { params, .. } => params.clone(), _ => vec![], @@ -2156,6 +2157,7 @@ impl Type { Self::Subr(SubrType { non_default_params, .. }) => Some(non_default_params), + Self::Quantified(quant) => quant.non_default_params(), Self::Callable { param_ts: _, .. } => todo!(), _ => None, } @@ -2172,6 +2174,7 @@ impl Type { var_params: var_args, .. }) => var_args.as_deref(), + Self::Quantified(quant) => quant.var_args(), Self::Callable { param_ts: _, .. } => todo!(), _ => None, } @@ -2185,6 +2188,7 @@ impl Type { .and_then(|t| t.default_params()), Self::Refinement(refine) => refine.t.default_params(), Self::Subr(SubrType { default_params, .. }) => Some(default_params), + Self::Quantified(quant) => quant.default_params(), _ => None, } } @@ -2221,7 +2225,12 @@ impl Type { Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => { Some(return_t) } - // Self::Quantified(quant) => quant.unbound_callable.mut_return_t(), + Self::Quantified(quant) => { + if quant.return_t().unwrap().is_generalized() { + log!(err "quantified return type (recursive function type inference)"); + } + quant.mut_return_t() + } _ => None, } }