From c9030809fd6d7dcef06f7ce892cb8c1050bc3674 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 16 May 2026 22:40:01 +0200 Subject: [PATCH 01/26] Compound assign statement --- mist-test/src/app.mist | 2 +- parser/src/ast.rs | 10 +++++++++- parser/src/grammar.pest | 17 +++++++++++++++++ parser/src/parser/common/statement.rs | 16 +++++++++++----- src/codegen.rs | 15 ++++++++++++++- 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/mist-test/src/app.mist b/mist-test/src/app.mist index 01fbd87..3358be9 100644 --- a/mist-test/src/app.mist +++ b/mist-test/src/app.mist @@ -46,7 +46,7 @@ pub class Application { void tick(self mut*) { self.logger.info("tick"); - self.ticks = self.ticks + 1; + self.ticks += 1; var task = task::create_task("background-job"); diff --git a/parser/src/ast.rs b/parser/src/ast.rs index d2acb95..834dc35 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -181,7 +181,15 @@ pub enum Statement { Block(Block), VarDecl(VarDeclStmt), - VarAssign(VarAssignStmt), + Assign { + target: Expression, + value: Expression, + }, + CompoundAssign { + target: Expression, + compound: String, + value: Expression, + }, If { initial: StatementBranch, else_if: Vec, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 945c825..64fb96b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -314,6 +314,7 @@ statement = _{ expr_stmt | match_stmt | assign_statement + | compound_assign_statement | if_stmt | while_stmt | c_for_stmt @@ -353,6 +354,22 @@ assign_statement = { expr ~ "=" ~ expr ~ semicolon } +compound_assign = { + "+=" + | "-=" + | "/=" + | "%=" + | "&=" + | "|=" + | "^=" + | "<<=" + | ">>=" +} + +compound_assign_statement = { + expr ~ compound_assign ~ expr ~ semicolon +} + // ------------------------------------------------------ // CONDITIONALS // ------------------------------------------------------ diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index 243e6a3..34d35f9 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -88,13 +88,10 @@ impl<'a> TryFrom> for Statement { body: inner.next().unwrap().try_into().map(Box::new), }), - Rule::assign_statement => ast_expr!(VarAssignStmt { + Rule::assign_statement => ast_expr!(Statement::Assign { target: inner.next().unwrap().try_into(), value: inner.next().unwrap().try_into(), - }) - .map(Statement::VarAssign) - .get_map(Statement::VarAssign), - + }), Rule::match_stmt => ast_expr!(Statement::Match( inner.next().unwrap().try_into(), inner @@ -108,6 +105,15 @@ impl<'a> TryFrom> for Statement { .collect::>>(), )), + Rule::compound_assign_statement => { + ast_expr!(Statement::CompoundAssign { + target: inner.next().unwrap().try_into(), + compound: Ok(inner.next().unwrap().as_str().trim().to_string()) + as AstResult<'_, String>, + value: inner.next().unwrap().try_into(), + }) + } + Rule::unexpected_statement => { return Err(AstError { span: pair.as_span(), diff --git a/src/codegen.rs b/src/codegen.rs index f60d37e..b3fbfe5 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -545,10 +545,23 @@ impl ToRust for Statement { cg.add_indentedln(&format!("let {}{};", decl.get_rust(), init)); } - Statement::VarAssign(VarAssignStmt { target, value }) => { + Statement::Assign { target, value } => { cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),)); } + Statement::CompoundAssign { + target, + compound, + value, + } => { + cg.add_indentedln(&format!( + "{} {} {};", + target.get_rust(), + compound, + value.get_rust(), + )); + } + Statement::Match(expr, match_items) => { cg.add_indentedln(&format!("match {} {{", expr.get_rust())); cg.indent += 1; From 13480b2c54500bcea56af640ded191a771158b79 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 16 May 2026 22:40:39 +0200 Subject: [PATCH 02/26] removed var assign statement struct --- parser/src/ast.rs | 6 ------ src/codegen.rs | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 834dc35..9498fac 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -249,12 +249,6 @@ pub struct FieldDeclStmt { pub init: Option, } -#[derive(Debug, Clone, Serialize)] -pub struct VarAssignStmt { - pub target: Expression, - pub value: Expression, -} - #[derive(Debug, Clone, Serialize)] pub struct StatementBranch { pub condition: Expression, diff --git a/src/codegen.rs b/src/codegen.rs index b3fbfe5..a5aec25 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,8 +1,8 @@ use mist_parser::ast::{ Attribute, BinaryOp, Block, ClassItem, EnumItem, Expression, FieldDecl, FunctionDecl, Generic, Generics, Identifier, ImplDecl, Literal, Path, Pattern, Postfix, Prefix, Statement, - StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, - VarDecl, VarDeclStmt, Visibility, + StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarDecl, + VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- From 0bd8bc2f031bbdf31533360f8e6a97df3cb3530c Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 16 May 2026 22:43:44 +0200 Subject: [PATCH 03/26] track caller on bug_unimplemented --- parser/src/error.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/parser/src/error.rs b/parser/src/error.rs index ebec476..1ad1b05 100644 --- a/parser/src/error.rs +++ b/parser/src/error.rs @@ -48,11 +48,19 @@ impl<'a, F> AstError<'a, F> { } } + #[track_caller] pub fn bug_unimplemented(pair: Pair<'a, Rule>) -> AstResult<'a, T, F> { + let loc = std::panic::Location::caller(); + Err(Self { span: pair.as_span(), error_code: ErrorCode::AstGenBug, - error_message: format!("Possible bug, unimplemented: {:#?}", pair.as_rule()), + error_message: format!( + "Possible bug, unimplemented: {:#?}, at {}:{}", + pair.as_rule(), + loc.file(), + loc.line(), + ), recovered: None, }) } From b802c5136946f42eb589a884a747f64ba2236787 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 16 May 2026 22:53:08 +0200 Subject: [PATCH 04/26] updated expr grammar --- parser/src/grammar.pest | 212 +++++++++++++++++----------------------- 1 file changed, 91 insertions(+), 121 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 64fb96b..8c611b6 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -51,6 +51,7 @@ program = { visibility = { "pub" ~ ("(" ~ static_path ~ ")")? } mutable = { "mut" } var = { "var" } +deref_px = { "*" } // ====================================================== // ERROR RECOVERY @@ -417,137 +418,106 @@ match_stmt = { } // ====================================================== -// EXPRESSIONS +// EXPRESSIONS (Nested by Precedence, Low to High) // ====================================================== -// ------------------------------------------------------ -// TUPLES -// ------------------------------------------------------ +// Base entry point for a pure expression +expr = { logical_or_expr } -tuple = { - "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" +// 1. Logical OR +logical_or_expr = { logical_and_expr ~ ("||" ~ logical_and_expr)* } + +// 2. Logical AND +logical_and_expr = { bit_or_expr ~ ("&&" ~ bit_or_expr)* } + +// 3. Bitwise OR +bit_or_expr = { bit_xor_expr ~ ("|" ~ bit_xor_expr)* } + +// 4. Bitwise XOR +bit_xor_expr = { bit_and_expr ~ ("^" ~ bit_and_expr)* } + +// 5. Bitwise AND +bit_and_expr = { comparison_expr ~ ("&" ~ comparison_expr)* } + +// 6. Comparisons +comparison_expr = { bshift_expr ~ (comp_op ~ bshift_expr)? } +comp_op = { "==" | "!=" | "<=" | ">=" | "<" | ">" } + +// 7. Bitwise Shifts +bshift_expr = { add_sub_expr ~ (shift_op ~ add_sub_expr)* } +shift_op = { "<<" | ">>" } + +// 8. Addition and Subtraction +add_sub_expr = { mul_div_mod_expr ~ (add_sub_op ~ mul_div_mod_expr)* } +add_sub_op = { "+" | "-" } + +// 9. Multiplication, Division, and Remainder +mul_div_mod_expr = { cast_expr ~ (mul_div_mod_op ~ cast_expr)* } +mul_div_mod_op = { "*" | "/" | "%" } + +// 10. Type Casting (as) +cast_expr = { range_expr ~ ("as" ~ type_expr)* } + +// 11. Ranges (e.g., start..end, start.., ..end, ..) +range_expr = { + (unary_expr? ~ ".." ~ "="? ~ unary_expr?) + | unary_expr } +// 12. Unary / Prefix Operators (Right-associative recursion) +unary_expr = { + (unary_op ~ unary_expr) + | postfix_expr +} +unary_op = { "-" | "!" | "*" | "&" ~ "mut"? } + +// 13. Postfix Operators (Method calls, indexing, fields, try, macro calls) +postfix_expr = { primary_expr ~ postfix_suffix* } +postfix_suffix = { + call_suffix + | macro_call_suffix + | index_suffix + | field_suffix + | try_suffix + | struct_suffix +} + +// Postfix Sub-rules +call_suffix = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ","? ~ ")" } +macro_call_suffix = { "!" ~ "(" ~ macro_inner_v* ~ ")" } +index_suffix = { "[" ~ expr ~ "]" } +field_suffix = { "." ~ (identifier | tuple_index) } +try_suffix = { "?" } +struct_suffix = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" } + // ------------------------------------------------------ -// MACROS +// PRIMARY EXPRESSIONS & ATOMS // ------------------------------------------------------ +primary_expr = { + literal + | macro_rules_call // Standalone macro like println!(...) + + | static_path // Variables, paths + + | group_or_tuple // (expr) or (a, b) + + | array_expr // [1, 2, 3] +} + +group_or_tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ","? ~ ")" } +array_expr = { "[" ~ (expr ~ ("," ~ expr)*)? ~ ","? ~ "]" } + +struct_field_decl = { identifier ~ ":" ~ expr } + macro_inner_v = { "(" ~ macro_inner_v* ~ ")" - | (!("(" | ")") ~ ANY) + | "[" ~ macro_inner_v* ~ "]" + | "{" ~ macro_inner_v* ~ "}" + | (!("(" | ")" | "[" | "]" | "{" | "}") ~ ANY) } -// ------------------------------------------------------ -// PRIMARY EXPRESSIONS -// ------------------------------------------------------ +macro_rules_call = { static_path ~ "!" ~ (("(" ~ macro_inner_v* ~ ")") | ("{" ~ macro_inner_v* ~ "}")) } -primary = { - literal - | static_path - | tuple -} - -// ------------------------------------------------------ -// POSTFIX EXPRESSIONS -// ------------------------------------------------------ - -field_px = { - "." ~ identifier -} - -call_px = { - "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" -} - -macro_call_px = { - "!" ~ "(" ~ macro_inner_v* ~ ")" -} - -struct_field_decl = { - identifier ~ ":" ~ expr -} - -struct_px = { - "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" -} - -index_px = { - "[" ~ expr ~ "]" -} - -binary_px = { - bin_op ~ expr -} - -postfix = { - field_px - | call_px - | macro_call_px - | struct_px - | index_px - | binary_px -} - -// ------------------------------------------------------ -// PREFIX EXPRESSIONS -// ------------------------------------------------------ - -deref_px = { - "*" -} - -mut_ref_px = { - "&" ~ mutable -} - -ref_px = { - "&" -} - -new_px = { - "new" -} - -not_px = { - "!" -} - -prefix = { - deref_px - | mut_ref_px - | ref_px - | new_px - | not_px -} - -prefix_list = { - prefix* -} - -// ------------------------------------------------------ -// OPERATORS -// ------------------------------------------------------ - -bin_op = { - "<=" - | ">=" - | "==" - | "!=" - | "&&" - | "||" - | "+" - | "-" - | "*" - | "/" - | "%" - | "<" - | ">" -} - -// ------------------------------------------------------ -// EXPRESSIONS -// ------------------------------------------------------ - -expr = { - prefix_list ~ primary ~ postfix* -} +// (Assumed rules from your codebase) +tuple_index = { ASCII_DIGIT+ } From 95f253c0cecbff060a90cf67977b852a79f405a7 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 16 May 2026 23:04:05 +0200 Subject: [PATCH 05/26] Refactored ast structure --- parser/src/ast.rs | 282 ------------------------------------ parser/src/ast/expr.rs | 69 +++++++++ parser/src/ast/mod.rs | 43 ++++++ parser/src/ast/statement.rs | 65 +++++++++ parser/src/ast/top_level.rs | 121 ++++++++++++++++ 5 files changed, 298 insertions(+), 282 deletions(-) delete mode 100644 parser/src/ast.rs create mode 100644 parser/src/ast/expr.rs create mode 100644 parser/src/ast/mod.rs create mode 100644 parser/src/ast/statement.rs create mode 100644 parser/src/ast/top_level.rs diff --git a/parser/src/ast.rs b/parser/src/ast.rs deleted file mode 100644 index 9498fac..0000000 --- a/parser/src/ast.rs +++ /dev/null @@ -1,282 +0,0 @@ -use serde::Serialize; - -#[derive(Debug, Clone, Serialize)] -pub struct Identifier(pub String); - -#[derive(Debug, Clone, Serialize, Default)] -pub struct ParamList(pub Vec); - -#[derive(Debug, Clone, Serialize, Default)] -pub struct Block(pub Vec); - -#[derive(Debug, Clone, Serialize)] -pub enum TypePostfix { - Ref, - RefMut, - RefLifetime(Identifier), - RefMutLifetime(Identifier), -} - -#[derive(Debug, Clone, Serialize)] -pub enum Visibility { - Public, - PublicTarget(Path), - Private, -} - -#[derive(Debug, Clone, Serialize)] -pub enum Attribute { - /// #[test] - Path(Path), - - /// #[name = "value"] - NameValue { path: Path, value: Literal }, - - /// #[derive(Clone, Copy)] - List { path: Path, items: Vec }, -} - -#[derive(Debug, Clone, Serialize)] -pub enum TypeExprKind { - Path(Path), - PathParams(Path, Vec), - Tuple(Vec), - Lifetime(Identifier), -} - -#[derive(Debug, Clone, Serialize)] -pub struct TypeExpr(pub TypeExprKind, pub Vec); - -#[derive(Debug, Clone, Serialize)] -pub struct Path(pub Vec); - -#[derive(Debug, Clone, Serialize)] -pub enum BinaryOp { - Plus, - Minus, - Multiply, - Divide, - Modulo, - Equal, - NotEqual, - LessThan, - GreaterThan, - LessThanOrEqual, - GreaterThanOrEqual, - And, - Or, -} - -#[derive(Debug, Clone, Serialize)] -pub struct TopLevel(pub TopLevelKind, pub Vec); - -#[derive(Debug, Clone, Serialize)] -pub enum TopLevelKind { - ModAttribute, - Import(Visibility, Path), - Mod(Visibility, Identifier), - ImplDecl(ImplDecl), - TraitDecl { - visibility: Visibility, - name: Identifier, - generics: Generics, - requirements: Vec, - items: Vec, - }, - EnumDecl { - visibility: Visibility, - name: Identifier, - generics: Generics, - fields: Vec, - }, - StructDecl { - visibility: Visibility, - name: Identifier, - generics: Generics, - fields: Vec, - }, - FunctionDecl(FunctionDecl), - ClassDecl { - visibility: Visibility, - name: Identifier, - generics: Generics, - fields: Vec, - constructor: ClassConstructor, - items: Vec, - }, -} - -#[derive(Debug, Clone, Serialize)] -pub enum ClassItem { - Method(FunctionDecl), - ImplDecl(ImplDecl), -} - -#[derive(Debug, Clone, Serialize, Default)] -pub struct Generics(pub Vec); - -#[derive(Debug, Clone, Serialize)] -pub enum Generic { - Lifetime(Identifier), - Type(Identifier, Vec), -} - -#[derive(Debug, Clone, Serialize)] -pub enum Pattern { - NamedTuple(Path, Vec), - Struct(Path, Vec), - Tuple(Vec), - Literal(Literal), - Path(Path), - Id(Identifier), -} - -#[derive(Debug, Clone, Serialize)] -pub enum EnumItem { - Named(Identifier), - Tuple(Identifier, Vec), - Struct(Identifier, Vec), -} - -#[derive(Debug, Clone, Serialize)] -pub struct ClassConstructor { - pub visibility: Visibility, - pub generics: Generics, - pub params: ParamList, - pub body: Block, -} - -#[derive(Debug, Clone, Serialize)] -pub struct FunctionDecl { - pub visibility: Visibility, - pub name: Identifier, - pub generics: Generics, - pub params: ParamList, - pub return_type: TypeExpr, - pub body: Option, -} - -#[derive(Debug, Clone, Serialize)] -pub enum Postfix { - FieldAccess(Identifier), - Call(Vec), - MacroCall(String), - StructCall(Vec<(Identifier, Expression)>), - Index(Expression), - Binary(BinaryOp, Expression), -} - -#[derive(Debug, Clone, Serialize)] -pub enum Prefix { - Ref, - RefMut, - Deref, - New, - Not, -} - -#[derive(Debug, Clone, Serialize)] -pub enum Statement { - Expression(Expression), - Block(Block), - - VarDecl(VarDeclStmt), - Assign { - target: Expression, - value: Expression, - }, - CompoundAssign { - target: Expression, - compound: String, - value: Expression, - }, - If { - initial: StatementBranch, - else_if: Vec, - else_branch: Option>, - }, - While(StatementBranch), - CStyleFor { - init: Box, - condition: Expression, - update: Box, - body: Box, - }, - For { - mutable: bool, - pattern: Pattern, - iterator: Expression, - body: Box, - }, - Match(Expression, Vec<(Pattern, Block)>), - - Return(Option), - Break, - Continue, -} - -#[derive(Debug, Clone, Serialize)] -pub struct ImplDecl { - pub generics: Generics, - pub target: TypeExpr, - pub trait_: Option, - pub methods: Vec, -} - -#[derive(Debug, Clone, Serialize)] -pub struct VarDecl { - pub mutable: bool, - pub name: Pattern, - pub type_: Option, -} - -#[derive(Debug, Clone, Serialize)] -pub struct VarDeclStmt { - pub decl: VarDecl, - pub init: Option, -} - -#[derive(Debug, Clone, Serialize)] -pub struct FieldDecl { - pub visibility: Visibility, - pub type_: TypeExpr, - pub name: Identifier, -} - -#[derive(Debug, Clone, Serialize)] -pub struct FieldDeclStmt { - pub decl: FieldDecl, - pub init: Option, -} - -#[derive(Debug, Clone, Serialize)] -pub struct StatementBranch { - pub condition: Expression, - pub body: Box, -} - -#[derive(Debug, Clone, Serialize)] -pub enum Expression { - Literal(Literal), - Path(Path), - Fix { - initial: Box, - prefixes: Vec, - postfixes: Vec, - }, -} - -#[derive(Debug, Clone, Serialize)] -pub enum Literal { - String(String), - Int(i64), - Float(f64), - Bool(bool), - Tuple(Vec), -} - -impl TypeExpr { - pub fn no_px(kind: TypeExprKind) -> Self { - Self(kind, Vec::new()) - } -} diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs new file mode 100644 index 0000000..fc54780 --- /dev/null +++ b/parser/src/ast/expr.rs @@ -0,0 +1,69 @@ +use serde::Serialize; + +use super::*; + +#[derive(Debug, Clone, Serialize)] +pub enum BinaryOp { + Plus, + Minus, + Multiply, + Divide, + Modulo, + Equal, + NotEqual, + LessThan, + GreaterThan, + LessThanOrEqual, + GreaterThanOrEqual, + And, + Or, +} + +#[derive(Debug, Clone, Serialize)] +pub enum Expression { + Literal(Literal), + Path(Path), + Fix { + initial: Box, + prefixes: Vec, + postfixes: Vec, + }, +} + +#[derive(Debug, Clone, Serialize)] +pub enum Literal { + String(String), + Int(i64), + Float(f64), + Bool(bool), + Tuple(Vec), +} + +#[derive(Debug, Clone, Serialize)] +pub enum Pattern { + NamedTuple(Path, Vec), + Struct(Path, Vec), + Tuple(Vec), + Literal(Literal), + Path(Path), + Id(Identifier), +} + +#[derive(Debug, Clone, Serialize)] +pub enum Postfix { + FieldAccess(Identifier), + Call(Vec), + MacroCall(String), + StructCall(Vec<(Identifier, Expression)>), + Index(Expression), + Binary(BinaryOp, Expression), +} + +#[derive(Debug, Clone, Serialize)] +pub enum Prefix { + Ref, + RefMut, + Deref, + New, + Not, +} diff --git a/parser/src/ast/mod.rs b/parser/src/ast/mod.rs new file mode 100644 index 0000000..1dd636d --- /dev/null +++ b/parser/src/ast/mod.rs @@ -0,0 +1,43 @@ +use serde::Serialize; + +pub mod expr; +pub mod statement; +pub mod top_level; + +pub use expr::*; +pub use statement::*; +pub use top_level::*; + +#[derive(Debug, Clone, Serialize)] +pub struct Path(pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub struct Identifier(pub String); + +#[derive(Debug, Clone, Serialize, Default)] +pub struct ParamList(pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub enum TypePostfix { + Ref, + RefMut, + RefLifetime(Identifier), + RefMutLifetime(Identifier), +} + +#[derive(Debug, Clone, Serialize)] +pub enum TypeExprKind { + Path(Path), + PathParams(Path, Vec), + Tuple(Vec), + Lifetime(Identifier), +} + +#[derive(Debug, Clone, Serialize)] +pub struct TypeExpr(pub TypeExprKind, pub Vec); + +impl TypeExpr { + pub fn no_px(kind: TypeExprKind) -> Self { + Self(kind, Vec::new()) + } +} diff --git a/parser/src/ast/statement.rs b/parser/src/ast/statement.rs new file mode 100644 index 0000000..69b12b1 --- /dev/null +++ b/parser/src/ast/statement.rs @@ -0,0 +1,65 @@ +use serde::Serialize; + +use super::*; + +#[derive(Debug, Clone, Serialize, Default)] +pub struct Block(pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub enum Statement { + Expression(Expression), + Block(Block), + + VarDecl(VarDeclStmt), + Assign { + target: Expression, + value: Expression, + }, + CompoundAssign { + target: Expression, + compound: String, + value: Expression, + }, + If { + initial: StatementBranch, + else_if: Vec, + else_branch: Option>, + }, + While(StatementBranch), + CStyleFor { + init: Box, + condition: Expression, + update: Box, + body: Box, + }, + For { + mutable: bool, + pattern: Pattern, + iterator: Expression, + body: Box, + }, + Match(Expression, Vec<(Pattern, Block)>), + + Return(Option), + Break, + Continue, +} + +#[derive(Debug, Clone, Serialize)] +pub struct VarDecl { + pub mutable: bool, + pub name: Pattern, + pub type_: Option, +} + +#[derive(Debug, Clone, Serialize)] +pub struct VarDeclStmt { + pub decl: VarDecl, + pub init: Option, +} + +#[derive(Debug, Clone, Serialize)] +pub struct StatementBranch { + pub condition: Expression, + pub body: Box, +} diff --git a/parser/src/ast/top_level.rs b/parser/src/ast/top_level.rs new file mode 100644 index 0000000..30021ea --- /dev/null +++ b/parser/src/ast/top_level.rs @@ -0,0 +1,121 @@ +use serde::Serialize; + +use super::*; + +#[derive(Debug, Clone, Serialize)] +pub enum Visibility { + Public, + PublicTarget(Path), + Private, +} + +#[derive(Debug, Clone, Serialize)] +pub enum Attribute { + /// #[test] + Path(Path), + + /// #[name = "value"] + NameValue { path: Path, value: Literal }, + + /// #[derive(Clone, Copy)] + List { path: Path, items: Vec }, +} + +#[derive(Debug, Clone, Serialize)] +pub struct TopLevel(pub TopLevelKind, pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub enum TopLevelKind { + ModAttribute, + Import(Visibility, Path), + Mod(Visibility, Identifier), + ImplDecl(ImplDecl), + TraitDecl { + visibility: Visibility, + name: Identifier, + generics: Generics, + requirements: Vec, + items: Vec, + }, + EnumDecl { + visibility: Visibility, + name: Identifier, + generics: Generics, + fields: Vec, + }, + StructDecl { + visibility: Visibility, + name: Identifier, + generics: Generics, + fields: Vec, + }, + FunctionDecl(FunctionDecl), + ClassDecl { + visibility: Visibility, + name: Identifier, + generics: Generics, + fields: Vec, + constructor: ClassConstructor, + items: Vec, + }, +} + +#[derive(Debug, Clone, Serialize)] +pub enum ClassItem { + Method(FunctionDecl), + ImplDecl(ImplDecl), +} + +#[derive(Debug, Clone, Serialize, Default)] +pub struct Generics(pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub enum Generic { + Lifetime(Identifier), + Type(Identifier, Vec), +} +#[derive(Debug, Clone, Serialize)] +pub enum EnumItem { + Named(Identifier), + Tuple(Identifier, Vec), + Struct(Identifier, Vec), +} + +#[derive(Debug, Clone, Serialize)] +pub struct ClassConstructor { + pub visibility: Visibility, + pub generics: Generics, + pub params: ParamList, + pub body: Block, +} + +#[derive(Debug, Clone, Serialize)] +pub struct FunctionDecl { + pub visibility: Visibility, + pub name: Identifier, + pub generics: Generics, + pub params: ParamList, + pub return_type: TypeExpr, + pub body: Option, +} + +#[derive(Debug, Clone, Serialize)] +pub struct ImplDecl { + pub generics: Generics, + pub target: TypeExpr, + pub trait_: Option, + pub methods: Vec, +} + +#[derive(Debug, Clone, Serialize)] +pub struct FieldDecl { + pub visibility: Visibility, + pub type_: TypeExpr, + pub name: Identifier, +} + +#[derive(Debug, Clone, Serialize)] +pub struct FieldDeclStmt { + pub decl: FieldDecl, + pub init: Option, +} From 6a0011c009d1325ef172e9f85d1bf62ed9836bea Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 16 May 2026 23:40:45 +0200 Subject: [PATCH 06/26] Restored grammar for now --- parser/src/grammar.pest | 212 +++++++++++++++++++++++----------------- 1 file changed, 121 insertions(+), 91 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 8c611b6..64fb96b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -51,7 +51,6 @@ program = { visibility = { "pub" ~ ("(" ~ static_path ~ ")")? } mutable = { "mut" } var = { "var" } -deref_px = { "*" } // ====================================================== // ERROR RECOVERY @@ -418,106 +417,137 @@ match_stmt = { } // ====================================================== -// EXPRESSIONS (Nested by Precedence, Low to High) +// EXPRESSIONS // ====================================================== -// Base entry point for a pure expression -expr = { logical_or_expr } - -// 1. Logical OR -logical_or_expr = { logical_and_expr ~ ("||" ~ logical_and_expr)* } - -// 2. Logical AND -logical_and_expr = { bit_or_expr ~ ("&&" ~ bit_or_expr)* } - -// 3. Bitwise OR -bit_or_expr = { bit_xor_expr ~ ("|" ~ bit_xor_expr)* } - -// 4. Bitwise XOR -bit_xor_expr = { bit_and_expr ~ ("^" ~ bit_and_expr)* } - -// 5. Bitwise AND -bit_and_expr = { comparison_expr ~ ("&" ~ comparison_expr)* } - -// 6. Comparisons -comparison_expr = { bshift_expr ~ (comp_op ~ bshift_expr)? } -comp_op = { "==" | "!=" | "<=" | ">=" | "<" | ">" } - -// 7. Bitwise Shifts -bshift_expr = { add_sub_expr ~ (shift_op ~ add_sub_expr)* } -shift_op = { "<<" | ">>" } - -// 8. Addition and Subtraction -add_sub_expr = { mul_div_mod_expr ~ (add_sub_op ~ mul_div_mod_expr)* } -add_sub_op = { "+" | "-" } - -// 9. Multiplication, Division, and Remainder -mul_div_mod_expr = { cast_expr ~ (mul_div_mod_op ~ cast_expr)* } -mul_div_mod_op = { "*" | "/" | "%" } - -// 10. Type Casting (as) -cast_expr = { range_expr ~ ("as" ~ type_expr)* } - -// 11. Ranges (e.g., start..end, start.., ..end, ..) -range_expr = { - (unary_expr? ~ ".." ~ "="? ~ unary_expr?) - | unary_expr -} - -// 12. Unary / Prefix Operators (Right-associative recursion) -unary_expr = { - (unary_op ~ unary_expr) - | postfix_expr -} -unary_op = { "-" | "!" | "*" | "&" ~ "mut"? } - -// 13. Postfix Operators (Method calls, indexing, fields, try, macro calls) -postfix_expr = { primary_expr ~ postfix_suffix* } -postfix_suffix = { - call_suffix - | macro_call_suffix - | index_suffix - | field_suffix - | try_suffix - | struct_suffix -} - -// Postfix Sub-rules -call_suffix = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ","? ~ ")" } -macro_call_suffix = { "!" ~ "(" ~ macro_inner_v* ~ ")" } -index_suffix = { "[" ~ expr ~ "]" } -field_suffix = { "." ~ (identifier | tuple_index) } -try_suffix = { "?" } -struct_suffix = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" } - // ------------------------------------------------------ -// PRIMARY EXPRESSIONS & ATOMS +// TUPLES // ------------------------------------------------------ -primary_expr = { - literal - | macro_rules_call // Standalone macro like println!(...) - - | static_path // Variables, paths - - | group_or_tuple // (expr) or (a, b) - - | array_expr // [1, 2, 3] +tuple = { + "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } -group_or_tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ","? ~ ")" } -array_expr = { "[" ~ (expr ~ ("," ~ expr)*)? ~ ","? ~ "]" } - -struct_field_decl = { identifier ~ ":" ~ expr } +// ------------------------------------------------------ +// MACROS +// ------------------------------------------------------ macro_inner_v = { "(" ~ macro_inner_v* ~ ")" - | "[" ~ macro_inner_v* ~ "]" - | "{" ~ macro_inner_v* ~ "}" - | (!("(" | ")" | "[" | "]" | "{" | "}") ~ ANY) + | (!("(" | ")") ~ ANY) } -macro_rules_call = { static_path ~ "!" ~ (("(" ~ macro_inner_v* ~ ")") | ("{" ~ macro_inner_v* ~ "}")) } +// ------------------------------------------------------ +// PRIMARY EXPRESSIONS +// ------------------------------------------------------ -// (Assumed rules from your codebase) -tuple_index = { ASCII_DIGIT+ } +primary = { + literal + | static_path + | tuple +} + +// ------------------------------------------------------ +// POSTFIX EXPRESSIONS +// ------------------------------------------------------ + +field_px = { + "." ~ identifier +} + +call_px = { + "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" +} + +macro_call_px = { + "!" ~ "(" ~ macro_inner_v* ~ ")" +} + +struct_field_decl = { + identifier ~ ":" ~ expr +} + +struct_px = { + "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" +} + +index_px = { + "[" ~ expr ~ "]" +} + +binary_px = { + bin_op ~ expr +} + +postfix = { + field_px + | call_px + | macro_call_px + | struct_px + | index_px + | binary_px +} + +// ------------------------------------------------------ +// PREFIX EXPRESSIONS +// ------------------------------------------------------ + +deref_px = { + "*" +} + +mut_ref_px = { + "&" ~ mutable +} + +ref_px = { + "&" +} + +new_px = { + "new" +} + +not_px = { + "!" +} + +prefix = { + deref_px + | mut_ref_px + | ref_px + | new_px + | not_px +} + +prefix_list = { + prefix* +} + +// ------------------------------------------------------ +// OPERATORS +// ------------------------------------------------------ + +bin_op = { + "<=" + | ">=" + | "==" + | "!=" + | "&&" + | "||" + | "+" + | "-" + | "*" + | "/" + | "%" + | "<" + | ">" +} + +// ------------------------------------------------------ +// EXPRESSIONS +// ------------------------------------------------------ + +expr = { + prefix_list ~ primary ~ postfix* +} From 675e3572977f7de6bee849049b1cc3a08bde826b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 02:18:09 +0200 Subject: [PATCH 07/26] Using term based expressions: grammar --- parser/src/grammar.pest | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 64fb96b..51a220b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -475,17 +475,12 @@ index_px = { "[" ~ expr ~ "]" } -binary_px = { - bin_op ~ expr -} - postfix = { field_px | call_px | macro_call_px | struct_px | index_px - | binary_px } // ------------------------------------------------------ @@ -520,10 +515,6 @@ prefix = { | not_px } -prefix_list = { - prefix* -} - // ------------------------------------------------------ // OPERATORS // ------------------------------------------------------ @@ -548,6 +539,7 @@ bin_op = { // EXPRESSIONS // ------------------------------------------------------ -expr = { - prefix_list ~ primary ~ postfix* -} +expr = { term ~ (bin_op ~ term)* } + +// A term is anything that acts as a single unit in an operation +term = _{ prefix* ~ primary ~ postfix* } From 020eebdaba7e471bedb545981fe14a257bb421b6 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 02:21:12 +0200 Subject: [PATCH 08/26] Updated expr ast --- parser/src/ast/expr.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index fc54780..bee7250 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -28,6 +28,11 @@ pub enum Expression { prefixes: Vec, postfixes: Vec, }, + Binary { + lhs: Box, + op: BinaryOp, + rhs: Box, + }, } #[derive(Debug, Clone, Serialize)] @@ -56,7 +61,6 @@ pub enum Postfix { MacroCall(String), StructCall(Vec<(Identifier, Expression)>), Index(Expression), - Binary(BinaryOp, Expression), } #[derive(Debug, Clone, Serialize)] From 50c98cf5f715463f23ad006564e0d4e98fcde739 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 02:30:03 +0200 Subject: [PATCH 09/26] Adapted parser and ast with grammar --- parser/src/grammar.pest | 73 ++++++++++---------- parser/src/parser/common/expr.rs | 115 ++++++++++++++++++++++--------- 2 files changed, 119 insertions(+), 69 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 51a220b..00cb2da 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -487,25 +487,11 @@ postfix = { // PREFIX EXPRESSIONS // ------------------------------------------------------ -deref_px = { - "*" -} - -mut_ref_px = { - "&" ~ mutable -} - -ref_px = { - "&" -} - -new_px = { - "new" -} - -not_px = { - "!" -} +deref_px = { "*" } +mut_ref_px = { "&" ~ mutable } +ref_px = { "&" } +new_px = { "new" } +not_px = { "!" } prefix = { deref_px @@ -516,30 +502,45 @@ prefix = { } // ------------------------------------------------------ -// OPERATORS +// OPERATORS (Named individually for Pratt Parser configuration) // ------------------------------------------------------ -bin_op = { - "<=" - | ">=" - | "==" - | "!=" - | "&&" - | "||" - | "+" - | "-" - | "*" - | "/" - | "%" - | "<" - | ">" +lte = { "<=" } +gte = { ">=" } +eq = { "==" } +neq = { "!=" } +and = { "&&" } +or = { "||" } +add = { "+" } +sub = { "-" } +mul = { "*" } +div = { "/" } +rem = { "%" } +lt = { "<" } +gt = { ">" } + +bin_op = _{ + lte + | gte + | eq + | neq + | and + | or + | add + | sub + | mul + | div + | rem + | lt + | gt } // ------------------------------------------------------ // EXPRESSIONS // ------------------------------------------------------ +// Top-level entry point for expressions expr = { term ~ (bin_op ~ term)* } -// A term is anything that acts as a single unit in an operation -term = _{ prefix* ~ primary ~ postfix* } +// A term handles your Prefix and Postfix combinations around a core Primary +term = { prefix* ~ primary ~ postfix* } diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index e49680d..a6d7545 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -2,37 +2,107 @@ use crate::{ Rule, ast::*, ast_expr, - error::{AstError, GetLength, IntoErr, collect_recovered, collect_recovered_map}, + error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map}, }; +use pest::pratt_parser::PrattParser; +use std::sync::OnceLock; impl<'a> TryFrom> for Expression { type Error = AstError<'a, Self>; fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { let rule = pair.as_rule(); - let mut inner = pair.clone().into_inner(); + let inner = pair.clone().into_inner(); match rule { + // 1. The top level expressions are now processed via the Pratt Parser Rule::expr => { - let prefixes = inner - .next() - .map(|p| collect_recovered::(p.into_inner())) - .unwrap_or_else(|| Ok(Vec::new())); + static PRATT_PARSER: OnceLock> = OnceLock::new(); + let pratt = PRATT_PARSER.get_or_init(|| { + use Rule::*; + use pest::pratt_parser::{Assoc::*, Op}; - let exp = Expression::try_from(inner.next().unwrap()); + // Precedence defined from lowest to highest + PrattParser::new() + .op(Op::infix(or, Left)) + .op(Op::infix(and, Left)) + .op(Op::infix(eq, Left) + | Op::infix(neq, Left) + | Op::infix(lt, Left) + | Op::infix(gt, Left) + | Op::infix(lte, Left) + | Op::infix(gte, Left)) + .op(Op::infix(add, Left) | Op::infix(sub, Left)) + .op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(rem, Left)) + }); - if inner.len() > 0 || prefixes.len() > 0 { + pratt + .map_primary(|primary_pair| { + // Elements handled by map_primary are either sub-expressions or 'term' rules + Expression::try_from(primary_pair) + }) + .map_infix(|lhs, op, rhs| { + let bin_op = match op.as_rule() { + Rule::lte => BinaryOp::LessThanOrEqual, + Rule::gte => BinaryOp::GreaterThanOrEqual, + Rule::eq => BinaryOp::Equal, + Rule::neq => BinaryOp::NotEqual, + Rule::and => BinaryOp::And, + Rule::or => BinaryOp::Or, + Rule::add => BinaryOp::Plus, + Rule::sub => BinaryOp::Minus, + Rule::mul => BinaryOp::Multiply, + Rule::div => BinaryOp::Divide, + Rule::rem => BinaryOp::Modulo, + Rule::lt => BinaryOp::LessThan, + Rule::gt => BinaryOp::GreaterThan, + _ => return AstError::bug_unimplemented(op), + }; + + ast_expr!(Expression::Binary { + lhs: lhs.map(Box::new), + op: Ok(bin_op) as AstResult<'_, BinaryOp>, + rhs: rhs.map(Box::new), + }) + }) + .parse(inner) + } + + // 2. The single unit 'term' replaces the old flat 'expr' layout + Rule::term => { + let mut prefix_pairs = Vec::new(); + let mut primary_pair = None; + let mut postfix_pairs = Vec::new(); + + // Sort out flat layout components + for p in inner { + match p.as_rule() { + Rule::prefix => prefix_pairs.push(p), + Rule::primary => primary_pair = Some(p), + Rule::postfix => postfix_pairs.push(p), + _ => {} + } + } + + let prefixes = collect_recovered::(prefix_pairs.into_iter()); + let exp = Expression::try_from( + primary_pair.expect("Term must contain a primary expression"), + ); + let postfixes = collect_recovered::(postfix_pairs.into_iter()); + + // Employs your exact original logic using the GetLength trait + if postfixes.len() > 0 || prefixes.len() > 0 { ast_expr!(Expression::Fix { initial: exp.map(Box::new), prefixes: prefixes, - postfixes: collect_recovered(inner), + postfixes: postfixes, }) } else { exp } } - Rule::primary => inner.next().unwrap().try_into(), + Rule::primary => pair.into_inner().next().unwrap().try_into(), Rule::static_path => ast_expr!(Expression::Path(pair.try_into())), Rule::literal => ast_expr!(Expression::Literal(pair.try_into())), @@ -86,31 +156,10 @@ impl<'a> TryFrom> for Postfix { ast_expr!(Postfix::Index(Expression::try_from(inner.next().unwrap()))) } - Rule::binary_px => { - let op_pair = inner.next().unwrap(); - let op = match op_pair.as_str() { - "+" => BinaryOp::Plus, - "-" => BinaryOp::Minus, - "*" => BinaryOp::Multiply, - "/" => BinaryOp::Divide, - "%" => BinaryOp::Modulo, - "==" => BinaryOp::Equal, - "!=" => BinaryOp::NotEqual, - "<" => BinaryOp::LessThan, - ">" => BinaryOp::GreaterThan, - "<=" => BinaryOp::LessThanOrEqual, - ">=" => BinaryOp::GreaterThanOrEqual, - "&&" => BinaryOp::And, - "||" => BinaryOp::Or, - - _ => return AstError::bug_unimplemented(op_pair), - }; - - Ok(Postfix::Binary(op, inner.next().unwrap().try_into().get()?)) - } - Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())), + // Note: Rule::binary_px has been completely decoupled from postfix rules + // as it is now safely managed inside the top-level Pratt execution above. _ => AstError::bug_unimplemented(pair), } } From bfaaa4006bbd864533dfc501ffacd320fb75c88a Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 02:32:41 +0200 Subject: [PATCH 10/26] Codegen --- mist-test/src/main.mist | 2 ++ src/codegen.rs | 42 ++++++++++++++++++++--------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 853e686..222415d 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -12,4 +12,6 @@ void main() { app_instance.boot(); app_instance.run(); + + 1+(1*2); } \ No newline at end of file diff --git a/src/codegen.rs b/src/codegen.rs index a5aec25..cf3c82d 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -156,6 +156,25 @@ impl GetRust for Expression { + &Some(prefixes).get_rust() + &postfixes.get_rust() } + // Safely integrated to handle the tree structure built by the Pratt Parser + Expression::Binary { lhs, op, rhs } => { + let op_str = match op { + BinaryOp::Plus => "+", + BinaryOp::Minus => "-", + BinaryOp::Multiply => "*", + BinaryOp::Divide => "/", + BinaryOp::Modulo => "%", + BinaryOp::Equal => "==", + BinaryOp::NotEqual => "!=", + BinaryOp::LessThan => "<", + BinaryOp::GreaterThan => ">", + BinaryOp::LessThanOrEqual => "<=", + BinaryOp::GreaterThanOrEqual => ">=", + BinaryOp::And => "&&", + BinaryOp::Or => "||", + }; + format!("{} {} {}", lhs.get_rust(), op_str, rhs.get_rust()) + } } } } @@ -225,26 +244,8 @@ impl GetRust for Postfix { Postfix::Index(idx) => { format!("[{}]", idx.get_rust()) - } - - Postfix::Binary(op, rhs) => { - let op_str = match op { - BinaryOp::Plus => "+", - BinaryOp::Minus => "-", - BinaryOp::Multiply => "*", - BinaryOp::Divide => "/", - BinaryOp::Modulo => "%", - BinaryOp::Equal => "==", - BinaryOp::NotEqual => "!=", - BinaryOp::LessThan => "<", - BinaryOp::GreaterThan => ">", - BinaryOp::LessThanOrEqual => "<=", - BinaryOp::GreaterThanOrEqual => ">=", - BinaryOp::And => "&&", - BinaryOp::Or => "||", - }; - format!(" {} {}", op_str, rhs.get_rust()) - } + } // Note: Postfix::Binary variant logic has been completely transferred + // to Expression::Binary to match your updated AST configuration. } } } @@ -254,7 +255,6 @@ impl GetRust for [Postfix] { self.iter().map(Postfix::get_rust).collect() } } - // --------------------------------------------------------------------------- // ToRust — output-writing (top-level, statements, blocks) // --------------------------------------------------------------------------- From 2c67d4e316819978db00ab49c68eb5af75c10ea7 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 02:37:18 +0200 Subject: [PATCH 11/26] Tuple fix --- mist-test/src/main.mist | 2 -- parser/src/parser/common/expr.rs | 8 ++++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 222415d..853e686 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -12,6 +12,4 @@ void main() { app_instance.boot(); app_instance.run(); - - 1+(1*2); } \ No newline at end of file diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index a6d7545..77d7c9a 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -102,6 +102,14 @@ impl<'a> TryFrom> for Expression { } } + Rule::tuple => { + ast_expr!(Expression::Literal( + collect_recovered(pair.into_inner()) + .map(Literal::Tuple) + .get_map(Literal::Tuple) + )) + } + Rule::primary => pair.into_inner().next().unwrap().try_into(), Rule::static_path => ast_expr!(Expression::Path(pair.try_into())), Rule::literal => ast_expr!(Expression::Literal(pair.try_into())), From 23cf00975da586152e3b23d3901a0e3169e8af22 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 03:25:02 +0200 Subject: [PATCH 12/26] Updated grammar for more extensive expressions --- parser/src/grammar.pest | 93 +++++++++++++++++++++++++++++------------ 1 file changed, 66 insertions(+), 27 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 00cb2da..df95248 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -421,13 +421,19 @@ match_stmt = { // ====================================================== // ------------------------------------------------------ -// TUPLES +// TUPLES & ARRAYS // ------------------------------------------------------ tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } +array = { + "[" ~ expr ~ ";" ~ expr ~ "]" // Repeat notation: [0; 10] + + | "[" ~ (expr ~ ("," ~ expr)* ~ ","?)? ~ "]" // Standard elements initialization +} + // ------------------------------------------------------ // MACROS // ------------------------------------------------------ @@ -441,10 +447,15 @@ macro_inner_v = { // PRIMARY EXPRESSIONS // ------------------------------------------------------ +expr_path = { + identifier ~ ("::" ~ generics)? ~ ("::" ~ identifier ~ ("::" ~ generics)?)* +} + primary = { literal - | static_path + | expr_path | tuple + | array } // ------------------------------------------------------ @@ -452,7 +463,7 @@ primary = { // ------------------------------------------------------ field_px = { - "." ~ identifier + "." ~ identifier ~ ("::" ~ generics)? } call_px = { @@ -475,23 +486,36 @@ index_px = { "[" ~ expr ~ "]" } +as_px = { + "as" ~ type_expr +} + +range_end_inc_px = { "..=" } +range_end_exc_px = { ".." } + postfix = { field_px | call_px | macro_call_px | struct_px | index_px + | as_px + | range_end_inc_px + | range_end_exc_px } // ------------------------------------------------------ // PREFIX EXPRESSIONS // ------------------------------------------------------ -deref_px = { "*" } -mut_ref_px = { "&" ~ mutable } -ref_px = { "&" } -new_px = { "new" } -not_px = { "!" } +deref_px = { "*" } +mut_ref_px = { "&" ~ mutable } +ref_px = { "&" } +new_px = { "new" } +not_px = { "!" } +neg_px = { "-" } +range_start_inc_px = { "..=" } +range_start_exc_px = { ".." } prefix = { deref_px @@ -499,48 +523,63 @@ prefix = { | ref_px | new_px | not_px + | neg_px + | range_start_inc_px + | range_start_exc_px } // ------------------------------------------------------ -// OPERATORS (Named individually for Pratt Parser configuration) +// OPERATORS (Arranged carefully for PEG priority matching) // ------------------------------------------------------ -lte = { "<=" } -gte = { ">=" } -eq = { "==" } -neq = { "!=" } -and = { "&&" } -or = { "||" } -add = { "+" } -sub = { "-" } -mul = { "*" } -div = { "/" } -rem = { "%" } -lt = { "<" } -gt = { ">" } +shl = { "<<" } +shr = { ">>" } +range_inc = { "..=" } +range_exc = { ".." } +lte = { "<=" } +gte = { ">=" } +eq = { "==" } +neq = { "!=" } +and = { "&&" } +or = { "||" } +add = { "+" } +sub = { "-" } +mul = { "*" } +div = { "/" } +rem = { "%" } +lt = { "<" } +gt = { ">" } +bitand = { "&" } +bitor = { "|" } +bitxor = { "^" } bin_op = _{ - lte + shl + | shr + | range_inc + | range_exc + | lte | gte | eq | neq | and | or + | lt + | gt | add | sub | mul | div | rem - | lt - | gt + | bitand + | bitor + | bitxor } // ------------------------------------------------------ // EXPRESSIONS // ------------------------------------------------------ -// Top-level entry point for expressions expr = { term ~ (bin_op ~ term)* } -// A term handles your Prefix and Postfix combinations around a core Primary term = { prefix* ~ primary ~ postfix* } From 33fae13c8a85a184e2bac8663eceab2f9500c1cd Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 03:28:22 +0200 Subject: [PATCH 13/26] Updated AST for extensive expressions --- parser/src/ast/expr.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index bee7250..d5f6d39 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -17,12 +17,19 @@ pub enum BinaryOp { GreaterThanOrEqual, And, Or, + ShiftLeft, + ShiftRight, + RangeInclusive, + RangeExclusive, + BitAnd, + BitOr, + BitXor, } #[derive(Debug, Clone, Serialize)] pub enum Expression { Literal(Literal), - Path(Path), + Path(ExprPath), // Updated from Path to support paths containing turbofish segments Fix { initial: Box, prefixes: Vec, @@ -42,6 +49,8 @@ pub enum Literal { Float(f64), Bool(bool), Tuple(Vec), + Array(Vec), + ArrayRepeat(Box, Box), } #[derive(Debug, Clone, Serialize)] @@ -56,11 +65,14 @@ pub enum Pattern { #[derive(Debug, Clone, Serialize)] pub enum Postfix { - FieldAccess(Identifier), + FieldAccess(Identifier, Option), // Updated to support method turbofish chains Call(Vec), MacroCall(String), StructCall(Vec<(Identifier, Expression)>), Index(Expression), + As(TypeExpr), + RangeInclusive, + RangeExclusive, } #[derive(Debug, Clone, Serialize)] @@ -70,4 +82,18 @@ pub enum Prefix { Deref, New, Not, + Neg, + RangeInclusive, + RangeExclusive, +} + +#[derive(Debug, Clone, Serialize)] +pub struct ExprPathSegment { + pub ident: Identifier, + pub generics: Option, +} + +#[derive(Debug, Clone, Serialize)] +pub struct ExprPath { + pub segments: Vec, } From 2a95ad4eb03b6a27fea38b3be6639de0f3401540 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 03:49:34 +0200 Subject: [PATCH 14/26] extended expression --- parser/src/ast/expr.rs | 2 +- parser/src/grammar.pest | 6 ++- parser/src/parser/common/expr.rs | 65 +++++++++++++++++++++++++------- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index d5f6d39..4eb8b91 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -65,7 +65,7 @@ pub enum Pattern { #[derive(Debug, Clone, Serialize)] pub enum Postfix { - FieldAccess(Identifier, Option), // Updated to support method turbofish chains + FieldAccess(Identifier, Option), Call(Vec), MacroCall(String), StructCall(Vec<(Identifier, Expression)>), diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index df95248..2003dc6 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -447,8 +447,12 @@ macro_inner_v = { // PRIMARY EXPRESSIONS // ------------------------------------------------------ +expr_path_segment = { + identifier ~ ("::" ~ generics)? +} + expr_path = { - identifier ~ ("::" ~ generics)? ~ ("::" ~ identifier ~ ("::" ~ generics)?)* + expr_path_segment ~ ("::" ~ expr_path_segment)* } primary = { diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 77d7c9a..c0dc13e 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -1,7 +1,7 @@ use crate::{ Rule, ast::*, - ast_expr, + ast_ensure, ast_expr, error::{AstError, AstResult, GetLength, IntoErr, collect_recovered, collect_recovered_map}, }; use pest::pratt_parser::PrattParser; @@ -15,34 +15,37 @@ impl<'a> TryFrom> for Expression { let inner = pair.clone().into_inner(); match rule { - // 1. The top level expressions are now processed via the Pratt Parser Rule::expr => { static PRATT_PARSER: OnceLock> = OnceLock::new(); let pratt = PRATT_PARSER.get_or_init(|| { use Rule::*; use pest::pratt_parser::{Assoc::*, Op}; - // Precedence defined from lowest to highest PrattParser::new() + .op(Op::infix(range_inc, Left) | Op::infix(range_exc, Left)) .op(Op::infix(or, Left)) .op(Op::infix(and, Left)) - .op(Op::infix(eq, Left) - | Op::infix(neq, Left) - | Op::infix(lt, Left) - | Op::infix(gt, Left) + .op(Op::infix(bitor, Left)) + .op(Op::infix(bitxor, Left)) + .op(Op::infix(bitand, Left)) + .op(Op::infix(eq, Left) | Op::infix(neq, Left)) + .op(Op::infix(lt, Left) | Op::infix(lte, Left) + | Op::infix(gt, Left) | Op::infix(gte, Left)) + .op(Op::infix(shl, Left) | Op::infix(shr, Left)) .op(Op::infix(add, Left) | Op::infix(sub, Left)) .op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(rem, Left)) }); pratt - .map_primary(|primary_pair| { - // Elements handled by map_primary are either sub-expressions or 'term' rules - Expression::try_from(primary_pair) - }) + .map_primary(|primary_pair| Expression::try_from(primary_pair)) .map_infix(|lhs, op, rhs| { let bin_op = match op.as_rule() { + Rule::shl => BinaryOp::ShiftLeft, + Rule::shr => BinaryOp::ShiftRight, + Rule::range_inc => BinaryOp::RangeInclusive, + Rule::range_exc => BinaryOp::RangeExclusive, Rule::lte => BinaryOp::LessThanOrEqual, Rule::gte => BinaryOp::GreaterThanOrEqual, Rule::eq => BinaryOp::Equal, @@ -56,6 +59,9 @@ impl<'a> TryFrom> for Expression { Rule::rem => BinaryOp::Modulo, Rule::lt => BinaryOp::LessThan, Rule::gt => BinaryOp::GreaterThan, + Rule::bitand => BinaryOp::BitAnd, + Rule::bitor => BinaryOp::BitOr, + Rule::bitxor => BinaryOp::BitXor, _ => return AstError::bug_unimplemented(op), }; @@ -130,6 +136,9 @@ impl<'a> TryFrom> for Prefix { Rule::ref_px => Self::Ref, Rule::new_px => Self::New, Rule::not_px => Self::Not, + Rule::neg_px => Self::Neg, + Rule::range_start_inc_px => Self::RangeInclusive, + Rule::range_start_exc_px => Self::RangeExclusive, _ => return AstError::bug_unimplemented(pair), }) @@ -147,7 +156,10 @@ impl<'a> TryFrom> for Postfix { Rule::postfix => Postfix::try_from(inner.next().unwrap()), Rule::field_px => { - ast_expr!(Postfix::FieldAccess(inner.next().unwrap().try_into())) + ast_expr!(Postfix::FieldAccess( + inner.next().unwrap().try_into(), + inner.next().map(Generics::try_from).transpose() + )) } Rule::call_px => ast_expr!(Postfix::Call(collect_recovered(inner))), @@ -166,9 +178,34 @@ impl<'a> TryFrom> for Postfix { Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())), - // Note: Rule::binary_px has been completely decoupled from postfix rules - // as it is now safely managed inside the top-level Pratt execution above. _ => AstError::bug_unimplemented(pair), } } } + +impl<'a> TryFrom> for ExprPath { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + ast_ensure!(pair, Rule::expr_path => { + ast_expr!(ExprPath { + segments: collect_recovered(pair.into_inner()), + }) + }) + } +} + +impl<'a> TryFrom> for ExprPathSegment { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + let mut inner = pair.clone().into_inner(); + + ast_ensure!(pair, Rule::expr_path_segment => { + ast_expr!(ExprPathSegment { + ident: Identifier::try_from(inner.next().unwrap()), + generics: inner.next().map(Generics::try_from).transpose(), + }) + }) + } +} From 16f169cdb04853c697df85067035be6396d9c436 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 04:00:15 +0200 Subject: [PATCH 15/26] Codegen --- src/codegen.rs | 69 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 62 insertions(+), 7 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index cf3c82d..7e0b200 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,8 +1,8 @@ use mist_parser::ast::{ - Attribute, BinaryOp, Block, ClassItem, EnumItem, Expression, FieldDecl, FunctionDecl, Generic, - Generics, Identifier, ImplDecl, Literal, Path, Pattern, Postfix, Prefix, Statement, - StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarDecl, - VarDeclStmt, Visibility, + Attribute, BinaryOp, Block, ClassItem, EnumItem, ExprPath, ExprPathSegment, Expression, + FieldDecl, FunctionDecl, Generic, Generics, Identifier, ImplDecl, Literal, Path, Pattern, + Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, + TypePostfix, VarDecl, VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- @@ -137,6 +137,17 @@ impl GetRust for Literal { .join(", ") ) } + Self::Array(values) => format!( + "[{}]", + values + .iter() + .map(Expression::get_rust) + .collect::>() + .join(", ") + ), + Self::ArrayRepeat(value, repeat) => { + format!("[{}; {}]", value.get_rust(), repeat.get_rust()) + } } } } @@ -172,6 +183,13 @@ impl GetRust for Expression { BinaryOp::GreaterThanOrEqual => ">=", BinaryOp::And => "&&", BinaryOp::Or => "||", + BinaryOp::ShiftLeft => "<<", + BinaryOp::ShiftRight => ">>", + BinaryOp::RangeInclusive => "..=", + BinaryOp::RangeExclusive => "..", + BinaryOp::BitAnd => "&", + BinaryOp::BitOr => "|", + BinaryOp::BitXor => "^", }; format!("{} {} {}", lhs.get_rust(), op_str, rhs.get_rust()) } @@ -187,6 +205,9 @@ impl GetRust for Prefix { Self::RefMut => "&mut ", Self::Not => "!", Self::New => "", + Self::Neg => "-", + Self::RangeInclusive => "..=", + Self::RangeExclusive => "..", } .to_string() } @@ -198,6 +219,29 @@ impl GetRust for [Prefix] { } } +impl GetRust for ExprPath { + fn get_rust(&self) -> String { + self.segments + .iter() + .map(ExprPathSegment::get_rust) + .collect::>() + .join(", ") + } +} + +impl GetRust for ExprPathSegment { + fn get_rust(&self) -> String { + format!( + "{}{}", + self.ident.get_rust(), + self.generics + .as_ref() + .map(|v| format!("::{}", v.get_rust())) + .unwrap_or_default() + ) + } +} + impl GetRust for Option<&Vec> { fn get_rust(&self) -> String { self.map(|prefixes| { @@ -218,7 +262,14 @@ impl GetRust for Option<&Vec> { impl GetRust for Postfix { fn get_rust(&self) -> String { match self { - Postfix::FieldAccess(field) => format!(".{}", field.get_rust()), + Postfix::FieldAccess(field, generics) => format!( + ".{}{}", + field.get_rust(), + generics + .as_ref() + .map(|v| format!("::{}", v.get_rust())) + .unwrap_or_default() + ), Postfix::Call(args) => { let args = args @@ -244,8 +295,12 @@ impl GetRust for Postfix { Postfix::Index(idx) => { format!("[{}]", idx.get_rust()) - } // Note: Postfix::Binary variant logic has been completely transferred - // to Expression::Binary to match your updated AST configuration. + } + + Postfix::As(ty) => format!("as {}", ty.get_rust()), + + Postfix::RangeInclusive => String::from("..="), + Postfix::RangeExclusive => String::from(".."), } } } From 82d748224f8d88fcdcd0fed5752f3b4368fff46c Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 04:13:27 +0200 Subject: [PATCH 16/26] Fixed expression --- parser/src/ast/expr.rs | 2 +- parser/src/parser/common/expr.rs | 2 +- src/codegen.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index 4eb8b91..f89da9a 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -29,7 +29,7 @@ pub enum BinaryOp { #[derive(Debug, Clone, Serialize)] pub enum Expression { Literal(Literal), - Path(ExprPath), // Updated from Path to support paths containing turbofish segments + Path(ExprPath), Fix { initial: Box, prefixes: Vec, diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index c0dc13e..68c858c 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -74,7 +74,6 @@ impl<'a> TryFrom> for Expression { .parse(inner) } - // 2. The single unit 'term' replaces the old flat 'expr' layout Rule::term => { let mut prefix_pairs = Vec::new(); let mut primary_pair = None; @@ -119,6 +118,7 @@ impl<'a> TryFrom> for Expression { Rule::primary => pair.into_inner().next().unwrap().try_into(), Rule::static_path => ast_expr!(Expression::Path(pair.try_into())), Rule::literal => ast_expr!(Expression::Literal(pair.try_into())), + Rule::expr_path => ast_expr!(Expression::Path(pair.try_into())), _ => AstError::bug_unimplemented(pair), } diff --git a/src/codegen.rs b/src/codegen.rs index 7e0b200..d6cb936 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -225,7 +225,7 @@ impl GetRust for ExprPath { .iter() .map(ExprPathSegment::get_rust) .collect::>() - .join(", ") + .join("::") } } From 4742fbebf7ebc94e75a3f2524f05a378c56c890d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 04:30:00 +0200 Subject: [PATCH 17/26] Codegen generics --- src/codegen.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index d6cb936..6cea264 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -890,7 +890,7 @@ impl GetRust for Generics { "<{}>", self.0 .iter() - .map(|v| (true, v).get_rust()) + .map(|v| (false, v).get_rust()) .collect::>() .join(", ") ) @@ -904,9 +904,7 @@ impl GetRust for (bool, &Generic) { Generic::Lifetime(name) => format!("'{}", name.get_rust()), Generic::Type(name, requirements) => { name.get_rust() - + &(if !self.0 && requirements.len() == 0 { - String::new() - } else { + + &(if self.0 && requirements.len() != 0 { format!( ": {}", requirements @@ -915,6 +913,8 @@ impl GetRust for (bool, &Generic) { .collect::>() .join("+") ) + } else { + String::new() }) } } From 9b632fcc0e85525b3c2395efe13fa11371c4dab1 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 04:35:00 +0200 Subject: [PATCH 18/26] New generics --- parser/src/ast/expr.rs | 2 +- parser/src/grammar.pest | 2 +- parser/src/parser/common/expr.rs | 7 ++++++- src/codegen.rs | 12 +++++++++--- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index f89da9a..ae6e96b 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -80,7 +80,7 @@ pub enum Prefix { Ref, RefMut, Deref, - New, + New(Option), Not, Neg, RangeInclusive, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 2003dc6..b955b95 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -515,7 +515,7 @@ postfix = { deref_px = { "*" } mut_ref_px = { "&" ~ mutable } ref_px = { "&" } -new_px = { "new" } +new_px = { "new" ~ generics? } not_px = { "!" } neg_px = { "-" } range_start_inc_px = { "..=" } diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 68c858c..8abf3f6 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -134,7 +134,12 @@ impl<'a> TryFrom> for Prefix { Rule::deref_px => Self::Deref, Rule::mut_ref_px => Self::RefMut, Rule::ref_px => Self::Ref, - Rule::new_px => Self::New, + Rule::new_px => Self::New( + pair.into_inner() + .next() + .map(|v| v.try_into().get()) + .transpose()?, + ), Rule::not_px => Self::Not, Rule::neg_px => Self::Neg, Rule::range_start_inc_px => Self::RangeInclusive, diff --git a/src/codegen.rs b/src/codegen.rs index 6cea264..932a260 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -204,7 +204,7 @@ impl GetRust for Prefix { Self::Ref => "&", Self::RefMut => "&mut ", Self::Not => "!", - Self::New => "", + Self::New(_) => "", Self::Neg => "-", Self::RangeInclusive => "..=", Self::RangeExclusive => "..", @@ -249,8 +249,14 @@ impl GetRust for Option<&Vec> { .iter() .last() .map(|p| match p { - Prefix::New => "::new", - _ => "", + Prefix::New(generics) => format!( + "::new{}", + generics + .as_ref() + .map(|v| format!("::{}", v.get_rust())) + .unwrap_or_default(), + ), + _ => String::new(), }) .unwrap_or_default() .to_string() From c7529412f4ccde148315caa60d262bbcb682a594 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 04:44:38 +0200 Subject: [PATCH 19/26] Adding increment --- mist-test/src/main.mist | 2 ++ parser/src/grammar.pest | 5 +++++ parser/src/parser/common/expr.rs | 9 +++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 853e686..6a71985 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -7,6 +7,8 @@ pub mod event; void main() { var mut app_instance = new app::Application("mist-app"); + i++; + // greeting::register(&mut app_instance); // statistics::register(&mut app_instance); diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index b955b95..3c45c37 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -497,8 +497,13 @@ as_px = { range_end_inc_px = { "..=" } range_end_exc_px = { ".." } +increment_px = { "++" } +decrement_px = { "++" } + postfix = { field_px + | increment_px + | decrement_px | call_px | macro_call_px | struct_px diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 8abf3f6..10fb2b2 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -79,7 +79,6 @@ impl<'a> TryFrom> for Expression { let mut primary_pair = None; let mut postfix_pairs = Vec::new(); - // Sort out flat layout components for p in inner { match p.as_rule() { Rule::prefix => prefix_pairs.push(p), @@ -95,7 +94,6 @@ impl<'a> TryFrom> for Expression { ); let postfixes = collect_recovered::(postfix_pairs.into_iter()); - // Employs your exact original logic using the GetLength trait if postfixes.len() > 0 || prefixes.len() > 0 { ast_expr!(Expression::Fix { initial: exp.map(Box::new), @@ -183,6 +181,13 @@ impl<'a> TryFrom> for Postfix { Rule::macro_call_px => Ok(Postfix::MacroCall(inner.as_str().to_string())), + Rule::as_px => { + ast_expr!(Postfix::As(inner.next().unwrap().try_into())) + } + + Rule::range_end_inc_px => Ok(Postfix::RangeInclusive), + Rule::range_end_exc_px => Ok(Postfix::RangeExclusive), + _ => AstError::bug_unimplemented(pair), } } From 1bcbca00b801cd73ac22603f08057a63b9a3b98a Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 05:13:28 +0200 Subject: [PATCH 20/26] Fixed loose error --- parser/src/grammar.pest | 8 ++++---- parser/src/lib.rs | 12 +++++++++++- parser/src/parser/common/expr.rs | 2 +- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 3c45c37..f98962e 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -497,13 +497,13 @@ as_px = { range_end_inc_px = { "..=" } range_end_exc_px = { ".." } -increment_px = { "++" } -decrement_px = { "++" } +inc_px = { "++" } +dec_px = { "++" } postfix = { field_px - | increment_px - | decrement_px + | inc_px + | dec_px | call_px | macro_call_px | struct_px diff --git a/parser/src/lib.rs b/parser/src/lib.rs index df5cbf5..245fd9f 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -41,7 +41,7 @@ macro_rules! ast_ensure { Err(AstError { span: $pair.as_span(), error_code: crate::error::ErrorCode::AstGenBug, - error_message: format!("Possible bug: expected {:?}, got {}", $rule, $pair), + error_message: format!("Possible bug: expected {:?}, got {:?}", $rule, $pair.as_rule()), recovered: None, }) } @@ -50,6 +50,16 @@ macro_rules! ast_ensure { #[macro_export] macro_rules! ast_expr { + (use $r:expr, $($v:expr),* $(,)?) => {{ + let mut analyzer = $crate::error::AstErrorAnalyzer(None); + + $( + analyzer.get($v).get()?; + )* + + analyzer.build($r) + }}; + ($($item:ident)::+ { $($k:ident: $v:expr),* $(,)? }) => {{ let mut analyzer = $crate::error::AstErrorAnalyzer(None); diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 10fb2b2..7de634e 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -101,7 +101,7 @@ impl<'a> TryFrom> for Expression { postfixes: postfixes, }) } else { - exp + ast_expr!(use exp?, prefixes, postfixes) } } From 77f35e05176a978e04d2bb3c417271b994b6f970 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 05:32:46 +0200 Subject: [PATCH 21/26] Removed incrementing tmp --- parser/src/grammar.pest | 5 ----- 1 file changed, 5 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index f98962e..b955b95 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -497,13 +497,8 @@ as_px = { range_end_inc_px = { "..=" } range_end_exc_px = { ".." } -inc_px = { "++" } -dec_px = { "++" } - postfix = { field_px - | inc_px - | dec_px | call_px | macro_call_px | struct_px From a893f9a12dccf95b051e3bea3ea9e66104cef2f3 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 05:43:16 +0200 Subject: [PATCH 22/26] Increment and decrement via ++ or -- --- mist-test/src/app.mist | 2 +- mist-test/src/main.mist | 2 -- parser/src/ast/statement.rs | 3 +++ parser/src/grammar.pest | 10 ++++++++++ parser/src/parser/common/statement.rs | 8 ++++++++ src/codegen.rs | 3 +++ 6 files changed, 25 insertions(+), 3 deletions(-) diff --git a/mist-test/src/app.mist b/mist-test/src/app.mist index 3358be9..42072ac 100644 --- a/mist-test/src/app.mist +++ b/mist-test/src/app.mist @@ -46,7 +46,7 @@ pub class Application { void tick(self mut*) { self.logger.info("tick"); - self.ticks += 1; + self.ticks++; var task = task::create_task("background-job"); diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 6a71985..853e686 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -7,8 +7,6 @@ pub mod event; void main() { var mut app_instance = new app::Application("mist-app"); - i++; - // greeting::register(&mut app_instance); // statistics::register(&mut app_instance); diff --git a/parser/src/ast/statement.rs b/parser/src/ast/statement.rs index 69b12b1..3d5c565 100644 --- a/parser/src/ast/statement.rs +++ b/parser/src/ast/statement.rs @@ -43,6 +43,9 @@ pub enum Statement { Return(Option), Break, Continue, + + Increment(Expression), + Decrement(Expression), } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index b955b95..7add0ea 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -324,6 +324,8 @@ statement = _{ | continue_stmt | block | var_decl_statement + | increment_statement + | decrement_statement } // ------------------------------------------------------ @@ -354,6 +356,14 @@ assign_statement = { expr ~ "=" ~ expr ~ semicolon } +increment_statement = { + expr ~ "++" ~ semicolon +} + +decrement_statement = { + expr ~ "--" ~ semicolon +} + compound_assign = { "+=" | "-=" diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index 34d35f9..28ebb0f 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -114,6 +114,14 @@ impl<'a> TryFrom> for Statement { }) } + Rule::increment_statement => { + ast_expr!(Statement::Increment(inner.next().unwrap().try_into())) + } + + Rule::decrement_statement => { + ast_expr!(Statement::Decrement(inner.next().unwrap().try_into())) + } + Rule::unexpected_statement => { return Err(AstError { span: pair.as_span(), diff --git a/src/codegen.rs b/src/codegen.rs index 932a260..883abae 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -713,6 +713,9 @@ impl ToRust for Statement { Statement::Break => cg.add_indentedln("break;"), Statement::Continue => cg.add_indentedln("continue;"), + + Statement::Increment(e) => cg.add(&format!("{}+=1;", e.get_rust())), + Statement::Decrement(e) => cg.add(&format!("{}-=1;", e.get_rust())), } } } From 212d5d69b503aaea3b660e7886bb5acdba892976 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 05:49:37 +0200 Subject: [PATCH 23/26] Fixed as --- src/codegen.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen.rs b/src/codegen.rs index 883abae..33a6b31 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -303,7 +303,7 @@ impl GetRust for Postfix { format!("[{}]", idx.get_rust()) } - Postfix::As(ty) => format!("as {}", ty.get_rust()), + Postfix::As(ty) => format!(" as {}", ty.get_rust()), Postfix::RangeInclusive => String::from("..="), Postfix::RangeExclusive => String::from(".."), From 46c6f5ffdd69406bdc1d4e88d8864f3232e05df4 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 05:52:23 +0200 Subject: [PATCH 24/26] Fixed range --- parser/src/ast/expr.rs | 4 ---- parser/src/grammar.pest | 9 --------- parser/src/parser/common/expr.rs | 5 ----- src/codegen.rs | 5 ----- 4 files changed, 23 deletions(-) diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index ae6e96b..267da27 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -71,8 +71,6 @@ pub enum Postfix { StructCall(Vec<(Identifier, Expression)>), Index(Expression), As(TypeExpr), - RangeInclusive, - RangeExclusive, } #[derive(Debug, Clone, Serialize)] @@ -83,8 +81,6 @@ pub enum Prefix { New(Option), Not, Neg, - RangeInclusive, - RangeExclusive, } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 7add0ea..308cbd6 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -504,9 +504,6 @@ as_px = { "as" ~ type_expr } -range_end_inc_px = { "..=" } -range_end_exc_px = { ".." } - postfix = { field_px | call_px @@ -514,8 +511,6 @@ postfix = { | struct_px | index_px | as_px - | range_end_inc_px - | range_end_exc_px } // ------------------------------------------------------ @@ -528,8 +523,6 @@ ref_px = { "&" } new_px = { "new" ~ generics? } not_px = { "!" } neg_px = { "-" } -range_start_inc_px = { "..=" } -range_start_exc_px = { ".." } prefix = { deref_px @@ -538,8 +531,6 @@ prefix = { | new_px | not_px | neg_px - | range_start_inc_px - | range_start_exc_px } // ------------------------------------------------------ diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 7de634e..9dbb5c1 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -140,8 +140,6 @@ impl<'a> TryFrom> for Prefix { ), Rule::not_px => Self::Not, Rule::neg_px => Self::Neg, - Rule::range_start_inc_px => Self::RangeInclusive, - Rule::range_start_exc_px => Self::RangeExclusive, _ => return AstError::bug_unimplemented(pair), }) @@ -185,9 +183,6 @@ impl<'a> TryFrom> for Postfix { ast_expr!(Postfix::As(inner.next().unwrap().try_into())) } - Rule::range_end_inc_px => Ok(Postfix::RangeInclusive), - Rule::range_end_exc_px => Ok(Postfix::RangeExclusive), - _ => AstError::bug_unimplemented(pair), } } diff --git a/src/codegen.rs b/src/codegen.rs index 33a6b31..ff3e0f1 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -206,8 +206,6 @@ impl GetRust for Prefix { Self::Not => "!", Self::New(_) => "", Self::Neg => "-", - Self::RangeInclusive => "..=", - Self::RangeExclusive => "..", } .to_string() } @@ -304,9 +302,6 @@ impl GetRust for Postfix { } Postfix::As(ty) => format!(" as {}", ty.get_rust()), - - Postfix::RangeInclusive => String::from("..="), - Postfix::RangeExclusive => String::from(".."), } } } From dd647afd59443c0f1f9cb9cff256d41c1776b4c8 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 05:55:43 +0200 Subject: [PATCH 25/26] Indentation increment --- src/codegen.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index ff3e0f1..c9877dc 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -709,8 +709,8 @@ impl ToRust for Statement { Statement::Break => cg.add_indentedln("break;"), Statement::Continue => cg.add_indentedln("continue;"), - Statement::Increment(e) => cg.add(&format!("{}+=1;", e.get_rust())), - Statement::Decrement(e) => cg.add(&format!("{}-=1;", e.get_rust())), + Statement::Increment(e) => cg.add_indentedln(&format!("{}+=1;", e.get_rust())), + Statement::Decrement(e) => cg.add_indentedln(&format!("{}-=1;", e.get_rust())), } } } From e89f5e805c8a4e5e7656baf51dfb5b036ba7e369 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 17 May 2026 06:00:26 +0200 Subject: [PATCH 26/26] Cleaned up AST --- parser/src/ast/expr.rs | 4 +--- parser/src/ast/statement.rs | 4 ---- parser/src/grammar.pest | 22 +++++++++------------- parser/src/parser/common/expr.rs | 4 +--- parser/src/parser/common/statement.rs | 11 ++--------- src/codegen.rs | 8 ++------ 6 files changed, 15 insertions(+), 38 deletions(-) diff --git a/parser/src/ast/expr.rs b/parser/src/ast/expr.rs index 267da27..9680af9 100644 --- a/parser/src/ast/expr.rs +++ b/parser/src/ast/expr.rs @@ -90,6 +90,4 @@ pub struct ExprPathSegment { } #[derive(Debug, Clone, Serialize)] -pub struct ExprPath { - pub segments: Vec, -} +pub struct ExprPath(pub Vec); diff --git a/parser/src/ast/statement.rs b/parser/src/ast/statement.rs index 3d5c565..8ae23e9 100644 --- a/parser/src/ast/statement.rs +++ b/parser/src/ast/statement.rs @@ -12,10 +12,6 @@ pub enum Statement { VarDecl(VarDeclStmt), Assign { - target: Expression, - value: Expression, - }, - CompoundAssign { target: Expression, compound: String, value: Expression, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 308cbd6..056511f 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -314,7 +314,6 @@ statement = _{ expr_stmt | match_stmt | assign_statement - | compound_assign_statement | if_stmt | while_stmt | c_for_stmt @@ -352,10 +351,6 @@ var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ semicolon } -assign_statement = { - expr ~ "=" ~ expr ~ semicolon -} - increment_statement = { expr ~ "++" ~ semicolon } @@ -365,7 +360,8 @@ decrement_statement = { } compound_assign = { - "+=" + "=" + | "+=" | "-=" | "/=" | "%=" @@ -376,7 +372,7 @@ compound_assign = { | ">>=" } -compound_assign_statement = { +assign_statement = { expr ~ compound_assign ~ expr ~ semicolon } @@ -517,12 +513,12 @@ postfix = { // PREFIX EXPRESSIONS // ------------------------------------------------------ -deref_px = { "*" } -mut_ref_px = { "&" ~ mutable } -ref_px = { "&" } -new_px = { "new" ~ generics? } -not_px = { "!" } -neg_px = { "-" } +deref_px = { "*" } +mut_ref_px = { "&" ~ mutable } +ref_px = { "&" } +new_px = { "new" ~ generics? } +not_px = { "!" } +neg_px = { "-" } prefix = { deref_px diff --git a/parser/src/parser/common/expr.rs b/parser/src/parser/common/expr.rs index 9dbb5c1..94baab8 100644 --- a/parser/src/parser/common/expr.rs +++ b/parser/src/parser/common/expr.rs @@ -193,9 +193,7 @@ impl<'a> TryFrom> for ExprPath { fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { ast_ensure!(pair, Rule::expr_path => { - ast_expr!(ExprPath { - segments: collect_recovered(pair.into_inner()), - }) + ast_expr!(ExprPath(collect_recovered(pair.into_inner()))) }) } } diff --git a/parser/src/parser/common/statement.rs b/parser/src/parser/common/statement.rs index 28ebb0f..860ec61 100644 --- a/parser/src/parser/common/statement.rs +++ b/parser/src/parser/common/statement.rs @@ -90,6 +90,8 @@ impl<'a> TryFrom> for Statement { Rule::assign_statement => ast_expr!(Statement::Assign { target: inner.next().unwrap().try_into(), + compound: Ok(inner.next().unwrap().as_str().trim().to_string()) + as AstResult<'_, String>, value: inner.next().unwrap().try_into(), }), Rule::match_stmt => ast_expr!(Statement::Match( @@ -105,15 +107,6 @@ impl<'a> TryFrom> for Statement { .collect::>>(), )), - Rule::compound_assign_statement => { - ast_expr!(Statement::CompoundAssign { - target: inner.next().unwrap().try_into(), - compound: Ok(inner.next().unwrap().as_str().trim().to_string()) - as AstResult<'_, String>, - value: inner.next().unwrap().try_into(), - }) - } - Rule::increment_statement => { ast_expr!(Statement::Increment(inner.next().unwrap().try_into())) } diff --git a/src/codegen.rs b/src/codegen.rs index c9877dc..8ba285b 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -219,7 +219,7 @@ impl GetRust for [Prefix] { impl GetRust for ExprPath { fn get_rust(&self) -> String { - self.segments + self.0 .iter() .map(ExprPathSegment::get_rust) .collect::>() @@ -601,11 +601,7 @@ impl ToRust for Statement { cg.add_indentedln(&format!("let {}{};", decl.get_rust(), init)); } - Statement::Assign { target, value } => { - cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),)); - } - - Statement::CompoundAssign { + Statement::Assign { target, compound, value,