diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index ff34768..fe6678d 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -4,10 +4,6 @@ pub mod top_level; use mist_parser::ast::*; -pub fn get_mutable(mutable: bool) -> String { - if mutable { "mut " } else { "" }.to_string() -} - pub struct Context { pub expr_ensure_semicolon: bool, } @@ -238,34 +234,39 @@ impl GetRust for TypeExprKind { impl GenRust for Pattern { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { - Self::Id(id) => cg.add(&id.get_rust()), - Self::Path(path) => cg.add(&path.get_rust()), + Self::Path(mutable, path) => { + if *mutable { + cg.add("mut "); + }; + + cg.add(&path.get_rust()) + } Self::Literal(lit) => lit.gen_rust(ctx, cg), - Self::Struct(path, ids) => { + Self::Struct(path, inner) => { cg.add(&path.get_rust()); cg.add(" {"); - for id in ids { - cg.add(&id.get_rust()); + for pat in inner { + pat.gen_rust(ctx, cg); cg.add(","); } cg.add("}"); } - Self::NamedTuple(path, ids) => { + Self::NamedTuple(path, inner) => { cg.add(&path.get_rust()); cg.add(" ("); - for id in ids { - cg.add(&id.get_rust()); + for pat in inner { + pat.gen_rust(ctx, cg); cg.add(","); } cg.add(")"); } - Self::Tuple(ids) => { + Self::Tuple(inner) => { cg.add("("); - for id in ids { - cg.add(&id.get_rust()); + for pat in inner { + pat.gen_rust(ctx, cg); cg.add(","); } cg.add(")"); diff --git a/crates/codegen/src/statement.rs b/crates/codegen/src/statement.rs index e55bf4c..b3c6901 100644 --- a/crates/codegen/src/statement.rs +++ b/crates/codegen/src/statement.rs @@ -1,6 +1,6 @@ use mist_parser::ast::*; -use crate::{Context, get_mutable}; +use crate::Context; use crate::{GenRust, GetRust, RustCodegen}; @@ -59,7 +59,11 @@ impl GenRust for Statement { cg.add(" {"); cg.indent += 1; - for (pat, body) in match_items { + for match_item in match_items { + cg.add_indentedln(&match_item.get_comment()); + + let MatchItem(pat, body) = &match_item.item; + for (i, p) in pat.iter().enumerate() { cg.addln(""); cg.add_indented(""); @@ -158,13 +162,11 @@ impl GenRust for Statement { } Statement::For { - mutable, pattern, iterator, body, } => { cg.add("for "); - cg.add(&get_mutable(*mutable)); pattern.gen_rust(ctx, cg); cg.add(" in "); iterator.gen_rust(ctx, cg); @@ -186,8 +188,6 @@ impl GenRust for Statement { impl GenRust for VarDecl { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add(&get_mutable(self.mutable)); - self.name.gen_rust(ctx, cg); cg.add( diff --git a/crates/codegen/src/top_level.rs b/crates/codegen/src/top_level.rs index 34bd69f..b13c531 100644 --- a/crates/codegen/src/top_level.rs +++ b/crates/codegen/src/top_level.rs @@ -212,8 +212,7 @@ impl GenRust for (&Vec>, &Spanned) { cg.add_indentedln("}\n"); let mut constructor_params = vec![VarDecl { - mutable: false, - name: Pattern::Id(Identifier(String::from("self"))), + name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])), type_: Some(TypeExpr( TypeExprKind::Path(Path(vec![Identifier(String::from("Self"))])), vec![TypePostfix::RefMut], diff --git a/crates/parser/src/ast/expr.rs b/crates/parser/src/ast/expr.rs index 1c6eb6b..23fb010 100644 --- a/crates/parser/src/ast/expr.rs +++ b/crates/parser/src/ast/expr.rs @@ -32,12 +32,11 @@ pub enum Literal { #[derive(Debug, Clone, Serialize)] pub enum Pattern { - NamedTuple(Path, Vec), - Struct(Path, Vec), - Tuple(Vec), + NamedTuple(Path, Vec>), + Struct(Path, Vec>), + Tuple(Vec>), Literal(Literal), - Path(Path), - Id(Identifier), + Path(bool, Path), } #[derive(Debug, Clone, Serialize)] diff --git a/crates/parser/src/ast/statement.rs b/crates/parser/src/ast/statement.rs index d4102ea..412e2f0 100644 --- a/crates/parser/src/ast/statement.rs +++ b/crates/parser/src/ast/statement.rs @@ -31,12 +31,11 @@ pub enum Statement { body: StatementBody, }, For { - mutable: bool, pattern: Pattern, iterator: Expression, body: StatementBody, }, - Match(Expression, Vec<(Vec, Expression)>), + Match(Expression, Vec>), VarDecl(VarDeclStmt), Return(Option), @@ -44,9 +43,11 @@ pub enum Statement { Continue, } +#[derive(Debug, Clone, Serialize)] +pub struct MatchItem(pub Vec, pub Expression); + #[derive(Debug, Clone, Serialize)] pub struct VarDecl { - pub mutable: bool, pub name: Pattern, pub type_: Option, } diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 6651ae5..9635b1d 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -134,16 +134,24 @@ literal = { // PATTERNS // ====================================================== +multi_pat_template = _{ + (pattern ~ ("," ~ pattern)*)? +} + tuple_pattern = { - "[" ~ (identifier ~ ("," ~ identifier)*) ~ "]" + "[" ~ multi_pat_template ~ "]" } named_tuple_pattern = { - static_path ~ "[" ~ (identifier ~ ("," ~ identifier)*)? ~ "]" + static_path ~ "[" ~ multi_pat_template ~ "]" } struct_pattern = { - static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" + static_path ~ "{" ~ multi_pat_template ~ "}" +} + +path_pattern = { + mutable? ~ static_path } pattern = _{ @@ -151,7 +159,7 @@ pattern = _{ | tuple_pattern | struct_pattern | literal - | static_path + | path_pattern } // ====================================================== @@ -171,7 +179,7 @@ meta = { } meta_list = { - meta ~ ("," ~ meta)* ~ ","? + (meta ~ ("," ~ meta)* ~ ","?)? } attributes = { @@ -182,7 +190,7 @@ attributes = { // DECLARATION HELPERS // ====================================================== var_decl = { - (var | type_expr) ~ mutable? ~ pattern + (var | type_expr) ~ pattern } field = { @@ -190,11 +198,11 @@ field = { } field_list = { - field ~ ("," ~ field)* ~ ","? + (field ~ ("," ~ field)* ~ ","?)? } param_list = { - var_decl ~ ("," ~ var_decl)* ~ ","? + (var_decl ~ ("," ~ var_decl)* ~ ","?)? } // ====================================================== @@ -252,7 +260,7 @@ enum_decl = { // ====================================================== class_constructor = { - visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list? ~ ")" ~ block + visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list ~ ")" ~ block } class_fields = { @@ -268,7 +276,7 @@ self_param = { } method = { - visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ block + visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list)? ~ ")" ~ block } class_item = _{ @@ -297,7 +305,7 @@ impl_decl = { trait_requirements = { ":" ~ type_expr_param ~ ("+" ~ type_expr_param)* } method_no_body = { - visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ semicolon + visibility? ~ type_expr ~ identifier ~ generics_decl? ~ "(" ~ self_param? ~ ("," ~ param_list)? ~ ")" ~ semicolon } trait_item = _{ @@ -314,7 +322,7 @@ trait_decl = { // ====================================================== function_decl = { - visibility? ~ type_expr ~ identifier ~ "(" ~ param_list? ~ ")" ~ block + visibility? ~ type_expr ~ identifier ~ "(" ~ param_list ~ ")" ~ block } // ====================================================== @@ -415,7 +423,7 @@ c_for_stmt = { } for_stmt = { - "for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body + "for" ~ "(" ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body } loop_stmt = { diff --git a/crates/parser/src/parser/common/decl.rs b/crates/parser/src/parser/common/decl.rs index 4cf8bfb..288745c 100644 --- a/crates/parser/src/parser/common/decl.rs +++ b/crates/parser/src/parser/common/decl.rs @@ -2,8 +2,7 @@ use crate::{ Rule, ast::*, ast_expr, - error::{AstError, AstResult, IntoErr}, - parser::listen_rule, + error::{AstError, IntoErr}, }; impl<'a> TryFrom> for VarDeclStmt { @@ -63,13 +62,10 @@ impl<'a> TryFrom> for VarDecl { }) .transpose(); - let mutable: AstResult<'_, bool> = Ok(listen_rule(&mut inner, Rule::mutable)); - let name = Pattern::try_from(inner.next().unwrap()); ast_expr!(VarDecl { type_: type_, - mutable: mutable, name: name, }) } diff --git a/crates/parser/src/parser/common/mod.rs b/crates/parser/src/parser/common/mod.rs index 206e3c9..59f0866 100644 --- a/crates/parser/src/parser/common/mod.rs +++ b/crates/parser/src/parser/common/mod.rs @@ -7,8 +7,8 @@ use crate::{ Rule, ast::*, ast_ensure, ast_expr, - error::{AstError, IntoErr, collect_recovered}, - parser::consume_rule, + error::{AstError, AstResult, IntoErr, collect_recovered, collect_recovered_map}, + parser::{consume_rule, listen_rule}, }; impl<'a> TryFrom> for Identifier { @@ -60,23 +60,26 @@ impl<'a> TryFrom> for Pattern { let mut inner = pair.clone().into_inner(); match rule { - Rule::tuple_pattern => ast_expr!(Pattern::Tuple(collect_recovered(pair.into_inner()))), + Rule::tuple_pattern => ast_expr!(Pattern::Tuple(collect_recovered_map(inner, |v| { + Self::try_from(v).map(Box::new) + }))), Rule::named_tuple_pattern => ast_expr!(Pattern::NamedTuple( Path::try_from(inner.next().unwrap()), - collect_recovered(inner), + collect_recovered_map(inner, |v| Self::try_from(v).map(Box::new)), )), Rule::struct_pattern => ast_expr!(Pattern::Struct( Path::try_from(inner.next().unwrap()), - collect_recovered(inner), + collect_recovered_map(inner, |v| Self::try_from(v).map(Box::new)), )), Rule::literal => ast_expr!(Pattern::Literal(pair.try_into())), - Rule::identifier => ast_expr!(Pattern::Id(pair.try_into())), - - Rule::static_path => ast_expr!(Pattern::Path(pair.try_into())), + Rule::path_pattern => ast_expr!(Pattern::Path( + Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>, + inner.next().unwrap().try_into() + )), _ => AstError::bug_unimplemented(pair), } diff --git a/crates/parser/src/parser/common/statement.rs b/crates/parser/src/parser/common/statement.rs index 3f2db09..5ca288e 100644 --- a/crates/parser/src/parser/common/statement.rs +++ b/crates/parser/src/parser/common/statement.rs @@ -2,8 +2,7 @@ use crate::{ Rule, ast::*, ast_ensure, ast_expr, - error::{AstError, AstResult, IntoErr, collect_recovered}, - parser::listen_rule, + error::{AstError, IntoErr, collect_recovered}, }; impl<'a> TryFrom> for Block { @@ -97,7 +96,6 @@ impl<'a> TryFrom> for Statement { }), Rule::for_stmt => ast_expr!(Statement::For { - mutable: Ok(listen_rule(&mut inner, Rule::mutable)) as AstResult<'_, bool>, pattern: inner.next().unwrap().try_into(), iterator: inner.next().unwrap().try_into(), body: inner.next().unwrap().try_into(), @@ -105,18 +103,23 @@ impl<'a> TryFrom> for Statement { Rule::match_stmt => ast_expr!(Statement::Match( inner.next().unwrap().try_into(), - inner - .map(|match_itms| { - let mut match_inner = match_itms.into_inner(); - Ok(( - collect_recovered(match_inner.next().unwrap().into_inner()).get()?, - Expression::try_from(match_inner.next().unwrap()).get()?, - )) - }) - .collect::>>(), + collect_recovered(inner), )), _ => AstError::bug_unimplemented(pair), } } } + +impl<'a> TryFrom> for MatchItem { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let mut match_inner = pair.into_inner(); + + Ok(MatchItem( + collect_recovered(match_inner.next().unwrap().into_inner()).get()?, + Expression::try_from(match_inner.next().unwrap()).get()?, + )) + } +} diff --git a/crates/parser/src/parser/items/function.rs b/crates/parser/src/parser/items/function.rs index 766de4c..2b52253 100644 --- a/crates/parser/src/parser/items/function.rs +++ b/crates/parser/src/parser/items/function.rs @@ -23,14 +23,11 @@ impl<'a> TryFrom> for FunctionDecl { let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { let mut param_inner = param.into_inner(); - let name = Pattern::Id(Identifier(String::from("self"))); - let mutable = listen_rule(&mut param_inner, Rule::mutable); - let is_ref = listen_rule(&mut param_inner, Rule::deref_px); + let name = Pattern::Path(mutable && !is_ref, Path(vec![Identifier(String::from("self"))])); VarDecl { - mutable: mutable && !is_ref, name: name.clone(), type_: Some(TypeExpr( TypeExprKind::Path(Path(vec![Identifier("Self".to_string())])),