From 020dd3b76b50602661662e44e0500f295f6e83ad Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 20:08:03 +0200 Subject: [PATCH 01/13] Generic lifetimes --- parser/src/ast.rs | 8 +++++++- parser/src/grammar.pest | 13 +++++++++++-- parser/src/lib.rs | 12 ++++++++---- src/codegen.rs | 32 ++++++++++++++++++-------------- test/src/main.mist | 2 ++ 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index ac6b1f0..8ecb25e 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -98,7 +98,13 @@ pub enum TopLevelKind { } #[derive(Debug, Clone, Serialize, Default)] -pub struct Generics(pub Vec<(Identifier, Vec)>); +pub struct Generics(pub Vec); + +#[derive(Debug, Clone, Serialize)] +pub enum Generic { + Lifetime(Identifier), + Type(Identifier, Vec), +} #[derive(Debug, Clone, Serialize)] pub enum Pattern { diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index c557e5d..5a31967 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -55,7 +55,7 @@ var = { "var" } // ====================================================== // GENERICS // ====================================================== -generic = { identifier ~ (":" ~ static_path ~ ("+" ~ static_path)*)? } +generic = { lifetime | (identifier ~ (":" ~ type_expr_param ~ ("+" ~ type_expr_param)*)?) } generics = { "<" ~ (generic ~ ("," ~ generic)*)? ~ ">" } // ====================================================== @@ -67,7 +67,7 @@ tuple_type = { } path_type = { - static_path ~ ("<" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ">")? + static_path ~ ("<" ~ (type_expr_param ~ ("," ~ type_expr_param)*)? ~ ">")? } ref_type = { @@ -78,6 +78,15 @@ type_expr = { (path_type | tuple_type) ~ ref_type* } +lifetime = { + "'" ~ identifier +} + +type_expr_param = { + type_expr + | lifetime +} + // ====================================================== // LITERALS // ====================================================== diff --git a/parser/src/lib.rs b/parser/src/lib.rs index fa01570..1996de7 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -238,10 +238,14 @@ impl From> for Generics { inner .map(|pair| { let mut inner = pair.into_inner(); - ( - Identifier::from(inner.next().unwrap()), - inner.map(Path::from).collect(), - ) + if let Some(pair) = consume_rule(&mut inner, Rule::lifetime) { + Generic::Lifetime(Identifier::from(pair.into_inner().next().unwrap())) + } else { + Generic::Type( + Identifier::from(inner.next().unwrap()), + inner.map(TypeExpr::from).collect(), + ) + } }) .collect(), ), diff --git a/src/codegen.rs b/src/codegen.rs index 78299c7..a107cc2 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -721,20 +721,24 @@ impl GetRust for Generics { "<{}>", self.0 .iter() - .map(|generic| generic.0.get_rust() - + &(if generic.1.len() == 0 { - String::new() - } else { - format!( - ": {}", - generic - .1 - .iter() - .map(Path::get_rust) - .collect::>() - .join("+") - ) - })) + .map(|generic| match generic { + parser::ast::Generic::Lifetime(name) => format!("'{}", name.get_rust()), + parser::ast::Generic::Type(name, requirements) => { + name.get_rust() + + &(if requirements.len() == 0 { + String::new() + } else { + format!( + ": {}", + requirements + .iter() + .map(TypeExpr::get_rust) + .collect::>() + .join("+") + ) + }) + } + }) .collect::>() .join(", ") ) diff --git a/test/src/main.mist b/test/src/main.mist index 602dd59..f7e1a08 100644 --- a/test/src/main.mist +++ b/test/src/main.mist @@ -2,6 +2,8 @@ mod my_class; use ; use ; +struct Test<'a> {} + void main() { var my_class = new MyClass("World"); my_class.greet(); From 910657c755f7c7a3ed2018cacb76943a38310f04 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Fri, 8 May 2026 20:15:56 +0200 Subject: [PATCH 02/13] Lifetimes --- parser/src/ast.rs | 1 + parser/src/lib.rs | 5 +++++ src/codegen.rs | 1 + 3 files changed, 7 insertions(+) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 8ecb25e..85c3713 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -41,6 +41,7 @@ pub enum TypeExprKind { Path(Path), PathParams(Path, Vec), Tuple(Vec), + Lifetime(Identifier), } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 1996de7..caf663f 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -36,6 +36,11 @@ impl From> for TypeExpr { TypeExprKind::from(inner.next().unwrap()), inner.map(TypePostfix::from).collect(), ), + Rule::type_expr_param => TypeExpr::from(inner.next().unwrap()), + Rule::lifetime => TypeExpr( + TypeExprKind::Lifetime(Identifier::from(inner.next().unwrap())), + Vec::new(), + ), _ => unimplemented!("{rule:#?}"), } } diff --git a/src/codegen.rs b/src/codegen.rs index a107cc2..7030837 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -96,6 +96,7 @@ impl GetRust for TypeExprKind { fn get_rust(&self) -> String { match self { TypeExprKind::Path(path) => get_static_type_path(path), + TypeExprKind::Lifetime(name) => format!("'{}", name.get_rust()), TypeExprKind::PathParams(path, params) => { format!( "{}<{}>", From 3e25bf04561d045ec6a620161347e649506b570b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 00:35:14 +0200 Subject: [PATCH 03/13] Refrence lifetimes --- parser/src/ast.rs | 2 ++ parser/src/grammar.pest | 2 +- parser/src/lib.rs | 20 ++++++++++++++++---- src/codegen.rs | 2 ++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 85c3713..db081d9 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -16,6 +16,8 @@ pub struct Block(pub Vec); pub enum TypePostfix { Ref, RefMut, + RefLifetime(Identifier), + RefMutLifetime(Identifier), } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 5a31967..16903b5 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -71,7 +71,7 @@ path_type = { } ref_type = { - mutable? ~ "*" + mutable? ~ lifetime? ~ "*" } type_expr = { diff --git a/parser/src/lib.rs b/parser/src/lib.rs index caf663f..7c90682 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -49,14 +49,26 @@ impl From> for TypeExpr { impl From> for TypePostfix { fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { let rule = pair.as_rule(); - let inner = pair.into_inner(); + let mut inner = pair.into_inner(); match rule { Rule::ref_type => { - if inner.peek().is_some() { - TypePostfix::RefMut + let mutable = listen_rule(&mut inner, Rule::mutable); + let lifetime = consume_rule(&mut inner, Rule::lifetime) + .map(|pair| Identifier::from(pair.into_inner().next().unwrap())); + + if mutable { + if let Some(lifetime) = lifetime { + TypePostfix::RefMutLifetime(lifetime) + } else { + TypePostfix::Ref + } } else { - TypePostfix::Ref + if let Some(lifetime) = lifetime { + TypePostfix::RefLifetime(lifetime) + } else { + TypePostfix::RefMut + } } } _ => unimplemented!("{rule:#?}"), diff --git a/src/codegen.rs b/src/codegen.rs index 7030837..702f3e1 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -634,6 +634,8 @@ impl GetRust for TypePostfix { match self { TypePostfix::Ref => format!("&"), TypePostfix::RefMut => format!("&mut "), + TypePostfix::RefLifetime(lifetime) => format!("&'{} ", lifetime.get_rust()), + TypePostfix::RefMutLifetime(lifetime) => format!("&'{} mut ", lifetime.get_rust()), } } } From 1b1d38cdbaa6e224b95cd49720b4e4f99fc3d358 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:11:39 +0200 Subject: [PATCH 04/13] Mist test --- .gitignore | 4 +- mist-test/Cargo.lock | 7 + mist-test/Cargo.toml | 10 + {test => mist-test}/mist.json | 0 {test => mist-test}/src/main.mist | 2 - {test => mist-test}/src/my_class.mist | 0 test/mist.map.json | 450 -------------------------- 7 files changed, 19 insertions(+), 454 deletions(-) create mode 100644 mist-test/Cargo.lock create mode 100644 mist-test/Cargo.toml rename {test => mist-test}/mist.json (100%) rename {test => mist-test}/src/main.mist (94%) rename {test => mist-test}/src/my_class.mist (100%) delete mode 100644 test/mist.map.json diff --git a/.gitignore b/.gitignore index 2112842..19a716d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,5 +26,5 @@ target /target -/test/build -/test/output.json \ No newline at end of file +/mist-test/build +/mist-test/output.json \ No newline at end of file diff --git a/mist-test/Cargo.lock b/mist-test/Cargo.lock new file mode 100644 index 0000000..d594070 --- /dev/null +++ b/mist-test/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "mist-test" +version = "0.1.0" diff --git a/mist-test/Cargo.toml b/mist-test/Cargo.toml new file mode 100644 index 0000000..a02d622 --- /dev/null +++ b/mist-test/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "mist-test" +version = "0.1.0" +edition = "2024" + +[[bin]] +name = "main" +path = "build/main.rs" + +[dependencies] diff --git a/test/mist.json b/mist-test/mist.json similarity index 100% rename from test/mist.json rename to mist-test/mist.json diff --git a/test/src/main.mist b/mist-test/src/main.mist similarity index 94% rename from test/src/main.mist rename to mist-test/src/main.mist index f7e1a08..602dd59 100644 --- a/test/src/main.mist +++ b/mist-test/src/main.mist @@ -2,8 +2,6 @@ mod my_class; use ; use ; -struct Test<'a> {} - void main() { var my_class = new MyClass("World"); my_class.greet(); diff --git a/test/src/my_class.mist b/mist-test/src/my_class.mist similarity index 100% rename from test/src/my_class.mist rename to mist-test/src/my_class.mist diff --git a/test/mist.map.json b/test/mist.map.json deleted file mode 100644 index 529a5df..0000000 --- a/test/mist.map.json +++ /dev/null @@ -1,450 +0,0 @@ -{ - "fmt": { - "package_name": "fmt", - "structs": {}, - "functions": { - "append": { - "export": true, - "name": "Append", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "b": { - "export": true, - "var_type": "[]byte", - "name": "b" - } - }, - "return_types": [ - "[]byte" - ] - }, - "appendf": { - "export": true, - "name": "Appendf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "b": { - "export": true, - "var_type": "[]byte", - "name": "b" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - } - }, - "return_types": [ - "[]byte" - ] - }, - "appendln": { - "export": true, - "name": "Appendln", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "b": { - "export": true, - "var_type": "[]byte", - "name": "b" - } - }, - "return_types": [ - "[]byte" - ] - }, - "errorf": { - "export": true, - "name": "Errorf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - } - }, - "return_types": [ - "error" - ] - }, - "formatString": { - "export": true, - "name": "FormatString", - "params": { - "state": { - "export": true, - "var_type": "fmt.State", - "name": "state" - }, - "verb": { - "export": true, - "var_type": "rune", - "name": "verb" - } - }, - "return_types": [ - "string" - ] - }, - "fprint": { - "export": true, - "name": "Fprint", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "w": { - "export": true, - "var_type": "io.Writer", - "name": "w" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "fprintf": { - "export": true, - "name": "Fprintf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - }, - "w": { - "export": true, - "var_type": "io.Writer", - "name": "w" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "fprintln": { - "export": true, - "name": "Fprintln", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "w": { - "export": true, - "var_type": "io.Writer", - "name": "w" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "fscan": { - "export": true, - "name": "Fscan", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "r": { - "export": true, - "var_type": "io.Reader", - "name": "r" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "fscanf": { - "export": true, - "name": "Fscanf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - }, - "r": { - "export": true, - "var_type": "io.Reader", - "name": "r" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "fscanln": { - "export": true, - "name": "Fscanln", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "r": { - "export": true, - "var_type": "io.Reader", - "name": "r" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "print": { - "export": true, - "name": "Print", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "printf": { - "export": true, - "name": "Printf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "println": { - "export": true, - "name": "Println", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "scan": { - "export": true, - "name": "Scan", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "scanf": { - "export": true, - "name": "Scanf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "scanln": { - "export": true, - "name": "Scanln", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "sprint": { - "export": true, - "name": "Sprint", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - } - }, - "return_types": [ - "string" - ] - }, - "sprintf": { - "export": true, - "name": "Sprintf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - } - }, - "return_types": [ - "string" - ] - }, - "sprintln": { - "export": true, - "name": "Sprintln", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - } - }, - "return_types": [ - "string" - ] - }, - "sscan": { - "export": true, - "name": "Sscan", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "str": { - "export": true, - "var_type": "string", - "name": "str" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "sscanf": { - "export": true, - "name": "Sscanf", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "format": { - "export": true, - "var_type": "string", - "name": "format" - }, - "str": { - "export": true, - "var_type": "string", - "name": "str" - } - }, - "return_types": [ - "int", - "error" - ] - }, - "sscanln": { - "export": true, - "name": "Sscanln", - "params": { - "a": { - "export": true, - "var_type": "[]any", - "name": "a" - }, - "str": { - "export": true, - "var_type": "string", - "name": "str" - } - }, - "return_types": [ - "int", - "error" - ] - } - } - } -} \ No newline at end of file From dff77a8c01120ab8e5853a6d2d7746f9aaf564d4 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:13:23 +0200 Subject: [PATCH 05/13] Fixed lifetime mutability --- parser/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 7c90682..e17057c 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -61,13 +61,13 @@ impl From> for TypePostfix { if let Some(lifetime) = lifetime { TypePostfix::RefMutLifetime(lifetime) } else { - TypePostfix::Ref + TypePostfix::RefMut } } else { if let Some(lifetime) = lifetime { TypePostfix::RefLifetime(lifetime) } else { - TypePostfix::RefMut + TypePostfix::Ref } } } From f69c53d3fc97164ce73b2acb4a43dfbdb4cae7ca Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:19:08 +0200 Subject: [PATCH 06/13] Removed unsafe warning (will work on later) --- src/codegen.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/codegen.rs b/src/codegen.rs index 702f3e1..532f069 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -394,6 +394,7 @@ impl ToRust for TopLevelKind { .collect::>() .join(", "); + cg.add_indentedln("#[allow(invalid_value)]"); cg.add_indentedln(&format!( "{}fn new{}({}) -> Self {{", constructor.visibility.get_rust(), From 0c2746eefcc370f86f2f78a62bb6543245b237a5 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:27:20 +0200 Subject: [PATCH 07/13] Fixed self param --- 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 16903b5..0800ebf 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -233,7 +233,7 @@ self_param = { } method = { - export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ param_list? ~ ")" ~ block + export? ~ type_expr ~ identifier ~ generics? ~ "(" ~ self_param? ~ ("," ~ param_list?)? ~ ")" ~ block } class_decl = { From 5a475f3b8acde94c80d58e75722241212549f1e8 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:35:13 +0200 Subject: [PATCH 08/13] Full app --- mist-test/src/core/app.mist | 90 ++++++++++++++++++++++++++++++++++ mist-test/src/core/event.mist | 7 +++ mist-test/src/core/logger.mist | 41 ++++++++++++++++ mist-test/src/core/mod.mist | 5 ++ mist-test/src/core/plugin.mist | 16 ++++++ mist-test/src/core/task.mist | 20 ++++++++ mist-test/src/main.mist | 29 ++++++----- 7 files changed, 193 insertions(+), 15 deletions(-) create mode 100644 mist-test/src/core/app.mist create mode 100644 mist-test/src/core/event.mist create mode 100644 mist-test/src/core/logger.mist create mode 100644 mist-test/src/core/mod.mist create mode 100644 mist-test/src/core/plugin.mist create mode 100644 mist-test/src/core/task.mist diff --git a/mist-test/src/core/app.mist b/mist-test/src/core/app.mist new file mode 100644 index 0000000..ba1d4ea --- /dev/null +++ b/mist-test/src/core/app.mist @@ -0,0 +1,90 @@ +use ; + + list::List tasks; + list::List plugins; + + logger::Logger logger; + + bool running; + i32 ticks; + + public constructor(String name) { + self.name = name; + + self.tasks = new list::List(); + self.plugins = new list::List(); + + self.logger = new logger::Logger("app"); + + self.running = false; + self.ticks = 0; + } + + public void boot(self mut*) { + self.logger.info("booting application"); + + self.running = true; + + self.emit(event::Event::Startup); + } + + public void run(self mut*) { + while(self.running) { + self.tick(); + + if(self.ticks >= 5) { + self.shutdown(); + } + } + } + + void tick(self mut*) { + self.logger.info("tick"); + + self.ticks = self.ticks + 1; + + var task = task::create_task("background-job"); + + self.tasks.push(task); + + println!("tasks: {}", self.tasks.len()); + } + + public void shutdown(self mut*) { + self.emit(event::Event::Shutdown); + + self.logger.warning("shutdown"); + + self.running = false; + } + + public void register_plugin(self mut*, String name) { + self.plugins.push(name); + + self.emit(event::Event::PluginLoaded(name)); + } + + void emit(self*, event::Event event) { + match(event) { + event::Event::Startup => { + self.logger.info("startup event"); + } + + event::Event::Shutdown => { + self.logger.info("shutdown event"); + } + + event::Event::PluginLoaded(name) => { + println!("plugin loaded: {}", name); + } + + event::Event::TaskExecuted(name) => { + println!("task executed: {}", name); + } + + event::Event::Error(message) => { + self.logger.error(message); + } + } + } +} \ No newline at end of file diff --git a/mist-test/src/core/event.mist b/mist-test/src/core/event.mist new file mode 100644 index 0000000..2c5cdb2 --- /dev/null +++ b/mist-test/src/core/event.mist @@ -0,0 +1,7 @@ +public enum Event { + Startup, + Shutdown, + TaskExecuted(String), + PluginLoaded(String), + Error(String), +} \ No newline at end of file diff --git a/mist-test/src/core/logger.mist b/mist-test/src/core/logger.mist new file mode 100644 index 0000000..340923e --- /dev/null +++ b/mist-test/src/core/logger.mist @@ -0,0 +1,41 @@ +public enum LogLevel { + Info, + Warning, + Error, +} + +public class Logger { + String prefix; + + public constructor(String prefix) { + self.prefix = prefix; + } + + public void info(self*, String message) { + self.log(LogLevel::Info, message); + } + + public void warning(self*, String message) { + self.log(LogLevel::Warning, message); + } + + public void error(self*, String message) { + self.log(LogLevel::Error, message); + } + + void log(self*, LogLevel level, String message) { + match(level) { + LogLevel::Info => { + println!("[INFO] {} {}", self.prefix, message); + } + + LogLevel::Warning => { + println!("[WARN] {} {}", self.prefix, message); + } + + LogLevel::Error => { + println!("[ERROR] {} {}", self.prefix, message); + } + } + } +} diff --git a/mist-test/src/core/mod.mist b/mist-test/src/core/mod.mist new file mode 100644 index 0000000..9de044b --- /dev/null +++ b/mist-test/src/core/mod.mist @@ -0,0 +1,5 @@ +mod app; +mod task; +mod plugin; +mod logger; +mod event; \ No newline at end of file diff --git a/mist-test/src/core/plugin.mist b/mist-test/src/core/plugin.mist new file mode 100644 index 0000000..9a706f0 --- /dev/null +++ b/mist-test/src/core/plugin.mist @@ -0,0 +1,16 @@ +public struct PluginInfo { + public String name, + public String version, +} + +public class PluginRegistry { + T plugins; + + public constructor(T plugins) { + self.plugins = plugins; + } + + public T plugins(self) { + return self.plugins; + } +} \ No newline at end of file diff --git a/mist-test/src/core/task.mist b/mist-test/src/core/task.mist new file mode 100644 index 0000000..d507015 --- /dev/null +++ b/mist-test/src/core/task.mist @@ -0,0 +1,20 @@ +public enum TaskState { + Pending, + Running, + Finished, + Failed, +} + +public struct Task { + public String name, + public TaskState state, + public i32 executions, +} + +public Task create_task(String name) { + return Task { + name: name, + state: TaskState::Pending, + executions: 0, + }; +} \ No newline at end of file diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 602dd59..a9a8190 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -1,18 +1,17 @@ -mod my_class; -use ; -use ; +mod core; -void main() { - var my_class = new MyClass("World"); - my_class.greet(); +use ; +use ; +use ; - match (MyEnum::Tuple(10, String::new())) { - MyEnum::Tuple(i, _) => { - println!("{i}"); - } - MyEnum::Named => { +i32 main() { + var app = new app::Application("mist-app"); - } - _ => {} - } -} + greeting::register(&mut app); + statistics::register(&mut app); + + app.boot(); + app.run(); + + return 0; +} \ No newline at end of file From 460d2967596e290032371af99dfc2968be5699df Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:37:40 +0200 Subject: [PATCH 09/13] Fixed directories --- src/compiler.rs | 152 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 103 insertions(+), 49 deletions(-) diff --git a/src/compiler.rs b/src/compiler.rs index db5d31c..adb6e57 100644 --- a/src/compiler.rs +++ b/src/compiler.rs @@ -1,4 +1,9 @@ -use std::{fs, path::PathBuf, process, time::Instant}; +use std::{ + fs, + path::{Path, PathBuf}, + process, + time::Instant, +}; use serde::Deserialize; @@ -21,58 +26,108 @@ pub fn build() { // 2. load config let config = load_config(&root); - let src = root.join(&config.src); + let src_dir = root.join(&config.src); + let out_dir = root.join(&config.output); - for entry in fs::read_dir(src).unwrap() { - if let Ok(entry) = entry { - let entry_path = root.join(&entry.path()); - let out_dir = root.join(&config.output); - let file_name = entry.file_name(); - let file_name = file_name.to_string_lossy(); - - // 3. read entry file - let source = match fs::read_to_string(&entry_path) { - Ok(s) => s, - Err(e) => { - eprintln!("error: failed to read entry file\n {}", e); - process::exit(1); - } - }; - - let parser_result = parser::parse(&source).map_err(|e| e.to_string()); - - let ast = match parser_result { - Ok(ast) => ast, - Err(e) => { - eprintln!("error: parse failed\n{}", e); - process::exit(1); - } - }; - - // semantic::walk_ast(semantic::scope::Scope::from_top(&root, &ast), &mut ast); - - let mut gc = crate::codegen::RustCodegen::new(); - let output = gc.generate(&ast); - - if let Err(e) = fs::create_dir_all(&out_dir) { - eprintln!("error: failed to create build dir\n {}", e); - process::exit(1); - } - - let out_file = out_dir.join(file_name.replace(".mist", ".rs")); - - if let Err(e) = fs::write(&out_file, output) { - eprintln!("error: failed to write output\n {}", e); - process::exit(1); - } - } - } + build_dir(&root, &src_dir, &src_dir, &out_dir); let elapsed = start.elapsed(); println!("build finished in {:.2?}", elapsed); } +fn build_dir(root: &Path, base_src: &Path, current_dir: &Path, out_dir: &Path) { + let entries = match fs::read_dir(current_dir) { + Ok(entries) => entries, + Err(e) => { + eprintln!( + "error: failed to read directory {}\n {}", + current_dir.display(), + e + ); + + process::exit(1); + } + }; + + for entry in entries { + let entry = match entry { + Ok(entry) => entry, + Err(e) => { + eprintln!("error: failed to read directory entry\n {}", e); + + process::exit(1); + } + }; + + let path = entry.path(); + + // recurse into nested directories + if path.is_dir() { + build_dir(root, base_src, &path, out_dir); + continue; + } + + // skip non-mist files + if path.extension().and_then(|e| e.to_str()) != Some("mist") { + continue; + } + + let relative = path.strip_prefix(base_src).unwrap(); + + let output_path = out_dir.join(relative).with_extension("rs"); + + // create parent directories + if let Some(parent) = output_path.parent() { + if let Err(e) = fs::create_dir_all(parent) { + eprintln!( + "error: failed to create output directory {}\n {}", + parent.display(), + e + ); + + process::exit(1); + } + } + + // read source + let source = match fs::read_to_string(&path) { + Ok(s) => s, + Err(e) => { + eprintln!("error: failed to read file {}\n {}", path.display(), e); + + process::exit(1); + } + }; + + let parser_result = parser::parse(&source).map_err(|e| e.to_string()); + + let ast = match parser_result { + Ok(ast) => ast, + Err(e) => { + eprintln!("error: parse failed in {}\n{}", path.display(), e); + + process::exit(1); + } + }; + + // semantic::walk_ast(semantic::scope::Scope::from_top(root, &ast), &mut ast); + + let mut gc = crate::codegen::RustCodegen::new(); + let output = gc.generate(&ast); + + if let Err(e) = fs::write(&output_path, output) { + eprintln!( + "error: failed to write output {}\n {}", + output_path.display(), + e + ); + + process::exit(1); + } + } +} + pub fn find_project_root() -> Option { let mut dir = std::env::current_dir().ok()?; @@ -87,9 +142,8 @@ pub fn find_project_root() -> Option { } } -fn load_config(root: &std::path::Path) -> Config { - let content = - std::fs::read_to_string(root.join("mist.json")).expect("failed to read mist.json"); +fn load_config(root: &Path) -> Config { + let content = fs::read_to_string(root.join("mist.json")).expect("failed to read mist.json"); serde_json::from_str(&content).expect("invalid mist.json format") } From 4e18f4530f7d899b776456f509b370da11fd6b0d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:44:34 +0200 Subject: [PATCH 10/13] Fix --- mist-test/src/core/app.mist | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/mist-test/src/core/app.mist b/mist-test/src/core/app.mist index ba1d4ea..f2192db 100644 --- a/mist-test/src/core/app.mist +++ b/mist-test/src/core/app.mist @@ -1,4 +1,10 @@ use ; +use ; +use ; +use ; + +public class Application { + String name; list::List tasks; list::List plugins; @@ -11,8 +17,8 @@ use ; public constructor(String name) { self.name = name; - self.tasks = new list::List(); - self.plugins = new list::List(); + self.tasks = new list::List(); + self.plugins = new list::List(); self.logger = new logger::Logger("app"); From e6c030e8c88f551cf4fa087718816d98d01368ba Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 03:54:47 +0200 Subject: [PATCH 11/13] Fixed problems --- mist-test/src/core/app.mist | 19 +++++++++---------- mist-test/src/core/logger.mist | 12 ++++++------ mist-test/src/core/task.mist | 4 ++-- mist-test/src/main.mist | 12 +++++------- mist-test/src/my_class.mist | 17 ----------------- parser/src/grammar.pest | 2 +- 6 files changed, 23 insertions(+), 43 deletions(-) delete mode 100644 mist-test/src/my_class.mist diff --git a/mist-test/src/core/app.mist b/mist-test/src/core/app.mist index f2192db..f19c4f4 100644 --- a/mist-test/src/core/app.mist +++ b/mist-test/src/core/app.mist @@ -1,13 +1,12 @@ -use ; -use ; -use ; -use ; +use ; +use ; +use ; public class Application { String name; - list::List tasks; - list::List plugins; + Vec tasks; + Vec plugins; logger::Logger logger; @@ -17,8 +16,8 @@ public class Application { public constructor(String name) { self.name = name; - self.tasks = new list::List(); - self.plugins = new list::List(); + self.tasks = new Vec(); + self.plugins = new Vec(); self.logger = new logger::Logger("app"); @@ -65,7 +64,7 @@ public class Application { } public void register_plugin(self mut*, String name) { - self.plugins.push(name); + self.plugins.push(name.clone()); self.emit(event::Event::PluginLoaded(name)); } @@ -89,7 +88,7 @@ public class Application { } event::Event::Error(message) => { - self.logger.error(message); + self.logger.error(&message); } } } diff --git a/mist-test/src/core/logger.mist b/mist-test/src/core/logger.mist index 340923e..94c4b4a 100644 --- a/mist-test/src/core/logger.mist +++ b/mist-test/src/core/logger.mist @@ -7,23 +7,23 @@ public enum LogLevel { public class Logger { String prefix; - public constructor(String prefix) { - self.prefix = prefix; + public constructor(str* prefix) { + self.prefix = prefix.to_string(); } - public void info(self*, String message) { + public void info(self*, str* message) { self.log(LogLevel::Info, message); } - public void warning(self*, String message) { + public void warning(self*, str* message) { self.log(LogLevel::Warning, message); } - public void error(self*, String message) { + public void error(self*, str* message) { self.log(LogLevel::Error, message); } - void log(self*, LogLevel level, String message) { + void log(self*, LogLevel level, str* message) { match(level) { LogLevel::Info => { println!("[INFO] {} {}", self.prefix, message); diff --git a/mist-test/src/core/task.mist b/mist-test/src/core/task.mist index d507015..e3befaa 100644 --- a/mist-test/src/core/task.mist +++ b/mist-test/src/core/task.mist @@ -11,9 +11,9 @@ public struct Task { public i32 executions, } -public Task create_task(String name) { +public Task create_task(str* name) { return Task { - name: name, + name: name.to_string(), state: TaskState::Pending, executions: 0, }; diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index a9a8190..36a5934 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -1,17 +1,15 @@ mod core; use ; -use ; -use ; +// use ; +// use ; -i32 main() { +void main() { var app = new app::Application("mist-app"); - greeting::register(&mut app); - statistics::register(&mut app); + // greeting::register(&mut app); + // statistics::register(&mut app); app.boot(); app.run(); - - return 0; } \ No newline at end of file diff --git a/mist-test/src/my_class.mist b/mist-test/src/my_class.mist deleted file mode 100644 index 7cc321d..0000000 --- a/mist-test/src/my_class.mist +++ /dev/null @@ -1,17 +0,0 @@ -public class MyClass { - String message; - - public constructor(str* name) { - self.message = format!("Hello {}!", name); - } - - public void greet(self*) { - println!("{}", self.message); - } -} - -public enum MyEnum { - Named, - Tuple(i32, String), - Struct { i32 x } -} diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index 0800ebf..5c6e8f7 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -272,7 +272,6 @@ statement_list = { statement = _{ expr_stmt | match_stmt - | var_decl_statement | assign_statement | if_stmt | while_stmt @@ -282,6 +281,7 @@ statement = _{ | break_stmt | continue_stmt | block + | var_decl_statement } // ------------------------------------------------------ From 5916daaada5153a904029e48ec1f5119a15a1b56 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 04:01:54 +0200 Subject: [PATCH 12/13] Fixed class lifetimes --- mist-test/src/{core => }/app.mist | 0 mist-test/src/core/mod.mist | 5 --- mist-test/src/{core => }/event.mist | 0 mist-test/src/{core => }/logger.mist | 0 mist-test/src/main.mist | 8 +++- mist-test/src/{core => }/plugin.mist | 0 mist-test/src/{core => }/task.mist | 0 src/codegen.rs | 63 ++++++++++++++++++---------- 8 files changed, 47 insertions(+), 29 deletions(-) rename mist-test/src/{core => }/app.mist (100%) delete mode 100644 mist-test/src/core/mod.mist rename mist-test/src/{core => }/event.mist (100%) rename mist-test/src/{core => }/logger.mist (100%) rename mist-test/src/{core => }/plugin.mist (100%) rename mist-test/src/{core => }/task.mist (100%) diff --git a/mist-test/src/core/app.mist b/mist-test/src/app.mist similarity index 100% rename from mist-test/src/core/app.mist rename to mist-test/src/app.mist diff --git a/mist-test/src/core/mod.mist b/mist-test/src/core/mod.mist deleted file mode 100644 index 9de044b..0000000 --- a/mist-test/src/core/mod.mist +++ /dev/null @@ -1,5 +0,0 @@ -mod app; -mod task; -mod plugin; -mod logger; -mod event; \ No newline at end of file diff --git a/mist-test/src/core/event.mist b/mist-test/src/event.mist similarity index 100% rename from mist-test/src/core/event.mist rename to mist-test/src/event.mist diff --git a/mist-test/src/core/logger.mist b/mist-test/src/logger.mist similarity index 100% rename from mist-test/src/core/logger.mist rename to mist-test/src/logger.mist diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 36a5934..688fbde 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -1,6 +1,10 @@ -mod core; +mod app; +mod task; +mod plugin; +mod logger; +mod event; -use ; +use ; // use ; // use ; diff --git a/mist-test/src/core/plugin.mist b/mist-test/src/plugin.mist similarity index 100% rename from mist-test/src/core/plugin.mist rename to mist-test/src/plugin.mist diff --git a/mist-test/src/core/task.mist b/mist-test/src/task.mist similarity index 100% rename from mist-test/src/core/task.mist rename to mist-test/src/task.mist diff --git a/src/codegen.rs b/src/codegen.rs index 532f069..437a99f 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -1,7 +1,7 @@ use parser::ast::{ - Attribute, BinaryOp, Block, EnumItem, Expression, FunctionDecl, Generics, Identifier, Literal, - Path, Pattern, Postfix, Prefix, Statement, StatementBranch, TopLevel, TopLevelKind, TypeExpr, - TypeExprKind, TypePostfix, VarAssignStmt, VarDecl, VarDeclStmt, Visibility, + 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, }; // --------------------------------------------------------------------------- @@ -383,7 +383,20 @@ impl ToRust for TopLevelKind { cg.addln("}\n"); // Constructor - cg.addln(&format!("impl {} {{", name.get_rust())); + cg.addln(&format!( + "impl{} {}{} {{", + generics.get_rust(), + name.get_rust(), + format!( + "<{}>", + generics + .0 + .iter() + .map(|v| (false, v).get_rust()) + .collect::>() + .join(", ") + ) + )); cg.indent += 1; let params_str = constructor @@ -725,24 +738,7 @@ impl GetRust for Generics { "<{}>", self.0 .iter() - .map(|generic| match generic { - parser::ast::Generic::Lifetime(name) => format!("'{}", name.get_rust()), - parser::ast::Generic::Type(name, requirements) => { - name.get_rust() - + &(if requirements.len() == 0 { - String::new() - } else { - format!( - ": {}", - requirements - .iter() - .map(TypeExpr::get_rust) - .collect::>() - .join("+") - ) - }) - } - }) + .map(|v| (true, v).get_rust()) .collect::>() .join(", ") ) @@ -750,6 +746,29 @@ impl GetRust for Generics { } } +impl GetRust for (bool, &Generic) { + fn get_rust(&self) -> String { + match &self.1 { + Generic::Lifetime(name) => format!("'{}", name.get_rust()), + Generic::Type(name, requirements) => { + name.get_rust() + + &(if !self.0 && requirements.len() == 0 { + String::new() + } else { + format!( + ": {}", + requirements + .iter() + .map(TypeExpr::get_rust) + .collect::>() + .join("+") + ) + }) + } + } + } +} + pub fn get_static_type_path(path: &Path) -> String { let rust_path = path.get_rust(); From d3b6e88b14dd0188aa4878a9660af47e4f7b2415 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 10 May 2026 04:03:50 +0200 Subject: [PATCH 13/13] Running simple app --- mist-test/src/app.mist | 4 ++-- mist-test/src/main.mist | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/mist-test/src/app.mist b/mist-test/src/app.mist index f19c4f4..3ffd4ec 100644 --- a/mist-test/src/app.mist +++ b/mist-test/src/app.mist @@ -13,8 +13,8 @@ public class Application { bool running; i32 ticks; - public constructor(String name) { - self.name = name; + public constructor(str* name) { + self.name = name.to_string(); self.tasks = new Vec(); self.plugins = new Vec(); diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 688fbde..8b0ab54 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -4,16 +4,12 @@ mod plugin; mod logger; mod event; -use ; -// use ; -// use ; - void main() { - var app = new app::Application("mist-app"); + var mut app_instance = new app::Application("mist-app"); - // greeting::register(&mut app); - // statistics::register(&mut app); + // greeting::register(&mut app_instance); + // statistics::register(&mut app_instance); - app.boot(); - app.run(); + app_instance.boot(); + app_instance.run(); } \ No newline at end of file