feat: implement methods declaration syntax

This commit is contained in:
Shunsuke Shibayama 2023-02-17 01:26:04 +09:00
parent a694880ff4
commit b4b02fd0f6
5 changed files with 82 additions and 11 deletions

View file

@ -2150,7 +2150,7 @@ impl ASTLowerer {
graph.add_node_if_none(path); graph.add_node_if_none(path);
} }
let ast = Reorderer::new(self.cfg.clone()) let ast = Reorderer::new(self.cfg.clone())
.reorder(ast) .reorder(ast, mode)
.map_err(|errs| { .map_err(|errs| {
IncompleteArtifact::new(None, errs, LowerWarnings::from(self.warns.take_all())) IncompleteArtifact::new(None, errs, LowerWarnings::from(self.warns.take_all()))
})?; })?;

View file

@ -4,7 +4,10 @@ use erg_common::log;
use erg_common::traits::{Locational, Stream}; use erg_common::traits::{Locational, Stream};
use erg_common::Str; use erg_common::Str;
use erg_parser::ast::{ClassDef, Expr, Methods, Module, PatchDef, PreDeclTypeSpec, TypeSpec, AST}; use erg_parser::ast::{
Accessor, ClassAttr, ClassDef, Expr, Methods, Module, PatchDef, PreDeclTypeSpec,
TypeAscription, TypeSpec, AST,
};
use crate::error::{TyCheckError, TyCheckErrors}; use crate::error::{TyCheckError, TyCheckErrors};
@ -28,7 +31,7 @@ impl Reorderer {
} }
} }
pub fn reorder(mut self, ast: AST) -> Result<AST, TyCheckErrors> { pub fn reorder(mut self, ast: AST, mode: &str) -> Result<AST, TyCheckErrors> {
log!(info "the reordering process has started."); log!(info "the reordering process has started.");
let mut new = vec![]; let mut new = vec![];
for chunk in ast.module.into_iter() { for chunk in ast.module.into_iter() {
@ -66,12 +69,17 @@ impl Reorderer {
} }
Expr::Methods(methods) => match &methods.class { Expr::Methods(methods) => match &methods.class {
TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => { TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) => {
self.link_methods(simple.ident.inspect().clone(), &mut new, methods) self.link_methods(simple.ident.inspect().clone(), &mut new, methods, mode)
} }
TypeSpec::TypeApp { spec, .. } => { TypeSpec::TypeApp { spec, .. } => {
if let TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) = spec.as_ref() if let TypeSpec::PreDeclTy(PreDeclTypeSpec::Simple(simple)) = spec.as_ref()
{ {
self.link_methods(simple.ident.inspect().clone(), &mut new, methods) self.link_methods(
simple.ident.inspect().clone(),
&mut new,
methods,
mode,
)
} else { } else {
let similar_name = self let similar_name = self
.def_root_pos_map .def_root_pos_map
@ -103,7 +111,54 @@ impl Reorderer {
} }
} }
fn link_methods(&mut self, name: Str, new: &mut Vec<Expr>, methods: Methods) { /// ```erg
/// C.
/// x: Int
/// f: (self: Self) -> Int
/// ```
/// ↓
/// ```erg
/// C.x: Int
/// C.y: (self: C) -> Int
/// ```
fn flatten_method_decls(&mut self, new: &mut Vec<Expr>, methods: Methods) {
let class = methods.class_as_expr.as_ref();
for method in methods.attrs.into_iter() {
match method {
ClassAttr::Decl(decl) => {
let Expr::Accessor(Accessor::Ident(ident)) = *decl.expr else {
self.errs.push(TyCheckError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
decl.expr.loc(),
"".into(),
"".into(),
None
));
continue;
};
let expr = class.clone().attr_expr(ident);
let decl = TypeAscription::new(expr, decl.t_spec);
new.push(Expr::TypeAscription(decl));
}
ClassAttr::Doc(doc) => {
new.push(Expr::Literal(doc));
}
ClassAttr::Def(def) => {
self.errs.push(TyCheckError::syntax_error(
self.cfg.input.clone(),
line!() as usize,
def.loc(),
"".into(),
"".into(),
None,
));
}
}
}
}
fn link_methods(&mut self, name: Str, new: &mut Vec<Expr>, methods: Methods, mode: &str) {
if let Some(pos) = self.def_root_pos_map.get(&name) { if let Some(pos) = self.def_root_pos_map.get(&name) {
match new.remove(*pos) { match new.remove(*pos) {
Expr::ClassDef(mut class_def) => { Expr::ClassDef(mut class_def) => {
@ -116,6 +171,8 @@ impl Reorderer {
} }
_ => unreachable!(), _ => unreachable!(),
} }
} else if mode == "declare" {
self.flatten_method_decls(new, methods);
} else { } else {
let similar_name = self let similar_name = self
.def_root_pos_map .def_root_pos_map

View file

@ -3670,6 +3670,7 @@ impl ReDef {
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Methods { pub struct Methods {
pub class: TypeSpec, pub class: TypeSpec,
pub class_as_expr: Box<Expr>,
pub vis: Token, // `.` or `::` pub vis: Token, // `.` or `::`
pub attrs: ClassAttrs, pub attrs: ClassAttrs,
} }
@ -3685,8 +3686,13 @@ impl_display_from_nested!(Methods);
impl_locational!(Methods, class, attrs); impl_locational!(Methods, class, attrs);
impl Methods { impl Methods {
pub const fn new(class: TypeSpec, vis: Token, attrs: ClassAttrs) -> Self { pub fn new(class: TypeSpec, class_as_expr: Expr, vis: Token, attrs: ClassAttrs) -> Self {
Self { class, vis, attrs } Self {
class,
class_as_expr: Box::new(class_as_expr),
vis,
attrs,
}
} }
} }

View file

@ -303,7 +303,12 @@ impl Desugarer {
} }
} }
let new_attrs = ClassAttrs::from(new_attrs); let new_attrs = ClassAttrs::from(new_attrs);
Expr::Methods(Methods::new(method_defs.class, method_defs.vis, new_attrs)) Expr::Methods(Methods::new(
method_defs.class,
*method_defs.class_as_expr,
method_defs.vis,
new_attrs,
))
} }
Expr::Accessor(acc) => Expr::Accessor(Self::perform_desugar_acc(desugar, acc)), Expr::Accessor(acc) => Expr::Accessor(Self::perform_desugar_acc(desugar, acc)),
Expr::Dummy(exprs) => { Expr::Dummy(exprs) => {

View file

@ -1039,6 +1039,9 @@ impl Parser {
Expr::TypeAscription(tasc) => { Expr::TypeAscription(tasc) => {
attrs.push(ClassAttr::Decl(tasc)); attrs.push(ClassAttr::Decl(tasc));
} }
Expr::Literal(lit) if lit.is_doc_comment() => {
attrs.push(ClassAttr::Doc(lit));
}
other => { other => {
self.errs self.errs
.push(ParseError::simple_syntax_error(0, other.loc())); .push(ParseError::simple_syntax_error(0, other.loc()));
@ -1054,9 +1057,9 @@ impl Parser {
} }
} }
let attrs = ClassAttrs::from(attrs); let attrs = ClassAttrs::from(attrs);
let class = Self::expr_to_type_spec(class).map_err(|e| self.errs.push(e))?; let t_spec = Self::expr_to_type_spec(class.clone()).map_err(|e| self.errs.push(e))?;
debug_exit_info!(self); debug_exit_info!(self);
Ok(Methods::new(class, vis, attrs)) Ok(Methods::new(t_spec, class, vis, attrs))
} }
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> { fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {