mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 21:21:10 +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::option_enum_unwrap;
|
||||||
use erg_common::python_util::{env_python_version, PythonVersion};
|
use erg_common::python_util::{env_python_version, PythonVersion};
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
|
use erg_common::vis::Visibility;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
debug_power_assert, enum_unwrap, fn_name, fn_name_full, impl_stream_for_wrapper, log,
|
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 {
|
fn escape_name(name: &str, vis: Visibility) -> 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_proc__");
|
||||||
let name = name.replace('$', "__erg_shared__");
|
let name = name.replace('$', "__erg_shared__");
|
||||||
if vis.is_private() {
|
if vis.is_private() {
|
||||||
|
@ -72,6 +68,14 @@ fn escape_name(ident: Identifier) -> Str {
|
||||||
} else {
|
} else {
|
||||||
Str::from(name)
|
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) {
|
fn emit_load_name_instr(&mut self, ident: Identifier) {
|
||||||
log!(info "entered {}({ident})", fn_name!());
|
log!(info "entered {}({ident})", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
match &escaped[..] {
|
match &escaped[..] {
|
||||||
"if__" | "for__" | "while__" | "with__" | "discard__" => {
|
"if__" | "for__" | "while__" | "with__" | "discard__" => {
|
||||||
self.load_control();
|
self.load_control();
|
||||||
|
@ -675,7 +679,7 @@ impl PyCodeGenerator {
|
||||||
|
|
||||||
fn emit_load_global_instr(&mut self, ident: Identifier) {
|
fn emit_load_global_instr(&mut self, ident: Identifier) {
|
||||||
log!(info "entered {} ({ident})", fn_name!());
|
log!(info "entered {} ({ident})", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Name)
|
.local_search(&escaped, Name)
|
||||||
.unwrap_or_else(|| self.register_name(escaped));
|
.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) {
|
fn emit_import_name_instr(&mut self, ident: Identifier, items_len: usize) {
|
||||||
log!(info "entered {}({ident})", fn_name!());
|
log!(info "entered {}({ident})", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Name)
|
.local_search(&escaped, Name)
|
||||||
.unwrap_or_else(|| self.register_name(escaped));
|
.unwrap_or_else(|| self.register_name(escaped));
|
||||||
|
@ -699,7 +703,7 @@ impl PyCodeGenerator {
|
||||||
|
|
||||||
fn emit_import_from_instr(&mut self, ident: Identifier) {
|
fn emit_import_from_instr(&mut self, ident: Identifier) {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Name)
|
.local_search(&escaped, Name)
|
||||||
.unwrap_or_else(|| self.register_name(escaped));
|
.unwrap_or_else(|| self.register_name(escaped));
|
||||||
|
@ -712,7 +716,7 @@ impl PyCodeGenerator {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
self.emit_load_const(0i32); // escaping to call access `Nat` before importing `Nat`
|
self.emit_load_const(0i32); // escaping to call access `Nat` before importing `Nat`
|
||||||
self.emit_load_const([Str::ever("*")]);
|
self.emit_load_const([Str::ever("*")]);
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Name)
|
.local_search(&escaped, Name)
|
||||||
.unwrap_or_else(|| self.register_name(escaped));
|
.unwrap_or_else(|| self.register_name(escaped));
|
||||||
|
@ -752,7 +756,7 @@ impl PyCodeGenerator {
|
||||||
|
|
||||||
fn emit_load_attr_instr(&mut self, ident: Identifier) {
|
fn emit_load_attr_instr(&mut self, ident: Identifier) {
|
||||||
log!(info "entered {} ({ident})", fn_name!());
|
log!(info "entered {} ({ident})", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Attr)
|
.local_search(&escaped, Attr)
|
||||||
.unwrap_or_else(|| self.register_attr(escaped));
|
.unwrap_or_else(|| self.register_attr(escaped));
|
||||||
|
@ -769,7 +773,7 @@ impl PyCodeGenerator {
|
||||||
if &ident.inspect()[..] == "__new__" {
|
if &ident.inspect()[..] == "__new__" {
|
||||||
log!("{:?}", ident.vi);
|
log!("{:?}", ident.vi);
|
||||||
}
|
}
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Method)
|
.local_search(&escaped, Method)
|
||||||
.unwrap_or_else(|| self.register_method(escaped));
|
.unwrap_or_else(|| self.register_method(escaped));
|
||||||
|
@ -784,7 +788,7 @@ impl PyCodeGenerator {
|
||||||
|
|
||||||
fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) {
|
fn emit_store_instr(&mut self, ident: Identifier, acc_kind: AccessKind) {
|
||||||
log!(info "entered {} ({ident})", fn_name!());
|
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(|| {
|
let name = self.local_search(&escaped, acc_kind).unwrap_or_else(|| {
|
||||||
if acc_kind.is_local() {
|
if acc_kind.is_local() {
|
||||||
self.register_name(escaped)
|
self.register_name(escaped)
|
||||||
|
@ -808,7 +812,7 @@ impl PyCodeGenerator {
|
||||||
// Ergの組み込みオブジェクトをimportするときなどに使う、通常は使わない
|
// Ergの組み込みオブジェクトをimportするときなどに使う、通常は使わない
|
||||||
fn emit_store_global_instr(&mut self, ident: Identifier) {
|
fn emit_store_global_instr(&mut self, ident: Identifier) {
|
||||||
log!(info "entered {} ({ident})", fn_name!());
|
log!(info "entered {} ({ident})", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Name)
|
.local_search(&escaped, Name)
|
||||||
.unwrap_or_else(|| self.register_name(escaped));
|
.unwrap_or_else(|| self.register_name(escaped));
|
||||||
|
@ -879,7 +883,14 @@ impl PyCodeGenerator {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_")),
|
.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))
|
.map(|s| self.get_cached(&s))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
@ -1555,7 +1566,7 @@ impl PyCodeGenerator {
|
||||||
fn emit_del_instr(&mut self, mut args: Args) {
|
fn emit_del_instr(&mut self, mut args: Args) {
|
||||||
let ident = enum_unwrap!(args.remove_left_or_key("obj").unwrap(), Expr::Accessor:(Accessor::Ident:(_)));
|
let ident = enum_unwrap!(args.remove_left_or_key("obj").unwrap(), Expr::Accessor:(Accessor::Ident:(_)));
|
||||||
log!(info "entered {} ({ident})", fn_name!());
|
log!(info "entered {} ({ident})", fn_name!());
|
||||||
let escaped = escape_name(ident);
|
let escaped = escape_ident(ident);
|
||||||
let name = self
|
let name = self
|
||||||
.local_search(&escaped, Name)
|
.local_search(&escaped, Name)
|
||||||
.unwrap_or_else(|| self.register_name(escaped));
|
.unwrap_or_else(|| self.register_name(escaped));
|
||||||
|
@ -2233,7 +2244,7 @@ impl PyCodeGenerator {
|
||||||
let kw = if is_py_api {
|
let kw = if is_py_api {
|
||||||
arg.keyword.content
|
arg.keyword.content
|
||||||
} else {
|
} else {
|
||||||
Str::from(format!("::{}", arg.keyword.content))
|
escape_name(&arg.keyword.content, Visibility::Private)
|
||||||
};
|
};
|
||||||
kws.push(ValueObj::Str(kw));
|
kws.push(ValueObj::Str(kw));
|
||||||
self.emit_expr(arg.expr);
|
self.emit_expr(arg.expr);
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use erg_common::config::ErgConfig;
|
use erg_common::config::ErgConfig;
|
||||||
use erg_common::log;
|
use erg_common::log;
|
||||||
use erg_common::traits::Stream;
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::vis::Visibility;
|
use erg_common::vis::Visibility;
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
@ -235,6 +235,44 @@ impl SideEffectChecker {
|
||||||
self.block_stack.push(ConstInstant);
|
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;
|
let last_idx = def.body.block.len() - 1;
|
||||||
for (i, chunk) in def.body.block.iter().enumerate() {
|
for (i, chunk) in def.body.block.iter().enumerate() {
|
||||||
self.check_expr(chunk);
|
self.check_expr(chunk);
|
||||||
|
@ -247,7 +285,7 @@ impl SideEffectChecker {
|
||||||
self.errs.push(EffectError::proc_assign_error(
|
self.errs.push(EffectError::proc_assign_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
&def.sig,
|
def.sig.loc(),
|
||||||
self.full_path(),
|
self.full_path(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ use erg_common::{
|
||||||
use erg_parser::error::{ParserRunnerError, ParserRunnerErrors};
|
use erg_parser::error::{ParserRunnerError, ParserRunnerErrors};
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
use crate::hir::{Expr, Identifier, Signature};
|
use crate::hir::{Expr, Identifier};
|
||||||
use crate::ty::{HasType, Predicate, Type};
|
use crate::ty::{HasType, Predicate, Type};
|
||||||
|
|
||||||
/// `unreachable!(self: Context)`
|
/// `unreachable!(self: Context)`
|
||||||
|
@ -1450,12 +1450,7 @@ impl EffectError {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn proc_assign_error(
|
pub fn proc_assign_error(input: Input, errno: usize, loc: Location, caused_by: String) -> Self {
|
||||||
input: Input,
|
|
||||||
errno: usize,
|
|
||||||
sig: &Signature,
|
|
||||||
caused_by: String,
|
|
||||||
) -> Self {
|
|
||||||
let hint = Some(
|
let hint = Some(
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"japanese" => {
|
"japanese" => {
|
||||||
|
@ -1490,7 +1485,7 @@ impl EffectError {
|
||||||
);
|
);
|
||||||
Self::new(
|
Self::new(
|
||||||
ErrorCore::new(
|
ErrorCore::new(
|
||||||
vec![SubMessage::ambiguous_new(sig.loc(), vec![], hint)],
|
vec![SubMessage::ambiguous_new(loc, vec![], hint)],
|
||||||
switch_lang!(
|
switch_lang!(
|
||||||
"japanese" => "プロシージャを通常の変数に代入することはできません",
|
"japanese" => "プロシージャを通常の変数に代入することはできません",
|
||||||
"simplified_chinese" => "不能将过程赋值给普通变量",
|
"simplified_chinese" => "不能将过程赋值给普通变量",
|
||||||
|
@ -1499,7 +1494,7 @@ impl EffectError {
|
||||||
),
|
),
|
||||||
errno,
|
errno,
|
||||||
HasEffect,
|
HasEffect,
|
||||||
sig.loc(),
|
loc,
|
||||||
),
|
),
|
||||||
input,
|
input,
|
||||||
caused_by,
|
caused_by,
|
||||||
|
|
|
@ -2127,6 +2127,7 @@ impl Type {
|
||||||
vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())]
|
vec![TyParam::t(*lhs.clone()), TyParam::t(*rhs.clone())]
|
||||||
}
|
}
|
||||||
Self::Subr(subr) => subr.typarams(),
|
Self::Subr(subr) => subr.typarams(),
|
||||||
|
Self::Quantified(quant) => quant.typarams(),
|
||||||
Self::Callable { param_ts: _, .. } => todo!(),
|
Self::Callable { param_ts: _, .. } => todo!(),
|
||||||
Self::Poly { params, .. } => params.clone(),
|
Self::Poly { params, .. } => params.clone(),
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
|
@ -2156,6 +2157,7 @@ impl Type {
|
||||||
Self::Subr(SubrType {
|
Self::Subr(SubrType {
|
||||||
non_default_params, ..
|
non_default_params, ..
|
||||||
}) => Some(non_default_params),
|
}) => Some(non_default_params),
|
||||||
|
Self::Quantified(quant) => quant.non_default_params(),
|
||||||
Self::Callable { param_ts: _, .. } => todo!(),
|
Self::Callable { param_ts: _, .. } => todo!(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -2172,6 +2174,7 @@ impl Type {
|
||||||
var_params: var_args,
|
var_params: var_args,
|
||||||
..
|
..
|
||||||
}) => var_args.as_deref(),
|
}) => var_args.as_deref(),
|
||||||
|
Self::Quantified(quant) => quant.var_args(),
|
||||||
Self::Callable { param_ts: _, .. } => todo!(),
|
Self::Callable { param_ts: _, .. } => todo!(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -2185,6 +2188,7 @@ impl Type {
|
||||||
.and_then(|t| t.default_params()),
|
.and_then(|t| t.default_params()),
|
||||||
Self::Refinement(refine) => refine.t.default_params(),
|
Self::Refinement(refine) => refine.t.default_params(),
|
||||||
Self::Subr(SubrType { default_params, .. }) => Some(default_params),
|
Self::Subr(SubrType { default_params, .. }) => Some(default_params),
|
||||||
|
Self::Quantified(quant) => quant.default_params(),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2221,7 +2225,12 @@ impl Type {
|
||||||
Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => {
|
Self::Subr(SubrType { return_t, .. }) | Self::Callable { return_t, .. } => {
|
||||||
Some(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,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue