From 0d2199ee3a8078ff205de7d7803e3fbfa446d0a9 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 9 Jul 2026 06:23:04 +0200 Subject: [PATCH 1/6] virtual keyword parsing and ast --- crates/codegen/src/class_decl.rs | 1 + crates/parser/src/ast/top_level.rs | 6 +++--- crates/parser/src/grammar.pest | 5 ++++- crates/parser/src/parser/items/function.rs | 5 ++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 0c205ce..e17dbdb 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -380,6 +380,7 @@ impl ClassProcessedData { column: constructor.column, item: FunctionDecl { visibility: constructor.item.visibility.clone(), + is_virtual: false, is_override: None, name: Identifier(String::from("constructor")), generics: constructor.item.generics.clone(), diff --git a/crates/parser/src/ast/top_level.rs b/crates/parser/src/ast/top_level.rs index 2e95aed..fd8427e 100644 --- a/crates/parser/src/ast/top_level.rs +++ b/crates/parser/src/ast/top_level.rs @@ -107,12 +107,13 @@ pub struct Override(pub Option); #[derive(Debug, Clone, Serialize)] pub struct FunctionDecl { pub visibility: Visibility, - pub is_override: Option, + pub is_virtual: bool, + pub return_type: Option, pub name: Identifier, pub generics: GenericsDecl, pub self_param: Option<(bool, Option, bool)>, pub params: ParamList, - pub return_type: Option, + pub is_override: Option, pub body: Option, } @@ -129,7 +130,6 @@ pub struct FieldDecl { pub visibility: Visibility, pub type_: TypeExpr, pub name: Identifier, - // pub tuple_names: Vec, } #[derive(Debug, Clone, Serialize)] diff --git a/crates/parser/src/grammar.pest b/crates/parser/src/grammar.pest index 24b188b..a51c7e2 100644 --- a/crates/parser/src/grammar.pest +++ b/crates/parser/src/grammar.pest @@ -36,6 +36,7 @@ keyword = { | "override" | "const" | "type" + | "virtual" } identifier = @{ @@ -373,10 +374,12 @@ trait_decl = { // FUNCTIONS // ====================================================== +virtual_kw = { "virtual" } + override_kw = { "override" ~ ("(" ~ expr_path ~ ")")? } function_decl = { - visibility? ~ ("void" | type_expr) ~ identifier ~ generics_decl? ~ "(" ~ method_args ~ ")" ~ override_kw? ~ (block | semicolon) + visibility? ~ virtual_kw? ~ ("void" | type_expr) ~ identifier ~ generics_decl? ~ "(" ~ method_args ~ ")" ~ override_kw? ~ (block | semicolon) } // ====================================================== diff --git a/crates/parser/src/parser/items/function.rs b/crates/parser/src/parser/items/function.rs index 7c7ac46..25ea082 100644 --- a/crates/parser/src/parser/items/function.rs +++ b/crates/parser/src/parser/items/function.rs @@ -14,6 +14,8 @@ impl<'a> TryFrom> for FunctionDecl { let mut inner = pair.into_inner(); let visibility = Visibility::try_from(&mut inner)?; + let is_virtual = listen_rule(&mut inner, Rule::virtual_kw); + let return_type = consume_rule(&mut inner, Rule::type_expr) .map(TypeExpr::try_from) .transpose()?; @@ -45,12 +47,13 @@ impl<'a> TryFrom> for FunctionDecl { Ok(Self { visibility: visibility, - is_override: is_override, + is_virtual: is_virtual, return_type: return_type, name: name, generics: generics, self_param: self_param, params: params, + is_override: is_override, body: body, }) }) From 08771fe5be7edded5b1cc577b3c6349a2b879946 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 9 Jul 2026 06:30:11 +0200 Subject: [PATCH 2/6] Virtual functions --- crates/codegen/src/class_decl.rs | 4 ++-- mist-test/src/items/class_test.mist | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index e17dbdb..587e91a 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -51,7 +51,7 @@ impl ClassProcessedData { if matches!(method.item.visibility, Visibility::Public) { match &method.item.is_override { None => { - if method.item.self_param.is_some() { + if method.item.is_virtual && method.item.self_param.is_some() { v_table.push(method.item.name.clone()); } } @@ -397,7 +397,7 @@ impl ClassProcessedData { for method in &self.methods { match method.item.visibility { Visibility::Public => { - if method.item.self_param.is_some() { + if method.item.is_virtual && method.item.self_param.is_some() { if method.item.is_override.is_none() { gen_method_point(&method.item, ctx, cg); } diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index 98d6f03..e169947 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -9,7 +9,7 @@ pub class Animal self.name = "Rex".to_string(); } - pub String speak(&self) + pub virtual String speak(&self) { "Unknown".to_string() } @@ -45,7 +45,7 @@ pub class Dog : Mammal super = Super::new(); } - pub String speak(&self) override(Animal) + pub virtual String speak(&self) override(Animal) { "Woof!".to_string() } From df8e67fd4f7f95779252e3498b57c36abf00df7d Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 9 Jul 2026 06:37:37 +0200 Subject: [PATCH 3/6] Implicit virtual on override --- crates/codegen/src/class_decl.rs | 18 +++++++++++++----- mist-test/src/items/class_test.mist | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index 587e91a..6977125 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -16,7 +16,7 @@ pub struct ClassProcessedData { items: Vec, methods: Vec>, v_table: Vec, - override_v_table: HashMap>>, + override_v_table: HashMap>>, } impl ClassProcessedData { @@ -64,7 +64,7 @@ impl ClassProcessedData { item: Vec::new(), }) .item - .push(method.item.name.clone()); + .push((method.item.name.clone(), method.item.is_virtual)); } } } @@ -191,13 +191,13 @@ impl ClassProcessedData { .as_ref() .unwrap_or(self.inherits.as_ref().unwrap()) .get_rust(); - for method_ident in &overriden_method_idents.item { + for (method_ident, is_virtual) in &overriden_method_idents.item { cg.add_indentedln(&format!( - "table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;", + "table[{}::__FN_{}] = {}::{} as *const std::ffi::c_void;", base_class_path, method_ident.0.to_uppercase(), self.self_path.get_rust(), - method_ident.get_rust() + get_virtual_name(method_ident, *is_virtual) )); } } @@ -618,3 +618,11 @@ pub fn get_type_from_path(path: &ExprPath) -> TypeExpr { path.0.last().unwrap().generics.clone(), ) } + +pub fn get_virtual_name(name: &Identifier, is_virtual: bool) -> String { + if is_virtual { + format!("__m_{}", name.get_rust()) + } else { + name.get_rust() + } +} diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index e169947..de58af4 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -45,7 +45,7 @@ pub class Dog : Mammal super = Super::new(); } - pub virtual String speak(&self) override(Animal) + pub String speak(&self) override(Animal) { "Woof!".to_string() } From aacc08b983e192c8a3203e8455091010dc3baf9b Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 9 Jul 2026 06:51:36 +0200 Subject: [PATCH 4/6] Updated class tests --- mist-test/src/items/class_test.mist | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index de58af4..e6153cf 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -1,5 +1,9 @@ pub module class_test; +pub enum AnimalType { + Mammal; +} + pub class Animal { pub String name; @@ -9,6 +13,10 @@ pub class Animal self.name = "Rex".to_string(); } + pub virtual AnimalType get_animal_type(&self) { + panic!() + } + pub virtual String speak(&self) { "Unknown".to_string() @@ -31,6 +39,11 @@ pub class Mammal : Animal super = Super::new(); } + // override without a target assumes current super + pub AnimalType get_animal_type(&self) override { + AnimalType::Mammal + } + pub void args_test(&self, i32 x, str& y) { assert_eq!(x, 10); @@ -124,6 +137,7 @@ pub void run_tests() let dawg = Dog::new(); dawg.args_test(10, "hello"); dawg.test_speak(); + dawg.get_animal_type(); assert_eq!(format!("{dawg}"), "🐾 Rex"); test_class_no_inheritance(); test_class_field_default(); From 18a13dd170ce8fd2f49243de8d7be58c750831c3 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 9 Jul 2026 06:59:25 +0200 Subject: [PATCH 5/6] Override and virtual semantic checking --- crates/parser/src/semantics.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/crates/parser/src/semantics.rs b/crates/parser/src/semantics.rs index 5a21f9b..2457254 100644 --- a/crates/parser/src/semantics.rs +++ b/crates/parser/src/semantics.rs @@ -102,6 +102,28 @@ pub fn check_class_semantics<'a>(top_level: &TopLevel) -> Result<(), Vec Date: Thu, 9 Jul 2026 07:34:08 +0200 Subject: [PATCH 6/6] Virtual and overrides in analyzer --- crates/analyzer/src/lib.rs | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index 0ba2e7d..7602f4c 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -26,7 +26,7 @@ use crate::transpiler::{ static MARKER_COUNTER: AtomicU64 = AtomicU64::new(0); -const KEYWORDS: [&'static str; 22] = [ +const KEYWORDS: [&'static str; 23] = [ "if", "else", "for", @@ -49,6 +49,7 @@ const KEYWORDS: [&'static str; 22] = [ "override", "module ", "void ", + "virtual ", ]; fn keyword_completion_items() -> impl Iterator { @@ -1630,11 +1631,11 @@ fn mist_ify_completions(source: &str, pos: &Position, items: &mut Vec