mirror of
https://github.com/mtshiba/pylyzer.git
synced 2025-07-24 08:43:43 +00:00
feat: infer external class attributes types
This commit is contained in:
parent
5ed9306ee2
commit
59284b6ad5
4 changed files with 88 additions and 25 deletions
|
@ -8,12 +8,12 @@ use erg_compiler::artifact::IncompleteArtifact;
|
|||
use erg_compiler::erg_parser::ast::{
|
||||
Accessor, Args, Array, ArrayTypeSpec, BinOp, Block, ClassAttr, ClassAttrs, ClassDef,
|
||||
ConstAccessor, ConstArgs, ConstExpr, Decorator, Def, DefBody, DefId, DefaultParamSignature,
|
||||
Dict, Dummy, Expr, Identifier, KeyValue, Lambda, LambdaSignature, Literal, Methods, Module,
|
||||
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
|
||||
ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set, Signature,
|
||||
SimpleTypeSpec, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec, TypeSpecWithOp,
|
||||
UnaryOp, VarName, VarPattern, VarRecordAttr, VarRecordAttrs, VarRecordPattern, VarSignature,
|
||||
VisModifierSpec,
|
||||
Dict, Dummy, Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods,
|
||||
Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet,
|
||||
NormalTuple, ParamPattern, Params, PosArg, PreDeclTypeSpec, ReDef, Record, RecordAttrs, Set,
|
||||
Signature, SimpleTypeSpec, SubrSignature, Tuple, TypeAscription, TypeBoundSpecs, TypeSpec,
|
||||
TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarRecordAttrs, VarRecordPattern,
|
||||
VarSignature, VisModifierSpec,
|
||||
};
|
||||
use erg_compiler::erg_parser::desugar::Desugarer;
|
||||
use erg_compiler::erg_parser::token::{Token, TokenKind, COLON, DOT, EQUAL};
|
||||
|
@ -1231,7 +1231,10 @@ impl ASTConverter {
|
|||
let classdef = if inherit {
|
||||
// TODO: multiple inheritance
|
||||
let pos_args = vec![PosArg::new(bases.remove(0))];
|
||||
let args = Args::pos_only(pos_args, None);
|
||||
let mut args = Args::pos_only(pos_args, None);
|
||||
if let Some(rec @ Expr::Record(_)) = base_type {
|
||||
args.push_kw(KwArg::new(Token::symbol("Additional"), None, rec));
|
||||
}
|
||||
let inherit_acc = Expr::Accessor(Accessor::Ident(
|
||||
self.convert_ident("Inherit".to_string(), loc),
|
||||
));
|
||||
|
|
|
@ -5,7 +5,8 @@ use erg_common::config::Input;
|
|||
use erg_common::log;
|
||||
use erg_compiler::context::register::PylyzerStatus;
|
||||
use erg_compiler::hir::{Expr, HIR};
|
||||
use erg_compiler::ty::HasType;
|
||||
use erg_compiler::ty::value::{GenTypeObj, TypeObj};
|
||||
use erg_compiler::ty::{HasType, Type};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum CheckStatus {
|
||||
|
@ -28,7 +29,7 @@ pub struct DeclFile {
|
|||
}
|
||||
|
||||
fn escape_type(typ: String) -> String {
|
||||
typ.replace('%', "Type_")
|
||||
typ.replace('%', "Type_").replace("<module>", "")
|
||||
}
|
||||
|
||||
pub fn gen_decl_er(input: &Input, hir: HIR, status: CheckStatus) -> DeclFile {
|
||||
|
@ -45,28 +46,65 @@ pub fn gen_decl_er(input: &Input, hir: HIR, status: CheckStatus) -> DeclFile {
|
|||
};
|
||||
let mut code = format!("{status}\n");
|
||||
for chunk in hir.module.into_iter() {
|
||||
match chunk {
|
||||
Expr::Def(def) => {
|
||||
let name = def.sig.ident().inspect().replace('\0', "");
|
||||
let typ = def.sig.ident().ref_t().to_string();
|
||||
let typ = escape_type(typ);
|
||||
let decl = format!(".{name}: {typ}");
|
||||
code += &decl;
|
||||
}
|
||||
Expr::ClassDef(def) => {
|
||||
let name = def.sig.ident().inspect().replace('\0', "");
|
||||
let decl = format!(".{name}: ClassType");
|
||||
code += &decl;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
code.push('\n');
|
||||
gen_chunk_decl("", chunk, &mut code);
|
||||
}
|
||||
log!("code:\n{code}");
|
||||
let filename = input.unescaped_filename().replace(".py", ".d.er");
|
||||
DeclFile { filename, code }
|
||||
}
|
||||
|
||||
fn gen_chunk_decl(namespace: &str, chunk: Expr, code: &mut String) {
|
||||
match chunk {
|
||||
Expr::Def(def) => {
|
||||
let name = def.sig.ident().inspect().replace('\0', "");
|
||||
let typ = def.sig.ident().ref_t().to_string();
|
||||
let typ = escape_type(typ);
|
||||
let decl = format!("{namespace}.{name}: {typ}");
|
||||
*code += &decl;
|
||||
}
|
||||
Expr::ClassDef(def) => {
|
||||
let class_name = def.sig.ident().inspect().replace('\0', "");
|
||||
let namespace = format!("{namespace}.{class_name}");
|
||||
let decl = format!(".{class_name}: ClassType");
|
||||
*code += &decl;
|
||||
code.push('\n');
|
||||
if let GenTypeObj::Subclass(class) = &def.obj {
|
||||
let sup = class.sup.as_ref().typ().to_string();
|
||||
let sup = escape_type(sup);
|
||||
let decl = format!(".{class_name} <: {sup}\n");
|
||||
*code += &decl;
|
||||
}
|
||||
if let Some(TypeObj::Builtin {
|
||||
t: Type::Record(rec),
|
||||
..
|
||||
}) = def.obj.base_or_sup()
|
||||
{
|
||||
for (attr, t) in rec.iter() {
|
||||
let typ = escape_type(t.to_string());
|
||||
let decl = format!("{namespace}.{}: {typ}\n", attr.symbol);
|
||||
*code += &decl;
|
||||
}
|
||||
}
|
||||
if let Some(TypeObj::Builtin {
|
||||
t: Type::Record(rec),
|
||||
..
|
||||
}) = def.obj.additional()
|
||||
{
|
||||
for (attr, t) in rec.iter() {
|
||||
let typ = escape_type(t.to_string());
|
||||
let decl = format!("{namespace}.{}: {typ}\n", attr.symbol);
|
||||
*code += &decl;
|
||||
}
|
||||
}
|
||||
for attr in def.methods.into_iter() {
|
||||
gen_chunk_decl(&namespace, attr, code);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
code.push('\n');
|
||||
}
|
||||
|
||||
pub fn dump_decl_er(input: Input, hir: HIR, status: CheckStatus) {
|
||||
let file = gen_decl_er(&input, hir, status);
|
||||
let mut dir = input.dir();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue