mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
Fix method call bug
This commit is contained in:
parent
a0b2917359
commit
aa2b45bf86
15 changed files with 106 additions and 101 deletions
|
@ -1462,8 +1462,8 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn emit_call(&mut self, call: Call) {
|
fn emit_call(&mut self, call: Call) {
|
||||||
log!(info "entered {} ({call})", fn_name!());
|
log!(info "entered {} ({call})", fn_name!());
|
||||||
if let Some(method_name) = call.method_name {
|
if let Some(attr_name) = call.attr_name {
|
||||||
self.emit_call_method(*call.obj, method_name, call.args);
|
self.emit_call_method(*call.obj, attr_name, call.args);
|
||||||
} else {
|
} else {
|
||||||
match *call.obj {
|
match *call.obj {
|
||||||
Expr::Accessor(Accessor::Ident(ident)) if ident.vis().is_private() => {
|
Expr::Accessor(Accessor::Ident(ident)) if ident.vis().is_private() => {
|
||||||
|
|
|
@ -16,7 +16,7 @@ use erg_parser::ast::*;
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
|
||||||
use crate::ty::constructors::dict_t;
|
use crate::ty::constructors::dict_t;
|
||||||
use crate::ty::constructors::proj_method;
|
use crate::ty::constructors::proj_call;
|
||||||
use crate::ty::constructors::{
|
use crate::ty::constructors::{
|
||||||
array_t, mono, not, poly, proj, ref_, ref_mut, refinement, subr_t, v_enum,
|
array_t, mono, not, poly, proj, ref_, ref_mut, refinement, subr_t, v_enum,
|
||||||
};
|
};
|
||||||
|
@ -854,11 +854,11 @@ impl Context {
|
||||||
// ?T(<: Add(?R(:> Int))).Output == ?T(<: Add(?R)).Output
|
// ?T(<: Add(?R(:> Int))).Output == ?T(<: Add(?R)).Output
|
||||||
// ?T(:> Int, <: Add(?R(:> Int))).Output == Int
|
// ?T(:> Int, <: Add(?R(:> Int))).Output == Int
|
||||||
Type::Proj { lhs, rhs } => self.eval_proj(*lhs, rhs, level, t_loc),
|
Type::Proj { lhs, rhs } => self.eval_proj(*lhs, rhs, level, t_loc),
|
||||||
Type::ProjMethod {
|
Type::ProjCall {
|
||||||
lhs,
|
lhs,
|
||||||
method_name,
|
attr_name,
|
||||||
args,
|
args,
|
||||||
} => self.eval_proj_method(*lhs, method_name, args, level, t_loc),
|
} => self.eval_proj_call(*lhs, attr_name, args, level, t_loc),
|
||||||
Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level, t_loc)?)),
|
Type::Ref(l) => Ok(ref_(self.eval_t_params(*l, level, t_loc)?)),
|
||||||
Type::RefMut { before, after } => {
|
Type::RefMut { before, after } => {
|
||||||
let before = self.eval_t_params(*before, level, t_loc)?;
|
let before = self.eval_t_params(*before, level, t_loc)?;
|
||||||
|
@ -999,10 +999,10 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_proj_method(
|
fn eval_proj_call(
|
||||||
&self,
|
&self,
|
||||||
lhs: TyParam,
|
lhs: TyParam,
|
||||||
method_name: Str,
|
attr_name: Str,
|
||||||
args: Vec<TyParam>,
|
args: Vec<TyParam>,
|
||||||
level: usize,
|
level: usize,
|
||||||
t_loc: Location,
|
t_loc: Location,
|
||||||
|
@ -1014,11 +1014,11 @@ impl Context {
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
t_loc,
|
t_loc,
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
&method_name,
|
&attr_name,
|
||||||
None, // TODO:
|
None, // TODO:
|
||||||
)
|
)
|
||||||
})? {
|
})? {
|
||||||
if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&method_name), &self.name) {
|
if let Ok(obj) = ty_ctx.get_const_local(&Token::symbol(&attr_name), &self.name) {
|
||||||
if let ValueObj::Subr(subr) = obj {
|
if let ValueObj::Subr(subr) = obj {
|
||||||
let is_method = subr.sig_t().self_t().is_some();
|
let is_method = subr.sig_t().self_t().is_some();
|
||||||
let mut pos_args = vec![];
|
let mut pos_args = vec![];
|
||||||
|
@ -1037,7 +1037,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (_class, methods) in ty_ctx.methods_list.iter() {
|
for (_class, methods) in ty_ctx.methods_list.iter() {
|
||||||
if let Ok(obj) = methods.get_const_local(&Token::symbol(&method_name), &self.name) {
|
if let Ok(obj) = methods.get_const_local(&Token::symbol(&attr_name), &self.name) {
|
||||||
if let ValueObj::Subr(subr) = obj {
|
if let ValueObj::Subr(subr) = obj {
|
||||||
let mut pos_args = vec![];
|
let mut pos_args = vec![];
|
||||||
for pos_arg in args.into_iter() {
|
for pos_arg in args.into_iter() {
|
||||||
|
@ -1073,13 +1073,13 @@ impl Context {
|
||||||
// In many cases, it is still better to determine the type variable than if the target is not found.
|
// In many cases, it is still better to determine the type variable than if the target is not found.
|
||||||
let coerced = self.deref_tp(lhs.clone(), Variance::Covariant, t_loc)?;
|
let coerced = self.deref_tp(lhs.clone(), Variance::Covariant, t_loc)?;
|
||||||
if lhs != coerced {
|
if lhs != coerced {
|
||||||
let proj = proj_method(coerced, method_name, args);
|
let proj = proj_call(coerced, attr_name, args);
|
||||||
self.eval_t_params(proj, level, t_loc).map(|t| {
|
self.eval_t_params(proj, level, t_loc).map(|t| {
|
||||||
self.coerce_tp(&lhs);
|
self.coerce_tp(&lhs);
|
||||||
t
|
t
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let proj = proj_method(lhs, method_name, args);
|
let proj = proj_call(lhs, attr_name, args);
|
||||||
Err(EvalErrors::from(EvalError::no_candidate_error(
|
Err(EvalErrors::from(EvalError::no_candidate_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
|
|
@ -1020,7 +1020,7 @@ impl Context {
|
||||||
let dict_getitem_t = fn1_met(
|
let dict_getitem_t = fn1_met(
|
||||||
dict_t.clone(),
|
dict_t.clone(),
|
||||||
mono_q("T"),
|
mono_q("T"),
|
||||||
proj_method(mono_q_tp("D"), "__getitem__", vec![ty_tp(mono_q("T"))]),
|
proj_call(mono_q_tp("D"), "__getitem__", vec![ty_tp(mono_q("T"))]),
|
||||||
);
|
);
|
||||||
let dict_getitem_t = quant(
|
let dict_getitem_t = quant(
|
||||||
dict_getitem_t,
|
dict_getitem_t,
|
||||||
|
@ -1057,7 +1057,7 @@ impl Context {
|
||||||
tuple_.register_superclass(mono("GenericTuple"), &generic_tuple);
|
tuple_.register_superclass(mono("GenericTuple"), &generic_tuple);
|
||||||
tuple_.register_marker_trait(poly("Output", vec![ty_tp(mono_q("Ts"))]));
|
tuple_.register_marker_trait(poly("Output", vec![ty_tp(mono_q("Ts"))]));
|
||||||
// __Tuple_getitem__: (self: Tuple(Ts), _: {N}) -> Ts[N]
|
// __Tuple_getitem__: (self: Tuple(Ts), _: {N}) -> Ts[N]
|
||||||
let return_t = proj_method(mono_q_tp("Ts"), "__getitem__", vec![mono_q_tp("N")]);
|
let return_t = proj_call(mono_q_tp("Ts"), "__getitem__", vec![mono_q_tp("N")]);
|
||||||
let tuple_getitem_t = fn1_met(
|
let tuple_getitem_t = fn1_met(
|
||||||
tuple_t.clone(),
|
tuple_t.clone(),
|
||||||
tp_enum(Nat, set! {mono_q_tp("N")}),
|
tp_enum(Nat, set! {mono_q_tp("N")}),
|
||||||
|
|
|
@ -525,11 +525,11 @@ impl Context {
|
||||||
fn search_callee_t(
|
fn search_callee_t(
|
||||||
&self,
|
&self,
|
||||||
obj: &hir::Expr,
|
obj: &hir::Expr,
|
||||||
method_name: &Option<Identifier>,
|
attr_name: &Option<Identifier>,
|
||||||
input: &Input,
|
input: &Input,
|
||||||
namespace: &Str,
|
namespace: &Str,
|
||||||
) -> SingleTyCheckResult<Type> {
|
) -> SingleTyCheckResult<Type> {
|
||||||
if let Some(method_name) = method_name.as_ref() {
|
if let Some(attr_name) = attr_name.as_ref() {
|
||||||
for ctx in self
|
for ctx in self
|
||||||
.get_nominal_super_type_ctxs(obj.ref_t())
|
.get_nominal_super_type_ctxs(obj.ref_t())
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
|
@ -545,19 +545,19 @@ impl Context {
|
||||||
{
|
{
|
||||||
if let Some(vi) = ctx
|
if let Some(vi) = ctx
|
||||||
.locals
|
.locals
|
||||||
.get(method_name.inspect())
|
.get(attr_name.inspect())
|
||||||
.or_else(|| ctx.decls.get(method_name.inspect()))
|
.or_else(|| ctx.decls.get(attr_name.inspect()))
|
||||||
{
|
{
|
||||||
self.validate_visibility(method_name, vi, input, namespace)?;
|
self.validate_visibility(attr_name, vi, input, namespace)?;
|
||||||
return Ok(vi.t());
|
return Ok(vi.t());
|
||||||
}
|
}
|
||||||
for (_, methods_ctx) in ctx.methods_list.iter() {
|
for (_, methods_ctx) in ctx.methods_list.iter() {
|
||||||
if let Some(vi) = methods_ctx
|
if let Some(vi) = methods_ctx
|
||||||
.locals
|
.locals
|
||||||
.get(method_name.inspect())
|
.get(attr_name.inspect())
|
||||||
.or_else(|| methods_ctx.decls.get(method_name.inspect()))
|
.or_else(|| methods_ctx.decls.get(attr_name.inspect()))
|
||||||
{
|
{
|
||||||
self.validate_visibility(method_name, vi, input, namespace)?;
|
self.validate_visibility(attr_name, vi, input, namespace)?;
|
||||||
return Ok(vi.t());
|
return Ok(vi.t());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,34 +565,34 @@ impl Context {
|
||||||
if let Ok(singular_ctx) = self.get_singular_ctx(obj, namespace) {
|
if let Ok(singular_ctx) = self.get_singular_ctx(obj, namespace) {
|
||||||
if let Some(vi) = singular_ctx
|
if let Some(vi) = singular_ctx
|
||||||
.locals
|
.locals
|
||||||
.get(method_name.inspect())
|
.get(attr_name.inspect())
|
||||||
.or_else(|| singular_ctx.decls.get(method_name.inspect()))
|
.or_else(|| singular_ctx.decls.get(attr_name.inspect()))
|
||||||
{
|
{
|
||||||
self.validate_visibility(method_name, vi, input, namespace)?;
|
self.validate_visibility(attr_name, vi, input, namespace)?;
|
||||||
return Ok(vi.t());
|
return Ok(vi.t());
|
||||||
}
|
}
|
||||||
for (_, method_ctx) in singular_ctx.methods_list.iter() {
|
for (_, method_ctx) in singular_ctx.methods_list.iter() {
|
||||||
if let Some(vi) = method_ctx
|
if let Some(vi) = method_ctx
|
||||||
.locals
|
.locals
|
||||||
.get(method_name.inspect())
|
.get(attr_name.inspect())
|
||||||
.or_else(|| method_ctx.decls.get(method_name.inspect()))
|
.or_else(|| method_ctx.decls.get(attr_name.inspect()))
|
||||||
{
|
{
|
||||||
self.validate_visibility(method_name, vi, input, namespace)?;
|
self.validate_visibility(attr_name, vi, input, namespace)?;
|
||||||
return Ok(vi.t());
|
return Ok(vi.t());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(TyCheckError::singular_no_attr_error(
|
return Err(TyCheckError::singular_no_attr_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
method_name.loc(),
|
attr_name.loc(),
|
||||||
namespace.into(),
|
namespace.into(),
|
||||||
obj.qual_name().unwrap_or("?"),
|
obj.qual_name().unwrap_or("?"),
|
||||||
obj.ref_t(),
|
obj.ref_t(),
|
||||||
method_name.inspect(),
|
attr_name.inspect(),
|
||||||
self.get_similar_attr_from_singular(obj, method_name.inspect()),
|
self.get_similar_attr_from_singular(obj, attr_name.inspect()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
match self.get_method_type_by_name(method_name) {
|
match self.get_method_type_by_name(attr_name) {
|
||||||
Ok(t) => {
|
Ok(t) => {
|
||||||
self.sub_unify(obj.ref_t(), &t.definition_type, obj.loc(), None)
|
self.sub_unify(obj.ref_t(), &t.definition_type, obj.loc(), None)
|
||||||
// HACK: change this func's return type to TyCheckResult<Type>
|
// HACK: change this func's return type to TyCheckResult<Type>
|
||||||
|
@ -608,11 +608,11 @@ impl Context {
|
||||||
Err(TyCheckError::no_attr_error(
|
Err(TyCheckError::no_attr_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
method_name.loc(),
|
attr_name.loc(),
|
||||||
namespace.into(),
|
namespace.into(),
|
||||||
obj.ref_t(),
|
obj.ref_t(),
|
||||||
method_name.inspect(),
|
attr_name.inspect(),
|
||||||
self.get_similar_attr(obj.ref_t(), method_name.inspect()),
|
self.get_similar_attr(obj.ref_t(), attr_name.inspect()),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Ok(obj.t())
|
Ok(obj.t())
|
||||||
|
@ -759,17 +759,17 @@ impl Context {
|
||||||
fn substitute_call(
|
fn substitute_call(
|
||||||
&self,
|
&self,
|
||||||
obj: &hir::Expr,
|
obj: &hir::Expr,
|
||||||
method_name: &Option<Identifier>,
|
attr_name: &Option<Identifier>,
|
||||||
instance: &Type,
|
instance: &Type,
|
||||||
pos_args: &[hir::PosArg],
|
pos_args: &[hir::PosArg],
|
||||||
kw_args: &[hir::KwArg],
|
kw_args: &[hir::KwArg],
|
||||||
) -> TyCheckResult<()> {
|
) -> TyCheckResult<()> {
|
||||||
match instance {
|
match instance {
|
||||||
Type::FreeVar(fv) if fv.is_linked() => {
|
Type::FreeVar(fv) if fv.is_linked() => {
|
||||||
self.substitute_call(obj, method_name, &fv.crack(), pos_args, kw_args)
|
self.substitute_call(obj, attr_name, &fv.crack(), pos_args, kw_args)
|
||||||
}
|
}
|
||||||
Type::FreeVar(fv) => {
|
Type::FreeVar(fv) => {
|
||||||
if let Some(_method_name) = method_name {
|
if let Some(_attr_name) = attr_name {
|
||||||
todo!()
|
todo!()
|
||||||
} else {
|
} else {
|
||||||
let is_procedural = obj
|
let is_procedural = obj
|
||||||
|
@ -789,16 +789,21 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Refinement(refine) => {
|
Type::Refinement(refine) => {
|
||||||
self.substitute_call(obj, method_name, &refine.t, pos_args, kw_args)
|
self.substitute_call(obj, attr_name, &refine.t, pos_args, kw_args)
|
||||||
}
|
}
|
||||||
Type::Subr(subr) => {
|
Type::Subr(subr) => {
|
||||||
let callee = if let Some(ident) = method_name {
|
let not_method_but_attr = subr.self_t().is_none();
|
||||||
|
let callee = if let Some(ident) = attr_name {
|
||||||
|
if not_method_but_attr {
|
||||||
|
obj.clone()
|
||||||
|
} else {
|
||||||
let attr = hir::Attribute::new(
|
let attr = hir::Attribute::new(
|
||||||
obj.clone(),
|
obj.clone(),
|
||||||
hir::Identifier::bare(ident.dot.clone(), ident.name.clone()),
|
hir::Identifier::bare(ident.dot.clone(), ident.name.clone()),
|
||||||
Type::Uninited,
|
Type::Uninited,
|
||||||
);
|
);
|
||||||
hir::Expr::Accessor(hir::Accessor::Attr(attr))
|
hir::Expr::Accessor(hir::Accessor::Attr(attr))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
obj.clone()
|
obj.clone()
|
||||||
};
|
};
|
||||||
|
@ -818,7 +823,7 @@ impl Context {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
let mut passed_params = set! {};
|
let mut passed_params = set! {};
|
||||||
let non_default_params_len = if method_name.is_some() {
|
let non_default_params_len = if attr_name.is_some() && !not_method_but_attr {
|
||||||
subr.non_default_params.len() - 1
|
subr.non_default_params.len() - 1
|
||||||
} else {
|
} else {
|
||||||
subr.non_default_params.len()
|
subr.non_default_params.len()
|
||||||
|
@ -895,13 +900,13 @@ impl Context {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
if let Some(method_name) = method_name {
|
if let Some(attr_name) = attr_name {
|
||||||
Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
|
Err(TyCheckErrors::from(TyCheckError::type_mismatch_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
Location::concat(obj, method_name),
|
Location::concat(obj, attr_name),
|
||||||
self.caused_by(),
|
self.caused_by(),
|
||||||
&(obj.to_string() + &method_name.to_string()),
|
&(obj.to_string() + &attr_name.to_string()),
|
||||||
&mono("Callable"),
|
&mono("Callable"),
|
||||||
other,
|
other,
|
||||||
self.get_candidates(other),
|
self.get_candidates(other),
|
||||||
|
@ -1073,7 +1078,7 @@ impl Context {
|
||||||
pub(crate) fn get_call_t(
|
pub(crate) fn get_call_t(
|
||||||
&self,
|
&self,
|
||||||
obj: &hir::Expr,
|
obj: &hir::Expr,
|
||||||
method_name: &Option<Identifier>,
|
attr_name: &Option<Identifier>,
|
||||||
pos_args: &[hir::PosArg],
|
pos_args: &[hir::PosArg],
|
||||||
kw_args: &[hir::KwArg],
|
kw_args: &[hir::KwArg],
|
||||||
input: &Input,
|
input: &Input,
|
||||||
|
@ -1103,10 +1108,10 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let found = self.search_callee_t(obj, method_name, input, namespace)?;
|
let found = self.search_callee_t(obj, attr_name, input, namespace)?;
|
||||||
log!(
|
log!(
|
||||||
"Found:\ncallee: {obj}{}\nfound: {found}",
|
"Found:\ncallee: {obj}{}\nfound: {found}",
|
||||||
fmt_option!(pre ".", method_name.as_ref().map(|ident| &ident.name))
|
fmt_option!(pre ".", attr_name.as_ref().map(|ident| &ident.name))
|
||||||
);
|
);
|
||||||
let instance = self.instantiate(found, obj)?;
|
let instance = self.instantiate(found, obj)?;
|
||||||
log!(
|
log!(
|
||||||
|
@ -1114,7 +1119,7 @@ impl Context {
|
||||||
fmt_slice(pos_args),
|
fmt_slice(pos_args),
|
||||||
fmt_slice(kw_args)
|
fmt_slice(kw_args)
|
||||||
);
|
);
|
||||||
self.substitute_call(obj, method_name, &instance, pos_args, kw_args)?;
|
self.substitute_call(obj, attr_name, &instance, pos_args, kw_args)?;
|
||||||
log!(info "Substituted:\ninstance: {instance}");
|
log!(info "Substituted:\ninstance: {instance}");
|
||||||
let res = self.eval_t_params(instance, self.level, obj.loc())?;
|
let res = self.eval_t_params(instance, self.level, obj.loc())?;
|
||||||
log!(info "Params evaluated:\nres: {res}\n");
|
log!(info "Params evaluated:\nres: {res}\n");
|
||||||
|
|
|
@ -1070,16 +1070,16 @@ impl Context {
|
||||||
let lhs = self.instantiate_t(*lhs, tmp_tv_ctx, loc)?;
|
let lhs = self.instantiate_t(*lhs, tmp_tv_ctx, loc)?;
|
||||||
Ok(proj(lhs, rhs))
|
Ok(proj(lhs, rhs))
|
||||||
}
|
}
|
||||||
ProjMethod {
|
ProjCall {
|
||||||
lhs,
|
lhs,
|
||||||
method_name,
|
attr_name,
|
||||||
mut args,
|
mut args,
|
||||||
} => {
|
} => {
|
||||||
let lhs = self.instantiate_tp(*lhs, tmp_tv_ctx, loc)?;
|
let lhs = self.instantiate_tp(*lhs, tmp_tv_ctx, loc)?;
|
||||||
for arg in args.iter_mut() {
|
for arg in args.iter_mut() {
|
||||||
*arg = self.instantiate_tp(mem::take(arg), tmp_tv_ctx, loc)?;
|
*arg = self.instantiate_tp(mem::take(arg), tmp_tv_ctx, loc)?;
|
||||||
}
|
}
|
||||||
Ok(proj_method(lhs, method_name, args))
|
Ok(proj_call(lhs, attr_name, args))
|
||||||
}
|
}
|
||||||
Poly { name, mut params } => {
|
Poly { name, mut params } => {
|
||||||
for param in params.iter_mut() {
|
for param in params.iter_mut() {
|
||||||
|
|
|
@ -187,16 +187,16 @@ impl Context {
|
||||||
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
|
let lhs = self.generalize_t_inner(*lhs, bounds, lazy_inits);
|
||||||
proj(lhs, rhs)
|
proj(lhs, rhs)
|
||||||
}
|
}
|
||||||
ProjMethod {
|
ProjCall {
|
||||||
lhs,
|
lhs,
|
||||||
method_name,
|
attr_name,
|
||||||
mut args,
|
mut args,
|
||||||
} => {
|
} => {
|
||||||
let lhs = self.generalize_tp(*lhs, bounds, lazy_inits);
|
let lhs = self.generalize_tp(*lhs, bounds, lazy_inits);
|
||||||
for arg in args.iter_mut() {
|
for arg in args.iter_mut() {
|
||||||
*arg = self.generalize_tp(mem::take(arg), bounds, lazy_inits);
|
*arg = self.generalize_tp(mem::take(arg), bounds, lazy_inits);
|
||||||
}
|
}
|
||||||
proj_method(lhs, method_name, args)
|
proj_call(lhs, attr_name, args)
|
||||||
}
|
}
|
||||||
And(l, r) => {
|
And(l, r) => {
|
||||||
let l = self.generalize_t_inner(*l, bounds, lazy_inits);
|
let l = self.generalize_t_inner(*l, bounds, lazy_inits);
|
||||||
|
|
|
@ -326,7 +326,7 @@ impl SideEffectChecker {
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
if (call.obj.t().is_procedural()
|
if (call.obj.t().is_procedural()
|
||||||
|| call
|
|| call
|
||||||
.method_name
|
.attr_name
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|name| name.is_procedural())
|
.map(|name| name.is_procedural())
|
||||||
.unwrap_or(false))
|
.unwrap_or(false))
|
||||||
|
|
|
@ -1075,7 +1075,7 @@ impl UnaryOp {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
pub obj: Box<Expr>,
|
pub obj: Box<Expr>,
|
||||||
pub method_name: Option<Identifier>,
|
pub attr_name: Option<Identifier>,
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
/// 全体の型(引数自体の型は関係ない)、e.g. `abs(-1)` -> `Neg -> Nat`
|
/// 全体の型(引数自体の型は関係ない)、e.g. `abs(-1)` -> `Neg -> Nat`
|
||||||
pub sig_t: Type,
|
pub sig_t: Type,
|
||||||
|
@ -1087,7 +1087,7 @@ impl NestedDisplay for Call {
|
||||||
f,
|
f,
|
||||||
"({}){} (: {}):",
|
"({}){} (: {}):",
|
||||||
self.obj,
|
self.obj,
|
||||||
fmt_option!(self.method_name),
|
fmt_option!(self.attr_name),
|
||||||
self.sig_t
|
self.sig_t
|
||||||
)?;
|
)?;
|
||||||
self.args.fmt_nest(f, level + 1)
|
self.args.fmt_nest(f, level + 1)
|
||||||
|
@ -1130,10 +1130,10 @@ impl Locational for Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Call {
|
impl Call {
|
||||||
pub fn new(obj: Expr, method_name: Option<Identifier>, args: Args, sig_t: Type) -> Self {
|
pub fn new(obj: Expr, attr_name: Option<Identifier>, args: Args, sig_t: Type) -> Self {
|
||||||
Self {
|
Self {
|
||||||
obj: Box::new(obj),
|
obj: Box::new(obj),
|
||||||
method_name,
|
attr_name,
|
||||||
args,
|
args,
|
||||||
sig_t,
|
sig_t,
|
||||||
}
|
}
|
||||||
|
|
|
@ -654,7 +654,7 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
|
fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
|
||||||
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.method_name));
|
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.attr_name));
|
||||||
let opt_cast_to = if call.is_assert_cast() {
|
let opt_cast_to = if call.is_assert_cast() {
|
||||||
if let Some(typ) = call.assert_cast_target_type() {
|
if let Some(typ) = call.assert_cast_target_type() {
|
||||||
Some(Parser::expr_to_type_spec(typ.clone()).map_err(|e| {
|
Some(Parser::expr_to_type_spec(typ.clone()).map_err(|e| {
|
||||||
|
@ -690,23 +690,23 @@ impl ASTLowerer {
|
||||||
let obj = self.lower_expr(*call.obj)?;
|
let obj = self.lower_expr(*call.obj)?;
|
||||||
let sig_t = self.ctx.get_call_t(
|
let sig_t = self.ctx.get_call_t(
|
||||||
&obj,
|
&obj,
|
||||||
&call.method_name,
|
&call.attr_name,
|
||||||
&hir_args.pos_args,
|
&hir_args.pos_args,
|
||||||
&hir_args.kw_args,
|
&hir_args.kw_args,
|
||||||
&self.cfg.input,
|
&self.cfg.input,
|
||||||
&self.ctx.name,
|
&self.ctx.name,
|
||||||
)?;
|
)?;
|
||||||
let method_name = if let Some(method_name) = call.method_name {
|
let attr_name = if let Some(attr_name) = call.attr_name {
|
||||||
Some(hir::Identifier::new(
|
Some(hir::Identifier::new(
|
||||||
method_name.dot,
|
attr_name.dot,
|
||||||
method_name.name,
|
attr_name.name,
|
||||||
None,
|
None,
|
||||||
Type::Uninited,
|
Type::Uninited,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let mut call = hir::Call::new(obj, method_name, hir_args, sig_t);
|
let mut call = hir::Call::new(obj, attr_name, hir_args, sig_t);
|
||||||
match call.additional_operation() {
|
match call.additional_operation() {
|
||||||
Some(kind @ (OperationKind::Import | OperationKind::PyImport)) => {
|
Some(kind @ (OperationKind::Import | OperationKind::PyImport)) => {
|
||||||
let mod_name =
|
let mod_name =
|
||||||
|
@ -744,7 +744,7 @@ impl ASTLowerer {
|
||||||
let class = self.lower_expr(*pack.class)?;
|
let class = self.lower_expr(*pack.class)?;
|
||||||
let args = self.lower_record(pack.args)?;
|
let args = self.lower_record(pack.args)?;
|
||||||
let args = vec![hir::PosArg::new(hir::Expr::Record(args))];
|
let args = vec![hir::PosArg::new(hir::Expr::Record(args))];
|
||||||
let method_name = ast::Identifier::new(
|
let attr_name = ast::Identifier::new(
|
||||||
Some(Token::new(
|
Some(Token::new(
|
||||||
TokenKind::Dot,
|
TokenKind::Dot,
|
||||||
Str::ever("."),
|
Str::ever("."),
|
||||||
|
@ -760,15 +760,15 @@ impl ASTLowerer {
|
||||||
);
|
);
|
||||||
let sig_t = self.ctx.get_call_t(
|
let sig_t = self.ctx.get_call_t(
|
||||||
&class,
|
&class,
|
||||||
&Some(method_name.clone()),
|
&Some(attr_name.clone()),
|
||||||
&args,
|
&args,
|
||||||
&[],
|
&[],
|
||||||
&self.cfg.input,
|
&self.cfg.input,
|
||||||
&self.ctx.name,
|
&self.ctx.name,
|
||||||
)?;
|
)?;
|
||||||
let args = hir::Args::new(args, None, vec![], None);
|
let args = hir::Args::new(args, None, vec![], None);
|
||||||
let method_name = hir::Identifier::bare(method_name.dot, method_name.name);
|
let attr_name = hir::Identifier::bare(attr_name.dot, attr_name.name);
|
||||||
Ok(hir::Call::new(class, Some(method_name), args, sig_t))
|
Ok(hir::Call::new(class, Some(attr_name), args, sig_t))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: varargs
|
/// TODO: varargs
|
||||||
|
|
|
@ -109,7 +109,7 @@ impl OwnershipChecker {
|
||||||
// TODO: referenced
|
// TODO: referenced
|
||||||
Expr::Call(call) => {
|
Expr::Call(call) => {
|
||||||
let args_owns = call.signature_t().unwrap().args_ownership();
|
let args_owns = call.signature_t().unwrap().args_ownership();
|
||||||
let non_defaults_len = if call.method_name.is_some() {
|
let non_defaults_len = if call.attr_name.is_some() {
|
||||||
args_owns.non_defaults.len() - 1
|
args_owns.non_defaults.len() - 1
|
||||||
} else {
|
} else {
|
||||||
args_owns.non_defaults.len()
|
args_owns.non_defaults.len()
|
||||||
|
|
|
@ -385,10 +385,10 @@ pub fn proj<S: Into<Str>>(lhs: Type, rhs: S) -> Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn proj_method<S: Into<Str>>(lhs: TyParam, method_name: S, args: Vec<TyParam>) -> Type {
|
pub fn proj_call<S: Into<Str>>(lhs: TyParam, attr_name: S, args: Vec<TyParam>) -> Type {
|
||||||
Type::ProjMethod {
|
Type::ProjCall {
|
||||||
lhs: Box::new(lhs),
|
lhs: Box::new(lhs),
|
||||||
method_name: method_name.into(),
|
attr_name: attr_name.into(),
|
||||||
args,
|
args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1188,9 +1188,9 @@ pub enum Type {
|
||||||
lhs: Box<Type>,
|
lhs: Box<Type>,
|
||||||
rhs: Str,
|
rhs: Str,
|
||||||
}, // e.g. T.U
|
}, // e.g. T.U
|
||||||
ProjMethod {
|
ProjCall {
|
||||||
lhs: Box<TyParam>,
|
lhs: Box<TyParam>,
|
||||||
method_name: Str,
|
attr_name: Str,
|
||||||
args: Vec<TyParam>,
|
args: Vec<TyParam>,
|
||||||
}, // e.g. Ts.__getitem__(N)
|
}, // e.g. Ts.__getitem__(N)
|
||||||
FreeVar(FreeTyVar), // a reference to the type of other expression, see docs/compiler/inference.md
|
FreeVar(FreeTyVar), // a reference to the type of other expression, see docs/compiler/inference.md
|
||||||
|
@ -1281,17 +1281,17 @@ impl PartialEq for Type {
|
||||||
},
|
},
|
||||||
) => lhs == rlhs && rhs == rrhs,
|
) => lhs == rlhs && rhs == rrhs,
|
||||||
(
|
(
|
||||||
Self::ProjMethod {
|
Self::ProjCall {
|
||||||
lhs,
|
lhs,
|
||||||
method_name,
|
attr_name,
|
||||||
args,
|
args,
|
||||||
},
|
},
|
||||||
Self::ProjMethod {
|
Self::ProjCall {
|
||||||
lhs: r,
|
lhs: r,
|
||||||
method_name: rm,
|
attr_name: rn,
|
||||||
args: ra,
|
args: ra,
|
||||||
},
|
},
|
||||||
) => lhs == r && method_name == rm && args == ra,
|
) => lhs == r && attr_name == rn && args == ra,
|
||||||
(Self::FreeVar(fv), other) if fv.is_linked() => &*fv.crack() == other,
|
(Self::FreeVar(fv), other) if fv.is_linked() => &*fv.crack() == other,
|
||||||
(_self, Self::FreeVar(fv)) if fv.is_linked() => _self == &*fv.crack(),
|
(_self, Self::FreeVar(fv)) if fv.is_linked() => _self == &*fv.crack(),
|
||||||
(Self::FreeVar(l), Self::FreeVar(r)) => l == r,
|
(Self::FreeVar(l), Self::FreeVar(r)) => l == r,
|
||||||
|
@ -1406,13 +1406,13 @@ impl LimitedDisplay for Type {
|
||||||
lhs.limited_fmt(f, limit - 1)?;
|
lhs.limited_fmt(f, limit - 1)?;
|
||||||
write!(f, ".{rhs}")
|
write!(f, ".{rhs}")
|
||||||
}
|
}
|
||||||
Self::ProjMethod {
|
Self::ProjCall {
|
||||||
lhs,
|
lhs,
|
||||||
method_name,
|
attr_name,
|
||||||
args,
|
args,
|
||||||
} => {
|
} => {
|
||||||
lhs.limited_fmt(f, limit - 1)?;
|
lhs.limited_fmt(f, limit - 1)?;
|
||||||
write!(f, ".{method_name}(")?;
|
write!(f, ".{attr_name}(")?;
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
write!(f, ", ")?;
|
write!(f, ", ")?;
|
||||||
|
@ -1918,7 +1918,7 @@ impl Type {
|
||||||
FreeKind::Unbound { id, .. } => Str::from(format!("%{id}")),
|
FreeKind::Unbound { id, .. } => Str::from(format!("%{id}")),
|
||||||
},
|
},
|
||||||
Self::Proj { .. } => Str::ever("MonoProj"),
|
Self::Proj { .. } => Str::ever("MonoProj"),
|
||||||
Self::ProjMethod { .. } => Str::ever("MonoProjMethod"),
|
Self::ProjCall { .. } => Str::ever("MonoProjMethod"),
|
||||||
Self::Failure => Str::ever("Failure"),
|
Self::Failure => Str::ever("Failure"),
|
||||||
Self::Uninited => Str::ever("Uninited"),
|
Self::Uninited => Str::ever("Uninited"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -924,7 +924,7 @@ impl UnaryOp {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
pub obj: Box<Expr>,
|
pub obj: Box<Expr>,
|
||||||
pub method_name: Option<Identifier>,
|
pub attr_name: Option<Identifier>,
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,8 +935,8 @@ impl NestedDisplay for Call {
|
||||||
} else {
|
} else {
|
||||||
write!(f, "{}", self.obj)?;
|
write!(f, "{}", self.obj)?;
|
||||||
}
|
}
|
||||||
if let Some(method_name) = self.method_name.as_ref() {
|
if let Some(attr_name) = self.attr_name.as_ref() {
|
||||||
write!(f, "{}", method_name)?;
|
write!(f, "{}", attr_name)?;
|
||||||
}
|
}
|
||||||
writeln!(f, ":")?;
|
writeln!(f, ":")?;
|
||||||
self.args.fmt_nest(f, level + 1)
|
self.args.fmt_nest(f, level + 1)
|
||||||
|
@ -952,10 +952,10 @@ impl Locational for Call {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Call {
|
impl Call {
|
||||||
pub fn new(obj: Expr, method_name: Option<Identifier>, args: Args) -> Self {
|
pub fn new(obj: Expr, attr_name: Option<Identifier>, args: Args) -> Self {
|
||||||
Self {
|
Self {
|
||||||
obj: Box::new(obj),
|
obj: Box::new(obj),
|
||||||
method_name,
|
attr_name,
|
||||||
args,
|
args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -181,7 +181,7 @@ impl Desugarer {
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let args = Args::new(pos_args, kw_args, paren);
|
let args = Args::new(pos_args, kw_args, paren);
|
||||||
Expr::Call(Call::new(obj, call.method_name, args))
|
Expr::Call(Call::new(obj, call.attr_name, args))
|
||||||
}
|
}
|
||||||
Expr::Def(def) => {
|
Expr::Def(def) => {
|
||||||
let mut chunks = vec![];
|
let mut chunks = vec![];
|
||||||
|
|
|
@ -1415,11 +1415,11 @@ impl Parser {
|
||||||
let mut call_or_acc = self.try_reduce_acc_chain(acc, in_type_args)?;
|
let mut call_or_acc = self.try_reduce_acc_chain(acc, in_type_args)?;
|
||||||
while let Some(res) = self.opt_reduce_args(in_type_args) {
|
while let Some(res) = self.opt_reduce_args(in_type_args) {
|
||||||
let args = res.map_err(|_| self.stack_dec())?;
|
let args = res.map_err(|_| self.stack_dec())?;
|
||||||
let (receiver, method_name) = match call_or_acc {
|
let (receiver, attr_name) = match call_or_acc {
|
||||||
Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
|
Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
|
||||||
other => (other, None),
|
other => (other, None),
|
||||||
};
|
};
|
||||||
let call = Call::new(receiver, method_name, args);
|
let call = Call::new(receiver, attr_name, args);
|
||||||
call_or_acc = Expr::Call(call);
|
call_or_acc = Expr::Call(call);
|
||||||
}
|
}
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
|
@ -1529,11 +1529,11 @@ impl Parser {
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LParen) && obj.col_end() == t.col_begin() => {
|
Some(t) if t.is(LParen) && obj.col_end() == t.col_begin() => {
|
||||||
let args = self.try_reduce_args(false).map_err(|_| self.stack_dec())?;
|
let args = self.try_reduce_args(false).map_err(|_| self.stack_dec())?;
|
||||||
let (receiver, method_name) = match obj {
|
let (receiver, attr_name) = match obj {
|
||||||
Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
|
Expr::Accessor(Accessor::Attr(attr)) => (*attr.obj, Some(attr.ident)),
|
||||||
other => (other, None),
|
other => (other, None),
|
||||||
};
|
};
|
||||||
let call = Call::new(receiver, method_name, args);
|
let call = Call::new(receiver, attr_name, args);
|
||||||
obj = Expr::Call(call);
|
obj = Expr::Call(call);
|
||||||
}
|
}
|
||||||
Some(t) if t.is(VBar) && !in_type_args => {
|
Some(t) if t.is(VBar) && !in_type_args => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue