From 2ccec652daafc0d46eb157d4f31acbe98251c0e2 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 18:08:58 +0200 Subject: [PATCH 01/21] refactored import syntax --- parser/src/ast.rs | 2 +- parser/src/grammar.pest | 3 +-- parser/src/lib.rs | 2 +- src/codegen.rs | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 05bca76..88aa6d8 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -67,7 +67,7 @@ pub struct TopLevel(pub TopLevelKind, pub Vec); #[derive(Debug, Clone, Serialize)] pub enum TopLevelKind { ModAttribute, - Include(Path), + Import(Path), StructDecl { visibility: Visibility, name: String, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 9913b8c..311b5bc 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -14,7 +14,6 @@ static_path = { identifier ~ ("::" ~ identifier)* } export = { "public" } mutable = { "mut" } -sharp = _{ "#" } var = { "var" } var_decl = { (var | type_expr) ~ mutable? ~ identifier } semicolon = _{ ";" } @@ -58,7 +57,7 @@ meta_list = { attributes = { attribute* } -import = { sharp ~ "include" ~ "<" ~ static_path ~ ">" } +import = { "use" ~ "<" ~ static_path ~ ">" ~ semicolon } field_list = { field ~ ("," ~ field)* ~ ","? } field = { export? ~ type_expr ~ identifier } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index bb3f16d..b6dc717 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -229,7 +229,7 @@ impl From> for TopLevelKind { let mut inner = pair.clone().into_inner(); match rule { - Rule::import => TopLevelKind::Include(Path::from(inner.next().unwrap())), + Rule::import => TopLevelKind::Import(Path::from(inner.next().unwrap())), Rule::function_decl => TopLevelKind::FunctionDecl(FunctionDecl::from(pair)), diff --git a/src/codegen.rs b/src/codegen.rs index 6bfa172..1f4eab4 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -308,7 +308,7 @@ impl ToRust for TopLevelKind { fn to_rust(&self, cg: &mut RustCodegen) { match self { Self::ModAttribute => {} - Self::Include(path) => { + Self::Import(path) => { cg.addln(&format!("use {};", path.get_rust())); } Self::FunctionDecl(decl) => decl.to_rust(cg), From 27c6eb74c38fccb612e37f08e26b49561f3925f7 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 18:15:48 +0200 Subject: [PATCH 02/21] mod decl --- parser/src/ast.rs | 1 + parser/src/grammar.pest | 4 +++- parser/src/lib.rs | 2 ++ src/codegen.rs | 5 ++--- test/src/main.mist | 13 ++----------- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 88aa6d8..ca4ca2a 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -68,6 +68,7 @@ pub struct TopLevel(pub TopLevelKind, pub Vec); pub enum TopLevelKind { ModAttribute, Import(Path), + Mod(String), StructDecl { visibility: Visibility, name: String, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 311b5bc..8d0d291 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -37,7 +37,7 @@ class_decl = { // ================= TOP LEVEL ================= -top_level = { (attributes ~ (import | function_decl | struct_decl | class_decl)) | mod_attribute } +top_level = { (attributes ~ (import | function_decl | struct_decl | class_decl | mod_package)) | mod_attribute } attribute = { "#" ~ "[" ~ meta ~ "]" @@ -59,6 +59,8 @@ attributes = { attribute* } import = { "use" ~ "<" ~ static_path ~ ">" ~ semicolon } +mod_package = { "mod" ~ identifier ~ semicolon } + field_list = { field ~ ("," ~ field)* ~ ","? } field = { export? ~ type_expr ~ identifier } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index b6dc717..50f90e7 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -259,6 +259,8 @@ impl From> for TopLevelKind { methods: inner.into_iter().map(FunctionDecl::from).collect(), }, + Rule::mod_package => TopLevelKind::Mod(inner.next().unwrap().as_str().to_string()), + _ => unimplemented!("{rule:#?}"), } } diff --git a/src/codegen.rs b/src/codegen.rs index 1f4eab4..66f8ad0 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -308,9 +308,8 @@ impl ToRust for TopLevelKind { fn to_rust(&self, cg: &mut RustCodegen) { match self { Self::ModAttribute => {} - Self::Import(path) => { - cg.addln(&format!("use {};", path.get_rust())); - } + Self::Import(path) => cg.addln(&format!("use {};", path.get_rust())), + Self::Mod(id) => cg.addln(&format!("mod {};", id)), Self::FunctionDecl(decl) => decl.to_rust(cg), Self::StructDecl { visibility, diff --git a/test/src/main.mist b/test/src/main.mist index 811a162..30ef530 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,14 +1,5 @@ -class MyClass { - String message; - - public constructor(str* name) { - self.message = format!("Hello {}!", name); - } - - public void greet(self*) { - println!("{}", self.message); - } -} +mod my_class; +use ; void main() { var my_class = new MyClass("World"); From c6e34bbc7029a0255852f2570634428de1b9f1c8 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 18:17:35 +0200 Subject: [PATCH 03/21] mod decl --- test/src/my_class.mist | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 test/src/my_class.mist diff --git a/test/src/my_class.mist b/test/src/my_class.mist new file mode 100644 index 0000000..48a2c7b --- /dev/null +++ b/test/src/my_class.mist @@ -0,0 +1,11 @@ +class MyClass { + String message; + + public constructor(str* name) { + self.message = format!("Hello {}!", name); + } + + public void greet(self*) { + println!("{}", self.message); + } +} From a9fdfe4100a66a0b3273d6e3fcdb948eaa7bfb8d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 18:54:07 +0200 Subject: [PATCH 04/21] Identifier in ASt --- parser/src/ast.rs | 23 +++++++++++++---------- parser/src/lib.rs | 35 +++++++++++++++++++---------------- src/codegen.rs | 40 +++++++++++++++++++++++----------------- 3 files changed, 55 insertions(+), 43 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index ca4ca2a..fe5845b 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -1,7 +1,10 @@ use serde::Serialize; #[derive(Debug, Clone, Serialize)] -pub struct FieldList(pub Vec<(String, Visibility, TypeExpr)>); +pub struct Identifier(pub String); + +#[derive(Debug, Clone, Serialize)] +pub struct FieldList(pub Vec<(Identifier, Visibility, TypeExpr)>); #[derive(Debug, Clone, Serialize)] pub struct ParamList(pub Vec); @@ -44,7 +47,7 @@ pub enum TypeExprKind { pub struct TypeExpr(pub TypeExprKind, pub Vec); #[derive(Debug, Clone, Serialize)] -pub struct Path(pub Vec); +pub struct Path(pub Vec); #[derive(Debug, Clone, Serialize)] pub enum BinaryOp { @@ -68,16 +71,16 @@ pub struct TopLevel(pub TopLevelKind, pub Vec); pub enum TopLevelKind { ModAttribute, Import(Path), - Mod(String), + Mod(Identifier), StructDecl { visibility: Visibility, - name: String, + name: Identifier, fields: FieldList, }, FunctionDecl(FunctionDecl), ClassDecl { visibility: Visibility, - name: String, + name: Identifier, fields: Vec, constructor: ClassConstructor, methods: Vec, @@ -94,7 +97,7 @@ pub struct ClassConstructor { #[derive(Debug, Clone, Serialize)] pub struct FunctionDecl { pub visibility: Visibility, - pub name: String, + pub name: Identifier, pub params: ParamList, pub return_type: TypeExpr, pub body: Block, @@ -102,10 +105,10 @@ pub struct FunctionDecl { #[derive(Debug, Clone, Serialize)] pub enum Postfix { - FieldAccess(String), + FieldAccess(Identifier), Call(Vec), MacroCall(String), - StructCall(Vec<(String, Expression)>), + StructCall(Vec<(Identifier, Expression)>), Index(Expression), Binary(BinaryOp, Expression), } @@ -139,7 +142,7 @@ pub enum Statement { body: Box, }, For { - pattern: String, + pattern: Identifier, iterator: Expression, body: Box, }, @@ -152,7 +155,7 @@ pub enum Statement { #[derive(Debug, Clone, Serialize)] pub struct VarDecl { pub mutable: bool, - pub name: String, + pub name: Identifier, pub type_: Option, } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 50f90e7..8b3783a 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -84,7 +84,7 @@ impl From> for TypeExprKind { impl From> for Path { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { match pair.as_rule() { - Rule::static_path => Path(pair.into_inner().map(|i| i.as_str().to_string()).collect()), + Rule::static_path => Path(pair.into_inner().map(Identifier::from).collect()), _ => unimplemented!("{pair:#?}"), } } @@ -98,7 +98,7 @@ impl From> for FieldList { let mut param_inner = p.into_inner(); let visibility = Visibility::from(&mut param_inner); let param_type = TypeExpr::from(param_inner.next().unwrap()); - let param_name = param_inner.next().unwrap().as_str().to_string(); + let param_name = Identifier::from(param_inner.next().unwrap()); (param_name, visibility, param_type) }) .collect(); @@ -235,7 +235,7 @@ impl From> for TopLevelKind { Rule::struct_decl => { let visibility = Visibility::from(&mut inner); - let name = inner.next().unwrap().as_str().to_string(); + let name = Identifier::from(inner.next().unwrap()); let fields_pair = inner.next().unwrap(); let fields = FieldList::from(fields_pair); @@ -248,7 +248,7 @@ impl From> for TopLevelKind { Rule::class_decl => TopLevelKind::ClassDecl { visibility: Visibility::from(&mut inner), - name: inner.next().unwrap().as_str().to_string(), + name: Identifier::from(inner.next().unwrap()), fields: inner .next() .unwrap() @@ -259,7 +259,7 @@ impl From> for TopLevelKind { methods: inner.into_iter().map(FunctionDecl::from).collect(), }, - Rule::mod_package => TopLevelKind::Mod(inner.next().unwrap().as_str().to_string()), + Rule::mod_package => TopLevelKind::Mod(Identifier::from(inner.next().unwrap())), _ => unimplemented!("{rule:#?}"), } @@ -331,7 +331,7 @@ impl From> for Statement { }, Rule::for_stmt => Statement::For { - pattern: inner.next().unwrap().as_str().to_string(), + pattern: Identifier::from(inner.next().unwrap()), iterator: inner.next().unwrap().into(), body: Box::new(Statement::from(inner.next().unwrap())), }, @@ -419,10 +419,7 @@ impl From> for Postfix { match rule { Rule::postfix => Postfix::from(inner.next().unwrap()), - Rule::field_px => { - let field_name = inner.next().unwrap().as_str().to_string(); - Postfix::FieldAccess(field_name) - } + Rule::field_px => Postfix::FieldAccess(Identifier::from(inner.next().unwrap())), Rule::call_px => Postfix::Call(inner.map(Expression::from).collect()), @@ -431,7 +428,7 @@ impl From> for Postfix { .map(|p| { let mut pi = p.into_inner(); ( - pi.next().unwrap().as_str().to_string(), + Identifier::from(pi.next().unwrap()), Expression::from(pi.next().unwrap()), ) }) @@ -502,7 +499,7 @@ impl From> for VarDecl { }); let mutable = listen_rule(&mut inner, Rule::mutable); - let name = inner.next().unwrap().as_str().to_string(); + let name = Identifier::from(inner.next().unwrap()); VarDecl { mutable, @@ -524,10 +521,10 @@ impl From> for FunctionDecl { let return_type = TypeExpr::from(inner.next().unwrap()); - let name = inner.next().unwrap().as_str().to_string(); + let name = Identifier::from(inner.next().unwrap()); let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { let mut param_inner = param.into_inner(); - let name = format!("self"); + let name = Identifier(String::from("self")); let mutable = listen_rule(&mut param_inner, Rule::mutable); @@ -535,9 +532,9 @@ impl From> for FunctionDecl { VarDecl { mutable: mutable && !is_ref, - name, + name: name.clone(), type_: Some(TypeExpr( - TypeExprKind::Path(Path(vec![format!("Self")])), + TypeExprKind::Path(Path(vec![name])), if is_ref { vec![if mutable { TypePostfix::RefMut @@ -610,3 +607,9 @@ pub fn consume_rule<'a>( if consumed { pairs.next() } else { None } } + +impl From> for Identifier { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + Identifier(pair.as_str().to_string()) + } +} diff --git a/src/codegen.rs b/src/codegen.rs index 66f8ad0..14c9982 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,7 @@ use parser::ast::{ - Attribute, BinaryOp, Block, Expression, FunctionDecl, Literal, Path, Postfix, Prefix, - Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, - VarAssignStmt, VarDecl, VarDeclStmt, Visibility, + Attribute, BinaryOp, Block, Expression, FunctionDecl, Identifier, Literal, Path, Postfix, + Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, + TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- @@ -197,7 +197,7 @@ impl GetRust for Option<&Vec> { impl GetRust for Postfix { fn get_rust(&self) -> String { match self { - Postfix::FieldAccess(field) => format!(".{}", field), + Postfix::FieldAccess(field) => format!(".{}", field.get_rust()), Postfix::Call(args) => { let args = args @@ -215,7 +215,7 @@ impl GetRust for Postfix { Postfix::StructCall(fields) => { let fields = fields .iter() - .map(|(k, v)| format!("{}: {}", k, v.get_rust())) + .map(|(k, v)| format!("{}: {}", k.get_rust(), v.get_rust())) .collect::>() .join(", "); format!("{{ {} }}", fields) @@ -309,19 +309,19 @@ impl ToRust for TopLevelKind { match self { Self::ModAttribute => {} Self::Import(path) => cg.addln(&format!("use {};", path.get_rust())), - Self::Mod(id) => cg.addln(&format!("mod {};", id)), + Self::Mod(id) => cg.addln(&format!("mod {};", id.get_rust())), Self::FunctionDecl(decl) => decl.to_rust(cg), Self::StructDecl { visibility, name, fields, } => { - cg.addln(&format!("{}struct {} {{", visibility.get_rust(), name)); + cg.addln(&format!("{}struct {} {{", visibility.get_rust(), name.get_rust())); cg.indent += 1; for (field_name, _, ty) in &fields.0 { let ty = ty.get_rust(); - cg.add_indentedln(&format!("pub {}: {},", field_name, ty)); + cg.add_indentedln(&format!("pub {}: {},", field_name.get_rust(), ty)); } cg.indent -= 1; @@ -335,19 +335,19 @@ impl ToRust for TopLevelKind { methods, } => { // Struct decl - cg.addln(&format!("{}struct {} {{", visibility.get_rust(), name)); + cg.addln(&format!("{}struct {} {{", visibility.get_rust(), name.get_rust())); cg.indent += 1; for field in fields { let ty = field.decl.type_.clone().unwrap().get_rust(); - cg.add_indentedln(&format!("pub {}: {},", field.decl.name, ty)); + cg.add_indentedln(&format!("pub {}: {},", field.decl.name.get_rust(), ty)); } cg.indent -= 1; cg.addln("}\n"); // Constructor - cg.addln(&format!("impl {} {{", name)); + cg.addln(&format!("impl {} {{", name.get_rust())); cg.indent += 1; let params_str = constructor @@ -371,7 +371,7 @@ impl ToRust for TopLevelKind { if let Some(init) = &field.init { cg.add_indentedln(&format!( "this.{} = {};", - field.decl.name, + field.decl.name.get_rust(), init.get_rust() )); } @@ -383,7 +383,7 @@ impl ToRust for TopLevelKind { .params .0 .iter() - .map(|e| e.name.to_string()) + .map(|e| e.name.get_rust()) .collect::>() .join(", ") )); @@ -501,7 +501,7 @@ impl ToRust for Statement { iterator, body, } => { - cg.add_indentedln(&format!("for {} in {}", pattern, iterator.get_rust())); + cg.add_indentedln(&format!("for {} in {}", pattern.get_rust(), iterator.get_rust())); cg.ensure_brackets(body); } @@ -529,7 +529,7 @@ impl ToRust for FunctionDecl { cg.add_indentedln(&format!( "{}fn {}({}) -> {} {{", self.visibility.get_rust(), - self.name, + self.name.get_rust(), params_str, self.return_type.get_rust() )); @@ -550,13 +550,13 @@ impl GetRust for VarDecl { .map(|t| format!(": {}", t.get_rust())) .unwrap_or_default(); - format!("{}{}{}", mutability, self.name, ty) + format!("{}{}{}", mutability, self.name.get_rust(), ty) } } impl GetRust for Path { fn get_rust(&self) -> String { - self.0.join("::") + self.0.iter().map(Identifier::get_rust).collect::>().join("::") } } @@ -579,6 +579,12 @@ impl GetRust for Visibility { } } +impl GetRust for Identifier { + fn get_rust(&self) -> String { + self.0.clone() + } +} + pub fn get_static_type_path(path: &Path) -> String { let rust_path = path.get_rust(); From 5eeaf8c35d567c44850931aa6c8b2e15500f7f1e Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 20:59:15 +0200 Subject: [PATCH 05/21] Enum grammar --- parser/src/grammar.pest | 12 +++++++++++- test/src/my_class.mist | 6 ++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 8d0d291..f3a50a3 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -37,7 +37,17 @@ class_decl = { // ================= TOP LEVEL ================= -top_level = { (attributes ~ (import | function_decl | struct_decl | class_decl | mod_package)) | mod_attribute } +enum_named = { identifier } +enum_tuple = { identifier ~ tuple_type } +enum_struct = { identifier ~ "{" ~ field_list ~ "}" } + +enum_field = _{ enum_tuple | enum_struct | enum_named } + +enum_fields = _{ enum_field ~ ("," ~ enum_field)* ~ ","? } + +enum_decl = { export? ~ "enum" ~ identifier ~ "{" ~ enum_fields ~ "}" } + +top_level = { (attributes ~ (import | function_decl | struct_decl | enum_decl | class_decl | mod_package)) | mod_attribute } attribute = { "#" ~ "[" ~ meta ~ "]" diff --git a/test/src/my_class.mist b/test/src/my_class.mist index 48a2c7b..0c31846 100644 --- a/test/src/my_class.mist +++ b/test/src/my_class.mist @@ -9,3 +9,9 @@ class MyClass { println!("{}", self.message); } } + +enum MyEnum { + Named, + Tuple(i32, String), + Struct { i32 x } +} From 580c3297cb95b269ab2e0a41f0c796b90429ba48 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 21:02:01 +0200 Subject: [PATCH 06/21] Enum ast --- parser/src/ast.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index fe5845b..a21380d 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -72,6 +72,11 @@ pub enum TopLevelKind { ModAttribute, Import(Path), Mod(Identifier), + EnumDecl { + visibility: Visibility, + name: Identifier, + fields: Vec, + }, StructDecl { visibility: Visibility, name: Identifier, @@ -87,6 +92,13 @@ pub enum TopLevelKind { }, } +#[derive(Debug, Clone, Serialize)] +pub enum EnumItem { + Named(Identifier), + Tuple(Identifier, Vec), + Struct(Identifier, FieldList), +} + #[derive(Debug, Clone, Serialize)] pub struct ClassConstructor { pub visibility: Visibility, From 3342893aabd149419d2593afcbad472e8d45bf40 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 21:10:27 +0200 Subject: [PATCH 07/21] Enum codegen --- src/codegen.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 6 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 14c9982..ed12620 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,6 +1,6 @@ use parser::ast::{ - Attribute, BinaryOp, Block, Expression, FunctionDecl, Identifier, Literal, Path, Postfix, - Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, + Attribute, BinaryOp, Block, EnumItem, Expression, FunctionDecl, Identifier, Literal, Path, + Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, }; @@ -311,12 +311,35 @@ impl ToRust for TopLevelKind { Self::Import(path) => cg.addln(&format!("use {};", path.get_rust())), Self::Mod(id) => cg.addln(&format!("mod {};", id.get_rust())), Self::FunctionDecl(decl) => decl.to_rust(cg), + Self::EnumDecl { + visibility, + name, + fields, + } => { + cg.addln(&format!( + "{}struct {} {{", + visibility.get_rust(), + name.get_rust() + )); + cg.indent += 1; + + for field in fields { + cg.add_indentedln(&(format!("{}", field.get_rust()) + ",")); + } + + cg.indent -= 1; + cg.addln("}\n"); + } Self::StructDecl { visibility, name, fields, } => { - cg.addln(&format!("{}struct {} {{", visibility.get_rust(), name.get_rust())); + cg.addln(&format!( + "{}struct {} {{", + visibility.get_rust(), + name.get_rust() + )); cg.indent += 1; for (field_name, _, ty) in &fields.0 { @@ -335,7 +358,11 @@ impl ToRust for TopLevelKind { methods, } => { // Struct decl - cg.addln(&format!("{}struct {} {{", visibility.get_rust(), name.get_rust())); + cg.addln(&format!( + "{}struct {} {{", + visibility.get_rust(), + name.get_rust() + )); cg.indent += 1; for field in fields { @@ -501,7 +528,11 @@ impl ToRust for Statement { iterator, body, } => { - cg.add_indentedln(&format!("for {} in {}", pattern.get_rust(), iterator.get_rust())); + cg.add_indentedln(&format!( + "for {} in {}", + pattern.get_rust(), + iterator.get_rust() + )); cg.ensure_brackets(body); } @@ -556,7 +587,11 @@ impl GetRust for VarDecl { impl GetRust for Path { fn get_rust(&self) -> String { - self.0.iter().map(Identifier::get_rust).collect::>().join("::") + self.0 + .iter() + .map(Identifier::get_rust) + .collect::>() + .join("::") } } @@ -585,6 +620,30 @@ impl GetRust for Identifier { } } +impl GetRust for EnumItem { + fn get_rust(&self) -> String { + match self { + Self::Named(id) => id.get_rust(), + Self::Struct(id, s) => format!( + "{} {{{}}}", + id.get_rust(), + s.0.iter() + .map(|(id, _, ty)| format!("{}: {}", id.get_rust(), ty.get_rust())) + .collect::>() + .join(", ") + ), + Self::Tuple(id, t) => format!( + "{} ({})", + id.get_rust(), + t.iter() + .map(TypeExpr::get_rust) + .collect::>() + .join(", ") + ), + } + } +} + pub fn get_static_type_path(path: &Path) -> String { let rust_path = path.get_rust(); From 81061f26a56acb5aea6e466a2d6c08a886ec4eac Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 21:21:41 +0200 Subject: [PATCH 08/21] Enum astgen --- parser/src/lib.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 8b3783a..5d67068 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -259,6 +259,12 @@ impl From> for TopLevelKind { methods: inner.into_iter().map(FunctionDecl::from).collect(), }, + Rule::enum_decl => TopLevelKind::EnumDecl { + visibility: Visibility::from(&mut inner), + name: Identifier::from(inner.next().unwrap()), + fields: inner.map(EnumItem::from).collect(), + }, + Rule::mod_package => TopLevelKind::Mod(Identifier::from(inner.next().unwrap())), _ => unimplemented!("{rule:#?}"), @@ -266,6 +272,34 @@ impl From> for TopLevelKind { } } +impl From> for EnumItem { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); + + match rule { + Rule::enum_named => EnumItem::Named(Identifier::from(inner.next().unwrap())), + + Rule::enum_tuple => EnumItem::Tuple( + Identifier::from(inner.next().unwrap()), + inner + .next() + .unwrap() + .into_inner() + .map(TypeExpr::from) + .collect(), + ), + + Rule::enum_struct => EnumItem::Struct( + Identifier::from(inner.next().unwrap()), + FieldList::from(inner.next().unwrap()), + ), + + _ => unimplemented!("{rule:#?}"), + } + } +} + impl From> for Block { fn from(pair: pest::iterators::Pair) -> Self { let statements = pair From cba78c2ac91e057e459092cba49c7b15f7a567d9 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 21:22:31 +0200 Subject: [PATCH 09/21] Fix enum codegen --- src/codegen.rs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index ed12620..08bca86 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -311,25 +311,6 @@ impl ToRust for TopLevelKind { Self::Import(path) => cg.addln(&format!("use {};", path.get_rust())), Self::Mod(id) => cg.addln(&format!("mod {};", id.get_rust())), Self::FunctionDecl(decl) => decl.to_rust(cg), - Self::EnumDecl { - visibility, - name, - fields, - } => { - cg.addln(&format!( - "{}struct {} {{", - visibility.get_rust(), - name.get_rust() - )); - cg.indent += 1; - - for field in fields { - cg.add_indentedln(&(format!("{}", field.get_rust()) + ",")); - } - - cg.indent -= 1; - cg.addln("}\n"); - } Self::StructDecl { visibility, name, @@ -350,6 +331,25 @@ impl ToRust for TopLevelKind { cg.indent -= 1; cg.addln("}\n"); } + Self::EnumDecl { + visibility, + name, + fields, + } => { + cg.addln(&format!( + "{}enum {} {{", + visibility.get_rust(), + name.get_rust() + )); + cg.indent += 1; + + for field in fields { + cg.add_indentedln(&(format!("{}", field.get_rust()) + ",")); + } + + cg.indent -= 1; + cg.addln("}\n"); + } Self::ClassDecl { visibility, name, From c51ff01ce83a1519cf1632fc872934ac5b8efb02 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:01:12 +0200 Subject: [PATCH 10/21] pattern grammar and ast --- parser/src/ast.rs | 8 ++++++++ parser/src/grammar.pest | 7 ++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index a21380d..2e0ed0c 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -92,6 +92,14 @@ pub enum TopLevelKind { }, } +#[derive(Debug, Clone, Serialize)] +pub enum Pattern { + Tuple(Path, Vec), + Struct(Path, Vec), + Path(Path), + Id(Identifier), +} + #[derive(Debug, Clone, Serialize)] pub enum EnumItem { Named(Identifier), diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index f3a50a3..5dc2706 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -12,10 +12,15 @@ string_lit = { "\"" ~ inner_str ~ "\"" } inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* } static_path = { identifier ~ ("::" ~ identifier)* } +// pattern +tuple_pattern = { static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } +struct_pattern = { static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" } +pattern = _{ tuple_pattern | struct_pattern | identifier } + export = { "public" } mutable = { "mut" } var = { "var" } -var_decl = { (var | type_expr) ~ mutable? ~ identifier } +var_decl = { (var | type_expr) ~ mutable? ~ pattern } semicolon = _{ ";" } // ================= CLASS ================= From a6fb70eebf7557f46fa2951589a323bfbc76baa0 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:10:26 +0200 Subject: [PATCH 11/21] Pattern AST and grammar --- parser/src/ast.rs | 3 ++- parser/src/grammar.pest | 7 ++++--- parser/src/lib.rs | 27 +++++++++++++++++++++++++++ test/src/main.mist | 3 ++- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 2e0ed0c..1750a25 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -94,8 +94,9 @@ pub enum TopLevelKind { #[derive(Debug, Clone, Serialize)] pub enum Pattern { - Tuple(Path, Vec), + NamedTuple(Path, Vec), Struct(Path, Vec), + Tuple(Vec), Path(Path), Id(Identifier), } diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 5dc2706..54c3d4b 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -13,9 +13,10 @@ inner_str = @{ (!"\"" ~ ("\\\"" | ANY))* } static_path = { identifier ~ ("::" ~ identifier)* } // pattern -tuple_pattern = { static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } -struct_pattern = { static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" } -pattern = _{ tuple_pattern | struct_pattern | identifier } +tuple_pattern = { "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } +named_tuple_pattern = { static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } +struct_pattern = { static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" } +pattern = _{ named_tuple_pattern | tuple_pattern | struct_pattern | identifier } export = { "public" } mutable = { "mut" } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 5d67068..d24ddcc 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -518,6 +518,33 @@ impl From> for VarDeclStmt { } } +impl From> for Pattern { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + let mut inner = pair.into_inner(); + + match rule { + Rule::tuple_pattern => Pattern::Tuple(inner.map(Identifier::from).collect()), + + Rule::named_tuple_pattern => Pattern::NamedTuple( + Path::from(inner.next().unwrap()), + inner.map(Identifier::from).collect(), + ), + + Rule::struct_pattern => Pattern::Struct( + Path::from(inner.next().unwrap()), + inner.map(Identifier::from).collect(), + ), + + Rule::identifier => Pattern::Id(Identifier::from(inner.next().unwrap())), + + Rule::static_path => Pattern::Path(Path::from(inner.next().unwrap())), + + _ => unimplemented!("{rule:?}"), + } + } +} + impl From> for VarDecl { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { match pair.as_rule() { diff --git a/test/src/main.mist b/test/src/main.mist index 30ef530..59a3194 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -4,5 +4,6 @@ use ; void main() { var my_class = new MyClass("World"); my_class.greet(); - var x = 1 + 2 + 3; + + var (x, y) = (10, 20); } From dc49cddc20a93ad61fdf064e158327c8ac4d91a6 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:25:35 +0200 Subject: [PATCH 12/21] Patterns --- parser/src/ast.rs | 2 +- parser/src/lib.rs | 12 ++++++------ src/codegen.rs | 38 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 1750a25..a3dbd6f 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -176,7 +176,7 @@ pub enum Statement { #[derive(Debug, Clone, Serialize)] pub struct VarDecl { pub mutable: bool, - pub name: Identifier, + pub name: Pattern, pub type_: Option, } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index d24ddcc..af8d95e 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -521,7 +521,7 @@ impl From> for VarDeclStmt { impl From> for Pattern { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); - let mut inner = pair.into_inner(); + let mut inner = pair.clone().into_inner(); match rule { Rule::tuple_pattern => Pattern::Tuple(inner.map(Identifier::from).collect()), @@ -536,9 +536,9 @@ impl From> for Pattern { inner.map(Identifier::from).collect(), ), - Rule::identifier => Pattern::Id(Identifier::from(inner.next().unwrap())), + Rule::identifier => Pattern::Id(Identifier::from(pair)), - Rule::static_path => Pattern::Path(Path::from(inner.next().unwrap())), + Rule::static_path => Pattern::Path(Path::from(pair)), _ => unimplemented!("{rule:?}"), } @@ -560,7 +560,7 @@ impl From> for VarDecl { }); let mutable = listen_rule(&mut inner, Rule::mutable); - let name = Identifier::from(inner.next().unwrap()); + let name = Pattern::from(inner.next().unwrap()); VarDecl { mutable, @@ -585,7 +585,7 @@ impl From> for FunctionDecl { let name = Identifier::from(inner.next().unwrap()); let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { let mut param_inner = param.into_inner(); - let name = Identifier(String::from("self")); + let name = Pattern::Id(Identifier(String::from("self"))); let mutable = listen_rule(&mut param_inner, Rule::mutable); @@ -595,7 +595,7 @@ impl From> for FunctionDecl { mutable: mutable && !is_ref, name: name.clone(), type_: Some(TypeExpr( - TypeExprKind::Path(Path(vec![name])), + TypeExprKind::Path(Path(vec![Identifier("Self".to_string())])), if is_ref { vec![if mutable { TypePostfix::RefMut diff --git a/src/codegen.rs b/src/codegen.rs index 08bca86..e57ec97 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,7 @@ use parser::ast::{ Attribute, BinaryOp, Block, EnumItem, Expression, FunctionDecl, Identifier, Literal, Path, - Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, TypeExprKind, - TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, + Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, + TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- @@ -644,6 +644,40 @@ impl GetRust for EnumItem { } } +impl GetRust for Pattern { + fn get_rust(&self) -> String { + match self { + Self::Id(id) => id.get_rust(), + Self::Path(path) => path.get_rust(), + Self::Struct(path, ids) => format!( + "{} {{{}}}", + path.get_rust(), + ids.iter() + .map(Identifier::get_rust) + .collect::>() + .join(", ") + ), + Self::Tuple(ids) => format!( + "({})", + ids.iter() + .map(Identifier::get_rust) + .collect::>() + .join(", ") + ), + Self::NamedTuple(path, ids) => { + format!( + "{} ({})", + path.get_rust(), + ids.iter() + .map(Identifier::get_rust) + .collect::>() + .join(", ") + ) + } + } + } +} + pub fn get_static_type_path(path: &Path) -> String { let rust_path = path.get_rust(); From f98b9d7514b618ef31e104b218a8a4d54a9a4794 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:32:53 +0200 Subject: [PATCH 13/21] match grammar --- parser/src/grammar.pest | 7 +++++++ test/src/main.mist | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 54c3d4b..e3e9c2d 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -98,6 +98,7 @@ statement_list = { statement* } statement = _{ expr_stmt + | match_stmt | var_decl_statement | assign_statement | if_stmt @@ -144,6 +145,12 @@ for_stmt = { "for" ~ "(" ~ identifier ~ "in" ~ expr ~ ")" ~ statement } +match_item = { pattern ~ "=>" ~ block } + +match_stmt = { + "match" ~ "(" ~ expr ~ ")" ~ match_item* +} + // ================= 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 59a3194..43b0343 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -1,9 +1,10 @@ mod my_class; use ; +use ; void main() { var my_class = new MyClass("World"); my_class.greet(); - var (x, y) = (10, 20); + match (MyEnum::Tuple(10)) {} } From aa5640175f31191415f514bf88f10c1866ddc709 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:35:19 +0200 Subject: [PATCH 14/21] match ast --- parser/src/ast.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index a3dbd6f..c20da68 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -167,6 +167,7 @@ pub enum Statement { iterator: Expression, body: Box, }, + Match(Expression, Vec<(Pattern, Block)>), Return(Option), Break, From 2d56cf121246d06e6be71e4c955fe2a2d364311e Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:39:38 +0200 Subject: [PATCH 15/21] match codegen --- src/codegen.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/codegen.rs b/src/codegen.rs index e57ec97..48a079b 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -472,6 +472,23 @@ impl ToRust for Statement { cg.add_indentedln(&format!("{} = {};", target.get_rust(), value.get_rust(),)); } + Statement::Match(expr, match_items) => { + cg.add_indentedln(&format!("match {} {{", expr.get_rust())); + cg.indent += 1; + + for itm in match_items { + cg.add_indentedln(&format!("{} =>", itm.0.get_rust())); + cg.add_indentedln("{"); + cg.indent += 1; + itm.1.to_rust(cg); + cg.indent -= 1; + cg.add_indentedln("}"); + } + + cg.indent -= 1; + cg.add_indentedln("}"); + } + Statement::If { initial, else_if, From 6f6c32b6463d516dfd50b5fee780222a496f6330 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:44:54 +0200 Subject: [PATCH 16/21] match astgen --- parser/src/lib.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/parser/src/lib.rs b/parser/src/lib.rs index af8d95e..fbec5d8 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -375,6 +375,19 @@ impl From> for Statement { value: Expression::from(inner.next().unwrap()), }), + Rule::match_stmt => Statement::Match( + Expression::from(inner.next().unwrap()), + inner + .map(|match_itms| { + let mut match_inner = match_itms.into_inner(); + ( + Pattern::from(match_inner.next().unwrap()), + Block::from(match_inner.next().unwrap()), + ) + }) + .collect(), + ), + _ => unimplemented!("{rule:#?}"), } } From 60bc1d2510cb121b0b1679ce69eda29b47f9a405 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:49:49 +0200 Subject: [PATCH 17/21] Fix match --- parser/src/grammar.pest | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index e3e9c2d..ff0efb5 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -148,7 +148,7 @@ for_stmt = { match_item = { pattern ~ "=>" ~ block } match_stmt = { - "match" ~ "(" ~ expr ~ ")" ~ match_item* + "match" ~ "(" ~ expr ~ ")" ~ "{" ~ match_item* ~ "}" } // ================= EXPRESSIONS ================= From 093c281ea93ef4bfa4b6975f6b6129713ee0dbd7 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 22:53:59 +0200 Subject: [PATCH 18/21] Working match --- test/src/main.mist | 7 ++++++- test/src/my_class.mist | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/test/src/main.mist b/test/src/main.mist index 43b0343..13cc58e 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -6,5 +6,10 @@ void main() { var my_class = new MyClass("World"); my_class.greet(); - match (MyEnum::Tuple(10)) {} + match (MyEnum::Tuple(10, String::new())) { + MyEnum::Tuple(i, _) => { + println!("{i}"); + } + _ => {} + } } diff --git a/test/src/my_class.mist b/test/src/my_class.mist index 0c31846..7927688 100644 --- a/test/src/my_class.mist +++ b/test/src/my_class.mist @@ -10,7 +10,7 @@ class MyClass { } } -enum MyEnum { +public enum MyEnum { Named, Tuple(i32, String), Struct { i32 x } From bd066e05d1bedacefeecabce7aa7add2faa3bd91 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 23:00:20 +0200 Subject: [PATCH 19/21] Fix class --- parser/src/grammar.pest | 2 +- test/src/my_class.mist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index ff0efb5..ec4edac 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -38,7 +38,7 @@ method = { } class_decl = { - "class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" + export? ~ "class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" } // ================= TOP LEVEL ================= diff --git a/test/src/my_class.mist b/test/src/my_class.mist index 7927688..7cc321d 100644 --- a/test/src/my_class.mist +++ b/test/src/my_class.mist @@ -1,4 +1,4 @@ -class MyClass { +public class MyClass { String message; public constructor(str* name) { From c7ada7202928aad4ccabc01cedd4ca5544691180 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 23:33:27 +0200 Subject: [PATCH 20/21] Match patterns --- parser/src/ast.rs | 1 + parser/src/grammar.pest | 10 +++++++--- parser/src/lib.rs | 7 ++++--- src/codegen.rs | 1 + test/src/main.mist | 3 +++ 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index c20da68..70c3516 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -97,6 +97,7 @@ pub enum Pattern { NamedTuple(Path, Vec), Struct(Path, Vec), Tuple(Vec), + Literal(Literal), Path(Path), Id(Identifier), } diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index ec4edac..4e67169 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -16,7 +16,7 @@ static_path = { identifier ~ ("::" ~ identifier)* } tuple_pattern = { "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } named_tuple_pattern = { static_path ~ "(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")" } struct_pattern = { static_path ~ "{" ~ (identifier ~ ("," ~ identifier)*)? ~ "}" } -pattern = _{ named_tuple_pattern | tuple_pattern | struct_pattern | identifier } +pattern = _{ named_tuple_pattern | tuple_pattern | struct_pattern | literal | static_path } export = { "public" } mutable = { "mut" } @@ -64,7 +64,7 @@ mod_attribute = { } meta = { - static_path ~ ("=" ~ primary | "(" ~ meta_list? ~ ")")? + static_path ~ ("=" ~ literal | "(" ~ meta_list? ~ ")")? } meta_list = { @@ -164,11 +164,15 @@ macro_inner_v = { tuple = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } -primary = { +literal = { float | integer | boolean | string_lit +} + +primary = { + literal | static_path | tuple } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index fbec5d8..e7f87f0 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -400,6 +400,7 @@ impl From> for Literal { match rule { Rule::primary => Self::from(inner.next().unwrap()), + Rule::literal => Self::from(inner.next().unwrap()), Rule::integer => Literal::Int(pair.as_str().parse::().unwrap()), Rule::float => Literal::Float(pair.as_str().parse::().unwrap()), Rule::boolean => Literal::Bool(pair.as_str().parse::().unwrap()), @@ -436,9 +437,7 @@ impl From> for Expression { } Rule::primary => Expression::from(inner.next().unwrap()), Rule::static_path => Expression::Path(Path::from(pair)), - Rule::integer | Rule::float | Rule::boolean | Rule::string_lit | Rule::tuple => { - Expression::Literal(Literal::from(pair)) - } + Rule::literal => Expression::Literal(Literal::from(pair)), _ => unimplemented!("{rule:#?}"), } } @@ -549,6 +548,8 @@ impl From> for Pattern { inner.map(Identifier::from).collect(), ), + Rule::literal => Pattern::Literal(Literal::from(pair)), + Rule::identifier => Pattern::Id(Identifier::from(pair)), Rule::static_path => Pattern::Path(Path::from(pair)), diff --git a/src/codegen.rs b/src/codegen.rs index 48a079b..70d2836 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -666,6 +666,7 @@ impl GetRust for Pattern { match self { Self::Id(id) => id.get_rust(), Self::Path(path) => path.get_rust(), + Self::Literal(lit) => lit.get_rust(), Self::Struct(path, ids) => format!( "{} {{{}}}", path.get_rust(), diff --git a/test/src/main.mist b/test/src/main.mist index 13cc58e..602dd59 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -9,6 +9,9 @@ void main() { match (MyEnum::Tuple(10, String::new())) { MyEnum::Tuple(i, _) => { println!("{i}"); + } + MyEnum::Named => { + } _ => {} } From 8b409f4ccf9bb5b6ba8f5dc2ce4e625fa5f3335b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 7 May 2026 23:43:22 +0200 Subject: [PATCH 21/21] Improved for loop --- parser/src/ast.rs | 3 ++- parser/src/grammar.pest | 2 +- parser/src/lib.rs | 3 ++- src/codegen.rs | 17 +++++++++++++---- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 70c3516..7ff1df8 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -164,7 +164,8 @@ pub enum Statement { body: Box, }, For { - pattern: Identifier, + mutable: bool, + pattern: Pattern, iterator: Expression, body: Box, }, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 4e67169..7c207f5 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -142,7 +142,7 @@ c_for_stmt = { } for_stmt = { - "for" ~ "(" ~ identifier ~ "in" ~ expr ~ ")" ~ statement + "for" ~ "(" ~ mutable? ~ pattern ~ "in" ~ expr ~ ")" ~ statement } match_item = { pattern ~ "=>" ~ block } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e7f87f0..636223a 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -365,7 +365,8 @@ impl From> for Statement { }, Rule::for_stmt => Statement::For { - pattern: Identifier::from(inner.next().unwrap()), + mutable: listen_rule(&mut inner, Rule::mutable), + pattern: Pattern::from(inner.next().unwrap()), iterator: inner.next().unwrap().into(), body: Box::new(Statement::from(inner.next().unwrap())), }, diff --git a/src/codegen.rs b/src/codegen.rs index 70d2836..6558d35 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -541,12 +541,14 @@ impl ToRust for Statement { } Statement::For { + mutable, pattern, iterator, body, } => { cg.add_indentedln(&format!( - "for {} in {}", + "for {}{} in {}", + get_mutable(*mutable), pattern.get_rust(), iterator.get_rust() )); @@ -590,15 +592,18 @@ impl ToRust for FunctionDecl { impl GetRust for VarDecl { fn get_rust(&self) -> String { - let mutability = if self.mutable { "mut " } else { "" }; - let ty = self .type_ .as_ref() .map(|t| format!(": {}", t.get_rust())) .unwrap_or_default(); - format!("{}{}{}", mutability, self.name.get_rust(), ty) + format!( + "{}{}{}", + get_mutable(self.mutable), + self.name.get_rust(), + ty + ) } } @@ -709,3 +714,7 @@ pub fn get_static_type_path(path: &Path) -> String { pub fn get_type_postfixes(postfixes: &[TypePostfix]) -> String { postfixes.iter().map(TypePostfix::get_rust).collect() } + +pub fn get_mutable(mutable: bool) -> String { + if mutable { "mut " } else { "" }.to_string() +}