mirror of
https://github.com/erg-lang/erg.git
synced 2025-07-07 21:25:31 +00:00
Implement Python class method declarations
This commit is contained in:
parent
e4c61392d2
commit
33edcd2e1c
7 changed files with 141 additions and 4 deletions
|
@ -1455,7 +1455,6 @@ impl CodeGenerator {
|
|||
log!(info "entered {}", fn_name!());
|
||||
let class = obj.ref_t().name(); // これは必ずmethodのあるクラスになっている
|
||||
let uniq_obj_name = obj.__name__().map(Str::rc);
|
||||
log!("{class} {method_name}");
|
||||
if &method_name.inspect()[..] == "update!" {
|
||||
return self.emit_call_update(obj, args);
|
||||
} else if is_fake_method(&class, method_name.inspect()) {
|
||||
|
|
|
@ -127,6 +127,43 @@ impl Context {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn get_mut_singular_ctx_from_ident(
|
||||
&mut self,
|
||||
ident: &ast::Identifier,
|
||||
namespace: &Str,
|
||||
) -> SingleTyCheckResult<&mut Context> {
|
||||
let err = TyCheckError::no_var_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
ident.loc(),
|
||||
namespace.into(),
|
||||
ident.inspect(),
|
||||
self.get_similar_name(ident.inspect()),
|
||||
);
|
||||
self.get_mut_type(ident.inspect())
|
||||
.map(|(_, ctx)| ctx)
|
||||
.ok_or(err)
|
||||
}
|
||||
|
||||
pub fn get_mut_singular_ctx(
|
||||
&mut self,
|
||||
obj: &ast::Expr,
|
||||
namespace: &Str,
|
||||
) -> SingleTyCheckResult<&mut Context> {
|
||||
match obj {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||
self.get_mut_singular_ctx_from_ident(ident, namespace)
|
||||
}
|
||||
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
|
||||
// REVIEW: 両方singularとは限らない?
|
||||
let ctx = self.get_mut_singular_ctx(&attr.obj, namespace)?;
|
||||
let attr = ast::Expr::Accessor(ast::Accessor::Ident(attr.ident.clone()));
|
||||
ctx.get_mut_singular_ctx(&attr, namespace)
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_match_call_t(
|
||||
&self,
|
||||
pos_args: &[hir::PosArg],
|
||||
|
@ -1567,6 +1604,16 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_mut_type(&mut self, name: &str) -> Option<(&Type, &mut Context)> {
|
||||
if let Some((t, ctx)) = self.mono_types.get_mut(name) {
|
||||
Some((t, ctx))
|
||||
} else if let Some((t, ctx)) = self.poly_types.get_mut(name) {
|
||||
Some((t, ctx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn rec_get_method_traits(&self, name: &Identifier) -> SingleTyCheckResult<&Type> {
|
||||
if let Some(candidates) = self.method_traits.get(name.inspect()) {
|
||||
let first_t = candidates.first().unwrap();
|
||||
|
|
|
@ -628,7 +628,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
fn register_gen_type(&mut self, ident: &Identifier, gen: GenTypeObj) {
|
||||
pub(crate) fn register_gen_type(&mut self, ident: &Identifier, gen: GenTypeObj) {
|
||||
match gen.kind {
|
||||
TypeKind::Class => {
|
||||
if gen.t.is_monomorphic() {
|
||||
|
|
|
@ -20,7 +20,7 @@ use erg_type::constructors::{
|
|||
};
|
||||
use erg_type::free::Constraint;
|
||||
use erg_type::typaram::TyParam;
|
||||
use erg_type::value::{GenTypeObj, TypeObj, ValueObj};
|
||||
use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||
use erg_type::{HasType, ParamTy, Type};
|
||||
|
||||
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
|
||||
|
@ -32,7 +32,7 @@ use crate::hir;
|
|||
use crate::hir::HIR;
|
||||
use crate::mod_cache::SharedModuleCache;
|
||||
use crate::reorder::Reorderer;
|
||||
use crate::varinfo::VarKind;
|
||||
use crate::varinfo::{Mutability, VarInfo, VarKind};
|
||||
use Visibility::*;
|
||||
|
||||
/// Singleton that checks types of an AST, and convert (lower) it into a HIR
|
||||
|
@ -1116,6 +1116,27 @@ impl ASTLowerer {
|
|||
res
|
||||
}
|
||||
|
||||
fn fake_lower_obj(&self, obj: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
match obj {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||
let acc = hir::Accessor::Ident(hir::Identifier::bare(ident.dot, ident.name));
|
||||
Ok(hir::Expr::Accessor(acc))
|
||||
}
|
||||
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
|
||||
let obj = self.fake_lower_obj(*attr.obj)?;
|
||||
let ident = hir::Identifier::bare(attr.ident.dot, attr.ident.name);
|
||||
let acc = hir::Accessor::attr(obj, ident, Type::Uninited);
|
||||
Ok(hir::Expr::Accessor(acc))
|
||||
}
|
||||
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
other.loc(),
|
||||
self.ctx.caused_by(),
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
fn declare_type(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||
log!(info "entered {}({})", fn_name!(), tasc);
|
||||
match *tasc.expr {
|
||||
|
@ -1126,17 +1147,75 @@ impl ASTLowerer {
|
|||
&mut None,
|
||||
RegistrationMode::Normal,
|
||||
)?;
|
||||
if ident.is_const() {
|
||||
let vi = VarInfo::new(
|
||||
t.clone(),
|
||||
Mutability::Const,
|
||||
ident.vis(),
|
||||
VarKind::Declared,
|
||||
None,
|
||||
);
|
||||
self.ctx.decls.insert(ident.name.clone(), vi);
|
||||
}
|
||||
self.ctx.assign_var_sig(
|
||||
&ast::VarSignature::new(ast::VarPattern::Ident(ident.clone()), None),
|
||||
&t,
|
||||
ast::DefId(0),
|
||||
)?;
|
||||
match t {
|
||||
Type::Class => {
|
||||
let ty_obj = GenTypeObj::new(
|
||||
TypeKind::Class,
|
||||
mono(self.ctx.path(), ident.inspect()),
|
||||
TypeObj::Builtin(Type::Uninited),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.ctx.register_gen_type(&ident, ty_obj);
|
||||
}
|
||||
Type::Trait => {
|
||||
let ty_obj = GenTypeObj::new(
|
||||
TypeKind::Trait,
|
||||
mono(self.ctx.path(), ident.inspect()),
|
||||
TypeObj::Builtin(Type::Uninited),
|
||||
None,
|
||||
None,
|
||||
);
|
||||
self.ctx.register_gen_type(&ident, ty_obj);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let ident = hir::Identifier::new(ident.dot, ident.name, None, t);
|
||||
Ok(hir::TypeAscription::new(
|
||||
hir::Expr::Accessor(hir::Accessor::Ident(ident)),
|
||||
tasc.t_spec,
|
||||
))
|
||||
}
|
||||
ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
|
||||
let t = self.ctx.instantiate_typespec(
|
||||
&tasc.t_spec,
|
||||
None,
|
||||
&mut None,
|
||||
RegistrationMode::Normal,
|
||||
)?;
|
||||
let namespace = self.ctx.name.clone();
|
||||
let ctx = self
|
||||
.ctx
|
||||
.get_mut_singular_ctx(attr.obj.as_ref(), &namespace)?;
|
||||
ctx.assign_var_sig(
|
||||
&ast::VarSignature::new(ast::VarPattern::Ident(attr.ident.clone()), None),
|
||||
&t,
|
||||
ast::DefId(0),
|
||||
)?;
|
||||
let obj = self.fake_lower_obj(*attr.obj)?;
|
||||
let ident =
|
||||
hir::Identifier::new(attr.ident.dot, attr.ident.name, None, Type::Uninited);
|
||||
let attr = hir::Accessor::attr(obj, ident, t);
|
||||
Ok(hir::TypeAscription::new(
|
||||
hir::Expr::Accessor(attr),
|
||||
tasc.t_spec,
|
||||
))
|
||||
}
|
||||
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||
self.cfg.input.clone(),
|
||||
line!() as usize,
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
.x: Int
|
||||
.f: Int -> Int
|
||||
|
||||
.C: ClassType
|
||||
.C.__call__: Int -> .C
|
||||
.C.f: Int -> Int
|
||||
|
|
|
@ -1,2 +1,8 @@
|
|||
x = 0
|
||||
def f(x: int) -> int: return x + 1
|
||||
|
||||
class C:
|
||||
def __init__(self, x: int) -> None:
|
||||
self.x = x
|
||||
def f(self, y: int) -> int:
|
||||
return self.x + y
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
declare = pyimport "declare"
|
||||
|
||||
print! declare.f(declare.x + 1)
|
||||
c = declare.C.__call__ 1
|
||||
print! c.f(1)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue