From 5b0cb74cee1c9662bff31a11ce764e50dbb00300 Mon Sep 17 00:00:00 2001 From: Selimaj Dev Date: Tue, 5 May 2026 21:44:36 +0200 Subject: [PATCH] Class method AST gen --- parser/src/ast.rs | 11 +++--- parser/src/grammar.pest | 4 +- parser/src/lib.rs | 83 +++++++++++++++++++++++++++++++++++++++++ src/codegen.rs | 2 + 4 files changed, 92 insertions(+), 8 deletions(-) diff --git a/parser/src/ast.rs b/parser/src/ast.rs index c946096..12d7b36 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -79,6 +79,7 @@ pub enum TopLevelKind { name: String, fields: Vec, constructor: ClassConstructor, + methods: Vec, }, } @@ -91,11 +92,11 @@ pub struct ClassConstructor { #[derive(Debug, Clone, Serialize)] pub struct ClassMethod { - export: bool, - name: String, - params: ParamList, - return_type: TypeExpr, - body: Block, + pub export: bool, + pub name: String, + pub params: ParamList, + pub return_type: TypeExpr, + pub body: Block, } #[derive(Debug, Clone, Serialize)] diff --git a/parser/src/grammar.pest b/parser/src/grammar.pest index d92a46a..a8b9643 100644 --- a/parser/src/grammar.pest +++ b/parser/src/grammar.pest @@ -26,8 +26,6 @@ class_constructor = { class_fields = { var_decl_statement* } -class_methods = { method* } - self_param = { "self" ~ mutable? ~ deref_px? } method = { @@ -35,7 +33,7 @@ method = { } class_decl = { - "class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ class_methods ~ "}" + "class" ~ identifier ~ "{" ~ class_fields ~ class_constructor ~ method* ~ "}" } // ================= TOP LEVEL ================= diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 26f51f4..0a669e8 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -320,6 +320,7 @@ impl From> for TopLevelKind { .map(VarDeclStmt::from) .collect(), constructor: ClassConstructor::from(inner.next().unwrap()), + methods: inner.into_iter().map(ClassMethod::from).collect(), }, _ => unimplemented!("{rule:#?}"), @@ -594,3 +595,85 @@ impl From> for VarDecl { } } } + +impl From> for ClassMethod { + fn from(pair: pest::iterators::Pair<'_, Rule>) -> Self { + let mut inner = pair.into_inner(); + + let export = if let Some(first) = inner.peek() { + if first.as_rule() == Rule::export { + inner.next(); + true + } else { + false + } + } else { + false + }; + + let return_type = TypeExpr::from(inner.next().unwrap()); + + let name = inner.next().unwrap().as_str().to_string(); + let self_param = if inner.peek().unwrap().as_rule() == Rule::self_param { + let mut param = inner.next().unwrap().into_inner(); + let name = format!("self"); + + let mutable = param + .peek() + .map(|p| p.as_rule() == Rule::mutable) + .unwrap_or_default(); + + if mutable { + param.next(); + } + + let is_ref = param + .peek() + .map(|p| p.as_rule() == Rule::deref_px) + .unwrap_or_default(); + + if is_ref { + param.next(); + } + + Some(VarDecl { + mutable: mutable && !is_ref, + name, + type_: Some(TypeExpr( + TypeExprKind::Path(Path(vec![format!("Self")])), + if is_ref { + vec![if mutable { + TypePostfix::RefMut + } else { + TypePostfix::Ref + }] + } else { + Vec::new() + }, + )), + }) + } else { + None + }; + + let params = if inner.peek().unwrap().as_rule() == Rule::param_list { + let mut params = ParamList::from(inner.next().unwrap()); + if let Some(x) = self_param { + params.0.insert(0, x); + } + params + } else { + ParamList(self_param.into_iter().collect()) + }; + + let body = Block::from(inner.next().unwrap()); + + Self { + export, + name, + params, + return_type, + body, + } + } +} diff --git a/src/codegen.rs b/src/codegen.rs index 865bf95..e598004 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -362,7 +362,9 @@ impl ToRust for TopLevelKind { name, fields, constructor, + methods, } => { + dbg!(methods); // Struct decl let vis = if *export { "pub " } else { "" }; cg.addln(&format!("{}struct {} {{", vis, name));