mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 13:11:11 +00:00
Fix #301
This commit is contained in:
parent
1fb397777b
commit
99dfc331bb
4 changed files with 86 additions and 33 deletions
|
@ -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);
|
||||
|
|
|
@ -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(),
|
||||
));
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue