mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 12:24:45 +00:00
Fix method call bugs
This commit is contained in:
parent
a71704329c
commit
c9ffceec57
4 changed files with 42 additions and 29 deletions
|
@ -26,7 +26,8 @@ use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||||
use crate::error::{CompileError, CompileErrors, CompileResult};
|
use crate::error::{CompileError, CompileErrors, CompileResult};
|
||||||
use crate::eval::eval_lit;
|
use crate::eval::eval_lit;
|
||||||
use crate::hir::{
|
use crate::hir::{
|
||||||
Accessor, Args, Array, Block, DefBody, Expr, Signature, SubrSignature, Tuple, VarSignature, HIR,
|
Accessor, Args, Array, Block, Call, DefBody, Expr, Local, Signature, SubrSignature, Tuple,
|
||||||
|
VarSignature, HIR,
|
||||||
};
|
};
|
||||||
use AccessKind::*;
|
use AccessKind::*;
|
||||||
|
|
||||||
|
@ -898,14 +899,28 @@ impl CodeGenerator {
|
||||||
Ok(pop_jump_points)
|
Ok(pop_jump_points)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_call_special(&mut self, name: VarName, mut args: Args) -> CompileResult<()> {
|
fn emit_call(&mut self, call: Call) {
|
||||||
match &name.inspect()[..] {
|
if let Some(method_name) = call.method_name {
|
||||||
|
self.emit_call_method(*call.obj, method_name, call.args);
|
||||||
|
} else {
|
||||||
|
match *call.obj {
|
||||||
|
Expr::Accessor(Accessor::Local(local)) => {
|
||||||
|
self.emit_call_local(local, call.args).unwrap()
|
||||||
|
}
|
||||||
|
other => todo!("calling {other}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_call_local(&mut self, local: Local, mut args: Args) -> CompileResult<()> {
|
||||||
|
match &local.inspect()[..] {
|
||||||
"assert" => self.emit_assert_instr(args),
|
"assert" => self.emit_assert_instr(args),
|
||||||
"discard" => self.emit_discard_instr(args),
|
"discard" => self.emit_discard_instr(args),
|
||||||
"for" | "for!" => self.emit_for_instr(args),
|
"for" | "for!" => self.emit_for_instr(args),
|
||||||
"if" | "if!" => self.emit_if_instr(args),
|
"if" | "if!" => self.emit_if_instr(args),
|
||||||
"match" | "match!" => self.emit_match_instr(args, true),
|
"match" | "match!" => self.emit_match_instr(args, true),
|
||||||
_ => {
|
_ => {
|
||||||
|
let name = VarName::new(local.name);
|
||||||
let ident = Identifier::new(None, name);
|
let ident = Identifier::new(None, name);
|
||||||
self.emit_load_name_instr(ident).unwrap_or_else(|e| {
|
self.emit_load_name_instr(ident).unwrap_or_else(|e| {
|
||||||
self.errs.push(e);
|
self.errs.push(e);
|
||||||
|
@ -936,11 +951,10 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_call(&mut self, obj: Expr, method_name: Option<Token>, mut args: Args) {
|
fn emit_call_method(&mut self, obj: Expr, method_name: Token, mut args: Args) {
|
||||||
let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている
|
let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている
|
||||||
let uniq_obj_name = obj.__name__().map(Str::rc);
|
let uniq_obj_name = obj.__name__().map(Str::rc);
|
||||||
self.codegen_expr(obj);
|
self.codegen_expr(obj);
|
||||||
if let Some(method_name) = method_name {
|
|
||||||
self.emit_load_method_instr(
|
self.emit_load_method_instr(
|
||||||
&class,
|
&class,
|
||||||
uniq_obj_name.as_ref().map(|s| &s[..]),
|
uniq_obj_name.as_ref().map(|s| &s[..]),
|
||||||
|
@ -949,7 +963,6 @@ impl CodeGenerator {
|
||||||
.unwrap_or_else(|err| {
|
.unwrap_or_else(|err| {
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
let argc = args.len();
|
let argc = args.len();
|
||||||
let mut kws = Vec::with_capacity(args.kw_len());
|
let mut kws = Vec::with_capacity(args.kw_len());
|
||||||
while let Some(arg) = args.try_remove_pos(0) {
|
while let Some(arg) = args.try_remove_pos(0) {
|
||||||
|
@ -1135,15 +1148,7 @@ impl CodeGenerator {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Call(call) => match *call.obj {
|
Expr::Call(call) => self.emit_call(call),
|
||||||
Expr::Accessor(Accessor::Local(local)) => {
|
|
||||||
let name = VarName::new(local.name);
|
|
||||||
self.emit_call_special(name, call.args).unwrap();
|
|
||||||
}
|
|
||||||
obj => {
|
|
||||||
self.emit_call(obj, call.method_name, call.args);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// TODO: list comprehension
|
// TODO: list comprehension
|
||||||
Expr::Array(arr) => match arr {
|
Expr::Array(arr) => match arr {
|
||||||
Array::Normal(mut arr) => {
|
Array::Normal(mut arr) => {
|
||||||
|
|
|
@ -1011,7 +1011,8 @@ impl Context {
|
||||||
|
|
||||||
fn rec_get_singular_ctx(&self, obj: &hir::Expr) -> Option<&Context> {
|
fn rec_get_singular_ctx(&self, obj: &hir::Expr) -> Option<&Context> {
|
||||||
match obj.ref_t() {
|
match obj.ref_t() {
|
||||||
Type::Module => self.rec_get_mod(obj.__name__()?),
|
// TODO: attr
|
||||||
|
Type::Module => self.rec_get_mod(&obj.var_full_name()?),
|
||||||
Type::Class => todo!(),
|
Type::Class => todo!(),
|
||||||
Type::Trait => todo!(),
|
Type::Trait => todo!(),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
@ -6,7 +6,7 @@ use erg_common::traits::{Locational, NestedDisplay, Stream};
|
||||||
use erg_common::vis::{Field, Visibility};
|
use erg_common::vis::{Field, Visibility};
|
||||||
use erg_common::Str;
|
use erg_common::Str;
|
||||||
use erg_common::{
|
use erg_common::{
|
||||||
enum_unwrap, impl_display_for_enum, impl_display_from_nested, impl_locational,
|
enum_unwrap, fmt_option, impl_display_for_enum, impl_display_from_nested, impl_locational,
|
||||||
impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum,
|
impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum,
|
||||||
impl_stream_for_wrapper,
|
impl_stream_for_wrapper,
|
||||||
};
|
};
|
||||||
|
@ -883,7 +883,13 @@ pub struct Call {
|
||||||
|
|
||||||
impl NestedDisplay for Call {
|
impl NestedDisplay for Call {
|
||||||
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
|
||||||
writeln!(f, "({})(: {}):", self.obj, self.sig_t)?;
|
writeln!(
|
||||||
|
f,
|
||||||
|
"({}){}(: {}):",
|
||||||
|
self.obj,
|
||||||
|
fmt_option!(pre ".", self.method_name),
|
||||||
|
self.sig_t
|
||||||
|
)?;
|
||||||
self.args.fmt_nest(f, level + 1)
|
self.args.fmt_nest(f, level + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
use erg_common::error::Location;
|
use erg_common::error::Location;
|
||||||
use erg_common::traits::{Locational, Stream};
|
use erg_common::traits::{Locational, Stream};
|
||||||
use erg_common::vis::Visibility;
|
use erg_common::vis::Visibility;
|
||||||
use erg_common::{enum_unwrap, get_hash};
|
use erg_common::{enum_unwrap, fmt_option, fn_name, get_hash, log, switch_lang, Str};
|
||||||
use erg_common::{fn_name, log, switch_lang, Str};
|
|
||||||
|
|
||||||
use erg_parser::ast;
|
use erg_parser::ast;
|
||||||
use erg_parser::ast::AST;
|
use erg_parser::ast::AST;
|
||||||
|
@ -316,7 +315,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);
|
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(pre ".", call.method_name));
|
||||||
let (pos_args, kw_args, paren) = call.args.deconstruct();
|
let (pos_args, kw_args, paren) = call.args.deconstruct();
|
||||||
let mut hir_args = hir::Args::new(
|
let mut hir_args = hir::Args::new(
|
||||||
Vec::with_capacity(pos_args.len()),
|
Vec::with_capacity(pos_args.len()),
|
||||||
|
@ -337,6 +336,8 @@ impl ASTLowerer {
|
||||||
&hir_args.kw_args,
|
&hir_args.kw_args,
|
||||||
&self.ctx.name,
|
&self.ctx.name,
|
||||||
)?;
|
)?;
|
||||||
|
log!(err "{}", obj);
|
||||||
|
log!(err "{:?}", call.method_name);
|
||||||
Ok(hir::Call::new(obj, call.method_name, hir_args, t))
|
Ok(hir::Call::new(obj, call.method_name, hir_args, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue