diff --git a/compiler/erg_common/traits.rs b/compiler/erg_common/traits.rs index aaa0248d..20d3c0dc 100644 --- a/compiler/erg_common/traits.rs +++ b/compiler/erg_common/traits.rs @@ -481,12 +481,26 @@ macro_rules! impl_display_from_nested { }; } +/// For Decl, Def, Call, etc., which can occupy a line by itself +#[macro_export] +macro_rules! impl_nested_display_for_chunk_enum { + ($Enum: ident; $($Variant: ident $(,)?)*) => { + impl NestedDisplay for $Enum { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + write!(f, "{}", " ".repeat(level))?; + match self { + $($Enum::$Variant(v) => v.fmt_nest(f, level),)* + } + } + } + } +} + #[macro_export] macro_rules! impl_nested_display_for_enum { ($Enum: ident; $($Variant: ident $(,)?)*) => { impl NestedDisplay for $Enum { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { - write!(f, "{}", " ".repeat(level))?; match self { $($Enum::$Variant(v) => v.fmt_nest(f, level),)* } diff --git a/compiler/erg_compiler/codegen.rs b/compiler/erg_compiler/codegen.rs index ea1d2afa..20397472 100644 --- a/compiler/erg_compiler/codegen.rs +++ b/compiler/erg_compiler/codegen.rs @@ -494,7 +494,7 @@ impl CodeGenerator { fn emit_var_pat(&mut self, pat: &VarPattern, op: &Token) { match pat { - VarPattern::VarName(var) => { + VarPattern::Local(var) => { if op.category_is(TokenCategory::DefOp) { self.emit_store_instr(var.inspect().clone(), Name); } else { diff --git a/compiler/erg_compiler/context.rs b/compiler/erg_compiler/context.rs index b15cb387..ff33ce5a 100644 --- a/compiler/erg_compiler/context.rs +++ b/compiler/erg_compiler/context.rs @@ -780,7 +780,7 @@ impl Context { let vis = Private; // TODO: let muty = Mutability::from(&sig.inspect().unwrap()[..]); match &sig.pat { - ast::VarPattern::VarName(v) => { + ast::VarPattern::Local(v) => { if sig.t_spec.is_none() && opt_t.is_none() { Err(TyCheckError::no_type_spec_error( line!() as usize, @@ -882,7 +882,7 @@ impl Context { }; match &sig.pat { ast::VarPattern::Discard(_token) => Ok(()), - ast::VarPattern::VarName(v) => { + ast::VarPattern::Local(v) => { if self.registered(v.inspect(), v.inspect().is_uppercase()) { Err(TyCheckError::reassign_error( line!() as usize, @@ -899,7 +899,7 @@ impl Context { Ok(()) } } - ast::VarPattern::SelfDot(_) => todo!(), + ast::VarPattern::Public(_) => todo!(), ast::VarPattern::Array(arr) => { for (elem, inf) in arr.iter().zip(generalized.inner_ts().iter()) { let id = DefId(get_hash(&(&self.name, elem))); @@ -2617,7 +2617,7 @@ impl Context { )); } } - ast::VarPattern::VarName(n) => { + ast::VarPattern::Local(n) => { if self.unify(&spec_t, body_t, None, Some(sig.loc())).is_err() { return Err(TyCheckError::type_mismatch_error( line!() as usize, diff --git a/compiler/erg_compiler/eval.rs b/compiler/erg_compiler/eval.rs index e054deeb..1d0e117d 100644 --- a/compiler/erg_compiler/eval.rs +++ b/compiler/erg_compiler/eval.rs @@ -166,7 +166,7 @@ impl Evaluator { Accessor::Local(_) => None, Accessor::Attr(_attr) => todo!(), Accessor::TupleAttr(_attr) => todo!(), - Accessor::SelfDot(_name) => todo!(), + Accessor::Public(_name) => todo!(), Accessor::Subscr(_subscr) => todo!(), } } else { diff --git a/compiler/erg_compiler/hir.rs b/compiler/erg_compiler/hir.rs index 06a4759e..f1e07253 100644 --- a/compiler/erg_compiler/hir.rs +++ b/compiler/erg_compiler/hir.rs @@ -8,7 +8,8 @@ use erg_common::value::ValueObj; use erg_common::Str; use erg_common::{ impl_display_for_enum, impl_display_from_nested, impl_locational, impl_locational_for_enum, - impl_nested_display_for_enum, impl_stream_for_wrapper, impl_t, impl_t_for_enum, + impl_nested_display_for_chunk_enum, impl_nested_display_for_enum, impl_stream_for_wrapper, + impl_t, impl_t_for_enum, }; use erg_parser::ast::{fmt_lines, DefId, Params, VarName, VarPattern}; @@ -1039,7 +1040,7 @@ pub enum Expr { Def(Def), } -impl_nested_display_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); +impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_display_from_nested!(Expr); impl_locational_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_t_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); diff --git a/compiler/erg_compiler/lower.rs b/compiler/erg_compiler/lower.rs index 1c9a34ac..e7b1b878 100644 --- a/compiler/erg_compiler/lower.rs +++ b/compiler/erg_compiler/lower.rs @@ -361,7 +361,7 @@ impl ASTLowerer { .assign_var(&sig, id, found_body_t)?; match block.first().unwrap() { hir::Expr::Call(call) => { - if let ast::VarPattern::VarName(name) = &sig.pat { + if let ast::VarPattern::Local(name) = &sig.pat { if call.is_import_call() { self.ctx .outer diff --git a/compiler/erg_parser/ast.rs b/compiler/erg_parser/ast.rs index 47d85133..75370af6 100644 --- a/compiler/erg_parser/ast.rs +++ b/compiler/erg_parser/ast.rs @@ -3,7 +3,7 @@ use std::borrow::Borrow; use std::fmt; use erg_common::error::Location; -use erg_common::set::Set; +use erg_common::set::Set as HashSet; use erg_common::traits::{Locational, NestedDisplay, Stream}; use erg_common::ty::SubrKind; use erg_common::value::ValueObj; @@ -11,7 +11,8 @@ use erg_common::Str; use erg_common::{ fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct, impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational, - impl_locational_for_enum, impl_nested_display_for_enum, impl_stream, impl_stream_for_wrapper, + impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum, + impl_stream, impl_stream_for_wrapper, }; use crate::token::{Token, TokenKind}; @@ -21,8 +22,8 @@ pub fn fmt_lines<'a, T: NestedDisplay + 'a>( f: &mut fmt::Formatter<'_>, level: usize, ) -> fmt::Result { - if let Some(line) = iter.next() { - line.fmt_nest(f, level)?; + if let Some(first) = iter.next() { + first.fmt_nest(f, level)?; } for arg in iter { writeln!(f)?; @@ -135,7 +136,8 @@ pub struct Args { impl NestedDisplay for Args { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { - fmt_lines(self.pos_args.iter(), f, level) + fmt_lines(self.pos_args.iter(), f, level)?; + fmt_lines(self.kw_args.iter(), f, level) } } @@ -217,21 +219,21 @@ impl Args { } } -/// represents a local variable +/// represents a local (private) variable #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Local { pub symbol: Token, } -impl_display_for_single_struct!(Local, symbol.content); - -impl Locational for Local { - #[inline] - fn loc(&self) -> Location { - self.symbol.loc() +impl NestedDisplay for Local { + fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { + write!(f, "{}", self.symbol.content) } } +impl_display_from_nested!(Local); +impl_locational!(Local, symbol, symbol); + impl Local { pub const fn new(symbol: Token) -> Self { Self { symbol } @@ -251,18 +253,56 @@ impl Local { } } +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Public { + pub dot: Token, + pub symbol: Token, +} + +impl NestedDisplay for Public { + fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { + write!(f, ".{}", self.symbol.content) + } +} + +impl_display_from_nested!(Public); +impl_locational!(Public, dot, symbol); + +impl Public { + pub const fn new(dot: Token, symbol: Token) -> Self { + Self { dot, symbol } + } + + pub fn dummy(name: &'static str) -> Self { + Self::new( + Token::from_str(TokenKind::Dot, "."), + Token::from_str(TokenKind::Symbol, name), + ) + } + + // &strにするとクローンしたいときにアロケーションコストがかかるので&Strのままで + pub const fn inspect(&self) -> &Str { + &self.symbol.content + } + + pub fn is_const(&self) -> bool { + self.symbol.inspect().chars().next().unwrap().is_uppercase() + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Attribute { pub obj: Box, pub name: Local, } -impl fmt::Display for Attribute { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl NestedDisplay for Attribute { + fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { write!(f, "({}).{}", self.obj, self.name) } } +impl_display_from_nested!(Attribute); impl_locational!(Attribute, obj, name); impl Attribute { @@ -281,12 +321,13 @@ pub struct TupleAttribute { pub index: Literal, } -impl fmt::Display for TupleAttribute { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl NestedDisplay for TupleAttribute { + fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { write!(f, "({}).{}", self.obj, self.index) } } +impl_display_from_nested!(TupleAttribute); impl_locational!(TupleAttribute, obj, index); impl TupleAttribute { @@ -304,12 +345,13 @@ pub struct Subscript { index: Box, } -impl fmt::Display for Subscript { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { +impl NestedDisplay for Subscript { + fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { write!(f, "({})[{}]", self.obj, self.index) } } +impl_display_from_nested!(Subscript); impl_locational!(Subscript, obj, index); impl Subscript { @@ -324,34 +366,23 @@ impl Subscript { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Accessor { Local(Local), - SelfDot(Local), + Public(Public), Attr(Attribute), TupleAttr(TupleAttribute), Subscr(Subscript), } -impl NestedDisplay for Accessor { - fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - match self { - Self::Local(name) => write!(f, "{}", name), - Self::SelfDot(attr) => write!(f, "self.{}", attr), - Self::Attr(attr) => write!(f, "{}", attr), - Self::TupleAttr(attr) => write!(f, "{}", attr), - Self::Subscr(subscr) => write!(f, "{}", subscr), - } - } -} - +impl_nested_display_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr); impl_display_from_nested!(Accessor); -impl_locational_for_enum!(Accessor; Local, SelfDot, Attr, TupleAttr, Subscr); +impl_locational_for_enum!(Accessor; Local, Public, Attr, TupleAttr, Subscr); impl Accessor { pub const fn local(symbol: Token) -> Self { Self::Local(Local::new(symbol)) } - pub const fn self_dot(attr: Token) -> Self { - Self::SelfDot(Local::new(attr)) + pub const fn public(dot: Token, symbol: Token) -> Self { + Self::Public(Public::new(dot, symbol)) } pub fn attr(obj: Expr, name: Local) -> Self { @@ -365,14 +396,15 @@ impl Accessor { pub const fn name(&self) -> Option<&Str> { match self { Self::Local(local) => Some(local.inspect()), - Self::SelfDot(local) => Some(local.inspect()), + Self::Public(local) => Some(local.inspect()), _ => None, } } pub fn is_const(&self) -> bool { match self { - Self::Local(local) | Self::SelfDot(local) => local.is_const(), + Self::Local(local) => local.is_const(), + Self::Public(public) => public.is_const(), Self::Subscr(subscr) => subscr.obj.is_const_acc(), Self::TupleAttr(attr) => attr.obj.is_const_acc(), Self::Attr(attr) => attr.obj.is_const_acc() && attr.name.is_const(), @@ -556,6 +588,85 @@ impl_nested_display_for_enum!(Dict; Normal, Comprehension); impl_display_for_enum!(Dict; Normal, Comprehension); impl_locational_for_enum!(Dict; Normal, Comprehension); +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct RecordAttrs(Vec); + +impl NestedDisplay for RecordAttrs { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + fmt_lines(self.0.iter(), f, level) + } +} + +impl From> for RecordAttrs { + fn from(attrs: Vec) -> Self { + Self(attrs) + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Record { + l_brace: Token, + r_brace: Token, + pub attrs: RecordAttrs, +} + +impl NestedDisplay for Record { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + writeln!(f, "{{")?; + self.attrs.fmt_nest(f, level + 1)?; + writeln!(f, "\n{}}}", " ".repeat(level)) + } +} + +impl_display_from_nested!(Record); +impl_locational!(Record, l_brace, r_brace); + +impl Record { + pub fn new(l_brace: Token, r_brace: Token, attrs: RecordAttrs) -> Self { + Self { + l_brace, + r_brace, + attrs, + } + } +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct NormalSet { + l_brace: Token, + r_brace: Token, + pub elems: Args, +} + +impl NestedDisplay for NormalSet { + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { + write!(f, "{{{}}}", self.elems) + } +} + +impl_display_from_nested!(NormalSet); +impl_locational!(NormalSet, l_brace, r_brace); + +impl NormalSet { + pub fn new(l_brace: Token, r_brace: Token, elems: Args) -> Self { + Self { + l_brace, + r_brace, + elems, + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum Set { + Normal(NormalSet), + // Comprehension(SetComprehension), +} + +impl_nested_display_for_enum!(Set; Normal); +impl_display_for_enum!(Set; Normal); +impl_locational_for_enum!(Set; Normal); + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct BinOp { pub op: Token, @@ -936,14 +1047,13 @@ pub enum ConstExpr { Accessor(ConstAccessor), App(ConstApp), Array(ConstArray), - // Dict(Dict), // Set(Set), Dict(ConstDict), BinOp(ConstBinOp), UnaryOp(ConstUnaryOp), } -impl_nested_display_for_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased); +impl_nested_display_for_chunk_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased); impl_display_from_nested!(ConstExpr); impl_locational_for_enum!(ConstExpr; Lit, Accessor, App, Array, Dict, BinOp, UnaryOp, Erased); @@ -977,9 +1087,8 @@ pub struct ConstKwArg { } impl NestedDisplay for ConstKwArg { - fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { - write!(f, "{}: ", self.keyword.inspect())?; - self.expr.fmt_nest(f, level + 1) + fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, _level: usize) -> std::fmt::Result { + write!(f, "{}: {}", self.keyword.inspect(), self.expr) } } @@ -1004,16 +1113,8 @@ pub struct ConstArgs { impl NestedDisplay for ConstArgs { fn fmt_nest(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result { - for arg in self.pos_args.iter() { - arg.fmt_nest(f, level)?; - write!(f, ", ")?; - } - write!(f, "?")?; - for arg in self.kw_args.iter() { - arg.fmt_nest(f, level)?; - write!(f, ", ")?; - } - Ok(()) + fmt_lines(self.pos_args(), f, level)?; + fmt_lines(self.kw_args(), f, level) } } @@ -1607,8 +1708,8 @@ impl VarRecordPattern { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum VarPattern { Discard(Token), - VarName(VarName), - SelfDot(VarName), // only self-attribute can assign once + Local(VarName), // x + Public(VarName), // .x /// e.g. `[x, y, z]` of `[x, y, z] = [1, 2, 3]` Array(VarArrayPattern), /// e.g. `(x, y, z)` of `(x, y, z) = (1, 2, 3)` @@ -1621,8 +1722,8 @@ impl NestedDisplay for VarPattern { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { match self { Self::Discard(_) => write!(f, "_"), - Self::VarName(n) => write!(f, "{}", n), - Self::SelfDot(n) => write!(f, "self.{}", n), + Self::Local(n) => write!(f, "{}", n), + Self::Public(n) => write!(f, ".{}", n), Self::Array(a) => write!(f, "{}", a), Self::Tuple(t) => write!(f, "{}", t), Self::Record(r) => write!(f, "{}", r), @@ -1631,19 +1732,19 @@ impl NestedDisplay for VarPattern { } impl_display_from_nested!(VarPattern); -impl_locational_for_enum!(VarPattern; Discard, VarName, SelfDot, Array, Tuple, Record); +impl_locational_for_enum!(VarPattern; Discard, Local, Public, Array, Tuple, Record); impl VarPattern { pub const fn inspect(&self) -> Option<&Str> { match self { - Self::VarName(n) | Self::SelfDot(n) => Some(n.inspect()), + Self::Local(n) | Self::Public(n) => Some(n.inspect()), _ => None, } } pub fn inspects(&self) -> Vec<&Str> { match self { - Self::VarName(n) | Self::SelfDot(n) => vec![n.inspect()], + Self::Local(n) | Self::Public(n) => vec![n.inspect()], Self::Array(VarArrayPattern { elems, .. }) | Self::Tuple(VarTuplePattern { elems, .. }) | Self::Record(VarRecordPattern { elems, .. }) => { @@ -1656,7 +1757,7 @@ impl VarPattern { // _!(...) = ... is invalid pub fn is_procedural(&self) -> bool { match self { - Self::VarName(n) | Self::SelfDot(n) => n.is_procedural(), + Self::Local(n) | Self::Public(n) => n.is_procedural(), _ => false, } } @@ -1664,7 +1765,7 @@ impl VarPattern { // _ = (type block) is invalid pub fn is_const(&self) -> bool { match self { - Self::VarName(n) | Self::SelfDot(n) => n.is_const(), + Self::Local(n) | Self::Public(n) => n.is_const(), _ => false, } } @@ -1773,8 +1874,8 @@ pub struct ParamRecordPattern { } impl NestedDisplay for ParamRecordPattern { - fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, _level: usize) -> fmt::Result { - write!(f, "{{{}}}", self.elems) + fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { + write!(f, "{}{{{}}}", " ".repeat(level), self.elems) } } @@ -1964,7 +2065,7 @@ impl Params { /// 引数を取るならTypeでもSubr扱い #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct SubrSignature { - pub decorators: Set, + pub decorators: HashSet, pub name: VarName, pub params: Params, pub return_t_spec: Option, @@ -2010,7 +2111,7 @@ impl Locational for SubrSignature { impl SubrSignature { pub const fn new( - decorators: Set, + decorators: HashSet, name: VarName, params: Params, return_t: Option, @@ -2128,7 +2229,7 @@ pub enum Signature { Subr(SubrSignature), } -impl_nested_display_for_enum!(Signature; Var, Subr); +impl_nested_display_for_chunk_enum!(Signature; Var, Subr); impl_display_from_nested!(Signature); impl_locational_for_enum!(Signature; Var, Subr); @@ -2143,7 +2244,7 @@ impl Signature { pub fn name(&self) -> Option<&VarName> { match self { Self::Var(v) => { - if let VarPattern::VarName(v) = &v.pat { + if let VarPattern::Local(v) = &v.pat { Some(v) } else { None @@ -2193,7 +2294,8 @@ pub struct Def { impl NestedDisplay for Def { fn fmt_nest(&self, f: &mut fmt::Formatter<'_>, level: usize) -> fmt::Result { - writeln!(f, "{} {}", self.sig, self.body.op.content)?; + self.sig.fmt_nest(f, level)?; + writeln!(f, " {}", self.body.op.content)?; self.body.block.fmt_nest(f, level + 1) } } @@ -2222,7 +2324,8 @@ pub enum Expr { Accessor(Accessor), Array(Array), Dict(Dict), - // Set(Set), + Set(Set), + Record(Record), BinOp(BinOp), UnaryOp(UnaryOp), Call(Call), @@ -2231,9 +2334,9 @@ pub enum Expr { Def(Def), } -impl_nested_display_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); +impl_nested_display_for_chunk_enum!(Expr; Lit, Accessor, Array, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl_display_from_nested!(Expr); -impl_locational_for_enum!(Expr; Lit, Accessor, Array, Dict, BinOp, UnaryOp, Call, Lambda, Decl, Def); +impl_locational_for_enum!(Expr; Lit, Accessor, Array, Dict, Set, Record, BinOp, UnaryOp, Call, Lambda, Decl, Def); impl Expr { pub fn is_match_call(&self) -> bool { diff --git a/compiler/erg_parser/parse.rs b/compiler/erg_parser/parse.rs index dd8dc7e9..f9c60229 100644 --- a/compiler/erg_parser/parse.rs +++ b/compiler/erg_parser/parse.rs @@ -9,7 +9,7 @@ use erg_common::color::{GREEN, RED, RESET}; use erg_common::config::ErgConfig; use erg_common::config::Input; use erg_common::error::Location; -use erg_common::set::Set; +use erg_common::set::Set as HashSet; use erg_common::traits::Runnable; use erg_common::traits::{Locational, Stream}; use erg_common::Str; @@ -66,6 +66,12 @@ pub enum ArrayInner { }, } +pub enum BraceContainer { + Set(Set), + Dict(Dict), + Record(Record), +} + /// Perform recursive descent parsing. /// /// `level` is raised by 1 by `debug_call_info!` in each analysis method and lowered by 1 when leaving (`.map_err` is called to lower the level). @@ -490,7 +496,7 @@ impl Parser { } #[inline] - fn opt_reduce_decorators(&mut self) -> ParseResult> { + fn opt_reduce_decorators(&mut self) -> ParseResult> { debug_call_info!(self); let mut decs = set![]; while let Some(deco) = self.opt_reduce_decorator().map_err(|_| self.stack_dec())? { @@ -509,7 +515,7 @@ impl Parser { return Ok(Signature::Var(var)); } let decorators = self.opt_reduce_decorators().map_err(|_| self.stack_dec())?; - let name = self.try_reduce_name().map_err(|_| self.stack_dec())?; + let (opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?; // TODO: parse bounds |...| let bounds = TypeBoundSpecs::empty(); if self.cur_is(VBar) { @@ -562,10 +568,12 @@ impl Parser { None }; self.level -= 1; - Ok(Signature::Var(VarSignature::new( - VarPattern::VarName(name), - t_spec, - ))) + let var_pat = if opt_dot.is_some() { + VarPattern::Public(name) + } else { + VarPattern::Local(name) + }; + Ok(Signature::Var(VarSignature::new(var_pat, t_spec))) } } @@ -624,14 +632,6 @@ impl Parser { #[inline] fn try_reduce_lambda_sig(&mut self) -> ParseResult { debug_call_info!(self); - let params = self.try_reduce_params().map_err(|_| self.stack_dec())?; - let return_t = match self.peek() { - Some(t) if t.is(SupertypeOf) => { - self.skip(); - Some(self.try_reduce_type_spec().map_err(|_| self.stack_dec())?) - } - _ => None, - }; let bounds = match self.peek() { Some(t) if t.is(VBar) => { self.skip(); @@ -639,6 +639,14 @@ impl Parser { } _ => TypeBoundSpecs::empty(), }; + let params = self.try_reduce_params().map_err(|_| self.stack_dec())?; + let return_t = match self.peek() { + Some(t) if t.is(Colon) => { + self.skip(); + Some(self.try_reduce_type_spec().map_err(|_| self.stack_dec())?) + } + _ => None, + }; self.level -= 1; Ok(LambdaSignature::new(params, return_t, bounds)) } @@ -898,9 +906,14 @@ impl Parser { debug_call_info!(self); match self.peek() { Some(t) if t.is(Symbol) => { - let varname = self.try_reduce_name().map_err(|_| self.stack_dec())?; + let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?; + let var_pat = if let Some(_dot) = opt_dot { + VarPattern::Public(varname) + } else { + VarPattern::Local(varname) + }; self.level -= 1; - Ok(VarPattern::VarName(varname)) + Ok(var_pat) } Some(t) if t.is(UBar) => { self.level -= 1; @@ -955,7 +968,23 @@ impl Parser { debug_call_info!(self); match self.peek() { Some(t) if t.is(Symbol) => { - let varname = self.try_reduce_name().map_err(|_| self.stack_dec())?; + let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?; + if let Some(dot) = opt_dot { + let loc = dot.loc(); + self.level -= 1; + self.errs.push(ParseError::syntax_error( + line!() as usize, + loc, + switch_lang!( + "japanese" => "仮引数に`.`は使えません", + "simplified_chinese" => "参数不能使用点(`.`)", + "traditional_chinese" => "參數不能使用點(`.`)", + "english" => "`.` is not allowed in parameters", + ), + None, + )); + return Err(()); + } self.level -= 1; Ok(ParamPattern::VarName(varname)) } @@ -971,10 +1000,25 @@ impl Parser { } Some(t) if t.is(Spread) => { self.skip(); + let (opt_dot, varname) = self.try_reduce_name().map_err(|_| self.stack_dec())?; + if let Some(dot) = opt_dot { + let loc = dot.loc(); + self.level -= 1; + self.errs.push(ParseError::syntax_error( + line!() as usize, + loc, + switch_lang!( + "japanese" => "仮引数に`.`は使えません", + "simplified_chinese" => "参数不能使用点(`.`)", + "traditional_chinese" => "參數不能使用點(`.`)", + "english" => "`.` is not allowed in parameters", + ), + None, + )); + return Err(()); + } self.level -= 1; - Ok(ParamPattern::VarArgsName( - self.try_reduce_name().map_err(|_| self.stack_dec())?, - )) + Ok(ParamPattern::VarArgsName(varname)) } Some(t) if t.is(LSqBr) => { let l_sqbr = self.lpop(); @@ -1117,7 +1161,8 @@ impl Parser { fn try_reduce_func_type_param(&mut self) -> ParseResult { debug_call_info!(self); if self.cur_is(Symbol) && self.nth_is(1, Colon) { - let name = self.try_reduce_name().map_err(|_| self.stack_dec())?; + // TODO: handle `.` + let (_opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?; self.skip(); let typ = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?; self.level -= 1; @@ -1183,7 +1228,8 @@ impl Parser { debug_call_info!(self); match self.peek() { Some(t) if t.is(Symbol) => { - let name = self.try_reduce_name().map_err(|_| self.stack_dec())?; + // TODO: handle dot + let (_opt_dot, name) = self.try_reduce_name().map_err(|_| self.stack_dec())?; if let Some(res) = self.opt_reduce_args() { let args = self.validate_const_args(res?)?; self.level -= 1; @@ -1562,58 +1608,62 @@ impl Parser { self.validate_const_expr(expr) } + #[inline] + fn try_reduce_def(&mut self) -> ParseResult { + debug_call_info!(self); + let sig = self.try_reduce_decl().map_err(|_| self.stack_dec())?; + match self.peek() { + Some(t) if t.is(Equal) => { + let op = self.lpop(); + self.counter.inc(); + let block = self.try_reduce_block().map_err(|_| self.stack_dec())?; + let body = DefBody::new(op, block, self.counter); + self.level -= 1; + Ok(Def::new(sig, body)) + } + _other => { + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); + return Err(()); + } + } + } + + #[inline] + fn try_reduce_lambda(&mut self) -> ParseResult { + debug_call_info!(self); + let sig = self.try_reduce_lambda_sig().map_err(|_| self.stack_dec())?; + let op = self.lpop(); + if op.category() != TC::LambdaOp { + self.level -= 1; + let err = self.skip_and_throw_syntax_err(caused_by!()); + self.errs.push(err); + return Err(()); + } + // REVIEW: need this? + while self.cur_is(Newline) { + self.skip(); + } + let body = self.try_reduce_block().map_err(|_| self.stack_dec())?; + self.counter.inc(); + self.level -= 1; + Ok(Lambda::new(sig, op, body, self.counter)) + } + fn try_reduce_expr(&mut self) -> ParseResult { debug_call_info!(self); let mut stack = Vec::::new(); match self.cur_side() { Side::LhsAssign => { - let sig = self.try_reduce_decl().map_err(|_| self.stack_dec())?; - match self.peek() { - Some(t) if t.is(Equal) => { - let op = self.lpop(); - self.counter.inc(); - let block = self.try_reduce_block().map_err(|_| self.stack_dec())?; - let body = DefBody::new(op, block, self.counter); - self.level -= 1; - Ok(Expr::Def(Def::new(sig, body))) - } - _other => { - self.level -= 1; - let err = self.skip_and_throw_syntax_err(caused_by!()); - self.errs.push(err); - return Err(()); - } - } + let def = self.try_reduce_def().map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(Expr::Def(def)) } Side::LhsLambda => { - let params = self.try_reduce_params().map_err(|_| self.stack_dec())?; - match self.peek() { - Some(t) if t.category_is(TC::LambdaOp) => { - let sig = LambdaSignature::new(params, None, TypeBoundSpecs::empty()); - let op = self.lpop(); - let body = self.try_reduce_block().map_err(|_| self.stack_dec())?; - self.counter.inc(); - self.level -= 1; - Ok(Expr::Lambda(Lambda::new(sig, op, body, self.counter))) - } - Some(t) if t.is(Colon) => { - self.lpop(); - let spec_t = self.try_reduce_type_spec().map_err(|_| self.stack_dec())?; - let sig = - LambdaSignature::new(params, Some(spec_t), TypeBoundSpecs::empty()); - let op = self.lpop(); - let body = self.try_reduce_block().map_err(|_| self.stack_dec())?; - self.counter.inc(); - self.level -= 1; - Ok(Expr::Lambda(Lambda::new(sig, op, body, self.counter))) - } - _other => { - self.level -= 1; - let err = self.skip_and_throw_syntax_err(caused_by!()); - self.errs.push(err); - return Err(()); - } - } + let lambda = self.try_reduce_lambda().map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(Expr::Lambda(lambda)) } Side::Rhs => { stack.push(ExprOrOp::Expr( @@ -1774,7 +1824,23 @@ impl Parser { Ok(Expr::Array(array)) } Some(t) if t.is(LBrace) => { - todo!() + match self + .try_reduce_brace_container() + .map_err(|_| self.stack_dec())? + { + BraceContainer::Dict(dic) => { + self.level -= 1; + Ok(Expr::Dict(dic)) + } + BraceContainer::Record(rec) => { + self.level -= 1; + Ok(Expr::Record(rec)) + } + BraceContainer::Set(set) => { + self.level -= 1; + Ok(Expr::Set(set)) + } + } } Some(t) if t.is(UBar) => { let token = self.lpop(); @@ -1807,27 +1873,6 @@ impl Parser { } } - #[inline] - fn try_reduce_lambda(&mut self) -> ParseResult { - debug_call_info!(self); - let sig = self.try_reduce_lambda_sig().map_err(|_| self.stack_dec())?; - let op = self.lpop(); - if op.category() != TC::LambdaOp { - self.level -= 1; - let err = self.skip_and_throw_syntax_err(caused_by!()); - self.errs.push(err); - return Err(()); - } - // REVIEW: この箇所必要か - while self.cur_is(Newline) { - self.skip(); - } - let body = self.try_reduce_block().map_err(|_| self.stack_dec())?; - self.counter.inc(); - self.level -= 1; - Ok(Lambda::new(sig, op, body, self.counter)) - } - #[inline] fn try_reduce_unary(&mut self) -> ParseResult { debug_call_info!(self); @@ -1860,12 +1905,92 @@ impl Parser { Ok(arr) } + /// Set, Dict, Record + fn try_reduce_brace_container(&mut self) -> ParseResult { + debug_call_info!(self); + let l_brace = self.lpop(); + if self.cur_is(Newline) { + self.skip(); + if self.cur_is(Indent) { + self.skip(); + } else { + todo!() + } + } + // TODO: K: V + let first = self.try_reduce_expr().map_err(|_| self.stack_dec())?; + match first { + Expr::Def(def) => { + let record = self + .try_reduce_record(l_brace, def) + .map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(BraceContainer::Record(record)) + } + Expr::Decl(_) => todo!(), // invalid syntax + other => { + let set = self + .try_reduce_set(l_brace, other) + .map_err(|_| self.stack_dec())?; + self.level -= 1; + Ok(BraceContainer::Set(set)) + } + } + } + + fn try_reduce_record(&mut self, l_brace: Token, first: Def) -> ParseResult { + debug_call_info!(self); + let mut attrs = vec![first]; + loop { + match self.peek() { + Some(t) if t.category_is(TC::Separator) => { + self.skip(); + if self.cur_is(Dedent) { + self.skip(); + if self.cur_is(RBrace) { + let r_brace = self.lpop(); + self.level -= 1; + let attrs = RecordAttrs::from(attrs); + return Ok(Record::new(l_brace, r_brace, attrs)); + } else { + todo!() + } + } + let def = self.try_reduce_def().map_err(|_| self.stack_dec())?; + attrs.push(def); + } + Some(term) if term.is(RBrace) => { + let r_brace = self.lpop(); + self.level -= 1; + let attrs = RecordAttrs::from(attrs); + return Ok(Record::new(l_brace, r_brace, attrs)); + } + _ => todo!(), + } + } + } + + fn _try_reduce_dict() -> ParseResult { + todo!() + } + + fn try_reduce_set(&mut self, _l_brace: Token, _first: Expr) -> ParseResult { + todo!() + } + + /// option: Dot(`.`) #[inline] - fn try_reduce_name(&mut self) -> ParseResult { + fn try_reduce_name(&mut self) -> ParseResult<(Option, VarName)> { debug_call_info!(self); self.level -= 1; match self.peek() { - Some(t) if t.is(Symbol) => Ok(VarName::new(self.lpop())), + Some(t) if t.is(Dot) => { + let dot = self.lpop(); + // TODO: + assert!(self.cur_category_is(TC::Symbol)); + Ok((Some(dot), VarName::new(self.lpop()))) + } + Some(t) if t.is(Symbol) => Ok((None, VarName::new(self.lpop()))), _ => { let err = self.skip_and_throw_syntax_err(caused_by!()); self.errs.push(err);