Add ast::AttrDef

This commit is contained in:
Shunsuke Shibayama 2022-12-11 12:15:34 +09:00
parent f1ff0d1ddf
commit 2e60d8c885
3 changed files with 83 additions and 33 deletions

View file

@ -1368,6 +1368,21 @@ impl ASTLowerer {
Ok(hir::PatchDef::new(hir_def.sig, base, hir_methods))
}
fn lower_attr_def(&mut self, attr_def: ast::AttrDef) -> LowerResult<hir::AttrDef> {
log!(info "entered {}({attr_def})", fn_name!());
let attr = self.lower_acc(attr_def.attr)?;
let expr = self.lower_expr(*attr_def.expr)?;
if let Err(err) = self.var_result_t_check(
attr.loc(),
&Str::from(attr.show()),
attr.ref_t(),
expr.ref_t(),
) {
self.errs.push(err);
}
Ok(hir::AttrDef::new(attr, hir::Block::new(vec![expr])))
}
fn register_trait_impl(
&mut self,
class: &Type,
@ -1748,6 +1763,7 @@ impl ASTLowerer {
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.lower_def(def)?)),
ast::Expr::ClassDef(defs) => Ok(hir::Expr::ClassDef(self.lower_class_def(defs)?)),
ast::Expr::PatchDef(defs) => Ok(hir::Expr::PatchDef(self.lower_patch_def(defs)?)),
ast::Expr::AttrDef(adef) => Ok(hir::Expr::AttrDef(self.lower_attr_def(adef)?)),
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.lower_type_asc(tasc)?)),
other => todo!("{other}"),
}

View file

@ -3385,6 +3385,33 @@ impl Def {
}
}
/// This is not necessary for Erg syntax, but necessary for mapping ASTs in Python
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct AttrDef {
pub attr: Accessor,
pub expr: Box<Expr>,
}
impl NestedDisplay for AttrDef {
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
self.attr.fmt_nest(f, level)?;
writeln!(f, " = ")?;
self.expr.fmt_nest(f, level + 1)
}
}
impl_display_from_nested!(AttrDef);
impl_locational!(AttrDef, attr, expr);
impl AttrDef {
pub fn new(attr: Accessor, expr: Expr) -> Self {
Self {
attr,
expr: Box::new(expr),
}
}
}
/// e.g.
/// ```python
/// T = Class ...
@ -3495,11 +3522,12 @@ pub enum Expr {
Methods(Methods),
ClassDef(ClassDef),
PatchDef(PatchDef),
AttrDef(AttrDef),
}
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef, PatchDef);
impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef, PatchDef, AttrDef);
impl_display_from_nested!(Expr);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef, PatchDef);
impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record, BinOp, UnaryOp, Call, DataPack, Lambda, TypeAsc, Def, Methods, ClassDef, PatchDef, AttrDef);
impl Expr {
pub fn is_match_call(&self) -> bool {

View file

@ -12,14 +12,14 @@ use erg_common::Str;
use erg_common::{enum_unwrap, get_hash, log, set};
use crate::ast::{
Accessor, Args, Array, ArrayComprehension, ArrayTypeSpec, ArrayWithLength, BinOp, Block, Call,
ClassAttr, ClassAttrs, ClassDef, ConstExpr, DataPack, Def, DefBody, DefId, Dict, Expr,
Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord, Module,
NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple,
ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record, RecordAttrOrIdent,
RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple, TupleTypeSpec,
TypeAppArgs, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern,
VarRecordAttr, VarSignature,
Accessor, Args, Array, ArrayComprehension, ArrayTypeSpec, ArrayWithLength, AttrDef, BinOp,
Block, Call, ClassAttr, ClassAttrs, ClassDef, ConstExpr, DataPack, Def, DefBody, DefId, Dict,
Expr, Identifier, KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, MixedRecord,
Module, NonDefaultParamSignature, NormalArray, NormalDict, NormalRecord, NormalSet,
NormalTuple, ParamPattern, ParamRecordAttr, Params, PatchDef, PosArg, Record,
RecordAttrOrIdent, RecordAttrs, Set as astSet, SetWithLength, Signature, SubrSignature, Tuple,
TupleTypeSpec, TypeAppArgs, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName,
VarPattern, VarRecordAttr, VarSignature,
};
use crate::token::{Token, TokenKind, COLON, DOT};
@ -73,6 +73,29 @@ impl Desugarer {
Args::new(pos_args, kw_args, paren)
}
fn perform_desugar_acc(mut desugar: impl FnMut(Expr) -> Expr, acc: Accessor) -> Accessor {
match acc {
Accessor::Ident(ident) => Accessor::Ident(ident),
Accessor::Attr(attr) => desugar(*attr.obj).attr(attr.ident),
Accessor::TupleAttr(tup) => {
let obj = desugar(*tup.obj);
obj.tuple_attr(tup.index)
}
Accessor::Subscr(sub) => {
let obj = desugar(*sub.obj);
let index = desugar(*sub.index);
obj.subscr(index, sub.r_sqbr)
}
Accessor::TypeApp(tapp) => {
let obj = desugar(*tapp.obj);
let args = Self::desugar_args(desugar, tapp.type_args.args);
let type_args =
TypeAppArgs::new(tapp.type_args.l_vbar, args, tapp.type_args.r_vbar);
obj.type_app(type_args)
}
}
}
fn perform_desugar(mut desugar: impl FnMut(Expr) -> Expr, expr: Expr) -> Expr {
match expr {
Expr::Lit(_) => expr,
@ -234,6 +257,11 @@ impl Desugarer {
.collect();
Expr::PatchDef(PatchDef::new(def, methods))
}
Expr::AttrDef(adef) => {
let expr = desugar(*adef.expr);
let attr = Self::perform_desugar_acc(desugar, adef.attr);
Expr::AttrDef(AttrDef::new(attr, expr))
}
Expr::Lambda(lambda) => {
let mut chunks = vec![];
for chunk in lambda.body.into_iter() {
@ -267,29 +295,7 @@ impl Desugarer {
let new_attrs = ClassAttrs::from(new_attrs);
Expr::Methods(Methods::new(method_defs.class, method_defs.vis, new_attrs))
}
Expr::Accessor(acc) => {
let acc = match acc {
Accessor::Ident(ident) => Accessor::Ident(ident),
Accessor::Attr(attr) => desugar(*attr.obj).attr(attr.ident),
Accessor::TupleAttr(tup) => {
let obj = desugar(*tup.obj);
obj.tuple_attr(tup.index)
}
Accessor::Subscr(sub) => {
let obj = desugar(*sub.obj);
let index = desugar(*sub.index);
obj.subscr(index, sub.r_sqbr)
}
Accessor::TypeApp(tapp) => {
let obj = desugar(*tapp.obj);
let args = Self::desugar_args(desugar, tapp.type_args.args);
let type_args =
TypeAppArgs::new(tapp.type_args.l_vbar, args, tapp.type_args.r_vbar);
obj.type_app(type_args)
}
};
Expr::Accessor(acc)
}
Expr::Accessor(acc) => Expr::Accessor(Self::perform_desugar_acc(desugar, acc)),
}
}