mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 14:04:33 +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,7 +1098,9 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
let kind = ContextKind::MethodDefs(impl_trait.as_ref().map(|(t, _)| t.clone()));
|
let kind = ContextKind::MethodDefs(impl_trait.as_ref().map(|(t, _)| t.clone()));
|
||||||
self.ctx.grow(&class.local_name(), kind, Private, None);
|
self.ctx.grow(&class.local_name(), kind, Private, None);
|
||||||
for def in methods.defs.iter_mut() {
|
for attr in methods.attrs.iter_mut() {
|
||||||
|
match attr {
|
||||||
|
ast::ClassAttr::Def(def) => {
|
||||||
if methods.vis.is(TokenKind::Dot) {
|
if methods.vis.is(TokenKind::Dot) {
|
||||||
def.sig.ident_mut().unwrap().dot = Some(Token::new(
|
def.sig.ident_mut().unwrap().dot = Some(Token::new(
|
||||||
TokenKind::Dot,
|
TokenKind::Dot,
|
||||||
|
@ -1109,14 +1111,23 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
self.ctx.preregister_def(def)?;
|
self.ctx.preregister_def(def)?;
|
||||||
}
|
}
|
||||||
for def in methods.defs.into_iter() {
|
ast::ClassAttr::Decl(_decl) => {}
|
||||||
match self.lower_def(def) {
|
}
|
||||||
|
}
|
||||||
|
for attr in methods.attrs.into_iter() {
|
||||||
|
match attr {
|
||||||
|
ast::ClassAttr::Def(def) => match self.lower_def(def) {
|
||||||
Ok(def) => {
|
Ok(def) => {
|
||||||
hir_methods.push(hir::Expr::Def(def));
|
hir_methods.push(hir::Expr::Def(def));
|
||||||
}
|
}
|
||||||
Err(errs) => {
|
Err(errs) => {
|
||||||
self.errs.extend(errs.into_iter());
|
self.errs.extend(errs.into_iter());
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
ast::ClassAttr::Decl(decl) => {
|
||||||
|
let decl = self.lower_type_asc(decl)?;
|
||||||
|
hir_methods.push(hir::Expr::TypeAsc(decl));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Err(mut errs) = self.ctx.check_decls() {
|
if let Err(mut errs) = self.ctx.check_decls() {
|
||||||
|
@ -1590,6 +1601,10 @@ impl ASTLowerer {
|
||||||
res
|
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> {
|
fn fake_lower_obj(&self, obj: ast::Expr) -> LowerResult<hir::Expr> {
|
||||||
match obj {
|
match obj {
|
||||||
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
|
||||||
|
@ -1748,12 +1763,9 @@ impl ASTLowerer {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_alias_or_import(def)?)),
|
ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_alias_or_import(def)?)),
|
||||||
ast::Expr::ClassDef(defs) => Err(LowerErrors::from(LowerError::feature_error(
|
ast::Expr::ClassDef(class_def) => {
|
||||||
self.cfg.input.clone(),
|
Ok(hir::Expr::ClassDef(self.declare_class_def(class_def)?))
|
||||||
defs.loc(),
|
}
|
||||||
"class declaration",
|
|
||||||
self.ctx.caused_by(),
|
|
||||||
))),
|
|
||||||
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
|
ast::Expr::TypeAsc(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
|
||||||
ast::Expr::Call(call)
|
ast::Expr::Call(call)
|
||||||
if call
|
if call
|
||||||
|
|
|
@ -704,6 +704,60 @@ impl_nested_display_for_enum!(Dict; Normal, Comprehension);
|
||||||
impl_display_for_enum!(Dict; Normal, Comprehension);
|
impl_display_for_enum!(Dict; Normal, Comprehension);
|
||||||
impl_locational_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)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct RecordAttrs(Vec<Def>);
|
pub struct RecordAttrs(Vec<Def>);
|
||||||
|
|
||||||
|
@ -3195,22 +3249,22 @@ impl Def {
|
||||||
pub struct Methods {
|
pub struct Methods {
|
||||||
pub class: TypeSpec,
|
pub class: TypeSpec,
|
||||||
pub vis: Token, // `.` or `::`
|
pub vis: Token, // `.` or `::`
|
||||||
pub defs: RecordAttrs, // TODO: allow declaration
|
pub attrs: ClassAttrs,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NestedDisplay for Methods {
|
impl NestedDisplay for Methods {
|
||||||
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result {
|
||||||
writeln!(f, "{}{}", self.class, self.vis.content)?;
|
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_display_from_nested!(Methods);
|
||||||
impl_locational!(Methods, class, defs);
|
impl_locational!(Methods, class, attrs);
|
||||||
|
|
||||||
impl Methods {
|
impl Methods {
|
||||||
pub const fn new(class: TypeSpec, vis: Token, defs: RecordAttrs) -> Self {
|
pub const fn new(class: TypeSpec, vis: Token, attrs: ClassAttrs) -> Self {
|
||||||
Self { class, vis, defs }
|
Self { class, vis, attrs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,11 +12,12 @@ use erg_common::{enum_unwrap, get_hash, log, set};
|
||||||
|
|
||||||
use crate::ast::{
|
use crate::ast::{
|
||||||
Accessor, Args, Array, ArrayComprehension, ArrayTypeSpec, ArrayWithLength, BinOp, Block, Call,
|
Accessor, Args, Array, ArrayComprehension, ArrayTypeSpec, ArrayWithLength, BinOp, Block, Call,
|
||||||
ConstExpr, DataPack, Def, DefBody, DefId, Dict, Expr, Identifier, KeyValue, KwArg, Lambda,
|
ClassAttr, ClassAttrs, ConstExpr, DataPack, Def, DefBody, DefId, Dict, Expr, Identifier,
|
||||||
LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature, NormalArray, NormalDict,
|
KeyValue, KwArg, Lambda, LambdaSignature, Literal, Methods, Module, NonDefaultParamSignature,
|
||||||
NormalRecord, NormalSet, NormalTuple, ParamPattern, Params, PosArg, Record, RecordAttrs,
|
NormalArray, NormalDict, NormalRecord, NormalSet, NormalTuple, ParamPattern, Params, PosArg,
|
||||||
Set as astSet, SetWithLength, ShortenedRecord, Signature, SubrSignature, Tuple, TypeBoundSpecs,
|
Record, RecordAttrs, Set as astSet, SetWithLength, ShortenedRecord, Signature, SubrSignature,
|
||||||
TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr, VarSignature,
|
Tuple, TypeBoundSpecs, TypeSpec, TypeSpecWithOp, UnaryOp, VarName, VarPattern, VarRecordAttr,
|
||||||
|
VarSignature,
|
||||||
};
|
};
|
||||||
use crate::token::{Token, TokenKind};
|
use crate::token::{Token, TokenKind};
|
||||||
|
|
||||||
|
@ -204,17 +205,25 @@ impl Desugarer {
|
||||||
expr.type_asc_expr(tasc.op, tasc.t_spec)
|
expr.type_asc_expr(tasc.op, tasc.t_spec)
|
||||||
}
|
}
|
||||||
Expr::Methods(method_defs) => {
|
Expr::Methods(method_defs) => {
|
||||||
let mut new_defs = vec![];
|
let mut new_attrs = vec![];
|
||||||
for def in method_defs.defs.into_iter() {
|
for attr in method_defs.attrs.into_iter() {
|
||||||
let mut chunks = vec![];
|
let mut chunks = vec![];
|
||||||
|
match attr {
|
||||||
|
ClassAttr::Def(def) => {
|
||||||
for chunk in def.body.block.into_iter() {
|
for chunk in def.body.block.into_iter() {
|
||||||
chunks.push(desugar(chunk));
|
chunks.push(desugar(chunk));
|
||||||
}
|
}
|
||||||
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
|
let body = DefBody::new(def.body.op, Block::new(chunks), def.body.id);
|
||||||
new_defs.push(Def::new(def.sig, body));
|
new_attrs.push(ClassAttr::Def(Def::new(def.sig, body)));
|
||||||
}
|
}
|
||||||
let new_defs = RecordAttrs::from(new_defs);
|
ClassAttr::Decl(decl) => {
|
||||||
Expr::Methods(Methods::new(method_defs.class, method_defs.vis, new_defs))
|
let expr = desugar(*decl.expr);
|
||||||
|
new_attrs.push(ClassAttr::Decl(expr.type_asc(decl.op, decl.t_spec)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let new_attrs = ClassAttrs::from(new_attrs);
|
||||||
|
Expr::Methods(Methods::new(method_defs.class, method_defs.vis, new_attrs))
|
||||||
}
|
}
|
||||||
// TODO: Accessor
|
// TODO: Accessor
|
||||||
other => other,
|
other => other,
|
||||||
|
|
|
@ -813,14 +813,18 @@ impl Parser {
|
||||||
let first = self
|
let first = self
|
||||||
.try_reduce_chunk(false, false)
|
.try_reduce_chunk(false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let Some(first) = option_enum_unwrap!(first, Expr::Def) else {
|
let first = match first {
|
||||||
|
Expr::Def(def) => ClassAttr::Def(def),
|
||||||
|
Expr::TypeAsc(tasc) => ClassAttr::Decl(tasc),
|
||||||
|
_ => {
|
||||||
// self.restore();
|
// self.restore();
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
let err = self.skip_and_throw_syntax_err(caused_by!());
|
let err = self.skip_and_throw_syntax_err(caused_by!());
|
||||||
self.errs.push(err);
|
self.errs.push(err);
|
||||||
return Err(());
|
return Err(());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let mut defs = vec![first];
|
let mut attrs = vec![first];
|
||||||
loop {
|
loop {
|
||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(t) if t.is(Newline) && self.nth_is(1, Dedent) => {
|
Some(t) if t.is(Newline) && self.nth_is(1, Dedent) => {
|
||||||
|
@ -838,7 +842,10 @@ impl Parser {
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
match def {
|
match def {
|
||||||
Expr::Def(def) => {
|
Expr::Def(def) => {
|
||||||
defs.push(def);
|
attrs.push(ClassAttr::Def(def));
|
||||||
|
}
|
||||||
|
Expr::TypeAsc(tasc) => {
|
||||||
|
attrs.push(ClassAttr::Decl(tasc));
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
self.errs
|
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))?;
|
let class = Self::expr_to_type_spec(class).map_err(|e| self.errs.push(e))?;
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Methods::new(class, vis, defs))
|
Ok(Methods::new(class, vis, attrs))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {
|
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {
|
||||||
|
|
|
@ -3,5 +3,13 @@
|
||||||
|
|
||||||
.C: ClassType
|
.C: ClassType
|
||||||
# or .C.__call__: Int -> .C
|
# or .C.__call__: Int -> .C
|
||||||
.C.__call__: (x: Int,) -> .C
|
.C.__call__: (x: Int) -> .C
|
||||||
.C.f: (self: .C, y: Int) -> Int
|
.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