From f604b52384c64ff5977970230d154684ee8536cc Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 15:17:36 +0200 Subject: [PATCH 01/15] codegen minor fix --- src/codegen.rs | 12 +++--------- test/src/main.mist | 4 ++++ 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index b4c4a35..a900512 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -202,7 +202,7 @@ impl GetRust for Postfix { BinaryOp::LessThanOrEqual => "<=", BinaryOp::GreaterThanOrEqual => ">=", }; - format!("{} {}", op_str, rhs.get_rust()) + format!(" {} {}", op_str, rhs.get_rust()) } } } @@ -358,18 +358,12 @@ impl ToRust for Statement { then_branch, else_branch, }) => { - cg.add_indentedln(&format!("if {} {{", condition.get_rust())); - cg.indent += 1; + cg.add_indentedln(&format!("if {}", condition.get_rust())); then_branch.to_rust(cg); - cg.indent -= 1; - cg.add_indentedln("}"); if let Some(else_br) = else_branch { - cg.add_indentedln("else {"); - cg.indent += 1; + cg.add_indentedln("else"); else_br.to_rust(cg); - cg.indent -= 1; - cg.add_indentedln("}"); } } diff --git a/test/src/main.mist b/test/src/main.mist index 40ba951..fbc6084 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -9,5 +9,9 @@ public struct ApiCall { void main() { ApiCall call = ApiCall { x: 10, y: 12 }; + if (call.x == 20) { + println("= 20"); + } + println!("{call:?}"); } From 6125ecfde47331a93ba132029ee476588fb13231 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 15:23:51 +0200 Subject: [PATCH 02/15] Refactored if statement AST --- parser/src/ast.rs | 17 +++++++---------- parser/src/lib.rs | 14 ++++++++------ src/codegen.rs | 25 +++++++++++++++---------- test/src/main.mist | 6 ++++++ 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 03a5bd1..98036bf 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -102,8 +102,12 @@ pub enum Statement { VarDecl(VarDeclStmt), VarAssign(VarAssignStmt), - If(IfStmt), - While(WhileStmt), + If { + initial: StatementBranch, + else_if: Vec, + else_branch: Option>, + }, + While(StatementBranch), For(ForStmt), Return(Option), @@ -131,14 +135,7 @@ pub struct VarAssignStmt { } #[derive(Debug, Clone, Serialize)] -pub struct IfStmt { - pub condition: Expression, - pub then_branch: Box, - pub else_branch: Option>, -} - -#[derive(Debug, Clone, Serialize)] -pub struct WhileStmt { +pub struct StatementBranch { pub condition: Expression, pub body: Box, } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e2014f4..1019e98 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -308,18 +308,20 @@ impl From> for Statement { let else_branch = inner.next().map(Statement::from); - Statement::If(IfStmt { - condition, - then_branch: Box::new(then_branch), - else_branch: else_branch.map(Box::new), - }) + Statement::Break + + // Statement::If(IfStmt { + // condition, + // then_branch: Box::new(then_branch), + // else_branch: else_branch.map(Box::new), + // }) } Rule::while_stmt => { let condition = Expression::from(inner.next().unwrap()); let body = Statement::from(inner.next().unwrap()); - Statement::While(WhileStmt { + Statement::While(StatementBranch { condition, body: Box::new(body), }) diff --git a/src/codegen.rs b/src/codegen.rs index a900512..d6af6dd 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,7 @@ use parser::ast::{ - Attribute, BinaryOp, Block, Expression, IfStmt, Literal, Path, Postfix, Prefix, Statement, - TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, - VarDeclStmt, WhileStmt, + Attribute, BinaryOp, Block, Expression, Literal, Path, Postfix, Prefix, Statement, + StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, + VarDecl, VarDeclStmt, }; // --------------------------------------------------------------------------- @@ -353,13 +353,18 @@ impl ToRust for Statement { cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),)); } - Statement::If(IfStmt { - condition, - then_branch, + Statement::If { + initial, + else_if, else_branch, - }) => { - cg.add_indentedln(&format!("if {}", condition.get_rust())); - then_branch.to_rust(cg); + } => { + cg.add_indentedln(&format!("if {}", initial.condition.get_rust())); + initial.body.to_rust(cg); + + for else_if_branch in else_if { + cg.add_indentedln(&format!("else if {}", else_if_branch.condition.get_rust())); + else_if_branch.body.to_rust(cg); + } if let Some(else_br) = else_branch { cg.add_indentedln("else"); @@ -367,7 +372,7 @@ impl ToRust for Statement { } } - Statement::While(WhileStmt { condition, body }) => { + Statement::While(StatementBranch { condition, body }) => { cg.add_indentedln(&format!("while {} {{", condition.get_rust())); cg.indent += 1; body.to_rust(cg); diff --git a/test/src/main.mist b/test/src/main.mist index fbc6084..fefc53e 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -11,6 +11,12 @@ void main() { if (call.x == 20) { println("= 20"); + } else if (call.x == 10) { + println("= 10"); + } else if (call.x == 5) { + println("= 5"); + } else { + println("= unknown"); } println!("{call:?}"); From 95c4826b5fd12ece6a220e742ce274f17fb8e346 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 15:54:51 +0200 Subject: [PATCH 03/15] Refactor: If statement --- parser/src/grammar.pest | 6 +++++- parser/src/lib.rs | 46 +++++++++++++++++++++++------------------ 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 59d1490..d243ebc 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -86,8 +86,12 @@ var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ ";" } assign_statement = { expr ~ "=" ~ expr ~ ";" } +else_if = { "else" ~ "if" ~ "(" ~ expr ~ ")" ~ statement } + +else_if_list = { else_if* } + if_stmt = { - "if" ~ "(" ~ expr ~ ")" ~ statement ~ ("else" ~ statement)? + "if" ~ "(" ~ expr ~ ")" ~ statement ~ else_if_list ~ ("else" ~ statement)? } while_stmt = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 1019e98..95be8ce 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -196,6 +196,20 @@ impl From> for TopLevel { } } +impl From> for StatementBranch { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let mut inner = pair.into_inner(); + + let condition = Expression::from(inner.next().unwrap()); + let body = Statement::from(inner.next().unwrap()); + + StatementBranch { + condition, + body: Box::new(body), + } + } +} + impl From> for TopLevelKind { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); @@ -303,29 +317,21 @@ impl From> for Statement { Rule::continue_stmt => Statement::Continue, Rule::if_stmt => { - let condition = Expression::from(inner.next().unwrap()); - let then_branch = Statement::from(inner.next().unwrap()); + let mut inner = inner.skip(2); - let else_branch = inner.next().map(Statement::from); - - Statement::Break - - // Statement::If(IfStmt { - // condition, - // then_branch: Box::new(then_branch), - // else_branch: else_branch.map(Box::new), - // }) + Statement::If { + initial: pair.into(), + else_if: inner + .next() + .unwrap() + .into_inner() + .map(StatementBranch::from) + .collect(), + else_branch: inner.next().map(Statement::from).map(Box::new), + } } - Rule::while_stmt => { - let condition = Expression::from(inner.next().unwrap()); - let body = Statement::from(inner.next().unwrap()); - - Statement::While(StatementBranch { - condition, - body: Box::new(body), - }) - } + Rule::while_stmt => Statement::While(pair.into()), Rule::assign_statement => Statement::VarAssign(VarAssignStmt { target: Expression::from(inner.next().unwrap()), From dfc3a56dffcdc4d6d2dd71a3f395265da66d5f06 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 15:58:42 +0200 Subject: [PATCH 04/15] Fix: Field list and struct all order --- parser/src/ast.rs | 6 ++---- parser/src/lib.rs | 2 +- src/codegen.rs | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 98036bf..a623e18 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -1,9 +1,7 @@ -use std::collections::HashMap; - use serde::Serialize; #[derive(Debug, Clone, Serialize)] -pub struct FieldList(pub HashMap); +pub struct FieldList(pub Vec<(String, bool, TypeExpr)>); #[derive(Debug, Clone, Serialize)] pub struct ParamList(pub Vec); @@ -83,7 +81,7 @@ pub enum Postfix { FieldAccess(String), Call(Vec), MacroCall(String), - StructCall(HashMap), + StructCall(Vec<(String, Expression)>), Index(Expression), Binary(BinaryOp, Expression), } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 95be8ce..851713d 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -104,7 +104,7 @@ impl From> for FieldList { }; let param_type = TypeExpr::from(param_inner.next().unwrap()); let param_name = param_inner.next().unwrap().as_str().to_string(); - (param_name, (export, param_type)) + (param_name, export, param_type) }) .collect(); diff --git a/src/codegen.rs b/src/codegen.rs index d6af6dd..b1ebd79 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -284,7 +284,7 @@ impl ToRust for TopLevelKind { cg.addln(&format!("{}struct {} {{", vis, name)); cg.indent += 1; - for (field_name, (_, ty)) in &fields.0 { + for (field_name, _, ty) in &fields.0 { let ty = ty.get_rust(); cg.add_indentedln(&format!("pub {}: {},", field_name, ty)); } From 31821300c66263b430d507f613fd98afa255afcf Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 15:59:52 +0200 Subject: [PATCH 05/15] Fixed mist test file --- test/src/main.mist | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/src/main.mist b/test/src/main.mist index fefc53e..c119fac 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -10,13 +10,13 @@ void main() { ApiCall call = ApiCall { x: 10, y: 12 }; if (call.x == 20) { - println("= 20"); + println!("= 20"); } else if (call.x == 10) { - println("= 10"); + println!("= 10"); } else if (call.x == 5) { - println("= 5"); + println!("= 5"); } else { - println("= unknown"); + println!("= unknown"); } println!("{call:?}"); From f4944103ac4130d3f689378eb0e11e23c9b51511 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 16:06:32 +0200 Subject: [PATCH 06/15] Fix minor grammar --- parser/src/grammar.pest | 23 ++++++++++++----------- test/src/main.mist | 7 ++++++- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index d243ebc..c5c2e20 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -12,10 +12,11 @@ string_lit = { "\"" ~ inner_str ~ "\"" } inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* } static_path = { identifier ~ ("::" ~ identifier)* } -export = { "public" } -mutable = { "mut" } -sharp = _{ "#" } -var_decl = { type_expr ~ mutable? ~ identifier } +export = { "public" } +mutable = { "mut" } +sharp = _{ "#" } +var_decl = { type_expr ~ mutable? ~ identifier } +semicolon = { ";" } // ================= TOP LEVEL ================= @@ -74,17 +75,17 @@ statement = _{ // --- basic statements --- -expr_stmt = { expr ~ ";" } +expr_stmt = { expr ~ semicolon } -return_stmt = { "return" ~ expr? ~ ";" } +return_stmt = { "return" ~ expr? ~ semicolon } -break_stmt = { "break" ~ ";" } +break_stmt = { "break" ~ semicolon } -continue_stmt = { "continue" ~ ";" } +continue_stmt = { "continue" ~ semicolon } -var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ ";" } +var_decl_statement = { var_decl ~ ("=" ~ expr)? ~ semicolon } -assign_statement = { expr ~ "=" ~ expr ~ ";" } +assign_statement = { expr ~ "=" ~ expr ~ semicolon } else_if = { "else" ~ "if" ~ "(" ~ expr ~ ")" ~ statement } @@ -135,7 +136,7 @@ macro_call_px = { "!" ~ "(" ~ macro_inner_v* ~ ")" } struct_px = { "{" ~ (struct_field_decl ~ ("," ~ struct_field_decl)*)? ~ ","? ~ "}" } index_px = { "[" ~ expr ~ "]" } binary_px = { bin_op ~ expr } -bin_op = { "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" } +bin_op = { "<=" | ">=" | "==" | "!=" | "+" | "-" | "*" | "/" | "%" | "<" | ">" } struct_field_decl = { identifier ~ ":" ~ expr } prefix = { diff --git a/test/src/main.mist b/test/src/main.mist index c119fac..37dbc73 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -7,7 +7,7 @@ public struct ApiCall { } void main() { - ApiCall call = ApiCall { x: 10, y: 12 }; + ApiCall mut call = ApiCall { x: 10, y: 12 }; if (call.x == 20) { println!("= 20"); @@ -19,5 +19,10 @@ void main() { println!("= unknown"); } + while (call.x <= 40) { + call.x = call.x - 1; + println!("while"); + } + println!("{call:?}"); } From ec45c24854cf137e378a88b5076340e5955e8446 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 16:19:27 +0200 Subject: [PATCH 07/15] Ensure brackets without overdoing it --- src/codegen.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index b1ebd79..fec5582 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -61,6 +61,19 @@ impl RustCodegen { } self.output.clone() } + + pub fn ensure_brackets(&mut self, stmt: &Statement) { + match stmt { + Statement::Block(_) => stmt.to_rust(self), + _ => { + self.add_indentedln("{"); + self.indent += 1; + stmt.to_rust(self); + self.indent -= 1; + self.add_indentedln("}"); + } + } + } } impl Default for RustCodegen { @@ -359,25 +372,22 @@ impl ToRust for Statement { else_branch, } => { cg.add_indentedln(&format!("if {}", initial.condition.get_rust())); - initial.body.to_rust(cg); + cg.ensure_brackets(&initial.body); for else_if_branch in else_if { cg.add_indentedln(&format!("else if {}", else_if_branch.condition.get_rust())); - else_if_branch.body.to_rust(cg); + cg.ensure_brackets(&else_if_branch.body); } if let Some(else_br) = else_branch { cg.add_indentedln("else"); - else_br.to_rust(cg); + cg.ensure_brackets(else_br); } } Statement::While(StatementBranch { condition, body }) => { - cg.add_indentedln(&format!("while {} {{", condition.get_rust())); - cg.indent += 1; - body.to_rust(cg); - cg.indent -= 1; - cg.add_indentedln("}"); + cg.add_indentedln(&format!("while {}", condition.get_rust())); + cg.ensure_brackets(body); } Statement::For { .. } => { From 0d00ebcd2c7c289b0e2e7e08e2390b6b7eff1099 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 16:30:41 +0200 Subject: [PATCH 08/15] Refactored for loops --- parser/src/ast.rs | 15 ++++++--------- src/codegen.rs | 27 +++++++++++++++++++++++++-- test/src/main.mist | 27 +-------------------------- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index a623e18..6cbbd92 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -106,7 +106,12 @@ pub enum Statement { else_branch: Option>, }, While(StatementBranch), - For(ForStmt), + CStyleFor { + init: Box, + condition: Box, + update: Box, + body: Box, + }, Return(Option), Break, @@ -138,14 +143,6 @@ pub struct StatementBranch { pub body: Box, } -#[derive(Debug, Clone, Serialize)] -pub struct ForStmt { - pub init: (bool, String, Option), - pub condition: Option, - pub update: Option>, - pub body: Box, -} - #[derive(Debug, Clone, Serialize)] pub enum Expression { Literal(Literal), diff --git a/src/codegen.rs b/src/codegen.rs index fec5582..58dbcfb 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -390,8 +390,31 @@ impl ToRust for Statement { cg.ensure_brackets(body); } - Statement::For { .. } => { - cg.add_indentedln("// TODO: transform into iterator-based loop"); + Statement::CStyleFor { + init, + condition, + update, + body, + } => { + cg.add_indentedln("{"); + cg.indent += 1; + + init.to_rust(cg); + + cg.add_indentedln(&format!("while {}", condition.get_rust())); + + cg.add_indentedln("{"); + cg.indent += 1; + + cg.ensure_brackets(body); + + update.to_rust(cg); + + cg.indent -= 1; + cg.add_indentedln("}"); + + cg.indent -= 1; + cg.add_indentedln("}"); } Statement::Return(expr) => { diff --git a/test/src/main.mist b/test/src/main.mist index 37dbc73..bd51952 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,28 +1,3 @@ -#![allow(unused_mut)] - -#[derive(Debug)] -public struct ApiCall { - i32 x, - i32 y, -} - void main() { - ApiCall mut call = ApiCall { x: 10, y: 12 }; - - if (call.x == 20) { - println!("= 20"); - } else if (call.x == 10) { - println!("= 10"); - } else if (call.x == 5) { - println!("= 5"); - } else { - println!("= unknown"); - } - - while (call.x <= 40) { - call.x = call.x - 1; - println!("while"); - } - - println!("{call:?}"); + } From 9eeaabbf199a1b9bcb2312f2ebed86d78a84eba3 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 16:34:55 +0200 Subject: [PATCH 09/15] C style for loop grammar --- parser/src/grammar.pest | 5 +++++ test/src/main.mist | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index c5c2e20..e19f0e9 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -67,6 +67,7 @@ statement = _{ | assign_statement | if_stmt | while_stmt + | c_for_stmt | return_stmt | break_stmt | continue_stmt @@ -99,6 +100,10 @@ while_stmt = { "while" ~ "(" ~ expr ~ ")" ~ statement } +c_for_stmt = { + "for" ~ "(" ~ statement ~ expr ~ ";" ~ statement ~ ")" ~ statement +} + // ================= EXPRESSIONS ================= tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? } diff --git a/test/src/main.mist b/test/src/main.mist index bd51952..1ecf710 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,3 +1,5 @@ void main() { - + for (usize i; i < 10; i = i + 1;) { + println!("{i}"); + } } From d9358ea38b82db1ec681e39947ce66395f1f21e4 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 16:41:59 +0200 Subject: [PATCH 10/15] C style for loop AST gen --- parser/src/ast.rs | 2 +- parser/src/lib.rs | 7 +++++++ test/src/main.mist | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 6cbbd92..50579e4 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -108,7 +108,7 @@ pub enum Statement { While(StatementBranch), CStyleFor { init: Box, - condition: Box, + condition: Expression, update: Box, body: Box, }, diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 851713d..9dc588c 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -333,6 +333,13 @@ impl From> for Statement { Rule::while_stmt => Statement::While(pair.into()), + Rule::c_for_stmt => Statement::CStyleFor { + init: Box::new(Statement::from(inner.next().unwrap())), + condition: inner.next().unwrap().into(), + update: Box::new(Statement::from(inner.next().unwrap())), + body: Box::new(Statement::from(inner.next().unwrap())), + }, + Rule::assign_statement => Statement::VarAssign(VarAssignStmt { target: Expression::from(inner.next().unwrap()), value: Expression::from(inner.next().unwrap()), diff --git a/test/src/main.mist b/test/src/main.mist index 1ecf710..b739c17 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,5 +1,5 @@ void main() { - for (usize i; i < 10; i = i + 1;) { + for (usize mut i = 0; i < 10; i = i + 1;) { println!("{i}"); } } From eb4cec50aa7b6961e71b488002384b0804cc397e Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 17:47:36 +0200 Subject: [PATCH 11/15] Fixed semicolon --- parser/src/grammar.pest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index e19f0e9..603f96d 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -16,7 +16,7 @@ export = { "public" } mutable = { "mut" } sharp = _{ "#" } var_decl = { type_expr ~ mutable? ~ identifier } -semicolon = { ";" } +semicolon = _{ ";" } // ================= TOP LEVEL ================= @@ -101,7 +101,7 @@ while_stmt = { } c_for_stmt = { - "for" ~ "(" ~ statement ~ expr ~ ";" ~ statement ~ ")" ~ statement + "for" ~ "(" ~ statement ~ expr ~ semicolon ~ statement ~ ")" ~ statement } // ================= EXPRESSIONS ================= From ccb6654127f596717261f158a2c5e9618b07a8fd Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 17:55:37 +0200 Subject: [PATCH 12/15] Iterator grammar --- parser/src/grammar.pest | 5 +++++ test/src/main.mist | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 603f96d..fd5efbe 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -68,6 +68,7 @@ statement = _{ | if_stmt | while_stmt | c_for_stmt + | for_stmt | return_stmt | break_stmt | continue_stmt @@ -104,6 +105,10 @@ c_for_stmt = { "for" ~ "(" ~ statement ~ expr ~ semicolon ~ statement ~ ")" ~ statement } +for_stmt = { + "for" ~ "(" ~ identifier ~ "in" ~ expr ~ ")" ~ statement +} + // ================= EXPRESSIONS ================= tuple_type = { "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" } path_type = { static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? } diff --git a/test/src/main.mist b/test/src/main.mist index b739c17..ec6c405 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,5 +1,7 @@ void main() { - for (usize mut i = 0; i < 10; i = i + 1;) { + let iter = vec!(1, 2, 3, 4, 5); + + for (i in iter) { println!("{i}"); } } From b39d52d0760275de1feeae509b122faed41bfdb5 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 17:58:28 +0200 Subject: [PATCH 13/15] Iterator AST --- parser/src/ast.rs | 4 ++++ parser/src/lib.rs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 50579e4..e58eba5 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -112,6 +112,10 @@ pub enum Statement { update: Box, body: Box, }, + For { + pattern: String, + iterator: Expression, + }, Return(Option), Break, diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 9dc588c..485829d 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -340,6 +340,11 @@ impl From> for Statement { body: Box::new(Statement::from(inner.next().unwrap())), }, + Rule::for_stmt => Statement::For { + pattern: inner.next().unwrap().as_str().to_string(), + iterator: inner.next().unwrap().into(), + }, + Rule::assign_statement => Statement::VarAssign(VarAssignStmt { target: Expression::from(inner.next().unwrap()), value: Expression::from(inner.next().unwrap()), From 6aa851fcf91b19a234b301f2697e54d65e131c7a Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 18:02:50 +0200 Subject: [PATCH 14/15] iterator codegen --- parser/src/ast.rs | 1 + parser/src/lib.rs | 1 + src/codegen.rs | 9 +++++++++ test/src/main.mist | 2 +- 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index e58eba5..fb72ea9 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -115,6 +115,7 @@ pub enum Statement { For { pattern: String, iterator: Expression, + body: Box, }, Return(Option), diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 485829d..14c4e46 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -343,6 +343,7 @@ impl From> for Statement { Rule::for_stmt => Statement::For { pattern: inner.next().unwrap().as_str().to_string(), iterator: inner.next().unwrap().into(), + body: Box::new(Statement::from(inner.next().unwrap())), }, Rule::assign_statement => Statement::VarAssign(VarAssignStmt { diff --git a/src/codegen.rs b/src/codegen.rs index 58dbcfb..3440a77 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -417,6 +417,15 @@ impl ToRust for Statement { cg.add_indentedln("}"); } + Statement::For { + pattern, + iterator, + body, + } => { + cg.add_indentedln(&format!("for {} in {}", pattern, iterator.get_rust())); + cg.ensure_brackets(body); + } + Statement::Return(expr) => { let val = expr.as_ref().map(|e| e.get_rust()).unwrap_or_default(); cg.add_indentedln(&format!("return {};", val)); diff --git a/test/src/main.mist b/test/src/main.mist index ec6c405..d07cd7b 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,5 +1,5 @@ void main() { - let iter = vec!(1, 2, 3, 4, 5); + Vec iter = vec!(1, 2, 3, 4, 5); for (i in iter) { println!("{i}"); From a8b6ff478970e408e11b74c35a01791affc0ad3e Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 18:11:17 +0200 Subject: [PATCH 15/15] Var definition without type --- parser/src/grammar.pest | 3 ++- parser/src/lib.rs | 8 +++++++- test/src/main.mist | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index fd5efbe..56e45ad 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -15,7 +15,8 @@ static_path = { identifier ~ ("::" ~ identifier)* } export = { "public" } mutable = { "mut" } sharp = _{ "#" } -var_decl = { type_expr ~ mutable? ~ identifier } +var = { "var" } +var_decl = { (var | type_expr) ~ mutable? ~ identifier } semicolon = _{ ";" } // ================= TOP LEVEL ================= diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 14c4e46..ce1dd56 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -516,7 +516,13 @@ impl From> for VarDecl { Rule::var_decl => { let mut inner = pair.into_inner(); - let type_ = Some(inner.next().map(TypeExpr::from).unwrap()); + let type_ = inner.next().and_then(|pair| { + if pair.as_str().trim() == "var" { + None + } else { + Some(TypeExpr::from(pair)) + } + }); let mutable = if inner.peek().unwrap().as_rule() == Rule::mutable { inner.next(); true diff --git a/test/src/main.mist b/test/src/main.mist index d07cd7b..fe1d604 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,5 +1,5 @@ void main() { - Vec iter = vec!(1, 2, 3, 4, 5); + var iter = vec!(1, 2, 3, 4, 5); for (i in iter) { println!("{i}");