From 2fb38b6974e2cb1ab68b4e950fe0e1966554189f Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 16:38:13 +0200 Subject: [PATCH 01/11] Class fields --- parser/src/ast.rs | 15 ++++++++++++++- parser/src/grammar.pest | 7 +++++-- parser/src/lib.rs | 42 ++++++++++++++++++++++++++++++++++++++++- src/codegen.rs | 2 +- 4 files changed, 61 insertions(+), 5 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index db081d9..7e64561 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -94,7 +94,7 @@ pub enum TopLevelKind { visibility: Visibility, name: Identifier, generics: Generics, - fields: Vec, + fields: Vec, constructor: ClassConstructor, methods: Vec, }, @@ -208,6 +208,19 @@ pub struct VarDeclStmt { 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 VarAssignStmt { pub target: Expression, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 5c6e8f7..7d99a5d 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -149,7 +149,6 @@ attributes = { // ====================================================== // DECLARATION HELPERS // ====================================================== - var_decl = { (var | type_expr) ~ mutable? ~ pattern } @@ -225,7 +224,11 @@ class_constructor = { } class_fields = { - var_decl_statement* + class_field* +} + +class_field = { + field ~ ("=" ~ expr)? ~ semicolon } self_param = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index e17057c..85645db 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -300,7 +300,7 @@ impl From> for TopLevelKind { .next() .unwrap() .into_inner() - .map(VarDeclStmt::from) + .map(FieldDeclStmt::from) .collect(), constructor: ClassConstructor::from(inner.next().unwrap()), methods: inner.into_iter().map(FunctionDecl::from).collect(), @@ -583,6 +583,24 @@ impl From> for VarDeclStmt { } } +impl From> for FieldDeclStmt { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::class_field => { + let mut inner = pair.into_inner(); + + let decl = FieldDecl::from(inner.next().unwrap()); + + let init = inner.next().map(Expression::from); + + FieldDeclStmt { decl, init } + } + + _ => unimplemented!(), + } + } +} + impl From> for Pattern { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); @@ -641,6 +659,28 @@ impl From> for VarDecl { } } +impl From> for FieldDecl { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + match pair.as_rule() { + Rule::field => { + let mut inner = pair.into_inner(); + + let visibility = Visibility::from(&mut inner); + let type_ = TypeExpr::from(inner.next().unwrap()); + let name = Identifier::from(inner.next().unwrap()); + + FieldDecl { + visibility, + type_, + name, + } + } + + _ => unimplemented!("{:?}", pair.as_rule()), + } + } +} + impl From> for FunctionDecl { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let mut inner = pair.into_inner(); diff --git a/src/codegen.rs b/src/codegen.rs index 437a99f..dffe6db 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -375,7 +375,7 @@ impl ToRust for TopLevelKind { cg.indent += 1; for field in fields { - let ty = field.decl.type_.clone().unwrap().get_rust(); + let ty = field.decl.type_.clone().get_rust(); cg.add_indentedln(&format!("pub {}: {},", field.decl.name.get_rust(), ty)); } From dfa5487031836e8d028cd0876c5c6fcc5a575033 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 16:45:07 +0200 Subject: [PATCH 02/11] Refactored fields --- parser/src/ast.rs | 7 ++----- parser/src/lib.rs | 27 ++++++++------------------- src/codegen.rs | 30 ++++++++++++++++++++---------- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 7e64561..e6f4106 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -3,9 +3,6 @@ use serde::Serialize; #[derive(Debug, Clone, Serialize)] pub struct Identifier(pub String); -#[derive(Debug, Clone, Serialize, Default)] -pub struct FieldList(pub Vec<(Identifier, Visibility, TypeExpr)>); - #[derive(Debug, Clone, Serialize, Default)] pub struct ParamList(pub Vec); @@ -87,7 +84,7 @@ pub enum TopLevelKind { visibility: Visibility, generics: Generics, name: Identifier, - fields: FieldList, + fields: Vec, }, FunctionDecl(FunctionDecl), ClassDecl { @@ -123,7 +120,7 @@ pub enum Pattern { pub enum EnumItem { Named(Identifier), Tuple(Identifier, Vec), - Struct(Identifier, FieldList), + Struct(Identifier, Vec), } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 85645db..eb8e90c 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -107,23 +107,6 @@ impl From> for Path { } } -impl From> for FieldList { - fn from(pair: pest::iterators::Pair) -> Self { - let params = pair - .into_inner() - .map(|p| { - 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 = Identifier::from(param_inner.next().unwrap()); - (param_name, visibility, param_type) - }) - .collect(); - - FieldList(params) - } -} - impl From> for ParamList { fn from(pair: pest::iterators::Pair) -> Self { ParamList(pair.into_inner().map(VarDecl::from).collect()) @@ -287,7 +270,10 @@ impl From> for TopLevelKind { generics: consume_rule(&mut inner, Rule::generics) .map(Generics::from) .unwrap_or_default(), - fields: inner.next().map(FieldList::from).unwrap_or_default(), + fields: inner + .next() + .map(|pair| pair.into_inner().map(FieldDecl::from).collect()) + .unwrap_or_default(), }, Rule::class_decl => TopLevelKind::ClassDecl { @@ -342,7 +328,10 @@ impl From> for EnumItem { Rule::enum_struct => EnumItem::Struct( Identifier::from(inner.next().unwrap()), - FieldList::from(inner.next().unwrap()), + inner + .next() + .map(|pair| pair.into_inner().map(FieldDecl::from).collect()) + .unwrap_or_default(), ), _ => unimplemented!("{rule:#?}"), diff --git a/src/codegen.rs b/src/codegen.rs index dffe6db..edc9fc6 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,8 @@ use parser::ast::{ - Attribute, BinaryOp, Block, EnumItem, Expression, FunctionDecl, Generic, Generics, Identifier, - Literal, Path, Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, - TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, + Attribute, BinaryOp, Block, EnumItem, Expression, FieldDecl, FunctionDecl, Generic, Generics, + Identifier, Literal, Path, Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, + TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, + Visibility, }; // --------------------------------------------------------------------------- @@ -328,9 +329,8 @@ impl ToRust for TopLevelKind { )); cg.indent += 1; - for (field_name, _, ty) in &fields.0 { - let ty = ty.get_rust(); - cg.add_indentedln(&format!("pub {}: {},", field_name.get_rust(), ty)); + for field in fields { + cg.add_indentedln(&field.get_rust()); } cg.indent -= 1; @@ -375,8 +375,7 @@ impl ToRust for TopLevelKind { cg.indent += 1; for field in fields { - let ty = field.decl.type_.clone().get_rust(); - cg.add_indentedln(&format!("pub {}: {},", field.decl.name.get_rust(), ty)); + cg.add_indentedln(&field.decl.get_rust()); } cg.indent -= 1; @@ -677,8 +676,8 @@ impl GetRust for EnumItem { Self::Struct(id, s) => format!( "{} {{{}}}", id.get_rust(), - s.0.iter() - .map(|(id, _, ty)| format!("{}: {}", id.get_rust(), ty.get_rust())) + s.iter() + .map(|field| format!("{}: {}", field.name.get_rust(), field.type_.get_rust())) .collect::>() .join(", ") ), @@ -769,6 +768,17 @@ impl GetRust for (bool, &Generic) { } } +impl GetRust for FieldDecl { + fn get_rust(&self) -> String { + format!( + "{}{}: {},", + self.visibility.get_rust(), + self.name.get_rust(), + self.type_.get_rust() + ) + } +} + pub fn get_static_type_path(path: &Path) -> String { let rust_path = path.get_rust(); From 22b1b377f3f73b02a6b83af8776d668dd5ce57f1 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 16:59:21 +0200 Subject: [PATCH 03/11] Impl grammar --- mist-test/src/logger.mist | 20 ++++++++++++++++++++ parser/src/grammar.pest | 20 ++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index 94c4b4a..2b567eb 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -1,9 +1,29 @@ +use ; + public enum LogLevel { Info, Warning, Error, } +impl fmt::Display for LogLevel { + std::fmt::Result fmt(self*, std::fmt::Formatter<'_> mut* f) { + match (self) { + LogLevel::Info => { + write!(f, "[INFO]"); + } + + LogLevel::Warning => { + write!(f, "[WARN]"); + } + + LogLevel::Error => { + write!(f, "[ERROR]"); + } + } + } +} + public class Logger { String prefix; diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 7d99a5d..afc0ea4 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -239,8 +239,24 @@ method = { export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ block } +class_item = _{ + impl_decl + | method +} + class_decl = { - export? ~ "class" ~ identifier ~ generics? ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" + export? ~ "class" ~ identifier ~ generics? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}" +} + +// ====================================================== +// IMPL +// ====================================================== +impl_for_decl = { + "impl" ~ generics? ~ type_expr ~ "for" ~ type_expr ~ "{" ~ method* ~ "}" +} + +impl_decl = { + "impl" ~ generics? ~ type_expr ~ "{" ~ method* ~ "}" } // ====================================================== @@ -256,7 +272,7 @@ function_decl = { // ====================================================== top_level = { - (attributes ~ (import | function_decl | struct_decl | enum_decl | class_decl | mod_package)) + (attributes ~ (import | impl_for_decl | impl_decl | function_decl | struct_decl | enum_decl | class_decl | mod_package)) | mod_attribute } From 81d0286226ff50add8d191b2e1033722f2be0cb3 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 17:08:58 +0200 Subject: [PATCH 04/11] AST and codegen --- parser/src/ast.rs | 9 +++++++++ src/codegen.rs | 34 +++++++++++++++++++++++++++++++--- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index e6f4106..eed2c93 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -74,6 +74,7 @@ pub enum TopLevelKind { ModAttribute, Import(Path), Mod(Identifier), + ImplDecl(ImplDecl), EnumDecl { visibility: Visibility, name: Identifier, @@ -192,6 +193,14 @@ pub enum Statement { 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, diff --git a/src/codegen.rs b/src/codegen.rs index edc9fc6..af5c39b 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,8 +1,8 @@ use parser::ast::{ Attribute, BinaryOp, Block, EnumItem, Expression, FieldDecl, FunctionDecl, Generic, Generics, - Identifier, Literal, Path, Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, - TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, - Visibility, + Identifier, ImplDecl, Literal, Path, Pattern, Postfix, Prefix, Statement, StatementBranch, + TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, + VarDeclStmt, Visibility, }; // --------------------------------------------------------------------------- @@ -315,6 +315,7 @@ 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::ImplDecl(impl_) => impl_.to_rust(cg), Self::StructDecl { visibility, name, @@ -615,6 +616,33 @@ impl ToRust for FunctionDecl { } } +impl ToRust for ImplDecl { + fn to_rust(&self, cg: &mut RustCodegen) { + if let Some(trait_) = &self.trait_ { + cg.add_indentedln(&format!( + "impl{} {} for {} {{", + self.generics.get_rust(), + trait_.get_rust(), + self.target.get_rust() + )); + } else { + cg.add_indentedln(&format!( + "impl{} {} {{", + self.generics.get_rust(), + self.target.get_rust() + )); + } + cg.indent += 1; + + for method in &self.methods { + method.to_rust(cg); + } + + cg.indent -= 1; + cg.add_indentedln("}"); + } +} + impl GetRust for VarDecl { fn get_rust(&self) -> String { let ty = self From 6f7f11719de77cfea968a1431c06efb7feb8cf05 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 17:18:53 +0200 Subject: [PATCH 05/11] Impl for --- mist-test/src/logger.mist | 12 ++++++------ parser/src/lib.rs | 9 +++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index 2b567eb..65dbe78 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -10,15 +10,15 @@ impl fmt::Display for LogLevel { std::fmt::Result fmt(self*, std::fmt::Formatter<'_> mut* f) { match (self) { LogLevel::Info => { - write!(f, "[INFO]"); + return write!(f, "[INFO]"); } LogLevel::Warning => { - write!(f, "[WARN]"); + return write!(f, "[WARN]"); } LogLevel::Error => { - write!(f, "[ERROR]"); + return write!(f, "[ERROR]"); } } } @@ -46,15 +46,15 @@ public class Logger { void log(self*, LogLevel level, str* message) { match(level) { LogLevel::Info => { - println!("[INFO] {} {}", self.prefix, message); + println!("{level} {} {}", self.prefix, message); } LogLevel::Warning => { - println!("[WARN] {} {}", self.prefix, message); + println!("{level} {} {}", self.prefix, message); } LogLevel::Error => { - println!("[ERROR] {} {}", self.prefix, message); + println!("{level} {} {}", self.prefix, message); } } } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index eb8e90c..7756176 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -303,6 +303,15 @@ impl From> for TopLevelKind { Rule::mod_package => TopLevelKind::Mod(Identifier::from(inner.next().unwrap())), + Rule::impl_for_decl => TopLevelKind::ImplDecl(ImplDecl { + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), + trait_: Some(TypeExpr::from(inner.next().unwrap())), + target: TypeExpr::from(inner.next().unwrap()), + methods: inner.map(FunctionDecl::from).collect(), + }), + _ => unimplemented!("{rule:#?}"), } } From bb9ad547a3fb171a981deeb6d03953123c7c64be Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 17:25:34 +0200 Subject: [PATCH 06/11] External impl --- parser/src/ast.rs | 2 +- parser/src/lib.rs | 28 +++++++++++++++++++++++++--- src/codegen.rs | 2 +- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index eed2c93..abcce46 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -94,7 +94,7 @@ pub enum TopLevelKind { generics: Generics, fields: Vec, constructor: ClassConstructor, - methods: Vec, + items: Vec, }, } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 7756176..c26d368 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -289,7 +289,7 @@ impl From> for TopLevelKind { .map(FieldDeclStmt::from) .collect(), constructor: ClassConstructor::from(inner.next().unwrap()), - methods: inner.into_iter().map(FunctionDecl::from).collect(), + items: inner.into_iter().map(FunctionDecl::from).collect(), }, Rule::enum_decl => TopLevelKind::EnumDecl { @@ -303,14 +303,36 @@ impl From> for TopLevelKind { Rule::mod_package => TopLevelKind::Mod(Identifier::from(inner.next().unwrap())), - Rule::impl_for_decl => TopLevelKind::ImplDecl(ImplDecl { + Rule::impl_for_decl | Rule::impl_decl => TopLevelKind::ImplDecl(ImplDecl::from(pair)), + + _ => unimplemented!("{rule:#?}"), + } + } +} + +impl From> for ImplDecl { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + let mut inner = pair.clone().into_inner(); + + match rule { + Rule::impl_for_decl => ImplDecl { generics: consume_rule(&mut inner, Rule::generics) .map(Generics::from) .unwrap_or_default(), trait_: Some(TypeExpr::from(inner.next().unwrap())), target: TypeExpr::from(inner.next().unwrap()), methods: inner.map(FunctionDecl::from).collect(), - }), + }, + + Rule::impl_decl => ImplDecl { + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), + trait_: None, + target: TypeExpr::from(inner.next().unwrap()), + methods: inner.map(FunctionDecl::from).collect(), + }, _ => unimplemented!("{rule:#?}"), } diff --git a/src/codegen.rs b/src/codegen.rs index af5c39b..304a904 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -364,7 +364,7 @@ impl ToRust for TopLevelKind { generics, fields, constructor, - methods, + items: methods, } => { // Struct decl cg.addln(&format!( From 28d4d784f23f5481b665cf182a0d87b5187e9588 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 17:35:33 +0200 Subject: [PATCH 07/11] Class impl --- mist-test/src/logger.mist | 6 ++++++ parser/src/ast.rs | 8 +++++++- parser/src/lib.rs | 16 +++++++++++++++- src/codegen.rs | 32 +++++++++++++++++++++++++------- 4 files changed, 53 insertions(+), 9 deletions(-) diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index 65dbe78..f6b55c5 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -58,4 +58,10 @@ public class Logger { } } } + + impl fmt::Display { + std::fmt::Result fmt(self*, std::fmt::Formatter<'_> mut* f) { + return write!(f, "logger ({})", self.prefix); + } + } } diff --git a/parser/src/ast.rs b/parser/src/ast.rs index abcce46..5f78fd4 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -94,10 +94,16 @@ pub enum TopLevelKind { generics: Generics, fields: Vec, constructor: ClassConstructor, - items: Vec, + items: Vec, }, } +#[derive(Debug, Clone, Serialize)] +pub enum ClassItem { + Method(FunctionDecl), + ImplDecl(ImplDecl), +} + #[derive(Debug, Clone, Serialize, Default)] pub struct Generics(pub Vec); diff --git a/parser/src/lib.rs b/parser/src/lib.rs index c26d368..d3861e2 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -289,7 +289,7 @@ impl From> for TopLevelKind { .map(FieldDeclStmt::from) .collect(), constructor: ClassConstructor::from(inner.next().unwrap()), - items: inner.into_iter().map(FunctionDecl::from).collect(), + items: inner.into_iter().map(ClassItem::from).collect(), }, Rule::enum_decl => TopLevelKind::EnumDecl { @@ -310,6 +310,20 @@ impl From> for TopLevelKind { } } +impl From> for ClassItem { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + + match rule { + Rule::impl_decl | Rule::impl_for_decl => ClassItem::ImplDecl(ImplDecl::from(pair)), + + Rule::method => ClassItem::Method(FunctionDecl::from(pair)), + + _ => unimplemented!("{rule:#?}"), + } + } +} + impl From> for ImplDecl { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); diff --git a/src/codegen.rs b/src/codegen.rs index 304a904..3df7404 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,8 +1,8 @@ use parser::ast::{ - Attribute, BinaryOp, Block, EnumItem, Expression, FieldDecl, FunctionDecl, Generic, Generics, - Identifier, ImplDecl, Literal, Path, Pattern, Postfix, Prefix, Statement, StatementBranch, - TopLevel, TopLevelKind, TypeExpr, TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, - VarDeclStmt, Visibility, + 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, }; // --------------------------------------------------------------------------- @@ -364,7 +364,7 @@ impl ToRust for TopLevelKind { generics, fields, constructor, - items: methods, + items, } => { // Struct decl cg.addln(&format!( @@ -458,12 +458,30 @@ impl ToRust for TopLevelKind { cg.indent -= 1; cg.add_indentedln("}\n"); - for method in methods { - method.to_rust(cg); + for item in items { + match item { + ClassItem::ImplDecl(_) => {} + ClassItem::Method(method) => method.to_rust(cg), + } } cg.indent -= 1; cg.addln("}\n"); + + for item in items { + match item { + ClassItem::ImplDecl(impl_) => { + let mut impl_ = impl_.clone(); + + impl_.trait_ = Some(impl_.target); + impl_.target = + TypeExpr(TypeExprKind::Path(Path(vec![name.clone()])), Vec::new()); + + impl_.to_rust(cg); + } + ClassItem::Method(_) => {} + } + } } } } From e063d4c68513936e2eb9a7e6031d77aab32a71b3 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 17:55:08 +0200 Subject: [PATCH 08/11] Traits --- mist-test/src/logger.mist | 2 ++ parser/src/ast.rs | 15 ++++++++++++++- parser/src/grammar.pest | 20 +++++++++++++++++++- parser/src/lib.rs | 25 +++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index f6b55c5..a1c5631 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -1,5 +1,7 @@ use ; +public trait TestLogging: Display {} + public enum LogLevel { Info, Warning, diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 5f78fd4..18509dd 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -75,6 +75,13 @@ pub enum TopLevelKind { Import(Path), Mod(Identifier), ImplDecl(ImplDecl), + TraitDecl { + visibility: Visibility, + name: Identifier, + generics: Generics, + requirements: Vec, + items: Vec, + }, EnumDecl { visibility: Visibility, name: Identifier, @@ -83,8 +90,8 @@ pub enum TopLevelKind { }, StructDecl { visibility: Visibility, - generics: Generics, name: Identifier, + generics: Generics, fields: Vec, }, FunctionDecl(FunctionDecl), @@ -98,6 +105,12 @@ pub enum TopLevelKind { }, } +#[derive(Debug, Clone, Serialize)] +pub enum TraitItem { + WithBody(FunctionDecl), + NoBody(FunctionDecl), +} + #[derive(Debug, Clone, Serialize)] pub enum ClassItem { Method(FunctionDecl), diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index afc0ea4..b9f3bfb 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -259,6 +259,24 @@ impl_decl = { "impl" ~ generics? ~ type_expr ~ "{" ~ method* ~ "}" } +// ====================================================== +// Traits +// ====================================================== +trait_requirements = { ":" ~ type_expr_param ~ ("+" ~ type_expr_param)* } + +method_no_body = { + export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" +} + +trait_item = _{ + method + | method_no_body +} + +trait_decl = { + export? ~ "trait" ~ identifier ~ generics? ~ trait_requirements? ~ "{" ~ trait_item* ~ "}" +} + // ====================================================== // FUNCTIONS // ====================================================== @@ -272,7 +290,7 @@ function_decl = { // ====================================================== top_level = { - (attributes ~ (import | impl_for_decl | impl_decl | function_decl | struct_decl | enum_decl | class_decl | mod_package)) + (attributes ~ (import | impl_for_decl | impl_decl | trait_decl | struct_decl | enum_decl | class_decl | mod_package | function_decl)) | mod_attribute } diff --git a/parser/src/lib.rs b/parser/src/lib.rs index d3861e2..fb0343e 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -305,6 +305,31 @@ impl From> for TopLevelKind { Rule::impl_for_decl | Rule::impl_decl => TopLevelKind::ImplDecl(ImplDecl::from(pair)), + Rule::trait_decl => TopLevelKind::TraitDecl { + visibility: Visibility::from(&mut inner), + name: Identifier::from(inner.next().unwrap()), + generics: consume_rule(&mut inner, Rule::generics) + .map(Generics::from) + .unwrap_or_default(), + requirements: consume_rule(&mut inner, Rule::trait_requirements) + .map(|pair| pair.into_inner().map(TypeExpr::from).collect()) + .unwrap_or_default(), + items: inner.map(TraitItem::from).collect(), + }, + + _ => unimplemented!("{rule:#?}"), + } + } +} + +impl From> for TraitItem { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let rule = pair.as_rule(); + + match rule { + Rule::method => TraitItem::WithBody(FunctionDecl::from(pair)), + Rule::method_no_body => TraitItem::NoBody(FunctionDecl::from(pair)), + _ => unimplemented!("{rule:#?}"), } } From 380755bf838a75f95436cb95f495591a58dc8ae0 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 18:08:15 +0200 Subject: [PATCH 09/11] traits --- mist-test/src/logger.mist | 2 +- parser/src/ast.rs | 10 ++-------- parser/src/lib.rs | 17 ++-------------- src/codegen.rs | 42 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 44 insertions(+), 27 deletions(-) diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index a1c5631..fbfc688 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -1,6 +1,6 @@ use ; -public trait TestLogging: Display {} +public trait TestLogging: fmt::Display {} public enum LogLevel { Info, diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 18509dd..ed75ba1 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -80,7 +80,7 @@ pub enum TopLevelKind { name: Identifier, generics: Generics, requirements: Vec, - items: Vec, + items: Vec, }, EnumDecl { visibility: Visibility, @@ -105,12 +105,6 @@ pub enum TopLevelKind { }, } -#[derive(Debug, Clone, Serialize)] -pub enum TraitItem { - WithBody(FunctionDecl), - NoBody(FunctionDecl), -} - #[derive(Debug, Clone, Serialize)] pub enum ClassItem { Method(FunctionDecl), @@ -158,7 +152,7 @@ pub struct FunctionDecl { pub generics: Generics, pub params: ParamList, pub return_type: TypeExpr, - pub body: Block, + pub body: Option, } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/lib.rs b/parser/src/lib.rs index fb0343e..ba4193b 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -314,7 +314,7 @@ impl From> for TopLevelKind { requirements: consume_rule(&mut inner, Rule::trait_requirements) .map(|pair| pair.into_inner().map(TypeExpr::from).collect()) .unwrap_or_default(), - items: inner.map(TraitItem::from).collect(), + items: inner.map(FunctionDecl::from).collect(), }, _ => unimplemented!("{rule:#?}"), @@ -322,19 +322,6 @@ impl From> for TopLevelKind { } } -impl From> for TraitItem { - fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { - let rule = pair.as_rule(); - - match rule { - Rule::method => TraitItem::WithBody(FunctionDecl::from(pair)), - Rule::method_no_body => TraitItem::NoBody(FunctionDecl::from(pair)), - - _ => unimplemented!("{rule:#?}"), - } - } -} - impl From> for ClassItem { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); @@ -789,7 +776,7 @@ impl From> for FunctionDecl { }) .unwrap_or_else(|| ParamList(self_param.into_iter().collect())); - let body = Block::from(inner.next().unwrap()); + let body = inner.next().map(Block::from); Self { visibility, diff --git a/src/codegen.rs b/src/codegen.rs index 3df7404..0330b60 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -358,6 +358,38 @@ impl ToRust for TopLevelKind { cg.indent -= 1; cg.addln("}\n"); } + Self::TraitDecl { + visibility, + name, + generics, + requirements, + items, + } => { + cg.addln(&format!( + "{}trait {}{}{} {{", + visibility.get_rust(), + name.get_rust(), + generics.get_rust(), + if requirements.len() != 0 { + String::from(": ") + + &requirements + .iter() + .map(TypeExpr::get_rust) + .collect::>() + .join("+") + } else { + String::new() + }, + )); + cg.indent += 1; + + for item in items { + item.to_rust(cg); + } + + cg.indent -= 1; + cg.addln("}\n"); + } Self::ClassDecl { visibility, name, @@ -627,9 +659,13 @@ impl ToRust for FunctionDecl { params_str, self.return_type.get_rust() )); - cg.indent += 1; - self.body.to_rust(cg); - cg.indent -= 1; + if let Some(body) = &self.body { + cg.indent += 1; + body.to_rust(cg); + cg.indent -= 1; + } else { + cg.add(";"); + } cg.add_indentedln("}\n"); } } From e97b3cac8fcc1aac01f952e5ac3a622e4b85c65e Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 18:10:13 +0200 Subject: [PATCH 10/11] Methods with no body --- mist-test/src/logger.mist | 4 +++- parser/src/grammar.pest | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mist-test/src/logger.mist b/mist-test/src/logger.mist index fbfc688..788c7bb 100644 --- a/mist-test/src/logger.mist +++ b/mist-test/src/logger.mist @@ -1,6 +1,8 @@ use ; -public trait TestLogging: fmt::Display {} +public trait TestLogging: fmt::Display { + String get(); +} public enum LogLevel { Info, diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index b9f3bfb..9c0aca9 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -265,7 +265,7 @@ impl_decl = { trait_requirements = { ":" ~ type_expr_param ~ ("+" ~ type_expr_param)* } method_no_body = { - export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" + export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ semicolon } trait_item = _{ From d3c1be859d80177eea262d48de05ce87aabcb46b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 18:14:01 +0200 Subject: [PATCH 11/11] Fix methods with no body --- src/codegen.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index 0330b60..5ed33b0 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -652,7 +652,7 @@ impl ToRust for FunctionDecl { .join(", "); cg.add_indentedln(&format!( - "{}fn {}{}({}) -> {} {{", + "{}fn {}{}({}) -> {}", self.visibility.get_rust(), self.name.get_rust(), self.generics.get_rust(), @@ -660,13 +660,14 @@ impl ToRust for FunctionDecl { self.return_type.get_rust() )); if let Some(body) = &self.body { + cg.add_indentedln("{\n"); cg.indent += 1; body.to_rust(cg); cg.indent -= 1; + cg.add_indentedln("}\n"); } else { cg.add(";"); } - cg.add_indentedln("}\n"); } }