From 4ab7827955dae58f1a310861ab9b5feeaaa772c8 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 25 Jun 2026 19:08:52 +0200 Subject: [PATCH 1/3] Added separate self param --- crates/codegen/src/class_decl.rs | 17 ++------- crates/parser/src/ast/top_level.rs | 1 + crates/parser/src/parser/items/function.rs | 41 +++++----------------- crates/parser/src/parser/mod.rs | 20 ++++++++++- 4 files changed, 31 insertions(+), 48 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index e0166a7..cf773b0 100644 --- a/crates/codegen/src/class_decl.rs +++ b/crates/codegen/src/class_decl.rs @@ -375,20 +375,6 @@ impl ClassProcessedData { 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 constructor.item.params.0.clone()); - Spanned { line: constructor.line, column: constructor.column, @@ -397,7 +383,8 @@ impl ClassProcessedData { is_override: None, name: Identifier(String::from("constructor")), generics: constructor.item.generics.clone(), - params: ParamList(constructor_params), + params: constructor.item.params.clone(), + self_param: Some((true, None, true)), return_type: Some(TypeExpr::Tuple(Vec::new())), body: Some(constructor.item.body.clone()), }, diff --git a/crates/parser/src/ast/top_level.rs b/crates/parser/src/ast/top_level.rs index 31847bf..a93fcaf 100644 --- a/crates/parser/src/ast/top_level.rs +++ b/crates/parser/src/ast/top_level.rs @@ -100,6 +100,7 @@ pub struct FunctionDecl { pub is_override: Option, pub name: Identifier, pub generics: GenericsDecl, + pub self_param: Option<(bool, Option, bool)>, pub params: ParamList, pub return_type: Option, pub body: Option, diff --git a/crates/parser/src/parser/items/function.rs b/crates/parser/src/parser/items/function.rs index 1486477..dca1d06 100644 --- a/crates/parser/src/parser/items/function.rs +++ b/crates/parser/src/parser/items/function.rs @@ -3,7 +3,7 @@ use crate::{ ast::*, ast_ensure, error::{self, AstError, AstResult}, - parser::{consume_rule, listen_rule}, + parser::{consume_rule, consume_rule_map, listen_rule}, }; impl<'a> TryFrom> for FunctionDecl { @@ -25,43 +25,19 @@ impl<'a> TryFrom> for FunctionDecl { .transpose() .map(|v| v.unwrap_or_default())?; - let self_param = consume_rule(&mut inner, Rule::self_param).map(|param| { + let self_param = consume_rule_map(&mut inner, Rule::self_param, |param| { let mut param_inner = param.into_inner(); + let is_ref = listen_rule(&mut param_inner, Rule::ref_px); let lifetime = consume_rule(&mut param_inner, Rule::lifetime); let mutable = listen_rule(&mut param_inner, Rule::mutable); - let name = Pattern::Path(mutable && !is_ref, Path(vec![Identifier(String::from("self"))])); - let self_ty = TypeExpr::Path(Path(vec![Identifier(String::from("Self"))]), None); - VarDecl { - name: name.clone(), - type_: Some(if is_ref { - TypeExpr::Ref { - lifetime: - lifetime.map(|v| Lifetime::try_from(v.into_inner().next().unwrap())) - .transpose() - .expect("Failed to get lifetime identifier"), - mutable, - ty: Box::new(self_ty) - } - } else { - self_ty - }), - } - }); + Ok((is_ref, lifetime.map(|v| -> AstResult { + Identifier::try_from(v.into_inner().next().unwrap()) + }).transpose()?, mutable)) + })?; - let params = consume_rule(&mut inner, Rule::param_list) - .map({ - let self_param = self_param.clone(); - |params_pair| -> AstResult<'a, ParamList> { - let mut params = ParamList::try_from(params_pair)?; - if let Some(x) = self_param { - params.0.insert(0, x); - } - Ok(params) - } - }) - .unwrap_or_else(|| Ok(ParamList(self_param.into_iter().collect())))?; + let params = consume_rule(&mut inner, Rule::param_list).map(ParamList::try_from).transpose()?.unwrap_or_default(); let is_override = consume_rule(&mut inner, Rule::override_kw).map(Override::try_from).transpose()?; @@ -73,6 +49,7 @@ impl<'a> TryFrom> for FunctionDecl { return_type: return_type, name: name, generics: generics, + self_param: self_param, params: params, body: body, }) diff --git a/crates/parser/src/parser/mod.rs b/crates/parser/src/parser/mod.rs index 30562a9..6292ec9 100644 --- a/crates/parser/src/parser/mod.rs +++ b/crates/parser/src/parser/mod.rs @@ -1,7 +1,11 @@ pub mod common; pub mod items; -use crate::{Rule, ast::Spanned, error::AstError}; +use crate::{ + Rule, + ast::Spanned, + error::{AstError, AstResult}, +}; pub fn listen_rule(pairs: &mut pest::iterators::Pairs<'_, Rule>, rule: Rule) -> bool { let consumed = pairs @@ -28,6 +32,20 @@ pub fn consume_rule<'a>( if consumed { pairs.next() } else { None } } +pub fn consume_rule_map<'a, T>( + pairs: &mut pest::iterators::Pairs<'a, Rule>, + rule: Rule, + map: impl Fn(pest::iterators::Pair<'a, Rule>) -> AstResult<'a, T>, +) -> AstResult<'a, Option> { + let pair = consume_rule(pairs, rule); + + if let Some(pair) = pair { + Some(map(pair)).transpose() + } else { + Ok(None) + } +} + impl Spanned { fn new_pair(pair: pest::iterators::Pair<'_, Rule>, item: T) -> Self { let span = pair.as_span().start_pos().line_col(); From 243b4ba5d03930b6fbaaf757d768b37a43af7213 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 25 Jun 2026 19:16:07 +0200 Subject: [PATCH 2/3] Updated codegen --- crates/codegen/src/top_level.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/crates/codegen/src/top_level.rs b/crates/codegen/src/top_level.rs index 5bda42f..2d627a8 100644 --- a/crates/codegen/src/top_level.rs +++ b/crates/codegen/src/top_level.rs @@ -80,6 +80,22 @@ impl GenRust for FunctionDecl { self.generics.get_rust(), )); + if let Some((is_ref, lifetime, is_mut)) = &self.self_param { + if *is_ref { + cg.add("&"); + } + + if let Some(lifetime) = lifetime { + cg.add(&format!("'{} ", lifetime.0)); + } + + if *is_mut { + cg.add("mut "); + } + + cg.add("self,"); + } + for (i, param) in self.params.0.iter().enumerate() { if i > 0 { cg.add(", "); From 2549535e4badc35a188c3c17b995548b735ac878 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Thu, 25 Jun 2026 19:47:07 +0200 Subject: [PATCH 3/3] Updated codegen for class decl --- crates/codegen/src/class_decl.rs | 53 ++++++++++++++++++----------- crates/parser/src/ast/top_level.rs | 15 -------- crates/parser/src/semantics.rs | 2 +- mist-test/src/items/class_test.mist | 2 +- 4 files changed, 35 insertions(+), 37 deletions(-) diff --git a/crates/codegen/src/class_decl.rs b/crates/codegen/src/class_decl.rs index cf773b0..ce0fd09 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.is_using_self() { + if method.item.self_param.is_some() { v_table.push(method.item.name.clone()); } } @@ -263,7 +263,7 @@ impl ClassProcessedData { continue; } - if let TypeExpr::Ref { mutable, .. } = params.remove(0) { + if let Some((_, _, mutable)) = &method.item.self_param { method.gen_span(cg); cg.add_indented(&format!("{}::__m_", target_rust_path)); cg.add(&method.item.name.get_rust()); @@ -273,7 +273,7 @@ impl ClassProcessedData { 0, TypeExpr::Ref { lifetime: None, - mutable, + mutable: *mutable, ty: Box::new(get_type_from_path(&target_path)), }, ); @@ -396,7 +396,7 @@ impl ClassProcessedData { for method in &self.methods { match method.item.visibility { Visibility::Public => { - if method.item.is_using_self() { + if method.item.self_param.is_some() { if method.item.is_override.is_none() { gen_method_point(&method.item, ctx, cg); } @@ -500,12 +500,32 @@ fn construct_pattern(pat: &Pattern, idx: usize) -> Pattern { } pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustCodegen) { - cg.add_indented(&format!( - "{}fn {}{}(", - method.visibility.get_rust(), - method.name.get_rust(), - method.generics.get_rust(), - )); + let mutable_self = if let Some((is_ref, lifetime, is_mut)) = &method.self_param { + cg.add_indented(&format!( + "{}fn {}{}(", + method.visibility.get_rust(), + method.name.get_rust(), + method.generics.get_rust(), + )); + + if *is_ref { + cg.add("&"); + } + + if let Some(lifetime) = lifetime { + cg.add(&format!("'{} ", lifetime.0)); + } + + if *is_mut { + cg.add("mut "); + } + + cg.add("self,"); + + *is_mut + } else { + panic!(); + }; let params = method .params @@ -553,14 +573,10 @@ pub fn gen_method_point(method: &FunctionDecl, ctx: &mut Context, cg: &mut RustC .filter_map(|v| v.type_) .collect(); - let TypeExpr::Ref { mutable, .. } = param_types.remove(0) else { - panic!("") - }; - param_types.insert( 0, TypeExpr::UnsafePtr { - mutable, + mutable: mutable_self, ty: Box::new(TypeExpr::Path( Path(vec![ Identifier(String::from("std")), @@ -575,16 +591,13 @@ 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);"); - if mutable { + if mutable_self { cg.add_indented("func(self as *mut Self as *const std::ffi::c_void"); } else { cg.add_indented("func(self as *const Self as *const std::ffi::c_void"); } - for (i, param) in ¶ms { - if *i == 0 { - continue; // self already fulfills it - } + for (_, param) in ¶ms { cg.add(", "); ctx.expr_ensure_semicolon = false; param.name.gen_rust(ctx, cg); diff --git a/crates/parser/src/ast/top_level.rs b/crates/parser/src/ast/top_level.rs index a93fcaf..d7d58ad 100644 --- a/crates/parser/src/ast/top_level.rs +++ b/crates/parser/src/ast/top_level.rs @@ -126,18 +126,3 @@ pub struct FieldDeclStmt { pub decl: FieldDecl, pub init: Option, } - -impl FunctionDecl { - pub fn is_using_self(&self) -> bool { - match self.params.0.get(0) { - Some(VarDecl { name, .. }) => { - if let Pattern::Path(_, v) = name { - v.0.len() == 1 && v.0[0].0 == "self" - } else { - false - } - } - _ => false, - } - } -} diff --git a/crates/parser/src/semantics.rs b/crates/parser/src/semantics.rs index 0b1a9aa..73d5a95 100644 --- a/crates/parser/src/semantics.rs +++ b/crates/parser/src/semantics.rs @@ -22,7 +22,7 @@ pub fn find_function_call<'a>( ) -> Option<&'a Spanned> { items.iter().find_map(|v| { if let ClassItem::Method(m) = v { - if m.item.is_using_self() && &m.item.name == name { + if m.item.self_param.is_some() && &m.item.name == name { Some(m) } else { None diff --git a/mist-test/src/items/class_test.mist b/mist-test/src/items/class_test.mist index 1bb6f20..9cd2fd0 100644 --- a/mist-test/src/items/class_test.mist +++ b/mist-test/src/items/class_test.mist @@ -11,7 +11,7 @@ pub class Animal { "Unknown".to_string() } - pub void test_speak(&self) { + pub void test_speak<'a>(&'a self) { assert_eq!(self.speak(), "Woof!"); }