From f0d686cd7b47aa7dead2cd1952ac1baf94c37a7c Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 2 Sep 2022 22:49:34 +0900 Subject: [PATCH] Change `ref` and `ref!` to unary operators --- compiler/erg_parser/ast.rs | 11 ++++- compiler/erg_parser/desugar.rs | 16 ++----- compiler/erg_parser/lex.rs | 2 + compiler/erg_parser/parse.rs | 87 ++++++++++++++++++++++------------ compiler/erg_parser/token.rs | 26 +++++----- 5 files changed, 87 insertions(+), 55 deletions(-) diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 4b0d8e58..b74b3298 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -1987,6 +1987,12 @@ impl NestedDisplay for VarRecordAttr { impl_display_from_nested!(VarRecordAttr); impl_locational!(VarRecordAttr, lhs, rhs); +impl VarRecordAttr { + pub const fn new(lhs: Identifier, rhs: Identifier) -> Self { + Self { lhs, rhs } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarRecordAttrs { pub(crate) elems: Vec, @@ -2038,7 +2044,7 @@ impl VarRecordPattern { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct VarDataPackPattern { - pub class: Identifier, // TODO: allow Attribute + pub class: Accessor, // TODO: allow polymorphic pub args: VarRecordPattern, } @@ -2051,7 +2057,7 @@ impl fmt::Display for VarDataPackPattern { impl_locational!(VarDataPackPattern, class, args); impl VarDataPackPattern { - pub const fn new(class: Identifier, args: VarRecordPattern) -> Self { + pub const fn new(class: Accessor, args: VarRecordPattern) -> Self { Self { class, args } } } @@ -2275,6 +2281,7 @@ pub enum ParamPattern { Array(ParamArrayPattern), Tuple(ParamTuplePattern), Record(ParamRecordPattern), + // DataPack(ParamDataPackPattern), Ref(VarName), RefMut(VarName), // e.g. `a` of `[...a, b] = [1, 2, 3]` (a == [1, 2], b == 3) diff --git a/compiler/erg_parser/desugar.rs b/compiler/erg_parser/desugar.rs index 1105ac81..9e288685 100644 --- a/compiler/erg_parser/desugar.rs +++ b/compiler/erg_parser/desugar.rs @@ -367,20 +367,14 @@ impl Desugarer { todo!("{dict}") } Expr::BinOp(binop) => { - let mut args = vec![]; - for arg in binop.args.into_iter() { - args.push(self.rec_desugar_shortened_record(*arg)); - } - let lhs = args.remove(0); - let rhs = args.remove(0); + let mut args = binop.args.into_iter(); + let lhs = self.rec_desugar_shortened_record(*args.next().unwrap()); + let rhs = self.rec_desugar_shortened_record(*args.next().unwrap()); Expr::BinOp(BinOp::new(binop.op, lhs, rhs)) } Expr::UnaryOp(unaryop) => { - let mut args = vec![]; - for arg in unaryop.args.into_iter() { - args.push(self.rec_desugar_shortened_record(*arg)); - } - let expr = args.remove(0); + let mut args = unaryop.args.into_iter(); + let expr = self.rec_desugar_shortened_record(*args.next().unwrap()); Expr::UnaryOp(UnaryOp::new(unaryop.op, expr)) } Expr::Call(call) => { diff --git a/compiler/erg_parser/lex.rs b/compiler/erg_parser/lex.rs index 74fb08af..2425f404 100644 --- a/compiler/erg_parser/lex.rs +++ b/compiler/erg_parser/lex.rs @@ -525,6 +525,8 @@ impl Lexer /*<'a>*/ { "isnot" => IsNotOp, "dot" => DotOp, "cross" => CrossOp, + "ref" => RefOp, + "ref!" => RefMutOp, // これらはリテラルというより定数だが便宜的にリテラルということにしておく "True" | "False" => BoolLit, "None" => NoneLit, diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index ef6576cb..5a55c460 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -1692,22 +1692,51 @@ impl Parser { todo!() } - fn convert_record_to_record_pat(&mut self, _record: Record) -> ParseResult { + fn convert_record_to_record_pat(&mut self, record: Record) -> ParseResult { debug_call_info!(self); - match _record { - Record::Normal(_rec) => { - todo!() + match record { + Record::Normal(rec) => { + let mut pats = vec![]; + for mut attr in rec.attrs.into_iter() { + let lhs = + option_enum_unwrap!(attr.sig, Signature::Var).unwrap_or_else(|| todo!()); + let lhs = + option_enum_unwrap!(lhs.pat, VarPattern::Ident).unwrap_or_else(|| todo!()); + assert_eq!(attr.body.block.len(), 1); + let rhs = option_enum_unwrap!(attr.body.block.remove(0), Expr::Accessor) + .unwrap_or_else(|| todo!()); + let rhs = self + .convert_accessor_to_ident(rhs) + .map_err(|_| self.stack_dec())?; + pats.push(VarRecordAttr::new(lhs, rhs)); + } + let attrs = VarRecordAttrs::new(pats); + self.level -= 1; + Ok(VarRecordPattern::new(rec.l_brace, attrs, rec.r_brace)) + } + Record::Shortened(rec) => { + let mut pats = vec![]; + for ident in rec.idents.into_iter() { + pats.push(VarRecordAttr::new(ident.clone(), ident)); + } + let attrs = VarRecordAttrs::new(pats); + self.level -= 1; + Ok(VarRecordPattern::new(rec.l_brace, attrs, rec.r_brace)) } - _ => todo!(), } } fn convert_data_pack_to_data_pack_pat( &mut self, - _pack: DataPack, + pack: DataPack, ) -> ParseResult { debug_call_info!(self); - todo!() + let class = option_enum_unwrap!(*pack.class, Expr::Accessor).unwrap_or_else(|| todo!()); + let args = self + .convert_record_to_record_pat(pack.args) + .map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(VarDataPackPattern::new(class, args)) } fn convert_tuple_to_tuple_pat(&mut self, tuple: Tuple) -> ParseResult { @@ -1868,30 +1897,26 @@ impl Parser { self.level -= 1; Ok(param) } - Expr::Call(mut call) => match *call.obj { - Expr::Accessor(Accessor::Local(local)) => match &local.inspect()[..] { - "ref" => { - assert_eq!(call.args.len(), 1); - let var = call.args.remove_pos(0).expr; - let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_))) - .unwrap_or_else(|| todo!()); - let pat = ParamPattern::Ref(VarName::new(var.symbol)); - let param = ParamSignature::new(pat, None, None); - self.level -= 1; - Ok(param) - } - "ref!" => { - assert_eq!(call.args.len(), 1); - let var = call.args.remove_pos(0).expr; - let var = option_enum_unwrap!(var, Expr::Accessor:(Accessor::Local:(_))) - .unwrap_or_else(|| todo!()); - let pat = ParamPattern::RefMut(VarName::new(var.symbol)); - let param = ParamSignature::new(pat, None, None); - self.level -= 1; - Ok(param) - } - other => todo!("{other}"), - }, + Expr::UnaryOp(unary) => match unary.op.kind { + TokenKind::RefOp => { + let var = unary.args.into_iter().next().unwrap(); + let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_))) + .unwrap_or_else(|| todo!()); + let pat = ParamPattern::Ref(VarName::new(var.symbol)); + let param = ParamSignature::new(pat, None, None); + self.level -= 1; + Ok(param) + } + TokenKind::RefMutOp => { + let var = unary.args.into_iter().next().unwrap(); + let var = option_enum_unwrap!(*var, Expr::Accessor:(Accessor::Local:(_))) + .unwrap_or_else(|| todo!()); + let pat = ParamPattern::RefMut(VarName::new(var.symbol)); + let param = ParamSignature::new(pat, None, None); + self.level -= 1; + Ok(param) + } + // Spread other => todo!("{other}"), }, other => todo!("{other}"), // Error diff --git a/compiler/erg_parser/token.rs b/compiler/erg_parser/token.rs index 4dabc27b..52a78893 100644 --- a/compiler/erg_parser/token.rs +++ b/compiler/erg_parser/token.rs @@ -103,6 +103,10 @@ pub enum TokenKind { DotOp, /// `cross` (vector product) CrossOp, + /// `ref` (special unary) + RefOp, + /// `ref!` (special unary) + RefMutOp, /// = Equal, /// := @@ -210,7 +214,7 @@ impl TokenKind { Symbol => TokenCategory::Symbol, NatLit | IntLit | RatioLit | StrLit | BoolLit | NoneLit | EllipsisLit | NoImplLit | InfLit => TokenCategory::Literal, - PrePlus | PreMinus | PreBitNot | Mutate => TokenCategory::UnaryOp, + PrePlus | PreMinus | PreBitNot | Mutate | RefOp | RefMutOp => TokenCategory::UnaryOp, Try => TokenCategory::PostfixOp, Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | Walrus => { TokenCategory::SpecialBinOp @@ -234,16 +238,16 @@ impl TokenKind { pub const fn precedence(&self) -> Option { let prec = match self { - Dot | DblColon => 200, // . - Pow => 190, // ** - PrePlus | PreMinus | PreBitNot => 180, // (unary) + - * ~ - Star | Slash | FloorDiv | Mod | CrossOp | DotOp => 170, // * / // % cross dot - Plus | Minus => 160, // + - - Shl | Shr => 150, // << >> - BitAnd => 140, // && - BitXor => 130, // ^^ - BitOr => 120, // || - Closed | LeftOpen | RightOpen | Open => 100, // range operators + Dot | DblColon => 200, // . + Pow => 190, // ** + PrePlus | PreMinus | PreBitNot | RefOp | RefMutOp => 180, // (unary) + - * ~ ref ref! + Star | Slash | FloorDiv | Mod | CrossOp | DotOp => 170, // * / // % cross dot + Plus | Minus => 160, // + - + Shl | Shr => 150, // << >> + BitAnd => 140, // && + BitXor => 130, // ^^ + BitOr => 120, // || + Closed | LeftOpen | RightOpen | Open => 100, // range operators Less | Gre | LessEq | GreEq | DblEq | NotEq | InOp | NotInOp | IsOp | IsNotOp => 90, // < > <= >= == != in notin is isnot AndOp => 80, // and OrOp => 70, // or