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__")
.or_else(|| methods.get_def("__init__!"))
.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 {
self.emit_new_func(&class.sig, class.__new__);
self.emit_new_func(&class.sig, class.constructor);
}
let __del__ = methods
.remove_def("__del__")
@ -3526,16 +3526,16 @@ impl PyCodeGenerator {
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!());
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 class_name = sig.ident().inspect();
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 vi = VarInfo::nd_parameter(
__new__.return_t().unwrap().clone(),
constructor.return_t().unwrap().clone(),
ident.vi.def_loc.clone(),
"?".into(),
);
@ -3622,16 +3622,16 @@ impl PyCodeGenerator {
/// ```python
/// class C:
/// # __new__ => C
/// # constructor => C
/// 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!());
let class_ident = sig.ident();
let line = sig.ln_begin().unwrap_or(0);
let mut ident = Identifier::public_with_line(DOT, Str::ever("new"), line);
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() {
let param_name = new_first_param
.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> {
#[allow(clippy::manual_find)]
for methods in self.methods_list.iter() {

View file

@ -264,6 +264,22 @@ impl TypeContext {
pub const fn new(typ: Type, ctx: Context) -> Self {
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)]

View file

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

View file

@ -20,6 +20,18 @@ pub use crate::error::tycheck::*;
use crate::hir::Expr;
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)`
#[macro_export]
macro_rules! unreachable_error {

View file

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

View file

@ -1,4 +1,4 @@
time = pyimport "time"
{StructTime;} = pyimport "time"
.MINYEAR: {1}
.MAXYEAR: {9999}
@ -36,7 +36,7 @@ time = pyimport "time"
fromisoformat: (date_string: Str) -> .Date
fromisocalendar: (year: Nat, week: 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
weekday: (self: .Date) -> 0..6
isoweekday: (self: .Date) -> 1..7

View file

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

View file

@ -1157,7 +1157,7 @@ impl PyScriptGenerator {
"{}def __init__(self, param__):\n",
" ".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) => {
for field in rec.keys() {
let vis = if field.vis.is_private() { "__" } else { "" };

View file

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