303 lines
11 KiB
Rust
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(),
|
|
}
|
|
}
|
|
}
|