From 83e98573aa975134790d579b01679d07279328ef Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 28 May 2026 11:30:47 +0200 Subject: [PATCH 1/7] Updated pattern grammar --- crates/parser/src/grammar.pest | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 6651ae5..9755861 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -134,16 +134,24 @@ literal = { // PATTERNS // ====================================================== +multi_pat_template = _{ + "[" ~ (identifier ~ ("," ~ identifier)*)? ~ "]" +} + 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 } // ====================================================== @@ -182,7 +190,7 @@ attributes = { // DECLARATION HELPERS // ====================================================== var_decl = { - (var | type_expr) ~ mutable? ~ pattern + (var | type_expr) ~ pattern } field = { @@ -415,7 +423,7 @@ c_for_stmt = { } for_stmt = { - "for" ~ "(" ~ mutable? ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body + "for" ~ "(" ~ pattern ~ ":" ~ expr ~ ")" ~ statement_body } loop_stmt = { From e09c7926e5497acae5514c06f7b5e20266a0c9a2 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 28 May 2026 11:34:14 +0200 Subject: [PATCH 2/7] Updated pattern ast --- crates/parser/src/ast/expr.rs | 2 +- crates/parser/src/grammar.pest | 2 +- crates/parser/src/parser/common/mod.rs | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/parser/src/ast/expr.rs b/crates/parser/src/ast/expr.rs index 1c6eb6b..a1fc4ad 100644 --- a/crates/parser/src/ast/expr.rs +++ b/crates/parser/src/ast/expr.rs @@ -36,7 +36,7 @@ pub enum Pattern { Struct(Path, Vec), Tuple(Vec), Literal(Literal), - Path(Path), + Path(bool, Path), Id(Identifier), } diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 9755861..476234a 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -135,7 +135,7 @@ literal = { // ====================================================== multi_pat_template = _{ - "[" ~ (identifier ~ ("," ~ identifier)*)? ~ "]" + (identifier ~ ("," ~ identifier)*)? } tuple_pattern = { diff --git a/crates/parser/src/parser/common/mod.rs b/crates/parser/src/parser/common/mod.rs index 206e3c9..3057472 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}, + parser::{consume_rule, listen_rule}, }; impl<'a> TryFrom> for Identifier { @@ -76,7 +76,10 @@ impl<'a> TryFrom> for Pattern { 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), } From 3444f93546984ca71b3c36cce50f2c32472ab7c7 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 28 May 2026 11:36:28 +0200 Subject: [PATCH 3/7] Updated codegen --- crates/codegen/src/lib.rs | 12 +++++++----- crates/codegen/src/statement.rs | 5 +---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index ff34768..bbdf66c 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, } @@ -239,7 +235,13 @@ 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) => { diff --git a/crates/codegen/src/statement.rs b/crates/codegen/src/statement.rs index e55bf4c..13b1a59 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}; @@ -164,7 +164,6 @@ impl GenRust for Statement { body, } => { cg.add("for "); - cg.add(&get_mutable(*mutable)); pattern.gen_rust(ctx, cg); cg.add(" in "); iterator.gen_rust(ctx, cg); @@ -186,8 +185,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( From 7007aa32f1ece9f385a3b2177e5c2f5981ec2189 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 28 May 2026 11:45:26 +0200 Subject: [PATCH 4/7] Refactored mutability --- crates/codegen/src/lib.rs | 1 - crates/codegen/src/statement.rs | 1 - crates/codegen/src/top_level.rs | 3 +-- crates/parser/src/ast/expr.rs | 1 - crates/parser/src/ast/statement.rs | 2 -- crates/parser/src/parser/common/decl.rs | 6 +----- crates/parser/src/parser/common/mod.rs | 2 -- crates/parser/src/parser/common/statement.rs | 2 -- crates/parser/src/parser/items/function.rs | 5 +---- 9 files changed, 3 insertions(+), 20 deletions(-) diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index bbdf66c..cf88d9d 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -234,7 +234,6 @@ 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(mutable, path) => { if *mutable { cg.add("mut "); diff --git a/crates/codegen/src/statement.rs b/crates/codegen/src/statement.rs index 13b1a59..aa7a37a 100644 --- a/crates/codegen/src/statement.rs +++ b/crates/codegen/src/statement.rs @@ -158,7 +158,6 @@ impl GenRust for Statement { } Statement::For { - mutable, pattern, iterator, body, 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 a1fc4ad..fcec338 100644 --- a/crates/parser/src/ast/expr.rs +++ b/crates/parser/src/ast/expr.rs @@ -37,7 +37,6 @@ pub enum Pattern { Tuple(Vec), Literal(Literal), Path(bool, Path), - Id(Identifier), } #[derive(Debug, Clone, Serialize)] diff --git a/crates/parser/src/ast/statement.rs b/crates/parser/src/ast/statement.rs index d4102ea..0196e72 100644 --- a/crates/parser/src/ast/statement.rs +++ b/crates/parser/src/ast/statement.rs @@ -31,7 +31,6 @@ pub enum Statement { body: StatementBody, }, For { - mutable: bool, pattern: Pattern, iterator: Expression, body: StatementBody, @@ -46,7 +45,6 @@ pub enum Statement { #[derive(Debug, Clone, Serialize)] pub struct VarDecl { - pub mutable: bool, pub name: Pattern, pub type_: Option, } 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 3057472..3b79896 100644 --- a/crates/parser/src/parser/common/mod.rs +++ b/crates/parser/src/parser/common/mod.rs @@ -74,8 +74,6 @@ impl<'a> TryFrom> for Pattern { Rule::literal => ast_expr!(Pattern::Literal(pair.try_into())), - Rule::identifier => ast_expr!(Pattern::Id(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() diff --git a/crates/parser/src/parser/common/statement.rs b/crates/parser/src/parser/common/statement.rs index 3f2db09..fddee57 100644 --- a/crates/parser/src/parser/common/statement.rs +++ b/crates/parser/src/parser/common/statement.rs @@ -3,7 +3,6 @@ use crate::{ ast::*, ast_ensure, ast_expr, error::{AstError, AstResult, IntoErr, collect_recovered}, - parser::listen_rule, }; 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(), 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())])), From 7a2ba74d9c6d36b87d9fea22af0310cba8d1acfd Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 28 May 2026 11:52:40 +0200 Subject: [PATCH 5/7] Working mut pattern --- crates/codegen/src/lib.rs | 18 +++++++++--------- crates/parser/src/ast/expr.rs | 6 +++--- crates/parser/src/grammar.pest | 2 +- crates/parser/src/parser/common/mod.rs | 10 ++++++---- 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index cf88d9d..fe6678d 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -243,30 +243,30 @@ impl GenRust for Pattern { } 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/parser/src/ast/expr.rs b/crates/parser/src/ast/expr.rs index fcec338..23fb010 100644 --- a/crates/parser/src/ast/expr.rs +++ b/crates/parser/src/ast/expr.rs @@ -32,9 +32,9 @@ 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(bool, Path), } diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 476234a..7267ca4 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -135,7 +135,7 @@ literal = { // ====================================================== multi_pat_template = _{ - (identifier ~ ("," ~ identifier)*)? + (pattern ~ ("," ~ pattern)*)? } tuple_pattern = { diff --git a/crates/parser/src/parser/common/mod.rs b/crates/parser/src/parser/common/mod.rs index 3b79896..59f0866 100644 --- a/crates/parser/src/parser/common/mod.rs +++ b/crates/parser/src/parser/common/mod.rs @@ -7,7 +7,7 @@ use crate::{ Rule, ast::*, ast_ensure, ast_expr, - error::{AstError, AstResult, IntoErr, collect_recovered}, + error::{AstError, AstResult, IntoErr, collect_recovered, collect_recovered_map}, parser::{consume_rule, listen_rule}, }; @@ -60,16 +60,18 @@ 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())), From ad11a3bd6a920201ee23fdaaebb5c867d0684bb2 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 28 May 2026 12:16:28 +0200 Subject: [PATCH 6/7] Improved match item span --- crates/codegen/src/statement.rs | 6 ++++- crates/parser/src/ast/statement.rs | 5 +++- crates/parser/src/parser/common/statement.rs | 25 ++++++++++++-------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/crates/codegen/src/statement.rs b/crates/codegen/src/statement.rs index aa7a37a..b3c6901 100644 --- a/crates/codegen/src/statement.rs +++ b/crates/codegen/src/statement.rs @@ -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(""); diff --git a/crates/parser/src/ast/statement.rs b/crates/parser/src/ast/statement.rs index 0196e72..412e2f0 100644 --- a/crates/parser/src/ast/statement.rs +++ b/crates/parser/src/ast/statement.rs @@ -35,7 +35,7 @@ pub enum Statement { iterator: Expression, body: StatementBody, }, - Match(Expression, Vec<(Vec, Expression)>), + Match(Expression, Vec>), VarDecl(VarDeclStmt), Return(Option), @@ -43,6 +43,9 @@ pub enum Statement { Continue, } +#[derive(Debug, Clone, Serialize)] +pub struct MatchItem(pub Vec, pub Expression); + #[derive(Debug, Clone, Serialize)] pub struct VarDecl { pub name: Pattern, diff --git a/crates/parser/src/parser/common/statement.rs b/crates/parser/src/parser/common/statement.rs index fddee57..5ca288e 100644 --- a/crates/parser/src/parser/common/statement.rs +++ b/crates/parser/src/parser/common/statement.rs @@ -2,7 +2,7 @@ use crate::{ Rule, ast::*, ast_ensure, ast_expr, - error::{AstError, AstResult, IntoErr, collect_recovered}, + error::{AstError, IntoErr, collect_recovered}, }; impl<'a> TryFrom> for Block { @@ -103,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()?, + )) + } +} From 583d51141f7a66c34199b50bf86a35ffa229c712 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Thu, 28 May 2026 15:44:52 +0200 Subject: [PATCH 7/7] Fixed empty items --- crates/parser/src/grammar.pest | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 7267ca4..9635b1d 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -179,7 +179,7 @@ meta = { } meta_list = { - meta ~ ("," ~ meta)* ~ ","? + (meta ~ ("," ~ meta)* ~ ","?)? } attributes = { @@ -198,11 +198,11 @@ field = { } field_list = { - field ~ ("," ~ field)* ~ ","? + (field ~ ("," ~ field)* ~ ","?)? } param_list = { - var_decl ~ ("," ~ var_decl)* ~ ","? + (var_decl ~ ("," ~ var_decl)* ~ ","?)? } // ====================================================== @@ -260,7 +260,7 @@ enum_decl = { // ====================================================== class_constructor = { - visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list? ~ ")" ~ block + visibility? ~ "constructor" ~ generics_decl? ~ "(" ~ param_list ~ ")" ~ block } class_fields = { @@ -276,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 = _{ @@ -305,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 = _{ @@ -322,7 +322,7 @@ trait_decl = { // ====================================================== function_decl = { - visibility? ~ type_expr ~ identifier ~ "(" ~ param_list? ~ ")" ~ block + visibility? ~ type_expr ~ identifier ~ "(" ~ param_list ~ ")" ~ block } // ======================================================