WIP: Enable to declare in class methods definitions

This commit is contained in:
Shunsuke Shibayama 2022-11-07 17:37:46 +09:00
parent 60956a590e
commit 14b143778f
5 changed files with 143 additions and 53 deletions

View file

@ -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

View file

@ -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 }
} }
} }

View file

@ -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,

View file

@ -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> {

View file

@ -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
]#