mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 10:49:54 +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!());
|
log!(info "entered {}", fn_name!());
|
||||||
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);
|
||||||
log!("{class} {method_name}");
|
|
||||||
if &method_name.inspect()[..] == "update!" {
|
if &method_name.inspect()[..] == "update!" {
|
||||||
return self.emit_call_update(obj, args);
|
return self.emit_call_update(obj, args);
|
||||||
} else if is_fake_method(&class, method_name.inspect()) {
|
} 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(
|
fn get_match_call_t(
|
||||||
&self,
|
&self,
|
||||||
pos_args: &[hir::PosArg],
|
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> {
|
fn rec_get_method_traits(&self, name: &Identifier) -> SingleTyCheckResult<&Type> {
|
||||||
if let Some(candidates) = self.method_traits.get(name.inspect()) {
|
if let Some(candidates) = self.method_traits.get(name.inspect()) {
|
||||||
let first_t = candidates.first().unwrap();
|
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 {
|
match gen.kind {
|
||||||
TypeKind::Class => {
|
TypeKind::Class => {
|
||||||
if gen.t.is_monomorphic() {
|
if gen.t.is_monomorphic() {
|
||||||
|
|
|
@ -20,7 +20,7 @@ use erg_type::constructors::{
|
||||||
};
|
};
|
||||||
use erg_type::free::Constraint;
|
use erg_type::free::Constraint;
|
||||||
use erg_type::typaram::TyParam;
|
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 erg_type::{HasType, ParamTy, Type};
|
||||||
|
|
||||||
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
|
use crate::context::{ClassDefType, Context, ContextKind, RegistrationMode};
|
||||||
|
@ -32,7 +32,7 @@ use crate::hir;
|
||||||
use crate::hir::HIR;
|
use crate::hir::HIR;
|
||||||
use crate::mod_cache::SharedModuleCache;
|
use crate::mod_cache::SharedModuleCache;
|
||||||
use crate::reorder::Reorderer;
|
use crate::reorder::Reorderer;
|
||||||
use crate::varinfo::VarKind;
|
use crate::varinfo::{Mutability, VarInfo, VarKind};
|
||||||
use Visibility::*;
|
use Visibility::*;
|
||||||
|
|
||||||
/// Singleton that checks types of an AST, and convert (lower) it into a HIR
|
/// Singleton that checks types of an AST, and convert (lower) it into a HIR
|
||||||
|
@ -1116,6 +1116,27 @@ impl ASTLowerer {
|
||||||
res
|
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> {
|
fn declare_type(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
|
||||||
log!(info "entered {}({})", fn_name!(), tasc);
|
log!(info "entered {}({})", fn_name!(), tasc);
|
||||||
match *tasc.expr {
|
match *tasc.expr {
|
||||||
|
@ -1126,17 +1147,75 @@ impl ASTLowerer {
|
||||||
&mut None,
|
&mut None,
|
||||||
RegistrationMode::Normal,
|
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(
|
self.ctx.assign_var_sig(
|
||||||
&ast::VarSignature::new(ast::VarPattern::Ident(ident.clone()), None),
|
&ast::VarSignature::new(ast::VarPattern::Ident(ident.clone()), None),
|
||||||
&t,
|
&t,
|
||||||
ast::DefId(0),
|
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);
|
let ident = hir::Identifier::new(ident.dot, ident.name, None, t);
|
||||||
Ok(hir::TypeAscription::new(
|
Ok(hir::TypeAscription::new(
|
||||||
hir::Expr::Accessor(hir::Accessor::Ident(ident)),
|
hir::Expr::Accessor(hir::Accessor::Ident(ident)),
|
||||||
tasc.t_spec,
|
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(
|
other => Err(LowerErrors::from(LowerError::declare_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
line!() as usize,
|
line!() as usize,
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
.x: Int
|
.x: Int
|
||||||
.f: Int -> Int
|
.f: Int -> Int
|
||||||
|
|
||||||
|
.C: ClassType
|
||||||
|
.C.__call__: Int -> .C
|
||||||
|
.C.f: Int -> Int
|
||||||
|
|
|
@ -1,2 +1,8 @@
|
||||||
x = 0
|
x = 0
|
||||||
def f(x: int) -> int: return x + 1
|
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"
|
declare = pyimport "declare"
|
||||||
|
|
||||||
print! declare.f(declare.x + 1)
|
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