mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 18:58:30 +00:00
WIP: Enable to declare in class methods definitions
This commit is contained in:
parent
60956a590e
commit
14b143778f
5 changed files with 143 additions and 53 deletions
|
@ -1098,24 +1098,35 @@ impl ASTLowerer {
|
|||
}
|
||||
let kind = ContextKind::MethodDefs(impl_trait.as_ref().map(|(t, _)| t.clone()));
|
||||
self.ctx.grow(&class.local_name(), kind, Private, None);
|
||||
for def in methods.defs.iter_mut() {
|
||||
if methods.vis.is(TokenKind::Dot) {
|
||||
def.sig.ident_mut().unwrap().dot = Some(Token::new(
|
||||
TokenKind::Dot,
|
||||
".",
|
||||
def.sig.ln_begin().unwrap(),
|
||||
def.sig.col_begin().unwrap(),
|
||||
));
|
||||
}
|
||||
self.ctx.preregister_def(def)?;
|
||||
}
|
||||
for def in methods.defs.into_iter() {
|
||||
match self.lower_def(def) {
|
||||
Ok(def) => {
|
||||
hir_methods.push(hir::Expr::Def(def));
|
||||
for attr in methods.attrs.iter_mut() {
|
||||
match attr {
|
||||
ast::ClassAttr::Def(def) => {
|
||||
if methods.vis.is(TokenKind::Dot) {
|
||||
def.sig.ident_mut().unwrap().dot = Some(Token::new(
|
||||
TokenKind::Dot,
|
||||
".",
|
||||
def.sig.ln_begin().unwrap(),
|
||||
def.sig.col_begin().unwrap(),
|
||||
));
|
||||
}
|
||||
self.ctx.preregister_def(def)?;
|
||||
}
|
||||
Err(errs) => {
|
||||
self.errs.extend(errs.into_iter());
|
||||
ast::ClassAttr::Decl(_decl) => {}
|
||||
}
|
||||
}
|
||||
for attr in methods.attrs.into_iter() {
|
||||
match attr {
|
||||
ast::ClassAttr::Def(def) => match self.lower_def(def) {
|
||||
Ok(def) => {
|
||||
hir_methods.push(hir::Expr::Def(def));
|
||||
}
|
||||
Err(errs) => {
|
||||
self.errs.extend(errs.into_iter());
|
||||
}
|
||||
},
|
||||
ast::ClassAttr::Decl(decl) => {
|
||||
let decl = self.lower_type_asc(decl)?;
|
||||
hir_methods.push(hir::Expr::TypeAsc(decl));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1590,6 +1601,10 @@ impl ASTLowerer {
|
|||
res
|
||||
}
|
||||
|
||||
fn declare_class_def(&mut self, _class_def: ast::ClassDef) -> LowerResult<hir::ClassDef> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn fake_lower_obj(&self, obj: ast::Expr) -> LowerResult<hir::Expr> {
|
||||
match obj {
|
||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||
|
@ -1748,12 +1763,9 @@ impl ASTLowerer {
|
|||
log!(info "entered {}", fn_name!());
|
||||
match expr {
|
||||
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_alias_or_import(def)?)),
|
||||
ast::Expr::ClassDef(defs) => Err(LowerErrors::from(LowerError::feature_error(
|
||||
self.cfg.input.clone(),
|
||||
defs.loc(),
|
||||
"class declaration",
|
||||
self.ctx.caused_by(),
|
||||
))),
|
||||
ast::Expr::ClassDef(class_def) => {
|
||||
Ok(hir::Expr::ClassDef(self.declare_class_def(class_def)?))
|
||||
}
|
||||
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
|
||||
ast::Expr::Call(call)
|
||||
if call
|
||||
|
|
|
@ -704,6 +704,60 @@ impl_nested_display_for_enum!(Dict; Normal, Comprehension);
|
|||
impl_display_for_enum!(Dict; Normal, Comprehension);
|
||||
impl_locational_for_enum!(Dict; Normal, Comprehension);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum ClassAttr {
|
||||
Def(Def),
|
||||
Decl(TypeAscription),
|
||||
}
|
||||
|
||||
impl_nested_display_for_enum!(ClassAttr; Def, Decl);
|
||||
impl_display_for_enum!(ClassAttr; Def, Decl);
|
||||
impl_locational_for_enum!(ClassAttr; Def, Decl);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct ClassAttrs(Vec<ClassAttr>);
|
||||
|
||||
impl NestedDisplay for ClassAttrs {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
fmt_lines(self.0.iter(), f, level)?;
|
||||
writeln!(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Locational for ClassAttrs {
|
||||
fn loc(&self) -> Location {
|
||||
Location::concat(self.0.first().unwrap(), self.0.last().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<ClassAttr>> for ClassAttrs {
|
||||
fn from(attrs: Vec<ClassAttr>) -> Self {
|
||||
Self(attrs)
|
||||
}
|
||||
}
|
||||
|
||||
impl ClassAttrs {
|
||||
pub const fn new(attrs: Vec<ClassAttr>) -> Self {
|
||||
Self(attrs)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &ClassAttr> {
|
||||
self.0.iter()
|
||||
}
|
||||
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut ClassAttr> {
|
||||
self.0.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for ClassAttrs {
|
||||
type Item = ClassAttr;
|
||||
type IntoIter = <Vec<ClassAttr> as IntoIterator>::IntoIter;
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct RecordAttrs(Vec<Def>);
|
||||
|
||||
|
@ -3194,23 +3248,23 @@ impl Def {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Methods {
|
||||
pub class: TypeSpec,
|
||||
pub vis: Token, // `.` or `::`
|
||||
pub defs: RecordAttrs, // TODO: allow declaration
|
||||
pub vis: Token, // `.` or `::`
|
||||
pub attrs: ClassAttrs,
|
||||
}
|
||||
|
||||
impl NestedDisplay for Methods {
|
||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||
writeln!(f, "{}{}", self.class, self.vis.content)?;
|
||||
self.defs.fmt_nest(f, level + 1)
|
||||
self.attrs.fmt_nest(f, level + 1)
|
||||
}
|
||||
}
|
||||
|
||||
impl_display_from_nested!(Methods);
|
||||
impl_locational!(Methods, class, defs);
|
||||
impl_locational!(Methods, class, attrs);
|
||||
|
||||
impl Methods {
|
||||
pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self {
|
||||
Self { class, vis, defs }
|
||||
pub const fn new(class: TypeSpec, vis: Token, attrs: ClassAttrs) -> Self {
|
||||
Self { class, vis, attrs }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,11 +12,12 @@ use erg_common::{enum_unwrap, get_hash, log, set};
|
|||
|
||||
use crate::ast::{
|
||||
Accessor, Args, Array, ArrayComprehension, ArrayTypeSpec, ArrayWithLength, BinOp, Block, Call,
|
||||
ConstExpr, DataPack, Def, DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda,
|
||||
LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict,
|
||||
NormalRecord, NormalSet, NormalTuple, ParamPattern, Params, PosArg, Record, RecordAttrs,
|
||||
Set as astSet, SetWithLength, ShortenedRecord, Signature, SubrSignature, Tuple, TypeBoundSpecs,
|
||||
TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
||||
ClassAttr, ClassAttrs, ConstExpr, DataPack, Def, DefBody, DefId, Dict, Expr, Identifier,
|
||||
KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature,
|
||||
NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern, Params, PosArg,
|
||||
Record, RecordAttrs, Set as astSet, SetWithLength, ShortenedRecord, Signature, SubrSignature,
|
||||
Tuple, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr,
|
||||
VarSignature,
|
||||
};
|
||||
use crate::token::{Token, TokenKind};
|
||||
|
||||
|
@ -204,17 +205,25 @@ impl Desugarer {
|
|||
expr.type_asc_expr(tasc.op, tasc.t_spec)
|
||||
}
|
||||
Expr::Methods(method_defs) => {
|
||||
let mut new_defs = vec![];
|
||||
for def in method_defs.defs.into_iter() {
|
||||
let mut new_attrs = vec![];
|
||||
for attr in method_defs.attrs.into_iter() {
|
||||
let mut chunks = vec![];
|
||||
for chunk in def.body.block.into_iter() {
|
||||
chunks.push(desugar(chunk));
|
||||
match attr {
|
||||
ClassAttr::Def(def) => {
|
||||
for chunk in def.body.block.into_iter() {
|
||||
chunks.push(desugar(chunk));
|
||||
}
|
||||
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
|
||||
new_attrs.push(ClassAttr::Def(Def::new(def.sig, body)));
|
||||
}
|
||||
ClassAttr::Decl(decl) => {
|
||||
let expr = desugar(*decl.expr);
|
||||
new_attrs.push(ClassAttr::Decl(expr.type_asc(decl.op, decl.t_spec)));
|
||||
}
|
||||
}
|
||||
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
|
||||
new_defs.push(Def::new(def.sig, body));
|
||||
}
|
||||
let new_defs = RecordAttrs::from(new_defs);
|
||||
Expr::Methods(Methods::new(method_defs.class, method_defs.vis, new_defs))
|
||||
let new_attrs = ClassAttrs::from(new_attrs);
|
||||
Expr::Methods(Methods::new(method_defs.class, method_defs.vis, new_attrs))
|
||||
}
|
||||
// TODO: Accessor
|
||||
other => other,
|
||||
|
|
|
@ -813,14 +813,18 @@ impl Parser {
|
|||
let first = self
|
||||
.try_reduce_chunk(false, false)
|
||||
.map_err(|_| self.stack_dec())?;
|
||||
let Some(first) = option_enum_unwrap!(first, Expr::Def) else {
|
||||
// self.restore();
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
let first = match first {
|
||||
Expr::Def(def) => ClassAttr::Def(def),
|
||||
Expr::TypeAsc(tasc) => ClassAttr::Decl(tasc),
|
||||
_ => {
|
||||
// self.restore();
|
||||
self.level -= 1;
|
||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||
self.errs.push(err);
|
||||
return Err(());
|
||||
}
|
||||
};
|
||||
let mut defs = vec![first];
|
||||
let mut attrs = vec![first];
|
||||
loop {
|
||||
match self.peek() {
|
||||
Some(t) if t.is(Newline) && self.nth_is(1, Dedent) => {
|
||||
|
@ -838,7 +842,10 @@ impl Parser {
|
|||
.map_err(|_| self.stack_dec())?;
|
||||
match def {
|
||||
Expr::Def(def) => {
|
||||
defs.push(def);
|
||||
attrs.push(ClassAttr::Def(def));
|
||||
}
|
||||
Expr::TypeAsc(tasc) => {
|
||||
attrs.push(ClassAttr::Decl(tasc));
|
||||
}
|
||||
other => {
|
||||
self.errs
|
||||
|
@ -854,10 +861,10 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
}
|
||||
let defs = RecordAttrs::from(defs);
|
||||
let attrs = ClassAttrs::from(attrs);
|
||||
let class = Self::expr_to_type_spec(class).map_err(|e| self.errs.push(e))?;
|
||||
self.level -= 1;
|
||||
Ok(Methods::new(class, vis, defs))
|
||||
Ok(Methods::new(class, vis, attrs))
|
||||
}
|
||||
|
||||
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {
|
||||
|
|
|
@ -3,5 +3,13 @@
|
|||
|
||||
.C: ClassType
|
||||
# or .C.__call__: Int -> .C
|
||||
.C.__call__: (x: Int,) -> .C
|
||||
.C.__call__: (x: Int) -> .C
|
||||
.C.f: (self: .C, y: Int) -> Int
|
||||
|
||||
#[
|
||||
# Class declaration syntax
|
||||
.C: ClassType {.x = Int}
|
||||
.C.
|
||||
__call__: (x: Int) -> .C
|
||||
f: (self: .C, y: Int) -> Int
|
||||
]#
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue