mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-01 13:11:11 +00:00
Merge branch 'class' into beta
This commit is contained in:
commit
2d365dce3b
15 changed files with 349 additions and 124 deletions
|
@ -32,7 +32,7 @@ use crate::error::{CompileError, CompileErrors, CompileResult};
|
|||
use crate::hir::AttrDef;
|
||||
use crate::hir::Attribute;
|
||||
use crate::hir::{
|
||||
Accessor, Args, Array, Block, Call, ClassDef, Def, DefBody, Expr, Literal, Local, Signature,
|
||||
Accessor, Args, Array, Block, Call, ClassDef, DefBody, Expr, Literal, Local, PosArg, Signature,
|
||||
SubrSignature, Tuple, VarSignature, HIR,
|
||||
};
|
||||
use AccessKind::*;
|
||||
|
@ -202,7 +202,7 @@ fn convert_to_python_attr(class: &str, uniq_obj_name: Option<&str>, name: Str) -
|
|||
("Array!", _, "push!") => Str::ever("append"),
|
||||
("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Real") => Str::ever("real"),
|
||||
("Complex" | "Real" | "Int" | "Nat" | "Float", _, "Imag") => Str::ever("imag"),
|
||||
(_, _, "new" | "__new__") => Str::ever("__call__"),
|
||||
(_, _, "__new__") => Str::ever("__call__"),
|
||||
("StringIO!", _, "getvalue!") => Str::ever("getvalue"),
|
||||
("Module", Some("importlib"), "reload!") => Str::ever("reload"),
|
||||
("Module", Some("random"), "randint!") => Str::ever("randint"),
|
||||
|
@ -446,7 +446,7 @@ impl CodeGenerator {
|
|||
self.stack_inc();
|
||||
}
|
||||
|
||||
fn local_search(&self, name: &str, acc_kind: AccessKind) -> Option<Name> {
|
||||
fn local_search(&self, name: &str, _acc_kind: AccessKind) -> Option<Name> {
|
||||
let current_is_toplevel = self.cur_block() == self.toplevel_block();
|
||||
if let Some(idx) = self
|
||||
.cur_block_codeobj()
|
||||
|
@ -454,11 +454,7 @@ impl CodeGenerator {
|
|||
.iter()
|
||||
.position(|n| &**n == name)
|
||||
{
|
||||
if current_is_toplevel || !acc_kind.is_local() {
|
||||
Some(Name::local(idx))
|
||||
} else {
|
||||
Some(Name::global(idx))
|
||||
}
|
||||
Some(Name::local(idx))
|
||||
} else if let Some(idx) = self
|
||||
.cur_block_codeobj()
|
||||
.varnames
|
||||
|
@ -667,6 +663,8 @@ impl CodeGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
/// Ergの文法として、属性への代入は存在しない(必ずオブジェクトはすべての属性を初期化しなくてはならないため)
|
||||
/// この関数はPythonへ落とし込むときに使う
|
||||
fn store_acc(&mut self, acc: Accessor) {
|
||||
log!(info "entered {} ({acc})", fn_name!());
|
||||
match acc {
|
||||
|
@ -719,6 +717,11 @@ impl CodeGenerator {
|
|||
.non_defaults
|
||||
.iter()
|
||||
.map(|p| p.inspect().map(|s| &s[..]).unwrap_or("_"))
|
||||
.chain(if let Some(var_args) = ¶ms.var_args {
|
||||
vec![var_args.inspect().map(|s| &s[..]).unwrap_or("_")]
|
||||
} else {
|
||||
vec![]
|
||||
})
|
||||
.chain(
|
||||
params
|
||||
.defaults
|
||||
|
@ -783,7 +786,7 @@ impl CodeGenerator {
|
|||
self.emit_store_instr(sig.ident, Name);
|
||||
}
|
||||
|
||||
fn emit_subr_def(&mut self, sig: SubrSignature, body: DefBody) {
|
||||
fn emit_subr_def(&mut self, class_name: Option<&str>, sig: SubrSignature, body: DefBody) {
|
||||
log!(info "entered {} ({sig} = {})", fn_name!(), body.block);
|
||||
let name = sig.ident.inspect().clone();
|
||||
let mut opcode_flag = 0u8;
|
||||
|
@ -800,7 +803,11 @@ impl CodeGenerator {
|
|||
self.write_arg(cellvars_len);
|
||||
opcode_flag += 8;
|
||||
}
|
||||
self.emit_load_const(name.clone());
|
||||
if let Some(class) = class_name {
|
||||
self.emit_load_const(Str::from(format!("{class}.{name}")));
|
||||
} else {
|
||||
self.emit_load_const(name);
|
||||
}
|
||||
self.write_instr(MAKE_FUNCTION);
|
||||
self.write_arg(opcode_flag);
|
||||
// stack_dec: <code obj> + <name> -> <function>
|
||||
|
@ -989,12 +996,15 @@ impl CodeGenerator {
|
|||
Expr::Accessor(Accessor::Local(local)) => {
|
||||
self.emit_call_local(local, call.args).unwrap()
|
||||
}
|
||||
other => todo!("calling {other}"),
|
||||
other => {
|
||||
self.codegen_expr(other);
|
||||
self.emit_args(call.args, Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_call_local(&mut self, local: Local, mut args: Args) -> CompileResult<()> {
|
||||
fn emit_call_local(&mut self, local: Local, args: Args) -> CompileResult<()> {
|
||||
log!(info "entered {}", fn_name!());
|
||||
match &local.inspect()[..] {
|
||||
"assert" => self.emit_assert_instr(args),
|
||||
|
@ -1008,33 +1018,13 @@ impl CodeGenerator {
|
|||
self.emit_load_name_instr(ident).unwrap_or_else(|e| {
|
||||
self.errs.push(e);
|
||||
});
|
||||
let argc = args.len();
|
||||
let mut kws = Vec::with_capacity(args.kw_len());
|
||||
while let Some(arg) = args.try_remove_pos(0) {
|
||||
self.codegen_expr(arg.expr);
|
||||
}
|
||||
while let Some(arg) = args.try_remove_kw(0) {
|
||||
kws.push(ValueObj::Str(arg.keyword.content.clone()));
|
||||
self.codegen_expr(arg.expr);
|
||||
}
|
||||
let kwsc = if !kws.is_empty() {
|
||||
let kws_tuple = ValueObj::from(kws);
|
||||
self.emit_load_const(kws_tuple);
|
||||
self.write_instr(CALL_FUNCTION_KW);
|
||||
1
|
||||
} else {
|
||||
self.write_instr(CALL_FUNCTION);
|
||||
0
|
||||
};
|
||||
self.write_arg(argc as u8);
|
||||
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
||||
self.stack_dec_n((1 + argc + kwsc) - 1);
|
||||
self.emit_args(args, Name);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_call_method(&mut self, obj: Expr, method_name: Token, mut args: Args) {
|
||||
fn emit_call_method(&mut self, obj: Expr, method_name: Token, args: Args) {
|
||||
log!(info "entered {}", fn_name!());
|
||||
if &method_name.inspect()[..] == "update!" {
|
||||
return self.emit_call_update(obj, args);
|
||||
|
@ -1050,11 +1040,29 @@ impl CodeGenerator {
|
|||
.unwrap_or_else(|err| {
|
||||
self.errs.push(err);
|
||||
});
|
||||
self.emit_args(args, Method);
|
||||
}
|
||||
|
||||
fn emit_args(&mut self, mut args: Args, kind: AccessKind) {
|
||||
let argc = args.len();
|
||||
let pos_len = args.pos_args.len();
|
||||
let mut kws = Vec::with_capacity(args.kw_len());
|
||||
while let Some(arg) = args.try_remove_pos(0) {
|
||||
self.codegen_expr(arg.expr);
|
||||
}
|
||||
if let Some(var_args) = &args.var_args {
|
||||
if pos_len > 0 {
|
||||
self.write_instr(Opcode::BUILD_LIST);
|
||||
self.write_arg(pos_len as u8);
|
||||
}
|
||||
self.codegen_expr(var_args.expr.clone());
|
||||
if pos_len > 0 {
|
||||
self.write_instr(Opcode::LIST_EXTEND);
|
||||
self.write_arg(1);
|
||||
self.write_instr(Opcode::LIST_TO_TUPLE);
|
||||
self.write_arg(0);
|
||||
}
|
||||
}
|
||||
while let Some(arg) = args.try_remove_kw(0) {
|
||||
kws.push(ValueObj::Str(arg.keyword.content.clone()));
|
||||
self.codegen_expr(arg.expr);
|
||||
|
@ -1063,13 +1071,27 @@ impl CodeGenerator {
|
|||
let kws_tuple = ValueObj::from(kws);
|
||||
self.emit_load_const(kws_tuple);
|
||||
self.write_instr(CALL_FUNCTION_KW);
|
||||
self.write_arg(argc as u8);
|
||||
1
|
||||
} else {
|
||||
self.write_instr(CALL_METHOD);
|
||||
if args.var_args.is_some() {
|
||||
self.write_instr(CALL_FUNCTION_EX);
|
||||
if kws.is_empty() {
|
||||
self.write_arg(0);
|
||||
} else {
|
||||
self.write_arg(1);
|
||||
}
|
||||
} else {
|
||||
if kind.is_method() {
|
||||
self.write_instr(CALL_METHOD);
|
||||
} else {
|
||||
self.write_instr(CALL_FUNCTION);
|
||||
}
|
||||
self.write_arg(argc as u8);
|
||||
}
|
||||
0
|
||||
};
|
||||
self.write_arg(argc as u8);
|
||||
// (1 (method) + argc + kwsc) input objects -> 1 return object
|
||||
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
||||
self.stack_dec_n((1 + argc + kwsc) - 1);
|
||||
}
|
||||
|
||||
|
@ -1149,7 +1171,7 @@ impl CodeGenerator {
|
|||
}
|
||||
Expr::Accessor(acc) => self.codegen_acc(acc),
|
||||
Expr::Def(def) => match def.sig {
|
||||
Signature::Subr(sig) => self.emit_subr_def(sig, def.body),
|
||||
Signature::Subr(sig) => self.emit_subr_def(None, sig, def.body),
|
||||
Signature::Var(sig) => self.emit_var_def(sig, def.body),
|
||||
},
|
||||
Expr::ClassDef(class) => self.emit_class_def(class),
|
||||
|
@ -1420,14 +1442,17 @@ impl CodeGenerator {
|
|||
let mod_name = self.toplevel_block_codeobj().name.clone();
|
||||
self.emit_load_const(mod_name);
|
||||
self.emit_store_instr(Identifier::public("__module__"), Name);
|
||||
self.emit_load_const(name);
|
||||
self.emit_load_const(name.clone());
|
||||
self.emit_store_instr(Identifier::public("__qualname__"), Name);
|
||||
self.emit_init_method(&class.sig, class.__new__.clone());
|
||||
if class.need_to_gen_new {
|
||||
self.emit_auto_new(&class.sig, class.__new__);
|
||||
self.emit_new_func(&class.sig, class.__new__);
|
||||
}
|
||||
// TODO: サブルーチンはT.subという書式でSTORE
|
||||
for def in class.private_methods.into_iter() {
|
||||
self.codegen_expr(Expr::Def(def));
|
||||
match def.sig {
|
||||
Signature::Subr(sig) => self.emit_subr_def(Some(&name[..]), sig, def.body),
|
||||
Signature::Var(sig) => self.emit_var_def(sig, def.body),
|
||||
}
|
||||
// TODO: discard
|
||||
if self.cur_block().stack_len == 1 {
|
||||
self.emit_pop_top();
|
||||
|
@ -1435,7 +1460,10 @@ impl CodeGenerator {
|
|||
}
|
||||
for mut def in class.public_methods.into_iter() {
|
||||
def.sig.ident_mut().dot = Some(Token::dummy());
|
||||
self.codegen_expr(Expr::Def(def));
|
||||
match def.sig {
|
||||
Signature::Subr(sig) => self.emit_subr_def(Some(&name[..]), sig, def.body),
|
||||
Signature::Var(sig) => self.emit_var_def(sig, def.body),
|
||||
}
|
||||
// TODO: discard
|
||||
if self.cur_block().stack_len == 1 {
|
||||
self.emit_pop_top();
|
||||
|
@ -1474,9 +1502,10 @@ impl CodeGenerator {
|
|||
unit.codeobj
|
||||
}
|
||||
|
||||
fn emit_auto_new(&mut self, sig: &Signature, __new__: Type) {
|
||||
fn emit_init_method(&mut self, sig: &Signature, __new__: Type) {
|
||||
log!(info "entered {}", fn_name!());
|
||||
let line = sig.ln_begin().unwrap();
|
||||
let class_name = sig.ident().inspect();
|
||||
let ident = Identifier::public_with_line(Token::dummy(), Str::ever("__init__"), line);
|
||||
let param_name = fresh_varname();
|
||||
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
||||
|
@ -1484,7 +1513,7 @@ impl CodeGenerator {
|
|||
let self_param = VarName::from_str_and_line(Str::ever("self"), line);
|
||||
let self_param = ParamSignature::new(ParamPattern::VarName(self_param), None, None);
|
||||
let params = Params::new(vec![self_param, param], None, vec![], None);
|
||||
let sig = Signature::Subr(SubrSignature::new(ident, params.clone(), __new__.clone()));
|
||||
let subr_sig = SubrSignature::new(ident, params.clone(), __new__.clone());
|
||||
let mut attrs = vec![];
|
||||
match __new__.non_default_params().unwrap()[0].typ() {
|
||||
// {x = Int; y = Int}
|
||||
|
@ -1519,8 +1548,49 @@ impl CodeGenerator {
|
|||
}
|
||||
let block = Block::new(attrs);
|
||||
let body = DefBody::new(Token::dummy(), block, DefId(0));
|
||||
let init_def = Def::new(sig, body.clone());
|
||||
self.codegen_expr(Expr::Def(init_def));
|
||||
self.emit_subr_def(Some(class_name), subr_sig, body);
|
||||
}
|
||||
|
||||
/// ```python
|
||||
/// class C:
|
||||
/// # __new__ => __call__
|
||||
/// def new(x): return C.__call__(x)
|
||||
/// ```
|
||||
fn emit_new_func(&mut self, sig: &Signature, __new__: Type) {
|
||||
log!(info "entered {}", fn_name!());
|
||||
let class_name = sig.ident().inspect();
|
||||
let line = sig.ln_begin().unwrap();
|
||||
let ident = Identifier::public_with_line(Token::dummy(), Str::ever("new"), line);
|
||||
let param_name = fresh_varname();
|
||||
let param = VarName::from_str_and_line(Str::from(param_name.clone()), line);
|
||||
let param = ParamSignature::new(ParamPattern::VarName(param), None, None);
|
||||
let sig = SubrSignature::new(
|
||||
ident,
|
||||
Params::new(vec![param], None, vec![], None),
|
||||
__new__.clone(),
|
||||
);
|
||||
let arg = PosArg::new(Expr::Accessor(Accessor::local(
|
||||
Token::symbol_with_line(¶m_name[..], line),
|
||||
Type::Failure,
|
||||
)));
|
||||
let class = Expr::Accessor(Accessor::local(
|
||||
Token::symbol_with_line(class_name, line),
|
||||
Type::Failure,
|
||||
));
|
||||
let class_new = Expr::Accessor(Accessor::attr(
|
||||
class,
|
||||
Token::symbol_with_line("__new__", line),
|
||||
Type::Failure,
|
||||
));
|
||||
let call = Expr::Call(Call::new(
|
||||
class_new,
|
||||
None,
|
||||
Args::new(vec![arg], None, vec![], None),
|
||||
Type::Failure,
|
||||
));
|
||||
let block = Block::new(vec![call]);
|
||||
let body = DefBody::new(Token::dummy(), block, DefId(0));
|
||||
self.emit_subr_def(Some(&class_name[..]), sig, body);
|
||||
}
|
||||
|
||||
fn codegen_block(&mut self, block: Block, opt_name: Option<Str>, params: Vec<Str>) -> CodeObj {
|
||||
|
|
|
@ -80,6 +80,10 @@ impl Context {
|
|||
})
|
||||
}
|
||||
|
||||
pub(crate) fn get_local_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
|
||||
self.locals.get_key_value(name)
|
||||
}
|
||||
|
||||
fn get_context(
|
||||
&self,
|
||||
obj: &hir::Expr,
|
||||
|
|
|
@ -490,6 +490,20 @@ impl Context {
|
|||
Self::poly_class(name, vec![], super_classes, super_traits, level)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn methods<S: Into<Str>>(name: S, level: usize) -> Self {
|
||||
Self::with_capacity(
|
||||
name.into(),
|
||||
ContextKind::MethodDefs,
|
||||
vec![],
|
||||
None,
|
||||
vec![],
|
||||
vec![],
|
||||
2,
|
||||
level,
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn poly_patch<S: Into<Str>>(
|
||||
name: S,
|
||||
|
|
|
@ -508,6 +508,7 @@ impl Context {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// e.g. .new
|
||||
fn register_auto_impl(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
|
@ -524,6 +525,23 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
/// e.g. ::__new__
|
||||
fn register_fixed_auto_impl(
|
||||
&mut self,
|
||||
name: &'static str,
|
||||
t: Type,
|
||||
muty: Mutability,
|
||||
vis: Visibility,
|
||||
) {
|
||||
let name = VarName::from_static(name);
|
||||
if self.locals.get(&name).is_some() {
|
||||
panic!("already registered: {name}");
|
||||
} else {
|
||||
self.locals
|
||||
.insert(name, VarInfo::new(t, muty, vis, VarKind::FixedAuto, None));
|
||||
}
|
||||
}
|
||||
|
||||
fn _register_gen_decl(&mut self, name: VarName, t: Type, vis: Visibility) {
|
||||
if self.decls.get(&name).is_some() {
|
||||
panic!("already registered: {name}");
|
||||
|
@ -577,11 +595,13 @@ impl Context {
|
|||
if gen.t.is_monomorphic() {
|
||||
let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||
let mut ctx = Self::mono_class(gen.t.name(), vec![], super_traits, self.level);
|
||||
let mut methods = Self::methods(gen.t.name(), self.level);
|
||||
let require = gen.require_or_sup.typ().clone();
|
||||
let new_t = func1(require, gen.t.clone());
|
||||
ctx.register_auto_impl("__new__", new_t.clone(), Immutable, Private);
|
||||
methods.register_fixed_auto_impl("__new__", new_t.clone(), Immutable, Private);
|
||||
// 必要なら、ユーザーが独自に上書きする
|
||||
ctx.register_auto_impl("new", new_t, Immutable, Public);
|
||||
methods.register_auto_impl("new", new_t, Immutable, Public);
|
||||
ctx.method_defs.push((gen.t.clone(), methods));
|
||||
self.register_gen_mono_type(gen, ctx, Const);
|
||||
} else {
|
||||
todo!()
|
||||
|
@ -593,6 +613,7 @@ impl Context {
|
|||
let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
|
||||
let mut ctx =
|
||||
Self::mono_class(gen.t.name(), super_classes, super_traits, self.level);
|
||||
let mut methods = Self::methods(gen.t.name(), self.level);
|
||||
if let Some(sup) = self.rec_get_const_obj(&gen.require_or_sup.typ().name()) {
|
||||
let sup = enum_unwrap!(sup, ValueObj::Type);
|
||||
let param_t = match sup {
|
||||
|
@ -607,9 +628,15 @@ impl Context {
|
|||
param_t.clone()
|
||||
};
|
||||
let new_t = func1(param_t, gen.t.clone());
|
||||
ctx.register_auto_impl("__new__", new_t.clone(), Immutable, Private);
|
||||
methods.register_fixed_auto_impl(
|
||||
"__new__",
|
||||
new_t.clone(),
|
||||
Immutable,
|
||||
Private,
|
||||
);
|
||||
// 必要なら、ユーザーが独自に上書きする
|
||||
ctx.register_auto_impl("new", new_t, Immutable, Public);
|
||||
methods.register_auto_impl("new", new_t, Immutable, Public);
|
||||
ctx.method_defs.push((gen.t.clone(), methods));
|
||||
self.register_gen_mono_type(gen, ctx, Const);
|
||||
} else {
|
||||
todo!("super class not found")
|
||||
|
|
|
@ -331,6 +331,30 @@ impl TyCheckError {
|
|||
)
|
||||
}
|
||||
|
||||
pub fn duplicate_definition_error(
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
caused_by: Str,
|
||||
name: &str,
|
||||
) -> Self {
|
||||
let name = readable_name(name);
|
||||
Self::new(
|
||||
ErrorCore::new(
|
||||
errno,
|
||||
NameError,
|
||||
loc,
|
||||
switch_lang!(
|
||||
"japanese" => format!("{name}は既に定義されています"),
|
||||
"simplified_chinese" => format!("{name}已定义"),
|
||||
"traditional_chinese" => format!("{name}已定義"),
|
||||
"english" => format!("{name} is already defined"),
|
||||
),
|
||||
Option::<Str>::None,
|
||||
),
|
||||
caused_by,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn violate_decl_error(
|
||||
errno: usize,
|
||||
loc: Location,
|
||||
|
|
|
@ -119,6 +119,7 @@ impl KwArg {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct Args {
|
||||
pub pos_args: Vec<PosArg>,
|
||||
pub var_args: Option<Box<PosArg>>,
|
||||
pub kw_args: Vec<KwArg>,
|
||||
paren: Option<(Token, Token)>,
|
||||
}
|
||||
|
@ -128,6 +129,10 @@ impl NestedDisplay for Args {
|
|||
if !self.pos_args.is_empty() {
|
||||
fmt_lines(self.pos_args.iter(), f, level)?;
|
||||
}
|
||||
if let Some(var_args) = &self.var_args {
|
||||
writeln!(f, "...")?;
|
||||
var_args.fmt_nest(f, level)?;
|
||||
}
|
||||
if !self.kw_args.is_empty() {
|
||||
fmt_lines(self.kw_args.iter(), f, level)?;
|
||||
}
|
||||
|
@ -139,6 +144,7 @@ impl From<Vec<Expr>> for Args {
|
|||
fn from(exprs: Vec<Expr>) -> Self {
|
||||
Self {
|
||||
pos_args: exprs.into_iter().map(PosArg::new).collect(),
|
||||
var_args: None,
|
||||
kw_args: Vec::new(),
|
||||
paren: None,
|
||||
}
|
||||
|
@ -167,30 +173,33 @@ impl Locational for Args {
|
|||
// impl_stream!(Args, KwArg, kw_args);
|
||||
|
||||
impl Args {
|
||||
pub const fn new(
|
||||
pub fn new(
|
||||
pos_args: Vec<PosArg>,
|
||||
var_args: Option<PosArg>,
|
||||
kw_args: Vec<KwArg>,
|
||||
paren: Option<(Token, Token)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
pos_args,
|
||||
var_args: var_args.map(Box::new),
|
||||
kw_args,
|
||||
paren,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn empty() -> Self {
|
||||
Self::new(vec![], vec![], None)
|
||||
pub fn empty() -> Self {
|
||||
Self::new(vec![], None, vec![], None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn len(&self) -> usize {
|
||||
self.pos_args.len() + self.kw_args.len()
|
||||
let var_argc = if self.var_args.is_none() { 0 } else { 1 };
|
||||
self.pos_args.len() + var_argc + self.kw_args.len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.pos_args.is_empty() && self.kw_args.is_empty()
|
||||
self.pos_args.is_empty() && self.var_args.is_none() && self.kw_args.is_empty()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -1338,7 +1347,7 @@ pub struct ClassDef {
|
|||
pub kind: TypeKind,
|
||||
pub sig: Signature,
|
||||
pub require_or_sup: Box<Expr>,
|
||||
/// The type of `new` and `__new__` that is automatically defined if not defined
|
||||
/// The type of `new` that is automatically defined if not defined
|
||||
pub need_to_gen_new: bool,
|
||||
pub __new__: Type,
|
||||
pub private_methods: RecordAttrs,
|
||||
|
|
|
@ -50,12 +50,12 @@ impl Linker {
|
|||
Expr::Methods(methods) => match &methods.class {
|
||||
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => {
|
||||
if let Some(pos) = self.def_root_pos_map.get(simple.name.inspect()) {
|
||||
let mut type_def = match new.remove(*pos) {
|
||||
Expr::ClassDef(type_def) => type_def,
|
||||
let mut class_def = match new.remove(*pos) {
|
||||
Expr::ClassDef(class_def) => class_def,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
type_def.methods_list.push(methods);
|
||||
new.insert(*pos, Expr::ClassDef(type_def));
|
||||
class_def.methods_list.push(methods);
|
||||
new.insert(*pos, Expr::ClassDef(class_def));
|
||||
} else {
|
||||
log!("{}", simple.name.inspect());
|
||||
log!("{}", self.def_root_pos_map);
|
||||
|
|
|
@ -330,6 +330,7 @@ impl ASTLowerer {
|
|||
let (pos_args, kw_args, paren) = call.args.deconstruct();
|
||||
let mut hir_args = hir::Args::new(
|
||||
Vec::with_capacity(pos_args.len()),
|
||||
None,
|
||||
Vec::with_capacity(kw_args.len()),
|
||||
paren,
|
||||
);
|
||||
|
@ -368,7 +369,7 @@ impl ASTLowerer {
|
|||
&[],
|
||||
&self.ctx.name,
|
||||
)?;
|
||||
let args = hir::Args::new(args, vec![], None);
|
||||
let args = hir::Args::new(args, None, vec![], None);
|
||||
Ok(hir::Call::new(class, Some(method_name), args, sig_t))
|
||||
}
|
||||
|
||||
|
@ -570,10 +571,33 @@ impl ASTLowerer {
|
|||
}
|
||||
}
|
||||
match self.ctx.pop() {
|
||||
Ok(ctx) => {
|
||||
self.check_override(&class, &ctx);
|
||||
Ok(methods) => {
|
||||
self.check_override(&class, &methods);
|
||||
if let Some((_, class_root)) = self.ctx.rec_get_mut_nominal_type_ctx(&class) {
|
||||
class_root.method_defs.push((class, ctx));
|
||||
for (newly_defined_name, _vi) in methods.locals.iter() {
|
||||
for (_, already_defined_methods) in class_root.method_defs.iter_mut() {
|
||||
// TODO: 特殊化なら同じ名前でもOK
|
||||
// TODO: 定義のメソッドもエラー表示
|
||||
if let Some((_already_defined_name, already_defined_vi)) =
|
||||
already_defined_methods
|
||||
.get_local_kv(&newly_defined_name.inspect())
|
||||
{
|
||||
if already_defined_vi.kind != VarKind::Auto {
|
||||
self.errs.push(LowerError::duplicate_definition_error(
|
||||
line!() as usize,
|
||||
newly_defined_name.loc(),
|
||||
methods.name.clone(),
|
||||
newly_defined_name.inspect(),
|
||||
));
|
||||
} else {
|
||||
already_defined_methods
|
||||
.locals
|
||||
.remove(&newly_defined_name.inspect()[..]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class_root.method_defs.push((class, methods));
|
||||
} else {
|
||||
todo!()
|
||||
}
|
||||
|
@ -589,8 +613,11 @@ impl ASTLowerer {
|
|||
.unwrap();
|
||||
let type_obj = enum_unwrap!(self.ctx.rec_get_const_obj(hir_def.sig.ident().inspect()).unwrap(), ValueObj::Type:(TypeObj::Generated:(_)));
|
||||
// vi.t.non_default_params().unwrap()[0].typ().clone()
|
||||
let (__new__, need_to_gen_new) = if let Some(vi) = ctx.get_current_scope_var("new") {
|
||||
(vi.t.clone(), vi.kind == VarKind::Auto)
|
||||
let (__new__, need_to_gen_new) = if let (Some(dunder_new_vi), Some(new_vi)) = (
|
||||
ctx.get_current_scope_var("__new__"),
|
||||
ctx.get_current_scope_var("new"),
|
||||
) {
|
||||
(dunder_new_vi.t.clone(), new_vi.kind == VarKind::Auto)
|
||||
} else {
|
||||
todo!()
|
||||
};
|
||||
|
|
|
@ -68,6 +68,7 @@ pub enum VarKind {
|
|||
default: DefaultInfo,
|
||||
},
|
||||
Auto,
|
||||
FixedAuto,
|
||||
DoesNotExist,
|
||||
Builtin,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue