mirror of
https://github.com/erg-lang/erg.git
synced 2025-10-03 05:54:33 +00:00
feat: implement methods declaration syntax
This commit is contained in:
parent
a694880ff4
commit
b4b02fd0f6
5 changed files with 82 additions and 11 deletions
|
@ -2150,7 +2150,7 @@ impl ASTLowerer {
|
|||
graph.add_node_if_none(path);
|
||||
}
|
||||
let ast = Reorderer::new(self.cfg.clone())
|
||||
.reorder(ast)
|
||||
.reorder(ast, mode)
|
||||
.map_err(|errs| {
|
||||
IncompleteArtifact::new(None, errs, LowerWarnings::from(self.warns.take_all()))
|
||||
})?;
|
||||
|
|
|
@ -4,7 +4,10 @@ use erg_common::log;
|
|||
use erg_common::traits::{Locational, Stream};
|
||||
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};
|
||||
|
||||
|
@ -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.");
|
||||
let mut new = vec![];
|
||||
for chunk in ast.module.into_iter() {
|
||||
|
@ -66,12 +69,17 @@ impl Reorderer {
|
|||
}
|
||||
Expr::Methods(methods) => match &methods.class {
|
||||
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, .. } => {
|
||||
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 {
|
||||
let similar_name = self
|
||||
.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) {
|
||||
match new.remove(*pos) {
|
||||
Expr::ClassDef(mut class_def) => {
|
||||
|
@ -116,6 +171,8 @@ impl Reorderer {
|
|||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else if mode == "declare" {
|
||||
self.flatten_method_decls(new, methods);
|
||||
} else {
|
||||
let similar_name = self
|
||||
.def_root_pos_map
|
||||
|
|
|
@ -3670,6 +3670,7 @@ impl ReDef {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Methods {
|
||||
pub class: TypeSpec,
|
||||
pub class_as_expr: Box<Expr>,
|
||||
pub vis: Token, // `.` or `::`
|
||||
pub attrs: ClassAttrs,
|
||||
}
|
||||
|
@ -3685,8 +3686,13 @@ impl_display_from_nested!(Methods);
|
|||
impl_locational!(Methods, class, attrs);
|
||||
|
||||
impl Methods {
|
||||
pub const fn new(class: TypeSpec, vis: Token, attrs: ClassAttrs) -> Self {
|
||||
Self { class, vis, attrs }
|
||||
pub fn new(class: TypeSpec, class_as_expr: Expr, vis: Token, attrs: ClassAttrs) -> Self {
|
||||
Self {
|
||||
class,
|
||||
class_as_expr: Box::new(class_as_expr),
|
||||
vis,
|
||||
attrs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -303,7 +303,12 @@ impl Desugarer {
|
|||
}
|
||||
}
|
||||
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::Dummy(exprs) => {
|
||||
|
|
|
@ -1039,6 +1039,9 @@ impl Parser {
|
|||
Expr::TypeAscription(tasc) => {
|
||||
attrs.push(ClassAttr::Decl(tasc));
|
||||
}
|
||||
Expr::Literal(lit) if lit.is_doc_comment() => {
|
||||
attrs.push(ClassAttr::Doc(lit));
|
||||
}
|
||||
other => {
|
||||
self.errs
|
||||
.push(ParseError::simple_syntax_error(0, other.loc()));
|
||||
|
@ -1054,9 +1057,9 @@ impl Parser {
|
|||
}
|
||||
}
|
||||
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);
|
||||
Ok(Methods::new(class, vis, attrs))
|
||||
Ok(Methods::new(t_spec, class, vis, attrs))
|
||||
}
|
||||
|
||||
fn try_reduce_do_block(&mut self) -> ParseResult<Lambda> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue