This commit is contained in:
Shunsuke Shibayama 2022-12-19 08:50:54 +09:00
parent 1fb397777b
commit 99dfc331bb
4 changed files with 86 additions and 33 deletions

View file

@ -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,12 +60,7 @@ fn debind(ident: &Identifier) -> Option<Str> {
}
}
fn escape_name(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();
fn escape_name(name: &str, vis: Visibility) -> Str {
let name = name.replace('!', "__erg_proc__");
let name = name.replace('$', "__erg_shared__");
if vis.is_private() {
@ -72,6 +68,14 @@ fn escape_name(ident: Identifier) -> Str {
} 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 {
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);

View file

@ -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(),
));
}

View file

@ -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,

View file

@ -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,
}
}