Refactored class decl generator

This commit is contained in:
2026-06-09 16:43:52 +02:00
parent f37a1019ae
commit e3e6caf4e6
4 changed files with 221 additions and 143 deletions
+213 -135
View File
@@ -1,98 +1,151 @@
use mist_parser::ast::*; 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( pub struct ClassProcessedData {
ctx: &mut Context, visibility: Visibility,
cg: &mut RustCodegen, name: Identifier,
generics: GenericsDecl,
inherits: Option<ExprPath>,
self_path: ExprPath,
self_ty: TypeExpr,
fields: Vec<Spanned<FieldDeclStmt>>,
constructor: Spanned<ClassConstructor>,
items: Vec<ClassItem>,
methods: Vec<Spanned<FunctionDecl>>,
v_table: Vec<(Identifier, Option<Override>)>,
}
visibility: &Visibility, impl ClassProcessedData {
name: &Identifier, pub fn analyze(
generics: &GenericsDecl, visibility: &Visibility,
inherits: &Option<ExprPath>, name: &Identifier,
fields: &Vec<Spanned<FieldDeclStmt>>, generics: &GenericsDecl,
constructor: &Spanned<ClassConstructor>, inherits: &Option<ExprPath>,
items: &Vec<ClassItem>, fields: &Vec<Spanned<FieldDeclStmt>>,
) { constructor: &Spanned<ClassConstructor>,
ctx.expr_super = inherits.clone(); items: &Vec<ClassItem>,
) -> Self {
let self_path = ExprPath(vec![ExprPathSegment {
ident: name.clone(),
generics: generics.clone().into(),
}]);
let self_path = ExprPath(vec![ExprPathSegment { let self_ty = get_type_from_path(&self_path);
ident: name.clone(),
generics: generics.clone().into(),
}]);
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::<Vec<_>>();
let methods = items let v_table = methods
.clone() .iter()
.into_iter() .filter_map(|method| match method.item.visibility {
.filter_map(|item| match item { Visibility::Public => {
ClassItem::ImplDecl(_) => None, Some((method.item.name.clone(), method.item.is_override.clone()))
ClassItem::Method(method) => Some(method), }
}) _ => None,
.collect::<Vec<_>>(); })
.collect::<Vec<_>>();
let v_table = methods ClassProcessedData {
.iter() visibility: visibility.clone(),
.filter_map(|method| match method.item.visibility { name: name.clone(),
Visibility::Public => Some((method.item.name.clone(), method.item.is_override.clone())), generics: generics.clone(),
_ => None, inherits: inherits.clone(),
}) self_path,
.collect::<Vec<_>>(); self_ty,
fields: fields.clone(),
// Struct decl constructor: constructor.clone(),
cg.addln(&format!( items: items.clone(),
"{}struct {}{} {{", methods,
visibility.get_rust(), v_table,
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(">,");
} }
for field in fields.clone() { // ── Stage 2: Code Emission ───────────────────────────────────────
cg.add_indentedln(&field.get_comment());
cg.add_indentedln(&field.item.decl.get_rust()); 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; fn emit_struct_decl(&self, cg: &mut RustCodegen) {
cg.addln("}\n"); cg.addln(&format!(
"{}struct {}{} {{",
self.visibility.get_rust(),
self.name.get_rust(),
self.generics.get_rust()
));
cg.indent += 1;
// Constructor cg.add_indentedln(
cg.addln(&format!( "pub _m_oop: (&'static [*const std::ffi::c_void], *mut std::ffi::c_void),",
"impl{} {} {{", );
generics.clone().get_rust(),
self_ty.get_rust()
));
cg.indent += 1;
// V TABLE if let Some(ref inherits) = self.inherits {
{ cg.add_indented("pub _super: Box<");
for (i, method_name) in v_table.iter().enumerate() { 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!( cg.add_indentedln(&format!(
"pub const __FN_{}: usize = {i};", "pub const __FN_{}: usize = {i};",
method_name.0.0.to_uppercase() method_name.0.to_uppercase()
)); ));
} }
cg.add_indentedln(&format!( cg.add_indentedln(&format!(
"pub const __V_TABLE: [*const std::ffi::c_void; {}] = [", "pub const __V_TABLE: [*const std::ffi::c_void; {}] = [",
v_table.len() self.v_table.len()
)); ));
cg.indent += 1; cg.indent += 1;
for (method_name, _) in &v_table { for (method_name, _) in &self.v_table {
cg.add_indented("Self::__m_"); cg.add_indented("Self::__m_");
cg.add(&method_name.get_rust()); cg.add(&method_name.get_rust());
cg.add(" as *const std::ffi::c_void"); cg.add(" as *const std::ffi::c_void");
@@ -103,8 +156,7 @@ pub fn class_decl(
cg.add_indentedln("];"); cg.add_indentedln("];");
} }
// Super V Table fn emit_super_v_table(&self, cg: &mut RustCodegen, inherits: &ExprPath) {
if let Some(inherits) = &inherits {
cg.add_indented("pub const __SUPER_V_TABLE: &'static [*const std::ffi::c_void] = &{"); cg.add_indented("pub const __SUPER_V_TABLE: &'static [*const std::ffi::c_void] = &{");
cg.indent += 1; cg.indent += 1;
@@ -112,13 +164,13 @@ pub fn class_decl(
cg.add(&inherits.get_rust()); cg.add(&inherits.get_rust());
cg.addln("::__V_TABLE;"); cg.addln("::__V_TABLE;");
for (name, is_override) in v_table { for (name, is_override) in &self.v_table {
if is_override.is_some() { if is_override.is_some() {
cg.add_indentedln(&format!( cg.add_indentedln(&format!(
"table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;", "table[{}::__FN_{}] = {}::__m_{} as *const std::ffi::c_void;",
inherits.get_rust(), inherits.get_rust(),
name.0.to_uppercase(), name.0.to_uppercase(),
self_path.get_rust(), self.self_path.get_rust(),
name.get_rust() name.get_rust()
)); ));
} }
@@ -132,18 +184,18 @@ pub fn class_decl(
cg.add_indentedln("const fn __test_vt() {"); cg.add_indentedln("const fn __test_vt() {");
cg.indent += 1; cg.indent += 1;
for i in &methods { for method in &self.methods {
if i.item.is_override.is_some() { if method.item.is_override.is_some() {
let mut params = i let mut params = method
.item .item
.params .params
.clone()
.0 .0
.clone()
.into_iter() .into_iter()
.filter_map(|v| v.type_) .filter_map(|v| v.type_)
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if params.len() == 0 { if params.is_empty() {
continue; continue;
} }
@@ -151,21 +203,24 @@ pub fn class_decl(
TypeExpr::Ref { mutable, .. } => { TypeExpr::Ref { mutable, .. } => {
cg.add_indented(&inherits.get_rust()); cg.add_indented(&inherits.get_rust());
cg.add("::__m_"); cg.add("::__m_");
cg.add(&i.item.name.get_rust()); cg.add(&method.item.name.get_rust());
cg.add(" as "); cg.add(" as ");
params.insert( params.insert(
0, 0,
TypeExpr::Ref { TypeExpr::Ref {
lifetime: None, lifetime: None,
mutable: mutable, mutable,
ty: Box::new(get_type_from_path(inherits)), ty: Box::new(get_type_from_path(inherits)),
}, },
); );
cg.add( cg.add(
&TypeExpr::StaticFn(params, i.item.return_type.clone().map(Box::new)) &TypeExpr::StaticFn(
.get_rust(), params,
method.item.return_type.clone().map(Box::new),
)
.get_rust(),
); );
cg.addln(";"); cg.addln(";");
} }
@@ -178,78 +233,101 @@ pub fn class_decl(
cg.add_indentedln("}"); 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("#[allow(invalid_value)]");
cg.add_indentedln(&constructor_comment); cg.add_indentedln(&constructor_comment);
(fields, constructor, inherits.is_some()).gen_rust(ctx, cg); (&self.fields, &self.constructor, self.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);
} }
cg.indent -= 1; fn emit_methods(&self, ctx: &mut Context, cg: &mut RustCodegen) {
cg.addln("}\n"); 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 { let mut prefixed = method.clone();
match item { prefixed.item.name.0.insert_str(0, "__m_");
ClassItem::ImplDecl(impl_) => { 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(); let mut impl_ = impl_.clone();
impl_.item.trait_ = Some(impl_.item.target); 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); impl_.gen_rust(ctx, cg);
} }
ClassItem::Method(_) => {}
} }
} }
if let Some(inherits) = inherits { fn emit_deref_impls(&self, cg: &mut RustCodegen) {
cg.add("impl std::ops::Deref for "); if let Some(ref inherits) = self.inherits {
cg.add(&name.get_rust()); cg.add("impl std::ops::Deref for ");
cg.add(&self.name.get_rust());
cg.addln(" {");
cg.indent += 1;
cg.addln(" {"); cg.add_indented("type Target = ");
cg.indent += 1; cg.add(&inherits.get_rust());
cg.addln(";");
cg.add_indented("type Target = "); cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}");
cg.add(&inherits.get_rust());
cg.addln(";");
cg.add_indentedln("fn deref(&self) -> &Self::Target {&self._super}"); cg.indent -= 1;
cg.addln("}");
cg.indent -= 1; cg.add("impl std::ops::DerefMut for ");
cg.addln("}"); 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.indent -= 1;
cg.add(&name.get_rust()); cg.addln("}");
}
cg.addln(" {");
cg.indent += 1;
cg.add_indentedln("fn deref_mut(&mut self) -> &mut Self::Target {&mut self._super}");
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<ExprPath>,
fields: &Vec<Spanned<FieldDeclStmt>>,
constructor: &Spanned<ClassConstructor>,
items: &Vec<ClassItem>,
) {
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 impl GenRust
for ( for (
&Vec<Spanned<FieldDeclStmt>>, &Vec<Spanned<FieldDeclStmt>>,
@@ -305,7 +383,7 @@ impl GenRust
} }
} }
cg.add_indented(&format!("this.constructor(")); cg.add_indented("this.constructor(");
for (i, param) in params { for (i, param) in params {
if i > 0 { if i > 0 {
+4 -4
View File
@@ -79,19 +79,19 @@ pub enum Prefix {
Neg, Neg,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub struct ExprPathSegment { pub struct ExprPathSegment {
pub ident: Identifier, pub ident: Identifier,
pub generics: Option<Generics>, pub generics: Option<Generics>,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub struct ExprPath(pub Vec<ExprPathSegment>); pub struct ExprPath(pub Vec<ExprPathSegment>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub struct Generics(pub Vec<Generic>); pub struct Generics(pub Vec<Generic>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub enum Generic { pub enum Generic {
Lifetime(Identifier), Lifetime(Identifier),
Type(TypeExpr), Type(TypeExpr),
+3 -3
View File
@@ -8,16 +8,16 @@ pub use expr::*;
pub use statement::*; pub use statement::*;
pub use top_level::*; pub use top_level::*;
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub struct Path(pub Vec<Identifier>); pub struct Path(pub Vec<Identifier>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub struct Identifier(pub String); pub struct Identifier(pub String);
#[derive(Debug, Clone, Serialize, Default)] #[derive(Debug, Clone, Serialize, Default)]
pub struct ParamList(pub Vec<VarDecl>); pub struct ParamList(pub Vec<VarDecl>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub enum TypeExpr { pub enum TypeExpr {
Ref { Ref {
lifetime: Option<Identifier>, lifetime: Option<Identifier>,
+1 -1
View File
@@ -91,7 +91,7 @@ pub struct ClassConstructor {
pub body: Block, pub body: Block,
} }
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize, PartialEq, Eq, Hash)]
pub struct Override(pub Option<ExprPath>); pub struct Override(pub Option<ExprPath>);
#[derive(Debug, Clone, Serialize)] #[derive(Debug, Clone, Serialize)]