Refactored class decl generator
This commit is contained in:
@@ -1,13 +1,25 @@
|
|||||||
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>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ClassProcessedData {
|
||||||
|
pub fn analyze(
|
||||||
visibility: &Visibility,
|
visibility: &Visibility,
|
||||||
name: &Identifier,
|
name: &Identifier,
|
||||||
generics: &GenericsDecl,
|
generics: &GenericsDecl,
|
||||||
@@ -15,9 +27,7 @@ pub fn class_decl(
|
|||||||
fields: &Vec<Spanned<FieldDeclStmt>>,
|
fields: &Vec<Spanned<FieldDeclStmt>>,
|
||||||
constructor: &Spanned<ClassConstructor>,
|
constructor: &Spanned<ClassConstructor>,
|
||||||
items: &Vec<ClassItem>,
|
items: &Vec<ClassItem>,
|
||||||
) {
|
) -> Self {
|
||||||
ctx.expr_super = inherits.clone();
|
|
||||||
|
|
||||||
let self_path = ExprPath(vec![ExprPathSegment {
|
let self_path = ExprPath(vec![ExprPathSegment {
|
||||||
ident: name.clone(),
|
ident: name.clone(),
|
||||||
generics: generics.clone().into(),
|
generics: generics.clone().into(),
|
||||||
@@ -37,62 +47,105 @@ pub fn class_decl(
|
|||||||
let v_table = methods
|
let v_table = methods
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|method| match method.item.visibility {
|
.filter_map(|method| match method.item.visibility {
|
||||||
Visibility::Public => Some((method.item.name.clone(), method.item.is_override.clone())),
|
Visibility::Public => {
|
||||||
|
Some((method.item.name.clone(), method.item.is_override.clone()))
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
// Struct decl
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn emit_struct_decl(&self, cg: &mut RustCodegen) {
|
||||||
cg.addln(&format!(
|
cg.addln(&format!(
|
||||||
"{}struct {}{} {{",
|
"{}struct {}{} {{",
|
||||||
visibility.get_rust(),
|
self.visibility.get_rust(),
|
||||||
name.clone().get_rust(),
|
self.name.get_rust(),
|
||||||
generics.clone().get_rust()
|
self.generics.get_rust()
|
||||||
));
|
));
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
cg.add_indentedln(&format!(
|
cg.add_indentedln(
|
||||||
"pub _m_oop: (&'static [*const std::ffi::c_void], *mut std::ffi::c_void),",
|
"pub _m_oop: (&'static [*const std::ffi::c_void], *mut std::ffi::c_void),",
|
||||||
));
|
);
|
||||||
|
|
||||||
if let Some(inherits) = inherits {
|
if let Some(ref inherits) = self.inherits {
|
||||||
cg.add_indented("pub _super: Box<");
|
cg.add_indented("pub _super: Box<");
|
||||||
cg.add(&get_type_from_path(inherits).get_rust());
|
cg.add(&get_type_from_path(inherits).get_rust());
|
||||||
cg.addln(">,");
|
cg.addln(">,");
|
||||||
}
|
}
|
||||||
|
|
||||||
for field in fields.clone() {
|
for field in &self.fields {
|
||||||
cg.add_indentedln(&field.get_comment());
|
cg.add_indentedln(&field.get_comment());
|
||||||
cg.add_indentedln(&field.item.decl.get_rust());
|
cg.add_indentedln(&field.item.decl.get_rust());
|
||||||
}
|
}
|
||||||
|
|
||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.addln("}\n");
|
cg.addln("}\n");
|
||||||
|
}
|
||||||
|
|
||||||
// Constructor
|
fn emit_impl_block(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
cg.addln(&format!(
|
cg.addln(&format!(
|
||||||
"impl{} {} {{",
|
"impl{} {} {{",
|
||||||
generics.clone().get_rust(),
|
self.generics.get_rust(),
|
||||||
self_ty.get_rust()
|
self.self_ty.get_rust()
|
||||||
));
|
));
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
// V TABLE
|
self.emit_v_table(cg);
|
||||||
{
|
|
||||||
for (i, method_name) in v_table.iter().enumerate() {
|
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,20 +203,23 @@ 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(
|
||||||
|
params,
|
||||||
|
method.item.return_type.clone().map(Box::new),
|
||||||
|
)
|
||||||
.get_rust(),
|
.get_rust(),
|
||||||
);
|
);
|
||||||
cg.addln(";");
|
cg.addln(";");
|
||||||
@@ -178,49 +233,49 @@ 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 {
|
fn emit_methods(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
|
for method in &self.methods {
|
||||||
match method.item.visibility {
|
match method.item.visibility {
|
||||||
Visibility::Public => {
|
Visibility::Public => {
|
||||||
if method.item.is_override.is_none() {
|
if method.item.is_override.is_none() {
|
||||||
gen_method_point(&method.item, ctx, cg);
|
gen_method_point(&method.item, ctx, cg);
|
||||||
}
|
}
|
||||||
|
|
||||||
method.item.name.0.insert_str(0, "__m_");
|
let mut prefixed = method.clone();
|
||||||
|
prefixed.item.name.0.insert_str(0, "__m_");
|
||||||
|
prefixed.gen_rust(ctx, cg);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {
|
||||||
}
|
|
||||||
|
|
||||||
method.gen_rust(ctx, cg);
|
method.gen_rust(ctx, cg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cg.indent -= 1;
|
fn emit_impl_decls(&self, ctx: &mut Context, cg: &mut RustCodegen) {
|
||||||
cg.addln("}\n");
|
for item in &self.items {
|
||||||
|
if let ClassItem::ImplDecl(impl_) = item {
|
||||||
for item in items {
|
|
||||||
match item {
|
|
||||||
ClassItem::ImplDecl(impl_) => {
|
|
||||||
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) {
|
||||||
|
if let Some(ref inherits) = self.inherits {
|
||||||
cg.add("impl std::ops::Deref for ");
|
cg.add("impl std::ops::Deref for ");
|
||||||
cg.add(&name.get_rust());
|
cg.add(&self.name.get_rust());
|
||||||
|
|
||||||
cg.addln(" {");
|
cg.addln(" {");
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
@@ -233,11 +288,8 @@ pub fn class_decl(
|
|||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.addln("}");
|
cg.addln("}");
|
||||||
|
|
||||||
// Mut
|
|
||||||
|
|
||||||
cg.add("impl std::ops::DerefMut for ");
|
cg.add("impl std::ops::DerefMut for ");
|
||||||
cg.add(&name.get_rust());
|
cg.add(&self.name.get_rust());
|
||||||
|
|
||||||
cg.addln(" {");
|
cg.addln(" {");
|
||||||
cg.indent += 1;
|
cg.indent += 1;
|
||||||
|
|
||||||
@@ -246,9 +298,35 @@ pub fn class_decl(
|
|||||||
cg.indent -= 1;
|
cg.indent -= 1;
|
||||||
cg.addln("}");
|
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 (
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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>,
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
Reference in New Issue
Block a user