From 03478920565da999ccf78307cb425ee14835741b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 12:30:22 +0200 Subject: [PATCH 01/12] Override(path) syntax --- crates/codegen/src/class_decl.rs | 10 +++++----- crates/parser/src/ast/top_level.rs | 5 ++++- crates/parser/src/grammar.pest | 2 +- crates/parser/src/parser/items/function.rs | 12 +++++++++++- 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 73f7713..237c293 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -81,7 +81,7 @@ pub fn class_decl( let v_table = methods .iter() .filter_map(|method| match method.item.visibility { - Visibility::Public => Some((method.item.name.clone(), method.item.is_override)), + Visibility::Public => Some((method.item.name.clone(), method.item.is_override.clone())), _ => None, }) .collect::>(); @@ -126,7 +126,7 @@ pub fn class_decl( cg.addln("::__V_TABLE;"); for (name, is_override) in v_table { - if is_override { + if is_override.is_some() { cg.add_indentedln(&format!( "table[{}::__FN_{}] = Self::__m_{} as *const std::ffi::c_void;", inherits.get_rust(), @@ -145,7 +145,7 @@ pub fn class_decl( cg.indent += 1; for i in &methods { - if i.item.is_override { + if i.item.is_override.is_some() { let mut params = i .item .params @@ -200,7 +200,7 @@ pub fn class_decl( for mut method in methods { match method.item.visibility { Visibility::Public => { - if !method.item.is_override { + if method.item.is_override.is_none() { gen_method_point(&method.item, ctx, cg); } @@ -358,7 +358,7 @@ impl GenRust column: self.1.column, item: FunctionDecl { visibility: self.1.item.visibility.clone(), - is_override: false, + is_override: None, name: Identifier(String::from("constructor")), generics: self.1.item.generics.clone(), params: ParamList(constructor_params), diff --git a/crates/parser/src/ast/top_level.rs b/crates/parser/src/ast/top_level.rs index f6fe296..b1196b6 100644 --- a/crates/parser/src/ast/top_level.rs +++ b/crates/parser/src/ast/top_level.rs @@ -91,10 +91,13 @@ pub struct ClassConstructor { pub body: Block, } +#[derive(Debug, Clone, Serialize)] +pub struct Override(pub Option); + #[derive(Debug, Clone, Serialize)] pub struct FunctionDecl { pub visibility: Visibility, - pub is_override: bool, + pub is_override: Option, pub name: Identifier, pub generics: GenericsDecl, pub params: ParamList, diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 3c20825..3a0d648 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -325,7 +325,7 @@ trait_decl = { // FUNCTIONS // ====================================================== -override_kw = { "override" } +override_kw = { "override" ~ ("(" ~ expr_path ~ ")")? } function_decl = { visibility? ~ override_kw? ~ "fn" ~ identifier ~ generics_decl? ~ "(" ~ method_args ~ ")" ~ type_expr? ~ (block | semicolon) diff --git a/crates/parser/src/parser/items/function.rs b/crates/parser/src/parser/items/function.rs index 4e68469..18b720b 100644 --- a/crates/parser/src/parser/items/function.rs +++ b/crates/parser/src/parser/items/function.rs @@ -13,7 +13,7 @@ impl<'a> TryFrom> for FunctionDecl { ast_ensure!(pair, Rule::function_decl => { let mut inner = pair.into_inner(); let visibility = Visibility::try_from(&mut inner); - let is_override: AstResult = Ok(listen_rule(&mut inner, Rule::override_kw)); + let is_override = consume_rule(&mut inner, Rule::override_kw).map(Override::try_from).transpose(); let name = Identifier::try_from(inner.next().unwrap()); let generics = consume_rule(&mut inner, Rule::generics_decl) @@ -77,3 +77,13 @@ impl<'a> TryFrom> for FunctionDecl { }) } } + +impl<'a> TryFrom> for Override { + type Error = AstError<'a, Self>; + + fn try_from(pair: pest::iterators::Pair<'a, Rule>) -> Result { + ast_ensure!(pair, Rule::override_kw => { + ast_expr!(Override(pair.into_inner().next().map(ExprPath::try_from).transpose())) + }) + } +} From a9f6cce1b3825612e8f1e69af8e3fbfddd4bee94 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 13:51:32 +0200 Subject: [PATCH 02/12] Improved override --- crates/codegen/src/class_decl.rs | 38 +++++++++++---------------- crates/codegen/src/expr.rs | 12 +-------- crates/codegen/src/lib.rs | 2 +- crates/parser/src/ast/top_level.rs | 2 +- crates/parser/src/grammar.pest | 2 +- crates/parser/src/parser/items/mod.rs | 4 +-- mist-test/src/items/class_test.mist | 2 +- 7 files changed, 23 insertions(+), 39 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 237c293..432142c 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -11,18 +11,12 @@ pub fn class_decl( visibility: &Visibility, name: &Identifier, generics: &GenericsDecl, - inherits: &Option, + inherits: &Option, fields: &Vec>, constructor: &Spanned, items: &Vec, ) { - let inherits = if let Some(inherits) = inherits { - let path = get_type_path(inherits); - ctx.expr_super = Some(path.clone()); - Some((inherits, path)) - } else { - None - }; + ctx.expr_super = inherits.clone(); // Struct decl cg.addln(&format!( @@ -37,9 +31,9 @@ pub fn class_decl( "pub _m_oop: (&'static [*const std::ffi::c_void; Self::__V_COUNT], *mut std::ffi::c_void),", ); - if let Some((inherits, _)) = inherits { + if let Some(inherits) = inherits { cg.add_indented("pub _super: Box<"); - cg.add(&inherits.get_rust()); + cg.add(&get_type_from_path(inherits).get_rust()); cg.addln(">,"); } @@ -112,7 +106,7 @@ pub fn class_decl( } // Super V Table - if let Some((inherits, inherit_path)) = &inherits { + if let Some(inherits) = &inherits { cg.add_indented(&format!( "pub const __SUPER_V_TABLE: [*const std::ffi::c_void; {}", inherits.get_rust() @@ -161,7 +155,7 @@ pub fn class_decl( match params.remove(0) { TypeExpr::Ref { mutable, .. } => { - cg.add_indented(&inherit_path.get_rust()); + cg.add_indented(&inherits.get_rust()); cg.add("::__m_"); cg.add(&i.item.name.get_rust()); cg.add(" as "); @@ -171,7 +165,7 @@ pub fn class_decl( TypeExpr::Ref { lifetime: None, mutable: mutable, - ty: Box::new((*inherits).clone()), + ty: Box::new(get_type_from_path(inherits)), }, ); @@ -229,7 +223,7 @@ pub fn class_decl( } } - if let Some((inherits, _)) = inherits { + if let Some(inherits) = inherits { cg.add("impl std::ops::Deref for "); cg.add(&name.get_rust()); @@ -451,12 +445,12 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC cg.add_indentedln("}"); } -pub fn get_type_path(ty: &TypeExpr) -> Path { - match ty { - TypeExpr::Path(p, _) => p.clone(), - TypeExpr::Dyn(v) => get_type_path(v), - TypeExpr::Ref { ty, .. } => get_type_path(ty), - TypeExpr::UnsafePtr { ty, .. } => get_type_path(ty), - _ => unimplemented!(), - } +pub fn get_type_from_path(path: &ExprPath) -> TypeExpr { + let last = path.0.last().unwrap(); + + let mut path = path.0.iter().map(|v| v.ident.clone()).collect::>(); + + path.push(last.ident.clone()); + + TypeExpr::Path(Path(path), last.generics.clone()) } diff --git a/crates/codegen/src/expr.rs b/crates/codegen/src/expr.rs index e4e2701..f6fb129 100644 --- a/crates/codegen/src/expr.rs +++ b/crates/codegen/src/expr.rs @@ -20,17 +20,7 @@ impl GetRust for ExprPath { if self.0[0].ident.0 == "super" && self.0.len() == 1 { a.0[0].ident.0 = String::from("self._super"); } else if self.0[0].ident.0 == "Super" { - a.0[0].ident = path.0[0].clone(); - - if path.0.len() > 1 { - a.0.splice( - 1..1, - path.0.clone().into_iter().skip(1).map(|v| ExprPathSegment { - ident: v, - generics: None, - }), - ); - } + a.0[0] = path.0[0].clone(); } } diff --git a/crates/codegen/src/lib.rs b/crates/codegen/src/lib.rs index f6c466b..cbcc7ef 100644 --- a/crates/codegen/src/lib.rs +++ b/crates/codegen/src/lib.rs @@ -7,7 +7,7 @@ use mist_parser::ast::*; pub struct Context { pub expr_ensure_semicolon: bool, - pub expr_super: Option, + pub expr_super: Option, } pub trait GenRust { diff --git a/crates/parser/src/ast/top_level.rs b/crates/parser/src/ast/top_level.rs index b1196b6..5bb6ed1 100644 --- a/crates/parser/src/ast/top_level.rs +++ b/crates/parser/src/ast/top_level.rs @@ -54,7 +54,7 @@ pub enum TopLevelKind { visibility: Visibility, name: Identifier, generics: GenericsDecl, - inherits: Option, + inherits: Option, fields: Vec>, constructor: Spanned, items: Vec, diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 3a0d648..67ab7d8 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -294,7 +294,7 @@ class_item = _{ } class_decl = { - visibility? ~ "class" ~ identifier ~ generics_decl? ~ (":" ~ type_expr)? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}" + visibility? ~ "class" ~ identifier ~ generics_decl? ~ (":" ~ expr_path)? ~ "{" ~ class_fields ~ class_constructor ~ class_item* ~ "}" } // ====================================================== diff --git a/crates/parser/src/parser/items/mod.rs b/crates/parser/src/parser/items/mod.rs index 7b49a1a..ebaf0a4 100644 --- a/crates/parser/src/parser/items/mod.rs +++ b/crates/parser/src/parser/items/mod.rs @@ -69,8 +69,8 @@ impl<'a> TryFrom> for TopLevelKind { .transpose() .map(|v| v.unwrap_or_default()), - inherits: consume_rule(&mut inner, Rule::type_expr) - .map(TypeExpr::try_from) + inherits: consume_rule(&mut inner, Rule::expr_path) + .map(ExprPath::try_from) .transpose(), fields: collect_recovered(inner.next().unwrap().into_inner()), diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index b95f19d..ad6c555 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -21,7 +21,7 @@ pub class Dog : Animal { } } - pub override fn speak(*self) { + pub override(Animal) fn speak(*self) { println!("Woof!"); } } From 9206ca440e12c3ffc982fbe175c23512a243fc85 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 14:27:27 +0200 Subject: [PATCH 03/12] Improved override --- crates/codegen/src/class_decl.rs | 39 ++++++++++++++------------------ crates/parser/src/ast/mod.rs | 16 +++++++++++++ 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 432142c..e32a894 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -18,6 +18,13 @@ pub fn class_decl( ) { ctx.expr_super = inherits.clone(); + let self_path = ExprPath(vec![ExprPathSegment { + ident: name.clone(), + generics: generics.clone().into(), + }]); + + let self_ty = get_type_from_path(&self_path); + // Struct decl cg.addln(&format!( "{}struct {}{} {{", @@ -27,9 +34,10 @@ pub fn class_decl( )); cg.indent += 1; - cg.add_indentedln( - "pub _m_oop: (&'static [*const std::ffi::c_void; Self::__V_COUNT], *mut std::ffi::c_void),", - ); + cg.add_indentedln(&format!( + "pub _m_oop: (&'static [*const std::ffi::c_void; {}::__V_COUNT], *mut std::ffi::c_void),", + self_path.get_rust() + )); if let Some(inherits) = inherits { cg.add_indented("pub _super: Box<"); @@ -47,19 +55,9 @@ pub fn class_decl( // Constructor cg.addln(&format!( - "impl{} {}{} {{", + "impl{} {} {{", generics.clone().get_rust(), - name.clone().get_rust(), - format!( - "<{}>", - generics - .clone() - .0 - .into_iter() - .map(|v| Generic::from(v).get_rust()) - .collect::>() - .join(", ") - ) + self_ty.get_rust() )); cg.indent += 1; @@ -446,11 +444,8 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC } pub fn get_type_from_path(path: &ExprPath) -> TypeExpr { - let last = path.0.last().unwrap(); - - let mut path = path.0.iter().map(|v| v.ident.clone()).collect::>(); - - path.push(last.ident.clone()); - - TypeExpr::Path(Path(path), last.generics.clone()) + TypeExpr::Path( + Path(path.0.iter().map(|v| v.ident.clone()).collect::>()), + path.0.last().unwrap().generics.clone(), + ) } diff --git a/crates/parser/src/ast/mod.rs b/crates/parser/src/ast/mod.rs index 89b12fb..fbfbf27 100644 --- a/crates/parser/src/ast/mod.rs +++ b/crates/parser/src/ast/mod.rs @@ -51,6 +51,22 @@ impl From for Generic { } } +impl Into> for GenericsDecl { + fn into(self) -> Option { + if self.0.len() == 0 { + None + } else { + Some(self.into()) + } + } +} + +impl From for Generics { + fn from(value: GenericsDecl) -> Self { + Self(value.0.into_iter().map(Generic::from).collect()) + } +} + impl Spanned { pub fn get_comment(&self) -> String { format!("/* {}:{} */", self.line, self.column) From 0215e295b5c71be1885ee870dccc7323355c5514 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 14:47:41 +0200 Subject: [PATCH 04/12] Working with generics --- crates/codegen/src/class_decl.rs | 46 ++++++++++++++++------------- mist-test/src/items/class_test.mist | 5 ++-- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index e32a894..e6027ba 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -25,6 +25,23 @@ pub fn class_decl( let self_ty = get_type_from_path(&self_path); + let methods = items + .clone() + .into_iter() + .filter_map(|item| match item { + ClassItem::ImplDecl(_) => None, + ClassItem::Method(method) => Some(method), + }) + .collect::>(); + + let v_table = methods + .iter() + .filter_map(|method| match method.item.visibility { + Visibility::Public => Some((method.item.name.clone(), method.item.is_override.clone())), + _ => None, + }) + .collect::>(); + // Struct decl cg.addln(&format!( "{}struct {}{} {{", @@ -35,8 +52,8 @@ pub fn class_decl( cg.indent += 1; cg.add_indentedln(&format!( - "pub _m_oop: (&'static [*const std::ffi::c_void; {}::__V_COUNT], *mut std::ffi::c_void),", - self_path.get_rust() + "pub _m_oop: (&'static [*const std::ffi::c_void; {}], *mut std::ffi::c_void),", + v_table.len() )); if let Some(inherits) = inherits { @@ -61,23 +78,6 @@ pub fn class_decl( )); cg.indent += 1; - let methods = items - .clone() - .into_iter() - .filter_map(|item| match item { - ClassItem::ImplDecl(_) => None, - ClassItem::Method(method) => Some(method), - }) - .collect::>(); - - let v_table = methods - .iter() - .filter_map(|method| match method.item.visibility { - Visibility::Public => Some((method.item.name.clone(), method.item.is_override.clone())), - _ => None, - }) - .collect::>(); - // V TABLE { cg.add_indentedln(&format!("pub const __V_COUNT: usize = {};", v_table.len())); @@ -89,7 +89,10 @@ pub fn class_decl( )); } - cg.add_indentedln("pub const __V_TABLE: [*const std::ffi::c_void; Self::__V_COUNT] = ["); + cg.add_indentedln(&format!( + "pub const __V_TABLE: [*const std::ffi::c_void; {}] = [", + v_table.len() + )); cg.indent += 1; for (method_name, _) in &v_table { @@ -120,9 +123,10 @@ pub fn class_decl( for (name, is_override) in v_table { if is_override.is_some() { cg.add_indentedln(&format!( - "table[{}::__FN_{}] = Self::__m_{} as *const std::ffi::c_void;", + "table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;", inherits.get_rust(), name.0.to_uppercase(), + self_path.get_rust(), name.get_rust() )); } diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index ad6c555..ae85717 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -1,5 +1,6 @@ -pub class Animal { +pub class Animal { pub name String; + pub val T; constructor() { self.name = "Rex".to_string(); @@ -14,7 +15,7 @@ pub class Animal { } } -pub class Dog : Animal { +pub class Dog : Animal { constructor() { unsafe { std::ptr::write(&mut super, Super::new()); From f37a1019ae2147688eb42deca1dbf43a40f25379 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 14:56:55 +0200 Subject: [PATCH 05/12] Working improved inheritance generics --- crates/codegen/src/class_decl.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index e6027ba..140e4ac 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -52,8 +52,7 @@ pub fn class_decl( cg.indent += 1; cg.add_indentedln(&format!( - "pub _m_oop: (&'static [*const std::ffi::c_void; {}], *mut std::ffi::c_void),", - v_table.len() + "pub _m_oop: (&'static [*const std::ffi::c_void], *mut std::ffi::c_void),", )); if let Some(inherits) = inherits { @@ -80,8 +79,6 @@ pub fn class_decl( // V TABLE { - cg.add_indentedln(&format!("pub const __V_COUNT: usize = {};", v_table.len())); - for (i, method_name) in v_table.iter().enumerate() { cg.add_indentedln(&format!( "pub const __FN_{}: usize = {i};", @@ -108,12 +105,7 @@ pub fn class_decl( // Super V Table if let Some(inherits) = &inherits { - cg.add_indented(&format!( - "pub const __SUPER_V_TABLE: [*const std::ffi::c_void; {}", - inherits.get_rust() - )); - - cg.addln("::__V_COUNT] = {"); + cg.add_indented("pub const __SUPER_V_TABLE: &'static [*const std::ffi::c_void] = &{"); cg.indent += 1; cg.add_indented("let mut table = "); From e3e6caf4e605854255c3cb3b0ef0d95c904d1e82 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 16:43:52 +0200 Subject: [PATCH 06/12] Refactored class decl generator --- crates/codegen/src/class_decl.rs | 348 ++++++++++++++++++----------- crates/parser/src/ast/expr.rs | 8 +- crates/parser/src/ast/mod.rs | 6 +- crates/parser/src/ast/top_level.rs | 2 +- 4 files changed, 221 insertions(+), 143 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 140e4ac..784ff34 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -1,98 +1,151 @@ use mist_parser::ast::*; -use crate::Context; +use crate::{Context, GenRust, GetRust, RustCodegen}; -use crate::{GenRust, GetRust, RustCodegen}; +// ── Stage 1: Data Collection & Metadata Analysis ────────────────────── -pub fn class_decl( - ctx: &mut Context, - cg: &mut RustCodegen, +pub struct ClassProcessedData { + visibility: Visibility, + name: Identifier, + generics: GenericsDecl, + inherits: Option, + self_path: ExprPath, + self_ty: TypeExpr, + fields: Vec>, + constructor: Spanned, + items: Vec, + methods: Vec>, + v_table: Vec<(Identifier, Option)>, +} - visibility: &Visibility, - name: &Identifier, - generics: &GenericsDecl, - inherits: &Option, - fields: &Vec>, - constructor: &Spanned, - items: &Vec, -) { - ctx.expr_super = inherits.clone(); +impl ClassProcessedData { + pub fn analyze( + visibility: &Visibility, + name: &Identifier, + generics: &GenericsDecl, + inherits: &Option, + fields: &Vec>, + constructor: &Spanned, + items: &Vec, + ) -> Self { + let self_path = ExprPath(vec![ExprPathSegment { + ident: name.clone(), + generics: generics.clone().into(), + }]); - let self_path = ExprPath(vec![ExprPathSegment { - ident: name.clone(), - generics: generics.clone().into(), - }]); + let self_ty = get_type_from_path(&self_path); - let self_ty = get_type_from_path(&self_path); + let methods = items + .clone() + .into_iter() + .filter_map(|item| match item { + ClassItem::ImplDecl(_) => None, + ClassItem::Method(method) => Some(method), + }) + .collect::>(); - let methods = items - .clone() - .into_iter() - .filter_map(|item| match item { - ClassItem::ImplDecl(_) => None, - ClassItem::Method(method) => Some(method), - }) - .collect::>(); + let v_table = methods + .iter() + .filter_map(|method| match method.item.visibility { + Visibility::Public => { + Some((method.item.name.clone(), method.item.is_override.clone())) + } + _ => None, + }) + .collect::>(); - let v_table = methods - .iter() - .filter_map(|method| match method.item.visibility { - Visibility::Public => Some((method.item.name.clone(), method.item.is_override.clone())), - _ => None, - }) - .collect::>(); - - // Struct decl - cg.addln(&format!( - "{}struct {}{} {{", - visibility.get_rust(), - name.clone().get_rust(), - generics.clone().get_rust() - )); - cg.indent += 1; - - cg.add_indentedln(&format!( - "pub _m_oop: (&'static [*const std::ffi::c_void], *mut std::ffi::c_void),", - )); - - if let Some(inherits) = inherits { - cg.add_indented("pub _super: Box<"); - cg.add(&get_type_from_path(inherits).get_rust()); - cg.addln(">,"); + ClassProcessedData { + visibility: visibility.clone(), + name: name.clone(), + generics: generics.clone(), + inherits: inherits.clone(), + self_path, + self_ty, + fields: fields.clone(), + constructor: constructor.clone(), + items: items.clone(), + methods, + v_table, + } } - for field in fields.clone() { - cg.add_indentedln(&field.get_comment()); - cg.add_indentedln(&field.item.decl.get_rust()); + // ── Stage 2: Code Emission ─────────────────────────────────────── + + pub fn emit(&self, ctx: &mut Context, cg: &mut RustCodegen) { + ctx.expr_super = self.inherits.clone(); + + self.emit_struct_decl(cg); + self.emit_impl_block(ctx, cg); + self.emit_impl_decls(ctx, cg); + self.emit_deref_impls(cg); + + ctx.expr_super = None; } - cg.indent -= 1; - cg.addln("}\n"); + fn emit_struct_decl(&self, cg: &mut RustCodegen) { + cg.addln(&format!( + "{}struct {}{} {{", + self.visibility.get_rust(), + self.name.get_rust(), + self.generics.get_rust() + )); + cg.indent += 1; - // Constructor - cg.addln(&format!( - "impl{} {} {{", - generics.clone().get_rust(), - self_ty.get_rust() - )); - cg.indent += 1; + cg.add_indentedln( + "pub _m_oop: (&'static [*const std::ffi::c_void], *mut std::ffi::c_void),", + ); - // V TABLE - { - for (i, method_name) in v_table.iter().enumerate() { + if let Some(ref inherits) = self.inherits { + cg.add_indented("pub _super: Box<"); + cg.add(&get_type_from_path(inherits).get_rust()); + cg.addln(">,"); + } + + for field in &self.fields { + cg.add_indentedln(&field.get_comment()); + cg.add_indentedln(&field.item.decl.get_rust()); + } + + cg.indent -= 1; + cg.addln("}\n"); + } + + fn emit_impl_block(&self, ctx: &mut Context, cg: &mut RustCodegen) { + cg.addln(&format!( + "impl{} {} {{", + self.generics.get_rust(), + self.self_ty.get_rust() + )); + cg.indent += 1; + + self.emit_v_table(cg); + + if let Some(ref inherits) = self.inherits { + self.emit_super_v_table(cg, inherits); + } + + self.emit_constructor(ctx, cg); + self.emit_methods(ctx, cg); + + cg.indent -= 1; + cg.addln("}\n"); + } + + fn emit_v_table(&self, cg: &mut RustCodegen) { + for (i, (method_name, _)) in self.v_table.iter().enumerate() { cg.add_indentedln(&format!( "pub const __FN_{}: usize = {i};", - method_name.0.0.to_uppercase() + method_name.0.to_uppercase() )); } cg.add_indentedln(&format!( "pub const __V_TABLE: [*const std::ffi::c_void; {}] = [", - v_table.len() + self.v_table.len() )); cg.indent += 1; - for (method_name, _) in &v_table { + for (method_name, _) in &self.v_table { cg.add_indented("Self::__m_"); cg.add(&method_name.get_rust()); cg.add(" as *const std::ffi::c_void"); @@ -103,8 +156,7 @@ pub fn class_decl( cg.add_indentedln("];"); } - // Super V Table - if let Some(inherits) = &inherits { + fn emit_super_v_table(&self, cg: &mut RustCodegen, inherits: &ExprPath) { cg.add_indented("pub const __SUPER_V_TABLE: &'static [*const std::ffi::c_void] = &{"); cg.indent += 1; @@ -112,13 +164,13 @@ pub fn class_decl( cg.add(&inherits.get_rust()); cg.addln("::__V_TABLE;"); - for (name, is_override) in v_table { + for (name, is_override) in &self.v_table { if is_override.is_some() { cg.add_indentedln(&format!( "table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;", inherits.get_rust(), name.0.to_uppercase(), - self_path.get_rust(), + self.self_path.get_rust(), name.get_rust() )); } @@ -132,18 +184,18 @@ pub fn class_decl( cg.add_indentedln("const fn __test_vt() {"); cg.indent += 1; - for i in &methods { - if i.item.is_override.is_some() { - let mut params = i + for method in &self.methods { + if method.item.is_override.is_some() { + let mut params = method .item .params - .clone() .0 + .clone() .into_iter() .filter_map(|v| v.type_) .collect::>(); - if params.len() == 0 { + if params.is_empty() { continue; } @@ -151,21 +203,24 @@ pub fn class_decl( TypeExpr::Ref { mutable, .. } => { cg.add_indented(&inherits.get_rust()); cg.add("::__m_"); - cg.add(&i.item.name.get_rust()); + cg.add(&method.item.name.get_rust()); cg.add(" as "); params.insert( 0, TypeExpr::Ref { lifetime: None, - mutable: mutable, + mutable, ty: Box::new(get_type_from_path(inherits)), }, ); cg.add( - &TypeExpr::StaticFn(params, i.item.return_type.clone().map(Box::new)) - .get_rust(), + &TypeExpr::StaticFn( + params, + method.item.return_type.clone().map(Box::new), + ) + .get_rust(), ); cg.addln(";"); } @@ -178,78 +233,101 @@ pub fn class_decl( cg.add_indentedln("}"); } - let constructor_comment = constructor.get_comment(); + fn emit_constructor(&self, ctx: &mut Context, cg: &mut RustCodegen) { + let constructor_comment = self.constructor.get_comment(); - cg.add_indentedln("#[allow(invalid_value)]"); - cg.add_indentedln(&constructor_comment); + cg.add_indentedln("#[allow(invalid_value)]"); + cg.add_indentedln(&constructor_comment); - (fields, constructor, inherits.is_some()).gen_rust(ctx, cg); - - for mut method in methods { - match method.item.visibility { - Visibility::Public => { - if method.item.is_override.is_none() { - gen_method_point(&method.item, ctx, cg); - } - - method.item.name.0.insert_str(0, "__m_"); - } - _ => {} - } - - method.gen_rust(ctx, cg); + (&self.fields, &self.constructor, self.inherits.is_some()).gen_rust(ctx, cg); } - cg.indent -= 1; - cg.addln("}\n"); + fn emit_methods(&self, ctx: &mut Context, cg: &mut RustCodegen) { + for method in &self.methods { + match method.item.visibility { + Visibility::Public => { + if method.item.is_override.is_none() { + gen_method_point(&method.item, ctx, cg); + } - for item in items { - match item { - ClassItem::ImplDecl(impl_) => { + let mut prefixed = method.clone(); + prefixed.item.name.0.insert_str(0, "__m_"); + prefixed.gen_rust(ctx, cg); + } + _ => { + method.gen_rust(ctx, cg); + } + } + } + } + + fn emit_impl_decls(&self, ctx: &mut Context, cg: &mut RustCodegen) { + for item in &self.items { + if let ClassItem::ImplDecl(impl_) = item { let mut impl_ = impl_.clone(); - impl_.item.trait_ = Some(impl_.item.target); - impl_.item.target = TypeExpr::Path(Path(vec![name.clone()]), None); - + impl_.item.target = TypeExpr::Path(Path(vec![self.name.clone()]), None); impl_.gen_rust(ctx, cg); } - ClassItem::Method(_) => {} } } - if let Some(inherits) = inherits { - cg.add("impl std::ops::Deref for "); - cg.add(&name.get_rust()); + fn emit_deref_impls(&self, cg: &mut RustCodegen) { + if let Some(ref inherits) = self.inherits { + cg.add("impl std::ops::Deref for "); + cg.add(&self.name.get_rust()); + cg.addln(" {"); + cg.indent += 1; - cg.addln(" {"); - cg.indent += 1; + cg.add_indented("type Target = "); + cg.add(&inherits.get_rust()); + cg.addln(";"); - cg.add_indented("type Target = "); - cg.add(&inherits.get_rust()); - cg.addln(";"); + cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}"); - cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}"); + cg.indent -= 1; + cg.addln("}"); - cg.indent -= 1; - cg.addln("}"); + cg.add("impl std::ops::DerefMut for "); + cg.add(&self.name.get_rust()); + cg.addln(" {"); + cg.indent += 1; - // Mut + cg.add_indentedln("fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}"); - cg.add("impl std::ops::DerefMut for "); - cg.add(&name.get_rust()); - - cg.addln(" {"); - cg.indent += 1; - - cg.add_indentedln("fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}"); - - cg.indent -= 1; - cg.addln("}"); + cg.indent -= 1; + cg.addln("}"); + } } - - ctx.expr_super = None; } +// ── Public entry point (delegates to the two-stage pipeline) ────────── + +pub fn class_decl( + ctx: &mut Context, + cg: &mut RustCodegen, + visibility: &Visibility, + name: &Identifier, + generics: &GenericsDecl, + inherits: &Option, + fields: &Vec>, + constructor: &Spanned, + items: &Vec, +) { + let data = ClassProcessedData::analyze( + visibility, + name, + generics, + inherits, + fields, + constructor, + items, + ); + data.emit(ctx, cg); +} + +// ── Constructor code generation (kept as a standalone impl) ─────────── + impl GenRust for ( &Vec>, @@ -305,7 +383,7 @@ impl GenRust } } - cg.add_indented(&format!("this.constructor(")); + cg.add_indented("this.constructor("); for (i, param) in params { if i > 0 { diff --git a/crates/parser/src/ast/expr.rs b/crates/parser/src/ast/expr.rs index 04715c6..747ebbf 100644 --- a/crates/parser/src/ast/expr.rs +++ b/crates/parser/src/ast/expr.rs @@ -79,19 +79,19 @@ pub enum Prefix { Neg, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub struct ExprPathSegment { pub ident: Identifier, pub generics: Option, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub struct ExprPath(pub Vec); -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub struct Generics(pub Vec); -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub enum Generic { Lifetime(Identifier), Type(TypeExpr), diff --git a/crates/parser/src/ast/mod.rs b/crates/parser/src/ast/mod.rs index fbfbf27..28e8cf8 100644 --- a/crates/parser/src/ast/mod.rs +++ b/crates/parser/src/ast/mod.rs @@ -8,16 +8,16 @@ pub use expr::*; pub use statement::*; pub use top_level::*; -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub struct Path(pub Vec); -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub struct Identifier(pub String); #[derive(Debug, Clone, Serialize, Default)] pub struct ParamList(pub Vec); -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub enum TypeExpr { Ref { lifetime: Option, diff --git a/crates/parser/src/ast/top_level.rs b/crates/parser/src/ast/top_level.rs index 5bb6ed1..521fb97 100644 --- a/crates/parser/src/ast/top_level.rs +++ b/crates/parser/src/ast/top_level.rs @@ -91,7 +91,7 @@ pub struct ClassConstructor { pub body: Block, } -#[derive(Debug, Clone, Serialize)] +#[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)] pub struct Override(pub Option); #[derive(Debug, Clone, Serialize)] From 72fa94bdc6707ca518237c613d521bd8d7e43ff9 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 17:18:05 +0200 Subject: [PATCH 07/12] Updated VTABLE and constructor --- crates/codegen/src/class_decl.rs | 420 ++++++++++++++++++------------- 1 file changed, 246 insertions(+), 174 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 784ff34..76769f3 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use mist_parser::ast::*; use crate::{Context, GenRust, GetRust, RustCodegen}; @@ -15,7 +17,8 @@ pub struct ClassProcessedData { constructor: Spanned, items: Vec, methods: Vec>, - v_table: Vec<(Identifier, Option)>, + v_table: Vec, + override_v_table: HashMap>, } impl ClassProcessedData { @@ -35,24 +38,36 @@ impl ClassProcessedData { let self_ty = get_type_from_path(&self_path); + // 1. Gather all raw methods from the class items let methods = items - .clone() - .into_iter() + .iter() // Switched to reference iteration to prevent unnecessary cloning .filter_map(|item| match item { ClassItem::ImplDecl(_) => None, - ClassItem::Method(method) => Some(method), + ClassItem::Method(method) => Some(method.clone()), }) - .collect::>(); + .collect::>>(); - let v_table = methods - .iter() - .filter_map(|method| match method.item.visibility { - Visibility::Public => { - Some((method.item.name.clone(), method.item.is_override.clone())) + let mut v_table = Vec::new(); + let mut override_v_table = std::collections::HashMap::new(); + + // 2. Distribute public methods between base table slots and inheritance overrides + for method in &methods { + if matches!(method.item.visibility, Visibility::Public) { + match &method.item.is_override { + // It's a brand new virtual method introduced by this class! + None => { + v_table.push(method.item.name.clone()); + } + // It's an override targeting either the immediate super or a deep ancestor + Some(override_spec) => { + override_v_table + .entry(override_spec.clone()) + .or_insert_with(Vec::new) + .push(method.item.name.clone()); + } } - _ => None, - }) - .collect::>(); + } + } ClassProcessedData { visibility: visibility.clone(), @@ -66,6 +81,7 @@ impl ClassProcessedData { items: items.clone(), methods, v_table, + override_v_table, } } @@ -120,9 +136,8 @@ impl ClassProcessedData { self.emit_v_table(cg); - if let Some(ref inherits) = self.inherits { - self.emit_super_v_table(cg, inherits); - } + self.emit_super_v_table(cg); + self.emit_super_v_tests(cg); self.emit_constructor(ctx, cg); self.emit_methods(ctx, cg); @@ -132,7 +147,7 @@ impl ClassProcessedData { } fn emit_v_table(&self, cg: &mut RustCodegen) { - for (i, (method_name, _)) in self.v_table.iter().enumerate() { + for (i, method_name) in self.v_table.iter().enumerate() { cg.add_indentedln(&format!( "pub const __FN_{}: usize = {i};", method_name.0.to_uppercase() @@ -145,7 +160,7 @@ impl ClassProcessedData { )); cg.indent += 1; - for (method_name, _) in &self.v_table { + for method_name in &self.v_table { cg.add_indented("Self::__m_"); cg.add(&method_name.get_rust()); cg.add(" as *const std::ffi::c_void"); @@ -156,53 +171,108 @@ impl ClassProcessedData { cg.add_indentedln("];"); } - fn emit_super_v_table(&self, cg: &mut RustCodegen, inherits: &ExprPath) { - cg.add_indented("pub const __SUPER_V_TABLE: &'static [*const std::ffi::c_void] = &{"); - cg.indent += 1; - - cg.add_indented("let mut table = "); - cg.add(&inherits.get_rust()); - cg.addln("::__V_TABLE;"); - - for (name, is_override) in &self.v_table { - if is_override.is_some() { - cg.add_indentedln(&format!( - "table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;", - inherits.get_rust(), - name.0.to_uppercase(), - self.self_path.get_rust(), - name.get_rust() - )); - } + fn emit_super_v_table(&self, cg: &mut RustCodegen) { + // If we aren't overriding anything across the tree, we don't need the table array + if self.override_v_table.is_empty() { + return; } - cg.add_indentedln("table"); - - cg.indent -= 1; - cg.add_indentedln("};"); - - cg.add_indentedln("const fn __test_vt() {"); + // 1. Emit the outer 2D array declaration + cg.add_indentedln(&format!( + "pub const __SUPER_V_TABLES: [&'static [*const std::ffi::c_void]; {}] = [", + self.override_v_table.len() + )); cg.indent += 1; - for method in &self.methods { - if method.item.is_override.is_some() { - let mut params = method - .item - .params - .0 - .clone() - .into_iter() - .filter_map(|v| v.type_) - .collect::>(); + // We enumerate over the map so each target class gets a stable outer index + for (override_tier, overriden_method_idents) in &self.override_v_table { + // Resolve the target path for this specific sub-table + let target_path = match &override_tier.0 { + // Override(Some(path)) / Override::Path(path) -> Targets deep ancestor + Some(path) => path.clone(), - if params.is_empty() { - continue; + // Override(None) / Override::Default -> Targets our immediate parent + None => { + if let Some(parent_path) = &self.inherits { + parent_path.clone() + } else { + continue; // Safeguard if AST has a dangling override without inheritance + } } + }; - match params.remove(0) { - TypeExpr::Ref { mutable, .. } => { - cg.add_indented(&inherits.get_rust()); - cg.add("::__m_"); + let target_rust_path = target_path.get_rust(); + + // 2. Emit the block for this specific index table + cg.add_indentedln("&{"); + cg.indent += 1; + + // Initialize this sub-table with the target parent class's base vtable + cg.add_indentedln(&format!("let mut table = {}::__V_TABLE;", target_rust_path)); + + // Patch the slots for every method registered under this specific override tier + for method_ident in overriden_method_idents { + cg.add_indentedln(&format!( + "table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;", + target_rust_path, + method_ident.0.to_uppercase(), + self.self_path.get_rust(), + method_ident.get_rust() + )); + } + + cg.add_indentedln("table"); + cg.indent -= 1; + cg.add_indentedln("},"); + } + + cg.indent -= 1; + cg.add_indentedln("];"); + } + + fn emit_super_v_tests(&self, cg: &mut RustCodegen) { + for (idx, (override_tier, _)) in + self.override_v_table.iter().enumerate() + { + // Resolve the target path for this specific sub-table + let target_path = match &override_tier.0 { + // Override(Some(path)) / Override::Path(path) -> Targets deep ancestor + Some(path) => path.clone(), + + // Override(None) / Override::Default -> Targets our immediate parent + None => { + if let Some(parent_path) = &self.inherits { + parent_path.clone() + } else { + continue; // Safeguard if AST has a dangling override without inheritance + } + } + }; + + let target_rust_path = target_path.get_rust(); + + // 3. Emit the compile-time signature layout validation test for this specific index + cg.add_indentedln(&format!("const fn __test_vt_{}() {{", idx)); + cg.indent += 1; + + for method in &self.methods { + // Only validate the methods that actually belong to the current target slice tier + if method.item.is_override.as_ref() == Some(override_tier) { + let mut params = method + .item + .params + .0 + .clone() + .into_iter() + .filter_map(|v| v.type_) + .collect::>(); + + if params.is_empty() { + continue; + } + + if let TypeExpr::Ref { mutable, .. } = params.remove(0) { + cg.add_indented(&format!("{}::__m_", target_rust_path)); cg.add(&method.item.name.get_rust()); cg.add(" as "); @@ -211,7 +281,7 @@ impl ClassProcessedData { TypeExpr::Ref { lifetime: None, mutable, - ty: Box::new(get_type_from_path(inherits)), + ty: Box::new(get_type_from_path(&target_path)), }, ); @@ -224,13 +294,12 @@ impl ClassProcessedData { ); cg.addln(";"); } - _ => {} } } - } - cg.indent -= 1; - cg.add_indentedln("}"); + cg.indent -= 1; + cg.add_indentedln("}"); + } } fn emit_constructor(&self, ctx: &mut Context, cg: &mut RustCodegen) { @@ -239,7 +308,120 @@ impl ClassProcessedData { cg.add_indentedln("#[allow(invalid_value)]"); cg.add_indentedln(&constructor_comment); - (&self.fields, &self.constructor, self.inherits.is_some()).gen_rust(ctx, cg); + cg.add_indented(&format!( + "{}fn new{}(", + self.constructor.item.visibility.get_rust(), + self.constructor.item.generics.get_rust() + )); + + // Enumerate and build constructor call parameters + let params = self + .constructor + .item + .params + .0 + .clone() + .into_iter() + .enumerate() + .map(|(idx, mut v)| { + v.name = construct_pattern(&v.name, idx); + (idx, v) + }) + .collect::>(); + + for (i, param) in ¶ms { + if *i > 0 { + cg.add(", "); + } + param.gen_rust(ctx, cg); + } + + cg.addln(") -> Box {"); + cg.indent += 1; + + // Allocate and zero-initialize state pointer + cg.add_indentedln("let mut this = Box::new(unsafe { std::mem::MaybeUninit::::zeroed().assume_init() });"); + cg.add_indentedln("let this_ptr = &mut *this as *mut Self as *mut std::ffi::c_void;"); + cg.add_indentedln("this._m_oop = (&Self::__V_TABLE, this_ptr);"); + + // Inline field declarations and initializers + for field in &self.fields { + let comment = field.get_comment(); + + if let Some(init) = &field.item.init { + cg.add_indentedln(&comment); + cg.add_indentedln(&format!("this.{} = ", field.item.decl.name.get_rust())); + init.gen_rust(ctx, cg); + } + } + + // Call Mist internal execution hook + cg.add_indented("this.constructor("); + for (i, param) in ¶ms { + if *i > 0 { + cg.add(", "); + } + ctx.expr_ensure_semicolon = false; + param.name.gen_rust(ctx, cg); + } + cg.addln(");"); + + // --- MULTI-INHERITANCE 2D VTABLE ASSIGNMENTS --- + if self.inherits.is_some() && !self.override_v_table.is_empty() { + for (idx, (override_tier, _)) in self.override_v_table.iter().enumerate() { + match &override_tier.0 { + // Direct base class layout updates + None => { + cg.add_indentedln(&format!( + "this._super._m_oop.0 = Self::__SUPER_V_TABLES[{}];", + idx + )); + } + // Deep ancestor trait table updates + Some(path) => { + cg.add_indentedln(&format!( + "<{} as std::ops::Deref>::deref(&this)._m_oop.0 = Self::__SUPER_V_TABLES[{}];", + path.get_rust(), + idx + )); + } + } + } + } + + cg.add_indentedln("this"); + cg.indent -= 1; + cg.add_indentedln("}\n"); + + // Generate matching inner initialization body block + let mut constructor_params = vec![VarDecl { + name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])), + type_: Some(TypeExpr::Ref { + lifetime: None, + mutable: true, + ty: Box::new(TypeExpr::Path( + Path(vec![Identifier(String::from("Self"))]), + None, + )), + }), + }]; + + constructor_params.append(&mut self.constructor.item.params.0.clone()); + + Spanned { + line: self.constructor.line, + column: self.constructor.column, + item: FunctionDecl { + visibility: self.constructor.item.visibility.clone(), + is_override: None, + name: Identifier(String::from("constructor")), + generics: self.constructor.item.generics.clone(), + params: ParamList(constructor_params), + return_type: Some(TypeExpr::Tuple(Vec::new())), + body: Some(self.constructor.item.body.clone()), + }, + } + .gen_rust(ctx, cg); } fn emit_methods(&self, ctx: &mut Context, cg: &mut RustCodegen) { @@ -326,116 +508,6 @@ pub fn class_decl( data.emit(ctx, cg); } -// ── Constructor code generation (kept as a standalone impl) ─────────── - -impl GenRust - for ( - &Vec>, - &Spanned, - bool, - ) -{ - fn gen_rust(&self, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add_indented(&format!( - "{}fn new{}(", - self.1.item.visibility.get_rust(), - self.1.item.generics.get_rust() - )); - - let params = self - .1 - .item - .params - .0 - .clone() - .into_iter() - .enumerate() - .map(|(idx, mut v)| { - v.name = construct_pattern(&v.name, idx); - (idx, v) - }) - .collect::>(); - - for (i, param) in ¶ms { - if *i > 0 { - cg.add(", "); - } - - param.gen_rust(ctx, cg); - } - - cg.addln(") -> Box {"); - cg.indent += 1; - - cg.add_indentedln("let mut this = Box::new(unsafe { std::mem::MaybeUninit::::zeroed().assume_init() });"); - cg.add_indentedln("let this_ptr = &mut *this as *mut Self as *mut std::ffi::c_void;"); - cg.add_indentedln("this._m_oop = (&Self::__V_TABLE, this_ptr);"); - - for field in self.0 { - let comment = field.get_comment(); - - if let Some(init) = &field.item.init { - cg.add_indentedln(&comment); - - cg.add_indentedln(&format!("this.{} = ", field.item.decl.name.get_rust())); - - init.gen_rust(ctx, cg); - } - } - - cg.add_indented("this.constructor("); - - for (i, param) in params { - if i > 0 { - cg.add(", "); - } - - ctx.expr_ensure_semicolon = false; - param.name.gen_rust(ctx, cg); - } - - cg.addln(");"); - - if self.2 { - cg.add_indentedln("this._super._m_oop.0 = &Self::__SUPER_V_TABLE;"); - } - - cg.add_indentedln("this"); - - cg.indent -= 1; - cg.add_indentedln("}\n"); - - let mut constructor_params = vec![VarDecl { - name: Pattern::Path(false, Path(vec![Identifier(String::from("self"))])), - type_: Some(TypeExpr::Ref { - lifetime: None, - mutable: true, - ty: Box::new(TypeExpr::Path( - Path(vec![Identifier(String::from("Self"))]), - None, - )), - }), - }]; - - constructor_params.append(&mut self.1.item.params.0.clone()); - - Spanned { - line: self.1.line, - column: self.1.column, - item: FunctionDecl { - visibility: self.1.item.visibility.clone(), - is_override: None, - name: Identifier(String::from("constructor")), - generics: self.1.item.generics.clone(), - params: ParamList(constructor_params), - return_type: Some(TypeExpr::Tuple(Vec::new())), - body: Some(self.1.item.body.clone()), - }, - } - .gen_rust(ctx, cg); - } -} - fn construct_pattern(pat: &Pattern, idx: usize) -> Pattern { match pat { Pattern::Literal(v) => Pattern::Literal(v.clone()), From abda2c4c4119bca8b738abc9231b6d89b8922236 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 17:25:27 +0200 Subject: [PATCH 08/12] Working override target --- crates/codegen/src/class_decl.rs | 6 ++---- mist-test/src/items/class_test.mist | 10 +++++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 76769f3..176baed 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -231,9 +231,7 @@ impl ClassProcessedData { } fn emit_super_v_tests(&self, cg: &mut RustCodegen) { - for (idx, (override_tier, _)) in - self.override_v_table.iter().enumerate() - { + for (idx, (override_tier, _)) in self.override_v_table.iter().enumerate() { // Resolve the target path for this specific sub-table let target_path = match &override_tier.0 { // Override(Some(path)) / Override::Path(path) -> Targets deep ancestor @@ -380,7 +378,7 @@ impl ClassProcessedData { // Deep ancestor trait table updates Some(path) => { cg.add_indentedln(&format!( - "<{} as std::ops::Deref>::deref(&this)._m_oop.0 = Self::__SUPER_V_TABLES[{}];", + "(|v: &mut {}| {{v._m_oop.0 = Self::__SUPER_V_TABLES[{}];}})(&mut this);", path.get_rust(), idx )); diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index ae85717..076571d 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -15,7 +15,15 @@ pub class Animal { } } -pub class Dog : Animal { +pub class Mammal : Animal { + constructor() { + unsafe { + std::ptr::write(&mut super, Super::new()); + } + } +} + +pub class Dog : Mammal { constructor() { unsafe { std::ptr::write(&mut super, Super::new()); From b20337b385747a2a45a94037e583619898c6c637 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 17:50:40 +0200 Subject: [PATCH 09/12] Fixed deref with generics --- crates/codegen/src/class_decl.rs | 25 +++++++++++++++++++------ mist-test/src/items/class_test.mist | 4 ++-- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 176baed..2aaa082 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -454,8 +454,16 @@ impl ClassProcessedData { fn emit_deref_impls(&self, cg: &mut RustCodegen) { if let Some(ref inherits) = self.inherits { - cg.add("impl std::ops::Deref for "); - cg.add(&self.name.get_rust()); + let generics_str = self.generics.get_rust(); + let generics_expr_str = Generics::from(self.generics.clone()).get_rust(); + + cg.add(&format!( + "impl{} std::ops::Deref for {}{}", + generics_str, + self.name.get_rust(), + generics_expr_str + )); + cg.addln(" {"); cg.indent += 1; @@ -463,17 +471,22 @@ impl ClassProcessedData { cg.add(&inherits.get_rust()); cg.addln(";"); - cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}"); + cg.add_indentedln("fn deref(&self) -> &Self::Target { &self._super }"); cg.indent -= 1; cg.addln("}"); - cg.add("impl std::ops::DerefMut for "); - cg.add(&self.name.get_rust()); + cg.add(&format!( + "impl{} std::ops::DerefMut for {}{}", + generics_str, + self.name.get_rust(), + generics_expr_str + )); + cg.addln(" {"); cg.indent += 1; - cg.add_indentedln("fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}"); + cg.add_indentedln("fn deref_mut(&mut self) -> &mut Self::Target { &mut self._super }"); cg.indent -= 1; cg.addln("}"); diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index 076571d..3174f54 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -15,7 +15,7 @@ pub class Animal { } } -pub class Mammal : Animal { +pub class Mammal : Animal { constructor() { unsafe { std::ptr::write(&mut super, Super::new()); @@ -23,7 +23,7 @@ pub class Mammal : Animal { } } -pub class Dog : Mammal { +pub class Dog : Mammal { constructor() { unsafe { std::ptr::write(&mut super, Super::new()); From ba5145d9ad861280a73ebb2964a93e137f2854a0 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 18:01:08 +0200 Subject: [PATCH 10/12] Fixed args --- crates/codegen/src/class_decl.rs | 35 ++++++++++++++++++++++++----- mist-test/src/items/class_test.mist | 4 ++++ 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 2aaa082..458be07 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -535,11 +535,22 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC method.generics.get_rust(), )); - for (i, param) in method.params.0.iter().enumerate() { - if i > 0 { + let params = method + .params + .0 + .clone() + .into_iter() + .enumerate() + .map(|(idx, mut v)| { + v.name = construct_pattern(&v.name, idx); + (idx, v) + }) + .collect::>(); + + for (i, param) in ¶ms { + if *i > 0 { cg.add(", "); } - param.gen_rust(ctx, cg); } @@ -570,7 +581,9 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC .filter_map(|v| v.type_) .collect(); - param_types.remove(0); + if !param_types.is_empty() { + param_types.remove(0); + } param_types.insert( 0, @@ -588,10 +601,20 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC ); cg.add(&TypeExpr::StaticFn(param_types, method.return_type.clone().map(Box::new)).get_rust()); - cg.addln(" = std::mem::transmute(func_ptr);"); - cg.add_indentedln("func(self._m_oop.1)"); + cg.add_indented("func(self._m_oop.1"); + + for (i, param) in ¶ms { + if *i == 0 { + continue; // self._m_oop.1 already fulfills it + } + cg.add(", "); + ctx.expr_ensure_semicolon = false; + param.name.gen_rust(ctx, cg); + } + + cg.addln(");"); cg.indent -= 1; cg.add_indentedln("}"); diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index 3174f54..4c79741 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -21,6 +21,8 @@ pub class Mammal : Animal { std::ptr::write(&mut super, Super::new()); } } + + pub fn args_test(*self, x i32, y *str) {} } pub class Dog : Mammal { @@ -38,5 +40,7 @@ pub class Dog : Mammal { pub fn run_tests() { let dawg = Dog::new(); + dawg.args_test(10, "hello"); + dawg.test_speak(); } From 9949027bc96c19a28bb5a887a9c3514a16da8826 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 18:05:47 +0200 Subject: [PATCH 11/12] Fixed returning --- crates/codegen/src/class_decl.rs | 2 +- mist-test/src/items/class_test.mist | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 458be07..016f0a9 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -614,7 +614,7 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC param.name.gen_rust(ctx, cg); } - cg.addln(");"); + cg.addln(")"); cg.indent -= 1; cg.add_indentedln("}"); diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index 4c79741..9c74c73 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -23,6 +23,10 @@ pub class Mammal : Animal { } pub fn args_test(*self, x i32, y *str) {} + + pub fn returning<'a>(*self) *'a str { + "Mammal" + } } pub class Dog : Mammal { @@ -35,6 +39,10 @@ pub class Dog : Mammal { pub override(Animal) fn speak(*self) { println!("Woof!"); } + + pub override fn returning(*self) *str { + "Dog" + } } pub fn run_tests() { @@ -43,4 +51,6 @@ pub fn run_tests() { dawg.args_test(10, "hello"); dawg.test_speak(); + + println!("{}", dawg.returning()); } From 41fd60dd12f54449eafa1aa38a98b6e26f6fbebc Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Tue, 9 Jun 2026 19:03:25 +0200 Subject: [PATCH 12/12] Optimized vt tests --- crates/codegen/src/class_decl.rs | 40 +++++++------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 016f0a9..ba1426b 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -4,8 +4,6 @@ use mist_parser::ast::*; use crate::{Context, GenRust, GetRust, RustCodegen}; -// ── Stage 1: Data Collection & Metadata Analysis ────────────────────── - pub struct ClassProcessedData { visibility: Visibility, name: Identifier, @@ -38,9 +36,8 @@ impl ClassProcessedData { let self_ty = get_type_from_path(&self_path); - // 1. Gather all raw methods from the class items let methods = items - .iter() // Switched to reference iteration to prevent unnecessary cloning + .iter() .filter_map(|item| match item { ClassItem::ImplDecl(_) => None, ClassItem::Method(method) => Some(method.clone()), @@ -50,15 +47,12 @@ impl ClassProcessedData { let mut v_table = Vec::new(); let mut override_v_table = std::collections::HashMap::new(); - // 2. Distribute public methods between base table slots and inheritance overrides for method in &methods { if matches!(method.item.visibility, Visibility::Public) { match &method.item.is_override { - // It's a brand new virtual method introduced by this class! None => { v_table.push(method.item.name.clone()); } - // It's an override targeting either the immediate super or a deep ancestor Some(override_spec) => { override_v_table .entry(override_spec.clone()) @@ -172,26 +166,19 @@ impl ClassProcessedData { } fn emit_super_v_table(&self, cg: &mut RustCodegen) { - // If we aren't overriding anything across the tree, we don't need the table array if self.override_v_table.is_empty() { return; } - // 1. Emit the outer 2D array declaration cg.add_indentedln(&format!( "pub const __SUPER_V_TABLES: [&'static [*const std::ffi::c_void]; {}] = [", self.override_v_table.len() )); cg.indent += 1; - // We enumerate over the map so each target class gets a stable outer index for (override_tier, overriden_method_idents) in &self.override_v_table { - // Resolve the target path for this specific sub-table let target_path = match &override_tier.0 { - // Override(Some(path)) / Override::Path(path) -> Targets deep ancestor Some(path) => path.clone(), - - // Override(None) / Override::Default -> Targets our immediate parent None => { if let Some(parent_path) = &self.inherits { parent_path.clone() @@ -231,13 +218,13 @@ impl ClassProcessedData { } fn emit_super_v_tests(&self, cg: &mut RustCodegen) { - for (idx, (override_tier, _)) in self.override_v_table.iter().enumerate() { - // Resolve the target path for this specific sub-table + cg.add_indentedln(&format!("const fn __test_vt() {{")); + cg.indent += 1; + + for (override_tier, _) in self.override_v_table.iter() { let target_path = match &override_tier.0 { - // Override(Some(path)) / Override::Path(path) -> Targets deep ancestor Some(path) => path.clone(), - // Override(None) / Override::Default -> Targets our immediate parent None => { if let Some(parent_path) = &self.inherits { parent_path.clone() @@ -249,12 +236,7 @@ impl ClassProcessedData { let target_rust_path = target_path.get_rust(); - // 3. Emit the compile-time signature layout validation test for this specific index - cg.add_indentedln(&format!("const fn __test_vt_{}() {{", idx)); - cg.indent += 1; - for method in &self.methods { - // Only validate the methods that actually belong to the current target slice tier if method.item.is_override.as_ref() == Some(override_tier) { let mut params = method .item @@ -294,10 +276,10 @@ impl ClassProcessedData { } } } - - cg.indent -= 1; - cg.add_indentedln("}"); } + + cg.indent -= 1; + cg.add_indentedln("}"); } fn emit_constructor(&self, ctx: &mut Context, cg: &mut RustCodegen) { @@ -312,7 +294,6 @@ impl ClassProcessedData { self.constructor.item.generics.get_rust() )); - // Enumerate and build constructor call parameters let params = self .constructor .item @@ -337,7 +318,6 @@ impl ClassProcessedData { cg.addln(") -> Box {"); cg.indent += 1; - // Allocate and zero-initialize state pointer cg.add_indentedln("let mut this = Box::new(unsafe { std::mem::MaybeUninit::::zeroed().assume_init() });"); cg.add_indentedln("let this_ptr = &mut *this as *mut Self as *mut std::ffi::c_void;"); cg.add_indentedln("this._m_oop = (&Self::__V_TABLE, this_ptr);"); @@ -353,7 +333,6 @@ impl ClassProcessedData { } } - // Call Mist internal execution hook cg.add_indented("this.constructor("); for (i, param) in ¶ms { if *i > 0 { @@ -364,7 +343,6 @@ impl ClassProcessedData { } cg.addln(");"); - // --- MULTI-INHERITANCE 2D VTABLE ASSIGNMENTS --- if self.inherits.is_some() && !self.override_v_table.is_empty() { for (idx, (override_tier, _)) in self.override_v_table.iter().enumerate() { match &override_tier.0 { @@ -494,8 +472,6 @@ impl ClassProcessedData { } } -// ── Public entry point (delegates to the two-stage pipeline) ────────── - pub fn class_decl( ctx: &mut Context, cg: &mut RustCodegen,