From 21cb0bb4c12bb4475670b49bd12530ef3aff56a9 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Sat, 9 Sep 2023 16:45:24 +0900 Subject: [PATCH] feat: support symbolized operators --- crates/erg_parser/ast.rs | 28 +--- crates/erg_parser/desugar.rs | 280 +++++++++++++++++++++-------------- crates/erg_parser/lex.rs | 17 ++- examples/a11y.er | 2 +- examples/impl.er | 7 +- 5 files changed, 187 insertions(+), 147 deletions(-) diff --git a/crates/erg_parser/ast.rs b/crates/erg_parser/ast.rs index de0114e1..f672b6e0 100644 --- a/crates/erg_parser/ast.rs +++ b/crates/erg_parser/ast.rs @@ -837,6 +837,8 @@ impl_locational_for_enum!(ClassAttr; Def, Decl, Doc); #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct ClassAttrs(Vec); +impl_stream!(ClassAttrs, ClassAttr); + impl NestedDisplay for ClassAttrs { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { fmt_lines(self.0.iter(), f, level)?; @@ -856,28 +858,6 @@ impl From> for ClassAttrs { } } -impl ClassAttrs { - pub const fn new(attrs: Vec) -> Self { - Self(attrs) - } - - pub fn iter(&self) -> impl Iterator { - self.0.iter() - } - - pub fn iter_mut(&mut self) -> impl Iterator { - self.0.iter_mut() - } -} - -impl IntoIterator for ClassAttrs { - type Item = ClassAttr; - type IntoIter = as IntoIterator>::IntoIter; - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct RecordAttrs(Vec); @@ -3135,6 +3115,10 @@ impl VarName { pub fn trim_end_proc_mark(&mut self) { self.0.content = Str::rc(self.0.content.trim_end_matches('!')); } + + pub fn rename(&mut self, new: Str) { + self.0.content = new; + } } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/crates/erg_parser/desugar.rs b/crates/erg_parser/desugar.rs index 06485fe6..c51a3709 100644 --- a/crates/erg_parser/desugar.rs +++ b/crates/erg_parser/desugar.rs @@ -23,6 +23,36 @@ use crate::ast::{ }; use crate::token::{Token, TokenKind, COLON, DOT}; +pub fn symop_to_dname(op: &str) -> Option<&'static str> { + match op { + "`_+_`" => Some("__add__"), + "`_-_`" => Some("__sub__"), + "`*`" | "`cross`" => Some("__mul__"), + "`/`" => Some("__div__"), + "`//`" => Some("__floordiv__"), + "`**`" => Some("__pow__"), + "`%`" => Some("__mod__"), + "`@`" | "`dot`" => Some("__matmul__"), + "`&&`" => Some("__and__"), + "`||`" => Some("__or__"), + "`^`" => Some("__xor__"), + "`==`" => Some("__eq__"), + "`!=`" => Some("__ne__"), + "`<`" => Some("__lt__"), + "`<=`" => Some("__le__"), + "`>`" => Some("__gt__"), + "`>=`" => Some("__ge__"), + "`<<`" => Some("__lshift__"), + "`>>`" => Some("__rshift__"), + "`+_`" => Some("__pos__"), + "`-_`" => Some("__neg__"), + "`~`" => Some("__invert__"), + "`!`" => Some("__mutate__"), + "`...`" => Some("__spread__"), + _ => None, + } +} + #[derive(Debug, Clone, PartialEq, Eq)] enum BufIndex<'i> { Array(usize), @@ -623,6 +653,107 @@ impl Desugarer { Block::new(self.desugar_pattern(block.into_iter())) } + fn desugar_def_pattern(&mut self, def: Def, new: &mut Vec) { + match def { + Def { + sig: Signature::Var(mut v), + body, + } => match &v.pat { + VarPattern::Tuple(tup) => { + let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec); + let block = body + .block + .into_iter() + .map(|ex| self.rec_desugar_lambda_pattern(ex)) + .collect(); + let block = self.desugar_pattern_in_block(block); + let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); + new.push(Expr::Def(buf_def)); + for (n, elem) in tup.elems.iter().enumerate() { + self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Tuple(n)); + } + } + VarPattern::Array(arr) => { + let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec); + let block = body + .block + .into_iter() + .map(|ex| self.rec_desugar_lambda_pattern(ex)) + .collect(); + let block = self.desugar_pattern_in_block(block); + let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); + new.push(Expr::Def(buf_def)); + for (n, elem) in arr.elems.iter().enumerate() { + self.desugar_nested_var_pattern(new, elem, &buf_name, BufIndex::Array(n)); + } + } + VarPattern::Record(rec) => { + let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec); + let block = body + .block + .into_iter() + .map(|ex| self.rec_desugar_lambda_pattern(ex)) + .collect(); + let block = self.desugar_pattern_in_block(block); + let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); + new.push(Expr::Def(buf_def)); + for VarRecordAttr { lhs, rhs } in rec.attrs.iter() { + self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs)); + } + } + VarPattern::DataPack(pack) => { + let t_spec = + TypeSpecWithOp::new(COLON, pack.class.clone(), *pack.class_as_expr.clone()); + let (buf_name, buf_sig) = self.gen_buf_name_and_sig( + v.loc(), + Some(t_spec), // TODO: これだとvの型指定の意味がなくなる + ); + let block = body + .block + .into_iter() + .map(|ex| self.rec_desugar_lambda_pattern(ex)) + .collect(); + let block = self.desugar_pattern_in_block(block); + let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); + new.push(Expr::Def(buf_def)); + for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() { + self.desugar_nested_var_pattern(new, rhs, &buf_name, BufIndex::Record(lhs)); + } + } + VarPattern::Ident(_) | VarPattern::Discard(_) => { + if let VarPattern::Ident(ident) = v.pat { + v.pat = VarPattern::Ident(Self::desugar_ident(ident)); + } + let block = body + .block + .into_iter() + .map(|ex| self.rec_desugar_lambda_pattern(ex)) + .collect(); + let block = self.desugar_pattern_in_block(block); + let body = DefBody::new(body.op, block, body.id); + let def = Def::new(Signature::Var(v), body); + new.push(Expr::Def(def)); + } + }, + Def { + sig: Signature::Subr(mut subr), + mut body, + } => { + subr.ident = Self::desugar_ident(subr.ident); + self.desugar_params_patterns(&mut subr.params, &mut body.block); + let block = body + .block + .into_iter() + .map(|ex| self.rec_desugar_lambda_pattern(ex)) + .collect(); + let block = self.desugar_pattern_in_block(block); + let body = DefBody::new(body.op, block, body.id); + let def = Def::new(Signature::Subr(subr), body); + new.push(Expr::Def(def)); + } + } + } + // TODO: nested function pattern /// `[i, j] = [1, 2]` -> `i = 1; j = 2` /// `[i, j] = l` -> `i = l[0]; j = l[1]` @@ -636,120 +767,33 @@ impl Desugarer { let mut new = Vec::with_capacity(chunks.len()); for chunk in chunks.into_iter() { match chunk { - Expr::Def(Def { - sig: Signature::Var(v), - body, - }) => match &v.pat { - VarPattern::Tuple(tup) => { - let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec); - let block = body - .block - .into_iter() - .map(|ex| self.rec_desugar_lambda_pattern(ex)) - .collect(); - let block = self.desugar_pattern_in_block(block); - let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); - new.push(Expr::Def(buf_def)); - for (n, elem) in tup.elems.iter().enumerate() { - self.desugar_nested_var_pattern( - &mut new, - elem, - &buf_name, - BufIndex::Tuple(n), - ); + Expr::Def(def) => { + self.desugar_def_pattern(def, &mut new); + } + Expr::Methods(methods) => { + let mut new_attrs = Vec::with_capacity(methods.attrs.len()); + for attr in methods.attrs.into_iter() { + match attr { + ClassAttr::Def(def) => { + let mut new = vec![]; + self.desugar_def_pattern(def, &mut new); + let Expr::Def(def) = new.remove(0) else { + todo!("{new:?}") + }; + new_attrs.push(ClassAttr::Def(def)); + } + _ => { + new_attrs.push(attr); + } } } - VarPattern::Array(arr) => { - let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec); - let block = body - .block - .into_iter() - .map(|ex| self.rec_desugar_lambda_pattern(ex)) - .collect(); - let block = self.desugar_pattern_in_block(block); - let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); - new.push(Expr::Def(buf_def)); - for (n, elem) in arr.elems.iter().enumerate() { - self.desugar_nested_var_pattern( - &mut new, - elem, - &buf_name, - BufIndex::Array(n), - ); - } - } - VarPattern::Record(rec) => { - let (buf_name, buf_sig) = self.gen_buf_name_and_sig(v.loc(), v.t_spec); - let block = body - .block - .into_iter() - .map(|ex| self.rec_desugar_lambda_pattern(ex)) - .collect(); - let block = self.desugar_pattern_in_block(block); - let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); - new.push(Expr::Def(buf_def)); - for VarRecordAttr { lhs, rhs } in rec.attrs.iter() { - self.desugar_nested_var_pattern( - &mut new, - rhs, - &buf_name, - BufIndex::Record(lhs), - ); - } - } - VarPattern::DataPack(pack) => { - let t_spec = TypeSpecWithOp::new( - COLON, - pack.class.clone(), - *pack.class_as_expr.clone(), - ); - let (buf_name, buf_sig) = self.gen_buf_name_and_sig( - v.loc(), - Some(t_spec), // TODO: これだとvの型指定の意味がなくなる - ); - let block = body - .block - .into_iter() - .map(|ex| self.rec_desugar_lambda_pattern(ex)) - .collect(); - let block = self.desugar_pattern_in_block(block); - let buf_def = Def::new(buf_sig, DefBody::new(body.op, block, body.id)); - new.push(Expr::Def(buf_def)); - for VarRecordAttr { lhs, rhs } in pack.args.attrs.iter() { - self.desugar_nested_var_pattern( - &mut new, - rhs, - &buf_name, - BufIndex::Record(lhs), - ); - } - } - VarPattern::Ident(_) | VarPattern::Discard(_) => { - let block = body - .block - .into_iter() - .map(|ex| self.rec_desugar_lambda_pattern(ex)) - .collect(); - let block = self.desugar_pattern_in_block(block); - let body = DefBody::new(body.op, block, body.id); - let def = Def::new(Signature::Var(v), body); - new.push(Expr::Def(def)); - } - }, - Expr::Def(Def { - sig: Signature::Subr(mut subr), - mut body, - }) => { - self.desugar_params_patterns(&mut subr.params, &mut body.block); - let block = body - .block - .into_iter() - .map(|ex| self.rec_desugar_lambda_pattern(ex)) - .collect(); - let block = self.desugar_pattern_in_block(block); - let body = DefBody::new(body.op, block, body.id); - let def = Def::new(Signature::Subr(subr), body); - new.push(Expr::Def(def)); + let methods = Methods::new( + methods.class, + *methods.class_as_expr, + methods.vis, + ClassAttrs::from(new_attrs), + ); + new.push(Expr::Methods(methods)); } Expr::Dummy(dummy) => { let loc = dummy.loc; @@ -1450,6 +1494,8 @@ impl Desugarer { /// x[y] => x.__getitem__(y) /// x.0 => x.__Tuple_getitem__(0) + /// `==`(x, y) => __eq__(x, y) + /// x.`==` y => x.__eq__ y fn desugar_acc(module: Module) -> Module { Self::desugar_all_chunks(module, Self::rec_desugar_acc) } @@ -1500,12 +1546,20 @@ impl Desugarer { } Accessor::Attr(mut attr) => { attr.obj = Box::new(Self::rec_desugar_acc(*attr.obj)); + attr.ident = Self::desugar_ident(attr.ident); Expr::Accessor(Accessor::Attr(attr)) } - other => Expr::Accessor(other), + Accessor::Ident(ident) => Expr::Accessor(Accessor::Ident(Self::desugar_ident(ident))), } } + fn desugar_ident(mut ident: Identifier) -> Identifier { + if let Some(name) = symop_to_dname(ident.inspect()) { + ident.name.rename(name.into()); + } + ident + } + // TODO: pipeline desugaring (move from `Parser`) fn desugar_operator(module: Module) -> Module { Self::desugar_all_chunks(module, Self::rec_desugar_operator) diff --git a/crates/erg_parser/lex.rs b/crates/erg_parser/lex.rs index 4949745d..d8e93d76 100644 --- a/crates/erg_parser/lex.rs +++ b/crates/erg_parser/lex.rs @@ -277,18 +277,17 @@ impl Lexer /*<'a>*/ { matches!( s, "+_" | "_+_" + | "-_" | "-" | "*" | "/" | "//" | "**" | "%" - | ".." - | "..=" | "~" | "&&" | "||" - | "^^" + | "^" | ">>" | "<<" | "==" @@ -1544,12 +1543,14 @@ impl Iterator for Lexer /*<'a>*/ { } } // Symbolized operators (シンボル化された演算子) - // e.g. `-`(l, r) = l + (-r) + // e.g. `-`(l, r) == __sub__(1, r) == l - r Some('`') => { let mut op = "".to_string(); while let Some(c) = self.consume() { if c == '`' { if Self::is_definable_operator(&op[..]) { + op.insert(0, '`'); + op.push('`'); return self.accept(Symbol, &op); } else { let token = self.emit_token(Illegal, &op); @@ -1569,10 +1570,10 @@ impl Iterator for Lexer /*<'a>*/ { line!() as usize, token.loc(), switch_lang!( - "japanese" => format!("`{}`はユーザー定義できません", &token.content), - "simplified_chinese" => format!("`{}`不能由用户定义", &token.content), - "traditional_chinese" => format!("`{}`不能由用戶定義", &token.content), - "english" => format!("`{}` cannot be defined by user", &token.content), + "japanese" => format!("`{}`は存在しないか、ユーザー定義できません", &token.content), + "simplified_chinese" => format!("`{}`不存在或不能由用户定义", &token.content), + "traditional_chinese" => format!("`{}`不存在或不能由用戶定義", &token.content), + "english" => format!("`{}` does not exist or cannot be defined by user", &token.content), ), hint, ))); diff --git a/examples/a11y.er b/examples/a11y.er index 63dc23f8..d7072dd4 100644 --- a/examples/a11y.er +++ b/examples/a11y.er @@ -5,5 +5,5 @@ private = "this is a private variable" .C. x = 1 .C|<: Eq|. - __eq__ self, other = + `==` self, other = self.x == other.x diff --git a/examples/impl.er b/examples/impl.er index 150de2ba..27a3c999 100644 --- a/examples/impl.er +++ b/examples/impl.er @@ -4,14 +4,15 @@ Point. norm self = self::x**2 + self::y**2 Point|<: Add(Point)|. Output = Point - __add__ self, other: Point = + # This is same as `__add__ self, other: Point = ...` + `_+_` self, other: Point = Point.new(self::x + other::x, self::y + other::y) Point|<: Mul(Point)|. Output = Int - __mul__ self, other: Point = + `*` self, other: Point = self::x * other::x + self::y * other::y Point|<: Eq|. - __eq__ self, other: Point = + `==` self, other: Point = self::x == other::x and self::y == other::y p = Point.new 1, 2