chore: remove __new__

This commit is contained in:
Shunsuke Shibayama 2024-03-06 01:33:46 +09:00
parent ca140680db
commit f8b7717682
10 changed files with 131 additions and 43 deletions

View file

@ -3476,9 +3476,9 @@ impl PyCodeGenerator {
.get_def("__init__") .get_def("__init__")
.or_else(|| methods.get_def("__init__!")) .or_else(|| methods.get_def("__init__!"))
.cloned(); .cloned();
self.emit_init_method(&class.sig, __init__, class.__new__.clone()); self.emit_init_method(&class.sig, __init__, class.constructor.clone());
if class.need_to_gen_new { if class.need_to_gen_new {
self.emit_new_func(&class.sig, class.__new__); self.emit_new_func(&class.sig, class.constructor);
} }
let __del__ = methods let __del__ = methods
.remove_def("__del__") .remove_def("__del__")
@ -3526,16 +3526,16 @@ impl PyCodeGenerator {
unit.codeobj unit.codeobj
} }
fn emit_init_method(&mut self, sig: &Signature, __init__: Option<Def>, __new__: Type) { fn emit_init_method(&mut self, sig: &Signature, __init__: Option<Def>, constructor: Type) {
log!(info "entered {}", fn_name!()); log!(info "entered {}", fn_name!());
let new_first_param = __new__.non_default_params().unwrap().first(); let new_first_param = constructor.non_default_params().unwrap().first();
let line = sig.ln_begin().unwrap_or(0); let line = sig.ln_begin().unwrap_or(0);
let class_name = sig.ident().inspect(); let class_name = sig.ident().inspect();
let mut ident = Identifier::public_with_line(DOT, Str::ever("__init__"), line); let mut ident = Identifier::public_with_line(DOT, Str::ever("__init__"), line);
ident.vi.t = __new__.clone(); ident.vi.t = constructor.clone();
let self_param = VarName::from_str_and_line(Str::ever("self"), line); let self_param = VarName::from_str_and_line(Str::ever("self"), line);
let vi = VarInfo::nd_parameter( let vi = VarInfo::nd_parameter(
__new__.return_t().unwrap().clone(), constructor.return_t().unwrap().clone(),
ident.vi.def_loc.clone(), ident.vi.def_loc.clone(),
"?".into(), "?".into(),
); );
@ -3622,16 +3622,16 @@ impl PyCodeGenerator {
/// ```python /// ```python
/// class C: /// class C:
/// # __new__ => C /// # constructor => C
/// def new(x): return C(x) /// def new(x): return C(x)
/// ``` /// ```
fn emit_new_func(&mut self, sig: &Signature, __new__: Type) { fn emit_new_func(&mut self, sig: &Signature, constructor: Type) {
log!(info "entered {}", fn_name!()); log!(info "entered {}", fn_name!());
let class_ident = sig.ident(); let class_ident = sig.ident();
let line = sig.ln_begin().unwrap_or(0); let line = sig.ln_begin().unwrap_or(0);
let mut ident = Identifier::public_with_line(DOT, Str::ever("new"), line); let mut ident = Identifier::public_with_line(DOT, Str::ever("new"), line);
let class = Expr::Accessor(Accessor::Ident(class_ident.clone())); let class = Expr::Accessor(Accessor::Ident(class_ident.clone()));
ident.vi.t = __new__; ident.vi.t = constructor;
if let Some(new_first_param) = ident.vi.t.non_default_params().unwrap().first() { if let Some(new_first_param) = ident.vi.t.non_default_params().unwrap().first() {
let param_name = new_first_param let param_name = new_first_param
.name() .name()

View file

@ -167,6 +167,27 @@ impl Context {
}) })
} }
pub(crate) fn get_current_scope_attr(&self, name: &VarName) -> Option<&VarInfo> {
#[cfg(feature = "py_compat")]
let search_name = self
.erg_to_py_names
.get(name.inspect())
.unwrap_or(name.inspect());
#[cfg(not(feature = "py_compat"))]
let search_name = name.inspect();
self.locals
.get(search_name)
.or_else(|| self.decls.get(search_name))
.or_else(|| {
for methods in self.methods_list.iter() {
if let Some(vi) = methods.get_current_scope_attr(name) {
return Some(vi);
}
}
None
})
}
pub(crate) fn get_method_context_of(&self, trait_: &Type) -> Option<&MethodContext> { pub(crate) fn get_method_context_of(&self, trait_: &Type) -> Option<&MethodContext> {
#[allow(clippy::manual_find)] #[allow(clippy::manual_find)]
for methods in self.methods_list.iter() { for methods in self.methods_list.iter() {

View file

@ -264,6 +264,22 @@ impl TypeContext {
pub const fn new(typ: Type, ctx: Context) -> Self { pub const fn new(typ: Type, ctx: Context) -> Self {
Self { typ, ctx } Self { typ, ctx }
} }
pub(crate) fn get_class_attr<'c>(
&'c self,
name: &VarName,
ctx: &'c Context,
) -> Option<&'c VarInfo> {
self.get_current_scope_attr(name).or_else(|| {
let sups = ctx.get_nominal_super_type_ctxs(&self.typ)?;
for sup in sups {
if let Some(vi) = sup.get_current_scope_attr(name) {
return Some(vi);
}
}
None
})
}
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]

View file

@ -31,7 +31,7 @@ use crate::ty::{
}; };
use crate::context::{ClassDefType, Context, ContextKind, DefaultInfo, RegistrationMode}; use crate::context::{ClassDefType, Context, ContextKind, DefaultInfo, RegistrationMode};
use crate::error::readable_name; use crate::error::{concat_result, readable_name};
use crate::error::{ use crate::error::{
CompileError, CompileErrors, CompileResult, TyCheckError, TyCheckErrors, TyCheckResult, CompileError, CompileErrors, CompileResult, TyCheckError, TyCheckErrors, TyCheckResult,
}; };
@ -1337,6 +1337,8 @@ impl Context {
} }
/// e.g. `::__call__` /// e.g. `::__call__`
///
/// NOTE: this is same as `register_auto_impl` if `PYTHON_MODE` is true
fn register_fixed_auto_impl( fn register_fixed_auto_impl(
&mut self, &mut self,
name: &'static str, name: &'static str,
@ -1346,6 +1348,11 @@ impl Context {
py_name: Option<Str>, py_name: Option<Str>,
) -> CompileResult<()> { ) -> CompileResult<()> {
let name = VarName::from_static(name); let name = VarName::from_static(name);
let kind = if PYTHON_MODE {
VarKind::Auto
} else {
VarKind::FixedAuto
};
if self.locals.get(&name).is_some() { if self.locals.get(&name).is_some() {
Err(CompileErrors::from(CompileError::reassign_error( Err(CompileErrors::from(CompileError::reassign_error(
self.cfg.input.clone(), self.cfg.input.clone(),
@ -1361,7 +1368,7 @@ impl Context {
t, t,
muty, muty,
vis, vis,
VarKind::FixedAuto, kind,
None, None,
self.kind.clone(), self.kind.clone(),
py_name, py_name,
@ -1607,8 +1614,9 @@ impl Context {
2, 2,
self.level, self.level,
); );
self.gen_class_new_method(&gen, call, &mut ctx)?; let res = self.gen_class_new_method(&gen, call, &mut ctx);
self.register_gen_mono_type(ident, gen, ctx, Const) let res2 = self.register_gen_mono_type(ident, gen, ctx, Const);
concat_result(res, res2)
} else { } else {
let params = gen let params = gen
.typ() .typ()
@ -1627,11 +1635,13 @@ impl Context {
2, 2,
self.level, self.level,
); );
self.gen_class_new_method(&gen, call, &mut ctx)?; let res = self.gen_class_new_method(&gen, call, &mut ctx);
self.register_gen_poly_type(ident, gen, ctx, Const) let res2 = self.register_gen_poly_type(ident, gen, ctx, Const);
concat_result(res, res2)
} }
} }
GenTypeObj::Subclass(_) => { GenTypeObj::Subclass(_) => {
let mut errs = CompileErrors::empty();
if gen.typ().is_monomorphic() { if gen.typ().is_monomorphic() {
let super_classes = vec![gen.base_or_sup().unwrap().typ().clone()]; let super_classes = vec![gen.base_or_sup().unwrap().typ().clone()];
// let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect(); // let super_traits = gen.impls.iter().map(|to| to.typ().clone()).collect();
@ -1643,7 +1653,7 @@ impl Context {
self.level, self.level,
); );
for sup in super_classes.into_iter() { for sup in super_classes.into_iter() {
let sup_ctx = self.get_nominal_type_ctx(&sup).ok_or_else(|| { let sup_ctx = match self.get_nominal_type_ctx(&sup).ok_or_else(|| {
TyCheckErrors::from(TyCheckError::type_not_found( TyCheckErrors::from(TyCheckError::type_not_found(
self.cfg.input.clone(), self.cfg.input.clone(),
line!() as usize, line!() as usize,
@ -1651,7 +1661,13 @@ impl Context {
self.caused_by(), self.caused_by(),
&sup, &sup,
)) ))
})?; }) {
Ok(ctx) => ctx,
Err(es) => {
errs.extend(es);
continue;
}
};
ctx.register_superclass(sup, sup_ctx); ctx.register_superclass(sup, sup_ctx);
} }
let mut methods = let mut methods =
@ -1669,40 +1685,58 @@ impl Context {
.. ..
} = additional } = additional
{ {
self.register_instance_attrs(&mut ctx, rec, call)?; if let Err(es) = self.register_instance_attrs(&mut ctx, rec, call) {
errs.extend(es);
}
} }
param_t param_t
.map(|t| self.intersection(t, additional.typ())) .map(|t| self.intersection(t, additional.typ()))
.or(Some(additional.typ().clone())) .or(Some(additional.typ().clone()))
} else { } else {
param_t.cloned() self.get_nominal_type_ctx(sup.typ())
.and_then(|ctx| {
ctx.get_class_attr(&VarName::from_static("__call__"), ctx)
})
.and_then(|vi| vi.t.param_ts().first().cloned())
.or(param_t.cloned())
}; };
let new_t = if let Some(t) = param_t { let new_t = if let Some(t) = param_t {
func1(t, gen.typ().clone()) func1(t, gen.typ().clone())
} else { } else {
func0(gen.typ().clone()) func0(gen.typ().clone())
}; };
methods.register_fixed_auto_impl( if let Err(es) = methods.register_fixed_auto_impl(
"__call__", "__call__",
new_t.clone(), new_t.clone(),
Immutable, Immutable,
Visibility::private(ctx.name.clone()), Visibility::private(ctx.name.clone()),
None, None,
)?; ) {
errs.extend(es);
}
// 必要なら、ユーザーが独自に上書きする // 必要なら、ユーザーが独自に上書きする
methods.register_auto_impl( if let Err(es) = methods.register_auto_impl(
"new", "new",
new_t, new_t,
Immutable, Immutable,
Visibility::public(ctx.name.clone()), Visibility::public(ctx.name.clone()),
None, None,
)?; ) {
errs.extend(es);
}
ctx.methods_list.push(MethodContext::new( ctx.methods_list.push(MethodContext::new(
DefId(0), DefId(0),
ClassDefType::Simple(gen.typ().clone()), ClassDefType::Simple(gen.typ().clone()),
methods, methods,
)); ));
self.register_gen_mono_type(ident, gen, ctx, Const) if let Err(es) = self.register_gen_mono_type(ident, gen, ctx, Const) {
errs.extend(es);
}
if errs.is_empty() {
Ok(())
} else {
Err(errs)
}
} else { } else {
let class_name = gen.base_or_sup().unwrap().typ().local_name(); let class_name = gen.base_or_sup().unwrap().typ().local_name();
Err(CompileErrors::from(CompileError::no_type_error( Err(CompileErrors::from(CompileError::no_type_error(
@ -1733,14 +1767,17 @@ impl Context {
2, 2,
self.level, self.level,
); );
if let Some(TypeObj::Builtin { let res = if let Some(TypeObj::Builtin {
t: Type::Record(req), t: Type::Record(req),
.. ..
}) = gen.base_or_sup() }) = gen.base_or_sup()
{ {
self.register_instance_attrs(&mut ctx, req, call)?; self.register_instance_attrs(&mut ctx, req, call)
} } else {
self.register_gen_mono_type(ident, gen, ctx, Const) Ok(())
};
let res2 = self.register_gen_mono_type(ident, gen, ctx, Const);
concat_result(res, res2)
} else { } else {
feature_error!( feature_error!(
CompileErrors, CompileErrors,
@ -1771,9 +1808,11 @@ impl Context {
} else { } else {
None None
}; };
if let Some(additional) = additional { let res = if let Some(additional) = additional {
self.register_instance_attrs(&mut ctx, additional, call)?; self.register_instance_attrs(&mut ctx, additional, call)
} } else {
Ok(())
};
for sup in super_classes.into_iter() { for sup in super_classes.into_iter() {
if let Some(sup_ctx) = self.get_nominal_type_ctx(&sup) { if let Some(sup_ctx) = self.get_nominal_type_ctx(&sup) {
ctx.register_supertrait(sup, sup_ctx); ctx.register_supertrait(sup, sup_ctx);
@ -1781,7 +1820,8 @@ impl Context {
log!(err "{sup} not found"); log!(err "{sup} not found");
} }
} }
self.register_gen_mono_type(ident, gen, ctx, Const) let res2 = self.register_gen_mono_type(ident, gen, ctx, Const);
concat_result(res, res2)
} else { } else {
feature_error!( feature_error!(
CompileErrors, CompileErrors,

View file

@ -20,6 +20,18 @@ pub use crate::error::tycheck::*;
use crate::hir::Expr; use crate::hir::Expr;
use crate::ty::HasType; use crate::ty::HasType;
pub(crate) fn concat_result(l: CompileResult<()>, r: CompileResult<()>) -> CompileResult<()> {
match (l, r) {
(Ok(()), Ok(())) => Ok(()),
(Ok(()), Err(r)) => Err(r),
(Err(l), Ok(())) => Err(l),
(Err(mut l), Err(mut r)) => {
l.0.append(&mut r.0);
Err(l)
}
}
}
/// `unreachable!(self: Context)` /// `unreachable!(self: Context)`
#[macro_export] #[macro_export]
macro_rules! unreachable_error { macro_rules! unreachable_error {

View file

@ -2435,7 +2435,7 @@ pub struct ClassDef {
pub require_or_sup: Option<Box<Expr>>, pub require_or_sup: Option<Box<Expr>>,
/// The type of `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 need_to_gen_new: bool,
pub __new__: Type, pub constructor: Type,
pub methods_list: Vec<Methods>, pub methods_list: Vec<Methods>,
} }
@ -2488,7 +2488,7 @@ impl ClassDef {
sig: Signature, sig: Signature,
require_or_sup: Option<Expr>, require_or_sup: Option<Expr>,
need_to_gen_new: bool, need_to_gen_new: bool,
__new__: Type, constructor: Type,
methods_list: Vec<Methods>, methods_list: Vec<Methods>,
) -> Self { ) -> Self {
Self { Self {
@ -2496,7 +2496,7 @@ impl ClassDef {
sig, sig,
require_or_sup: require_or_sup.map(Box::new), require_or_sup: require_or_sup.map(Box::new),
need_to_gen_new, need_to_gen_new,
__new__, constructor,
methods_list, methods_list,
} }
} }

View file

@ -1,4 +1,4 @@
time = pyimport "time" {StructTime;} = pyimport "time"
.MINYEAR: {1} .MINYEAR: {1}
.MAXYEAR: {9999} .MAXYEAR: {9999}
@ -36,7 +36,7 @@ time = pyimport "time"
fromisoformat: (date_string: Str) -> .Date fromisoformat: (date_string: Str) -> .Date
fromisocalendar: (year: Nat, week: Nat, day: Nat) -> .Date fromisocalendar: (year: Nat, week: Nat, day: Nat) -> .Date
replace: (self: .Date, year := Nat, month := Nat, day := Nat) -> .Date replace: (self: .Date, year := Nat, month := Nat, day := Nat) -> .Date
timetuple: (self: .Date) -> time.StructTime timetuple: (self: .Date) -> StructTime
toordinal: (self: .Date) -> Nat toordinal: (self: .Date) -> Nat
weekday: (self: .Date) -> 0..6 weekday: (self: .Date) -> 0..6
isoweekday: (self: .Date) -> 1..7 isoweekday: (self: .Date) -> 1..7

View file

@ -2301,9 +2301,8 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
self.errs.extend(err); self.errs.extend(err);
} }
} }
let Some(__new__) = class_ctx let Some(constructor) =
.get_current_scope_var(&VarName::from_static("__new__")) class_ctx.get_class_attr(&VarName::from_static("__call__"), &self.module.context)
.or(class_ctx.get_current_scope_var(&VarName::from_static("__call__")))
else { else {
return unreachable_error!(LowerErrors, LowerError, self); return unreachable_error!(LowerErrors, LowerError, self);
}; };
@ -2316,7 +2315,7 @@ impl<A: ASTBuildable> GenericASTLowerer<A> {
hir_def.sig, hir_def.sig,
require_or_sup, require_or_sup,
need_to_gen_new, need_to_gen_new,
__new__.t.clone(), constructor.t.clone(),
hir_methods_list, hir_methods_list,
)) ))
} }

View file

@ -1157,7 +1157,7 @@ impl PyScriptGenerator {
"{}def __init__(self, param__):\n", "{}def __init__(self, param__):\n",
" ".repeat(self.level + 1) " ".repeat(self.level + 1)
); );
match classdef.__new__.non_default_params().unwrap()[0].typ() { match classdef.constructor.non_default_params().unwrap()[0].typ() {
Type::Record(rec) => { Type::Record(rec) => {
for field in rec.keys() { for field in rec.keys() {
let vis = if field.vis.is_private() { "__" } else { "" }; let vis = if field.vis.is_private() { "__" } else { "" };

View file

@ -125,7 +125,7 @@ fn exec_invalid_class_inheritable() -> Result<(), ()> {
"Point3d.", "Point3d.",
"@Override", "@Override",
"new(x, y, z) =", "new(x, y, z) =",
"Point3d::__new__{x; y; z}", "Point3d {x; y; z}",
"", "",
"norm self = self::x**2 + self::y**2 + self::z**2", "norm self = self::x**2 + self::y**2 + self::z**2",
"", "",