From 3ddb1bc601081b02799506dcaae3ada656742a4a Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 28 Jun 2026 05:24:30 +0200 Subject: [PATCH 1/5] Unsafe pointer --- crates/codegen/src/fmt/mod.rs | 21 +++++---------- crates/codegen/src/lib.rs | 24 +++++------------ crates/parser/src/ast/mod.rs | 8 +----- crates/parser/src/grammar.pest | 11 ++++---- crates/parser/src/parser/common/types.rs | 31 +++++++++++++++------- crates/parser/src/parser/items/function.rs | 17 +----------- 6 files changed, 44 insertions(+), 68 deletions(-) diff --git a/crates/codegen/src/fmt/mod.rs b/crates/codegen/src/fmt/mod.rs index 6da4bdd..f549491 100644 --- a/crates/codegen/src/fmt/mod.rs +++ b/crates/codegen/src/fmt/mod.rs @@ -176,7 +176,7 @@ impl GetMist for TypeExpr { } Self::UnsafePtr { mutable, ty } => { let mutable = if *mutable { "mut " } else { "const " }; - format!("*{mutable}{}", ty.get_mist()) + format!("{} {mutable} unsafe&", ty.get_mist()) } Self::Ref { lifetime, @@ -185,19 +185,12 @@ impl GetMist for TypeExpr { } => { let base = ty.get_mist(); if let Some(lifetime) = lifetime { - match lifetime { - Lifetime::Lifetime(v) => { - format!( - "{} {} '{}&", - base, - if *mutable { "mut" } else { "" }, - v.get_mist() - ) - } - Lifetime::Unsafe => { - format!("{} {} unsafe&", base, if *mutable { "mut" } else { "const" }) - } - } + format!( + "{} {} '{}&", + base, + if *mutable { "mut" } else { "" }, + lifetime.get_mist() + ) } else if *mutable { format!("{} mut&", base) } else { diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 6323b91..9919ac3 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -239,6 +239,7 @@ impl GetRust for TypeExpr { Self::UnsafePtr { mutable, ty } => { let mutable = if *mutable { "mut " } else { "const " }; format!("*{mutable}{}", ty.get_rust()) + } Self::Ref { @@ -247,23 +248,12 @@ impl GetRust for TypeExpr { ty, } => { if let Some(lifetime) = lifetime { - match lifetime { - Lifetime::Lifetime(v) => { - format!( - "&'{} {}{}", - v.get_rust(), - if *mutable { "mut " } else { "" }, - ty.get_rust() - ) - } - Lifetime::Unsafe => { - format!( - "*{} {}", - if *mutable { "mut" } else { "const" }, - ty.get_rust() - ) - } - } + format!( + "&'{} {}{}", + lifetime.get_rust(), + if *mutable { "mut " } else { "" }, + ty.get_rust() + ) } else { format!("&{}{}", if *mutable { "mut " } else { "" }, ty.get_rust()) } diff --git a/crates/parser/src/ast/mod.rs b/crates/parser/src/ast/mod.rs index 7de3984..5c61cb3 100644 --- a/crates/parser/src/ast/mod.rs +++ b/crates/parser/src/ast/mod.rs @@ -17,16 +17,10 @@ pub struct Identifier(pub String); #[derive(Debug, Clone, Serialize, Default)] pub struct ParamList(pub Vec); -#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] -pub enum Lifetime { - Lifetime(Identifier), - Unsafe, -} - #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub enum TypeExpr { Ref { - lifetime: Option, + lifetime: Option, mutable: bool, ty: Box, }, diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index ae5c4bc..ad70449 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -81,7 +81,6 @@ module_program = { visibility = { "pub" ~ ("(" ~ static_path ~ ")")? } mutable = { "mut" } -unsafe_kw = { "unsafe" } // ====================================================== // GENERICS @@ -104,10 +103,12 @@ path_type = { static_path ~ generics? } -ref_lifetime = { lifetime | unsafe_kw } +unsafe_ref_type = { + mutable? ~ "unsafe" ~ "*" +} ref_type = { - mutable? ~ ref_lifetime? ~ "&" + mutable? ~ lifetime? ~ "&" } dyn_type = { @@ -115,7 +116,7 @@ dyn_type = { } type_expr = { - (path_type | tuple_type | dyn_type) ~ ref_type* + (path_type | tuple_type | dyn_type) ~ (unsafe_ref_type | ref_type)* } lifetime = { @@ -467,7 +468,7 @@ match_stmt = { closure = { ("(" ~ param_list ~ ")" ~ "=>" ~ expr) - | (type_expr ~ "(" ~ param_list ~ ")" ~ "=>" ~ expr) + | (type_expr ~ "(" ~ param_list ~ ")" ~ "=>" ~ expr) } // ------------------------------------------------------ diff --git a/crates/parser/src/parser/common/types.rs b/crates/parser/src/parser/common/types.rs index adf253d..fbca7ea 100644 --- a/crates/parser/src/parser/common/types.rs +++ b/crates/parser/src/parser/common/types.rs @@ -21,16 +21,29 @@ impl<'a> TryFrom> for TypeExpr { let mut ty = TypeExpr::try_from(inner.next().unwrap())?; for ref_pair in inner { - let mut ref_inner = ref_pair.into_inner(); + let mut ref_inner = ref_pair.clone().into_inner(); - ty = TypeExpr::Ref { - lifetime: consume_rule(&mut ref_inner, Rule::ref_lifetime) - .map(|v| v.into_inner().next().map(Lifetime::try_from)) - .unwrap_or_default() - .transpose()?, - mutable: listen_rule(&mut ref_inner, Rule::mutable), - ty: Box::new(ty), - }; + match ref_pair.as_rule() { + Rule::ref_type => { + ty = TypeExpr::Ref { + mutable: listen_rule(&mut ref_inner, Rule::mutable), + lifetime: consume_rule(&mut ref_inner, Rule::lifetime) + .map(|v| v.into_inner().next().map(Identifier::try_from)) + .unwrap_or_default() + .transpose()?, + ty: Box::new(ty), + }; + } + + Rule::unsafe_ref_type => { + ty = TypeExpr::UnsafePtr { + mutable: listen_rule(&mut ref_inner, Rule::mutable), + ty: Box::new(ty), + }; + } + + _ => AstError::bug_unimplemented(ref_pair)?, + } } Ok(ty) diff --git a/crates/parser/src/parser/items/function.rs b/crates/parser/src/parser/items/function.rs index dca1d06..7c7ac46 100644 --- a/crates/parser/src/parser/items/function.rs +++ b/crates/parser/src/parser/items/function.rs @@ -2,7 +2,7 @@ use crate::{ Rule, ast::*, ast_ensure, - error::{self, AstError, AstResult}, + error::{AstError, AstResult}, parser::{consume_rule, consume_rule_map, listen_rule}, }; @@ -66,18 +66,3 @@ impl<'a> TryFrom> for Override { }) } } - -impl<'a> TryFrom> for Lifetime { - type Error = AstError<'a>; - - fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { - let mut inner = pair.clone().into_inner(); - - match pair.as_rule() { - Rule::ref_lifetime => inner.next().unwrap().try_into(), - Rule::lifetime => Ok(Lifetime::Lifetime(inner.next().unwrap().try_into()?)), - Rule::unsafe_kw => Ok(Lifetime::Unsafe), - _ => error::AstError::bug_unimplemented(pair), - } - } -} From 76541040c9c2f25674de31819f48ddb12b5ee1d2 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 28 Jun 2026 05:45:13 +0200 Subject: [PATCH 2/5] Function types --- crates/codegen/src/fmt/mod.rs | 29 ++++++++++++++++++++++ crates/codegen/src/lib.rs | 31 +++++++++++++++++++++++- crates/parser/src/ast/mod.rs | 14 +++++++++++ crates/parser/src/grammar.pest | 24 +++++++++++++++++- crates/parser/src/parser/common/types.rs | 6 +++++ mist-test/src/main.mist | 2 ++ 6 files changed, 104 insertions(+), 2 deletions(-) diff --git a/crates/codegen/src/fmt/mod.rs b/crates/codegen/src/fmt/mod.rs index f549491..0dd8128 100644 --- a/crates/codegen/src/fmt/mod.rs +++ b/crates/codegen/src/fmt/mod.rs @@ -200,10 +200,39 @@ impl GetMist for TypeExpr { Self::Dyn(ty) => { format!("dyn {}", ty.get_mist()) } + Self::Fn { + kind, + return_type, + params, + } => { + format!( + "{} {}({})", + return_type.get_mist(), + kind.get_mist(), + params + .iter() + .map(TypeExpr::get_mist) + .collect::>() + .join(", ") + ) + } } } } +impl GetMist for FnKind { + fn get_mist(&self) -> String { + match self { + Self::Fn => "fn", + Self::UnsafeFn => "unsafe fn", + Self::FnClosure => "Fn", + Self::FnMut => "FnMut", + Self::FnOnce => "FnOnce", + } + .to_string() + } +} + impl GetMist for ExprPath { fn get_mist(&self) -> String { self.0 diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 9919ac3..cd11bf1 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -239,7 +239,6 @@ impl GetRust for TypeExpr { Self::UnsafePtr { mutable, ty } => { let mutable = if *mutable { "mut " } else { "const " }; format!("*{mutable}{}", ty.get_rust()) - } Self::Ref { @@ -262,10 +261,40 @@ impl GetRust for TypeExpr { Self::Dyn(ty) => { format!("dyn {}", ty.get_rust()) } + + Self::Fn { + kind, + return_type, + params, + } => { + format!( + "{} -> {}({})", + kind.get_rust(), + return_type.get_rust(), + params + .iter() + .map(TypeExpr::get_rust) + .collect::>() + .join(", ") + ) + } } } } +impl GetRust for FnKind { + fn get_rust(&self) -> String { + match self { + Self::Fn => "fn", + Self::UnsafeFn => "unsafe fn", + Self::FnClosure => "Fn", + Self::FnMut => "FnMut", + Self::FnOnce => "FnOnce", + } + .to_string() + } +} + impl GenRust for Pattern { fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { match self { diff --git a/crates/parser/src/ast/mod.rs b/crates/parser/src/ast/mod.rs index 5c61cb3..429c9c0 100644 --- a/crates/parser/src/ast/mod.rs +++ b/crates/parser/src/ast/mod.rs @@ -17,6 +17,15 @@ pub struct Identifier(pub String); #[derive(Debug, Clone, Serialize, Default)] pub struct ParamList(pub Vec); +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] +pub enum FnKind { + Fn, + UnsafeFn, + FnClosure, + FnOnce, + FnMut, +} + #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub enum TypeExpr { Ref { @@ -33,6 +42,11 @@ pub enum TypeExpr { StaticFn(Vec, Option>), Tuple(Vec), Lifetime(Identifier), + Fn { + kind: FnKind, + return_type: Box, + params: Vec, + }, } #[derive(Debug, Clone, Serialize)] diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index ad70449..4cfbbe1 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -111,12 +111,34 @@ ref_type = { mutable? ~ lifetime? ~ "&" } +fn_kind_fn = { "fn" } +fn_kind_unsafe = { "unsafe" ~ "fn" } +fn_kind_closure = { "Fn" } +fn_kind_once = { "FnOnce" } +fn_kind_mut = { "FnMut" } + +fn_kind = _{ + fn_kind_fn + | fn_kind_unsafe + | fn_kind_closure + | fn_kind_once + | fn_kind_mut +} + +fn_type = { + fn_kind ~ "(" ~ (type_expr ~ ("," ~ type_expr)*)? ~ ")" +} + dyn_type = { "dyn" ~ type_expr } +void_type = { + "void" +} + type_expr = { - (path_type | tuple_type | dyn_type) ~ (unsafe_ref_type | ref_type)* + (void_type | path_type | tuple_type | dyn_type) ~ (unsafe_ref_type | ref_type | fn_type)* } lifetime = { diff --git a/crates/parser/src/parser/common/types.rs b/crates/parser/src/parser/common/types.rs index fbca7ea..64b032d 100644 --- a/crates/parser/src/parser/common/types.rs +++ b/crates/parser/src/parser/common/types.rs @@ -42,6 +42,10 @@ impl<'a> TryFrom> for TypeExpr { }; } + Rule::fn_type => { + + } + _ => AstError::bug_unimplemented(ref_pair)?, } } @@ -50,7 +54,9 @@ impl<'a> TryFrom> for TypeExpr { } Rule::lifetime => Ok(TypeExpr::Lifetime(inner.next().unwrap().try_into()?)), + Rule::void_type => Ok(TypeExpr::Tuple(Vec::new())), Rule::tuple_type => Ok(TypeExpr::Tuple(collect_recovered(inner)?)), + Rule::path_type => Ok(TypeExpr::Path( Path::try_from(inner.next().unwrap())?, inner.next().map(Generics::try_from).transpose()?, diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index e5fd2e4..689fc94 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -15,4 +15,6 @@ void main() items::impl_test::run_tests(); items::attribute_test::run_tests(); println!("\x1b[32m\nAll tests passed!\x1b[0m"); + + void fn() hello = () => {}; } From dbfcaa9b0d756a06a63db562cff80886ff22ffd6 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 28 Jun 2026 05:49:35 +0200 Subject: [PATCH 3/5] Void type --- crates/codegen/src/fmt/mod.rs | 1 + crates/codegen/src/lib.rs | 2 +- crates/parser/src/ast/mod.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/codegen/src/fmt/mod.rs b/crates/codegen/src/fmt/mod.rs index 0dd8128..b714300 100644 --- a/crates/codegen/src/fmt/mod.rs +++ b/crates/codegen/src/fmt/mod.rs @@ -200,6 +200,7 @@ impl GetMist for TypeExpr { Self::Dyn(ty) => { format!("dyn {}", ty.get_mist()) } + Self::Void => "void".to_string(), Self::Fn { kind, return_type, diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index cd11bf1..064e822 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -261,7 +261,7 @@ impl GetRust for TypeExpr { Self::Dyn(ty) => { format!("dyn {}", ty.get_rust()) } - + Self::Void => "()".to_string(), Self::Fn { kind, return_type, diff --git a/crates/parser/src/ast/mod.rs b/crates/parser/src/ast/mod.rs index 429c9c0..44ab48d 100644 --- a/crates/parser/src/ast/mod.rs +++ b/crates/parser/src/ast/mod.rs @@ -42,6 +42,7 @@ pub enum TypeExpr { StaticFn(Vec, Option>), Tuple(Vec), Lifetime(Identifier), + Void, Fn { kind: FnKind, return_type: Box, From a2fc8a49225ca10de299a3beb6152a8f7f1dc441 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 28 Jun 2026 06:00:11 +0200 Subject: [PATCH 4/5] AST gen for function type --- crates/parser/src/parser/common/types.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/crates/parser/src/parser/common/types.rs b/crates/parser/src/parser/common/types.rs index 64b032d..6726f41 100644 --- a/crates/parser/src/parser/common/types.rs +++ b/crates/parser/src/parser/common/types.rs @@ -43,7 +43,11 @@ impl<'a> TryFrom> for TypeExpr { } Rule::fn_type => { - + ty = TypeExpr::Fn { + return_type: Box::new(ty), + kind: ref_inner.next().unwrap().try_into()?, + params: collect_recovered(ref_inner)?, + }; } _ => AstError::bug_unimplemented(ref_pair)?, @@ -54,7 +58,7 @@ impl<'a> TryFrom> for TypeExpr { } Rule::lifetime => Ok(TypeExpr::Lifetime(inner.next().unwrap().try_into()?)), - Rule::void_type => Ok(TypeExpr::Tuple(Vec::new())), + Rule::void_type => Ok(TypeExpr::Void), Rule::tuple_type => Ok(TypeExpr::Tuple(collect_recovered(inner)?)), Rule::path_type => Ok(TypeExpr::Path( @@ -71,6 +75,22 @@ impl<'a> TryFrom> for TypeExpr { } } +impl<'a> TryFrom> for FnKind { + type Error = AstError<'a>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + match pair.as_rule() { + Rule::fn_kind_fn => Ok(FnKind::Fn), + Rule::fn_kind_unsafe => Ok(FnKind::UnsafeFn), + Rule::fn_kind_closure => Ok(FnKind::FnClosure), + Rule::fn_kind_once => Ok(FnKind::FnOnce), + Rule::fn_kind_mut => Ok(FnKind::FnMut), + + _ => AstError::bug_unimplemented(pair), + } + } +} + impl<'a> TryFrom> for GenericsDecl { type Error = AstError<'a>; From a867dbc7975f56784b24410dbcbf5bec5f68a73b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sun, 28 Jun 2026 06:04:39 +0200 Subject: [PATCH 5/5] Fixed codegen for function type --- crates/codegen/src/lib.rs | 6 +++--- mist-test/src/main.mist | 2 -- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index 064e822..3e0610a 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -268,14 +268,14 @@ impl GetRust for TypeExpr { params, } => { format!( - "{} -> {}({})", + "{}({}) -> {}", kind.get_rust(), - return_type.get_rust(), params .iter() .map(TypeExpr::get_rust) .collect::>() - .join(", ") + .join(", "), + return_type.get_rust(), ) } } diff --git a/mist-test/src/main.mist b/mist-test/src/main.mist index 689fc94..e5fd2e4 100644 --- a/mist-test/src/main.mist +++ b/mist-test/src/main.mist @@ -15,6 +15,4 @@ void main() items::impl_test::run_tests(); items::attribute_test::run_tests(); println!("\x1b[32m\nAll tests passed!\x1b[0m"); - - void fn() hello = () => {}; }