suicmez/src/codegen/transpiler.rs

303 lines
11 KiB
Rust

use crate::ast::*;
use crate::c_ir::*;
use std::collections::HashMap;
use crate::c_lowerer::declaration_transpiler::DeclarationTranspiler;
use crate::c_lowerer::statements_transpiler::StatementsTranspiler;
pub struct Transpiler {
structs: HashMap<String, CStructDecl>,
functions: Vec<CFuncDecl>,
globals: Vec<CVarDecl>,
decl_transpiler: DeclarationTranspiler,
stmt_transpiler: StatementsTranspiler,
}
impl Transpiler {
pub fn new() -> Self {
Transpiler {
structs: HashMap::new(),
functions: Vec::new(),
globals: Vec::new(),
decl_transpiler: DeclarationTranspiler::new(),
stmt_transpiler: StatementsTranspiler::new(),
}
}
pub fn transpile_program(&mut self, nodes: &[TypedASTNode]) -> Result<String, String> {
for node in nodes {
self.lower_declarations_to_c_ir(node)?;
}
self.lower_function_bodies_to_c_ir(nodes)?;
// Generate C code
let mut output = String::new();
// Add includes
output.push_str("#include <stdio.h>\n");
output.push_str("#include <stdlib.h>\n");
output.push_str("#include <stdbool.h>\n");
output.push_str("#include <string.h>\n");
// Generate struct declarations
for struct_decl in self.structs.values() {
output.push_str(&self.generate_struct_decl(struct_decl));
output.push_str(";\n");
}
// Generate function declarations (prototypes)
for func in &self.functions {
output.push_str(&self.generate_func_proto(func));
output.push_str(";\n");
}
output.push_str("\n");
// Generate global variables
for global in &self.globals {
output.push_str(&self.generate_var_decl(global));
output.push_str(";\n");
}
output.push_str("\n");
// Generate function definitions
for func in &self.functions {
output.push_str(&self.generate_func_def(func));
output.push_str("\n");
}
Ok(output)
}
fn lower_declarations_to_c_ir(&mut self, node: &TypedASTNode) -> Result<(), String> {
match &node.kind {
TypedASTNodeKind::Struct(s) => {
let struct_decl = self.decl_transpiler.transpile_struct(s)?;
self.structs.insert(s.name.clone(), struct_decl);
}
TypedASTNodeKind::Enum(e) => {
let enum_structs = self.decl_transpiler.transpile_enum(e)?;
for struct_decl in enum_structs {
self.structs.insert(struct_decl.name.clone(), struct_decl);
}
}
TypedASTNodeKind::Function(f) => {
let mut func_decl = self.decl_transpiler.transpile_function(f)?;
// Body will be filled later
func_decl.body = Some(Vec::new());
self.functions.push(func_decl);
}
TypedASTNodeKind::Impl(imp) => {
for method in &imp.methods {
let mut func_decl = self.decl_transpiler.transpile_function(method)?;
func_decl.name = format!("{}_{}", imp.target, method.name);
func_decl.body = Some(Vec::new());
self.functions.push(func_decl);
}
}
TypedASTNodeKind::Extern(e) => {
// For externs, we might need to add function prototypes
// But for now, skip as they're handled differently
}
TypedASTNodeKind::Load(_) => {}
TypedASTNodeKind::Trait(_) => {}
TypedASTNodeKind::Use(_) => {}
}
Ok(())
}
fn lower_function_bodies_to_c_ir(&mut self, nodes: &[TypedASTNode]) -> Result<(), String> {
for node in nodes {
match &node.kind {
TypedASTNodeKind::Function(f) => {
// Find the corresponding function declaration
if let Some(func_decl) = self.functions.iter_mut().find(|fd| fd.name == f.name)
{
let body_stmts = self.stmt_transpiler.expr_to_stmts(&f.body)?;
func_decl.body = Some(body_stmts);
}
}
TypedASTNodeKind::Impl(imp) => {
for method in &imp.methods {
let method_name = format!("{}_{}", imp.target, method.name);
if let Some(func_decl) =
self.functions.iter_mut().find(|fd| fd.name == method_name)
{
let body_stmts = self.stmt_transpiler.expr_to_stmts(&method.body)?;
func_decl.body = Some(body_stmts);
}
}
}
_ => {}
}
}
Ok(())
}
fn generate_struct_decl(&self, struct_decl: &CStructDecl) -> String {
let mut output = format!("struct {} {{\n", struct_decl.name);
for field in &struct_decl.fields {
output.push_str(&format!(" {} {};\n", field.ty.to_string(), field.name));
}
output.push_str("}");
output
}
fn generate_func_proto(&self, func: &CFuncDecl) -> String {
let params_str = if func.params.is_empty() {
"void".to_string()
} else {
func.params
.iter()
.map(|p| format!("{} {}", p.ty.to_string(), p.name))
.collect::<Vec<_>>()
.join(", ")
};
format!(
"{} {}({})",
func.return_type.to_string(),
func.name,
params_str
)
}
fn generate_func_def(&self, func: &CFuncDecl) -> String {
let proto = self.generate_func_proto(func);
let mut output = format!("{} {{\n", proto);
if let Some(body) = &func.body {
for stmt in body {
output.push_str(&self.generate_stmt(stmt));
}
}
output.push_str("}\n");
output
}
fn generate_var_decl(&self, var: &CVarDecl) -> String {
let mut output = format!("{} {}", var.ty.to_string(), var.name);
if let Some(init) = &var.initializer {
output.push_str(&format!(" = {}", self.generate_expr(init)));
}
output
}
fn generate_stmt(&self, stmt: &CStmt) -> String {
match stmt {
CStmt::VarDecl(var) => format!(" {};\n", self.generate_var_decl(var)),
CStmt::Expr(expr) => format!(" {};\n", self.generate_expr(expr)),
CStmt::Assign(lhs, rhs) => format!(
" {} = {};\n",
self.generate_expr(lhs),
self.generate_expr(rhs)
),
CStmt::Return(Some(expr)) => format!(" return {};\n", self.generate_expr(expr)),
CStmt::Return(None) => " return;\n".to_string(),
CStmt::If(cond, then_stmts, else_stmts) => {
let mut output = format!(" if ({}) {{\n", self.generate_expr(cond));
for stmt in then_stmts {
output.push_str(&format!(" {}", self.generate_stmt(stmt)));
}
output.push_str(" }");
if let Some(else_stmts) = else_stmts {
output.push_str(" else {\n");
for stmt in else_stmts {
output.push_str(&format!(" {}", self.generate_stmt(stmt)));
}
output.push_str(" }");
}
output.push_str("\n");
output
}
CStmt::While(cond, body) => {
let mut output = format!(" while ({}) {{\n", self.generate_expr(cond));
for stmt in body {
output.push_str(&format!(" {}", self.generate_stmt(stmt)));
}
output.push_str(" }\n");
output
}
CStmt::Block(stmts) => {
let mut output = " {\n".to_string();
for stmt in stmts {
output.push_str(&format!(" {}", self.generate_stmt(stmt)));
}
output.push_str(" }\n");
output
}
_ => "// TODO: unimplemented stmt\n".to_string(),
}
}
fn generate_expr(&self, expr: &CExpr) -> String {
match expr {
CExpr::IntLit(i) => format!("{}", i),
CExpr::FloatLit(f) => format!("{:.6}", f),
CExpr::BoolLit(b) => format!("{}", b),
CExpr::StringLit(s) => format!("\"{}\"", s),
CExpr::Var(name) => name.clone(),
CExpr::Call(func, args) => {
let args_str = args
.iter()
.map(|arg| self.generate_expr(arg))
.collect::<Vec<_>>()
.join(", ");
format!("{}({})", func, args_str)
}
CExpr::BinOp(lhs, op, rhs) => {
format!(
"({} {} {})",
self.generate_expr(lhs),
op.to_string(),
self.generate_expr(rhs)
)
}
CExpr::UnOp(op, expr) => {
format!("{}{}", op.to_string(), self.generate_expr(expr))
}
CExpr::Cast(expr, ty) => {
format!("({}) {}", ty.to_string(), self.generate_expr(expr))
}
CExpr::AddrOf(expr) => format!("&{}", self.generate_expr(expr)),
CExpr::Deref(expr) => format!("*{}", self.generate_expr(expr)),
CExpr::Dot(expr, field) => format!("{}.{}", self.generate_expr(expr), field),
CExpr::Index(array, index) => format!(
"{}[{}]",
self.generate_expr(array),
self.generate_expr(index)
),
CExpr::StructLit(struct_name, fields) => {
let field_inits: Vec<String> = fields
.iter()
.map(|(name, expr)| format!(".{} = {}", name, self.generate_expr(expr)))
.collect();
format!("(struct {}){{ {} }}", struct_name, field_inits.join(", "))
}
CExpr::EnumLit(enum_name, variant_name, args) => {
// Find the variant index - for simplicity, assume variants are in order
// TODO: This should be stored properly
let variant_index = 0; // Placeholder - need to map variant name to index
let variant_struct_name = format!("{}_{}", enum_name, variant_name);
let union_field_name = variant_name.to_lowercase();
let struct_init = if args.is_empty() {
"{}".to_string()
} else {
let field_inits: Vec<String> = args
.iter()
.enumerate()
.map(|(i, arg)| format!(".field_{} = {}", i, self.generate_expr(arg)))
.collect();
format!("{{ {} }}", field_inits.join(", "))
};
format!(
"({}){{ .discriminant = {}, .data = {{ .{} = ({}{}) }} }}",
enum_name, variant_index, union_field_name, variant_struct_name, struct_init
)
}
_ => "// TODO: unimplemented expr".to_string(),
}
}
}