// c_backend.bux — C transpiler backend (ported from c_backend.nim) // Generates C code from the HIR. module CBackend { // --------------------------------------------------------------------------- // Type → C type name // --------------------------------------------------------------------------- func CBackend_TypeToC(kind: int) -> String { if kind == tyVoid { return "void"; } if kind == tyBool { return "bool"; } if kind == tyBool8 { return "bool"; } if kind == tyBool16 { return "bool"; } if kind == tyBool32 { return "bool"; } if kind == tyChar8 { return "char"; } if kind == tyChar16 { return "uint16_t"; } if kind == tyChar32 { return "uint32_t"; } if kind == tyStr { return "const char*"; } if kind == tyInt8 { return "int8_t"; } if kind == tyInt16 { return "int16_t"; } if kind == tyInt32 { return "int32_t"; } if kind == tyInt64 { return "int64_t"; } if kind == tyInt{ return "int"; } if kind == tyUInt8 { return "uint8_t"; } if kind == tyUInt16 { return "uint16_t"; } if kind == tyUInt32 { return "uint32_t"; } if kind == tyUInt64 { return "uint64_t"; } if kind == tyUInt { return "unsigned int"; } if kind == tyFloat32 { return "float"; } if kind == tyFloat64 { return "double"; } if kind == tyPointer { return "void*"; } if kind == tyNamed { return "void*"; } return "int"; } func CBackend_OpToC(op: int) -> String { if op == tkPlus { return "+"; } if op == tkMinus { return "-"; } if op == tkStar { return "*"; } if op == tkSlash { return "/"; } if op == tkPercent { return "%"; } if op == tkEq { return "=="; } if op == tkNe { return "!="; } if op == tkLt { return "<"; } if op == tkLe { return "<="; } if op == tkGt { return ">"; } if op == tkGe { return ">="; } if op == tkAmpAmp { return "&&"; } if op == tkPipePipe { return "||"; } if op == tkBang { return "!"; } if op == tkAmp { return "&"; } if op == tkPipe { return "|"; } if op == tkCaret { return "^"; } if op == tkShl { return "<<"; } if op == tkShr { return ">>"; } if op == tkAssign { return "="; } return "?"; } // --------------------------------------------------------------------------- // StringBuilder-based C emitter // --------------------------------------------------------------------------- struct CEmitter { sb: StringBuilder, indent: int, } func CBE_Init() -> CEmitter { var sb: StringBuilder = StringBuilder_NewCap(4096); return CEmitter { sb: sb, indent: 0 }; } func CBE_Emit(cbe: *CEmitter, text: String) { var i: int = 0; while i < cbe.indent { StringBuilder_Append(&cbe.sb, " "); i = i + 1; } StringBuilder_Append(&cbe.sb, text); } func CBE_EmitLine(cbe: *CEmitter, text: String) { CBE_Emit(cbe, text); StringBuilder_Append(&cbe.sb, "\n"); } func CBE_Build(cbe: *CEmitter) -> String { return StringBuilder_Build(&cbe.sb); } // --------------------------------------------------------------------------- // Emit HIR node // --------------------------------------------------------------------------- func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) { if node == null as *HirNode { return; } let kind: int = node.kind; // Literal if kind == hLit { StringBuilder_Append(&cbe.sb, node.strValue); return; } // Variable if kind == hVar { StringBuilder_Append(&cbe.sb, node.strValue); return; } // Binary if kind == hBinary { CBE_EmitExpr(cbe, node.child1); StringBuilder_Append(&cbe.sb, " "); StringBuilder_Append(&cbe.sb, CBackend_OpToC(node.intValue)); StringBuilder_Append(&cbe.sb, " "); CBE_EmitExpr(cbe, node.child2); return; } // Unary if kind == hUnary { StringBuilder_Append(&cbe.sb, CBackend_OpToC(node.intValue)); CBE_EmitExpr(cbe, node.child1); return; } // Call if kind == hCall { StringBuilder_Append(&cbe.sb, node.strValue); StringBuilder_Append(&cbe.sb, "("); if node.child1 != null as *HirNode { CBE_EmitExpr(cbe, node.child1); } if node.child2 != null as *HirNode { StringBuilder_Append(&cbe.sb, ", "); CBE_EmitExpr(cbe, node.child2); } StringBuilder_Append(&cbe.sb, ")"); return; } // Return if kind == hReturn { StringBuilder_Append(&cbe.sb, "return"); if node.child1 != null as *HirNode { StringBuilder_Append(&cbe.sb, " "); CBE_EmitExpr(cbe, node.child1); } return; } // Alloca if kind == hAlloca { StringBuilder_Append(&cbe.sb, CBackend_TypeToC(tyInt)); // simplified type StringBuilder_Append(&cbe.sb, " "); StringBuilder_Append(&cbe.sb, node.strValue); StringBuilder_Append(&cbe.sb, ";\n"); return; } // Store if kind == hStore { CBE_EmitExpr(cbe, node.child1); StringBuilder_Append(&cbe.sb, " = "); CBE_EmitExpr(cbe, node.child2); return; } // Cast if kind == hCast { StringBuilder_Append(&cbe.sb, "(("); StringBuilder_Append(&cbe.sb, CBackend_TypeToC(tyPointer)); StringBuilder_Append(&cbe.sb, ")"); CBE_EmitExpr(cbe, node.child1); StringBuilder_Append(&cbe.sb, ")"); return; } } // --------------------------------------------------------------------------- // Emit function declaration // --------------------------------------------------------------------------- func CBE_EmitFuncDecl(cbe: *CEmitter, f: *HirFunc) { // Return type if String_Eq(f.retTypeName, "") || String_Eq(f.retTypeName, "void") { StringBuilder_Append(&cbe.sb, "void "); } else { StringBuilder_Append(&cbe.sb, "int "); // simplified } StringBuilder_Append(&cbe.sb, f.name); StringBuilder_Append(&cbe.sb, "("); // Parameters var i: int = 0; while i < f.paramCount { if i > 0 { StringBuilder_Append(&cbe.sb, ", "); } StringBuilder_Append(&cbe.sb, "int "); // simplified param type var pname: String = ""; if i == 0 { pname = f.param0.name; } if i == 1 { pname = f.param1.name; } if i == 2 { pname = f.param2.name; } if i == 3 { pname = f.param3.name; } if i == 4 { pname = f.param4.name; } if i == 5 { pname = f.param5.name; } StringBuilder_Append(&cbe.sb, pname); i = i + 1; } StringBuilder_Append(&cbe.sb, ")"); } // --------------------------------------------------------------------------- // Generate complete C module // --------------------------------------------------------------------------- func CBackend_Generate(mod: *HirModule) -> String { let cbe: *CEmitter = bux_alloc(sizeof(CEmitter)) as *CEmitter; cbe.sb = StringBuilder_NewCap(8192); cbe.indent = 0; // Header StringBuilder_Append(&cbe.sb, "// Generated by Bux C Backend\n"); StringBuilder_Append(&cbe.sb, "#include \n"); StringBuilder_Append(&cbe.sb, "#include \n"); StringBuilder_Append(&cbe.sb, "#include \n"); StringBuilder_Append(&cbe.sb, "#include \n"); StringBuilder_Append(&cbe.sb, "#include \n\n"); // Extern declarations var i: int = 0; while i < mod.externCount { CBE_EmitFuncDecl(cbe, &mod.externFuncs[i]); StringBuilder_Append(&cbe.sb, ";\n"); i = i + 1; } StringBuilder_Append(&cbe.sb, "\n"); // Function definitions i = 0; while i < mod.funcCount { CBE_EmitFuncDecl(cbe, &mod.funcs[i]); StringBuilder_Append(&cbe.sb, " {\n"); // Body (simplified) if mod.funcs[i].body != null as *HirNode { StringBuilder_Append(&cbe.sb, " "); CBE_EmitExpr(cbe, mod.funcs[i].body); StringBuilder_Append(&cbe.sb, ";\n"); } StringBuilder_Append(&cbe.sb, " return 0;\n}\n\n"); i = i + 1; } return StringBuilder_Build(&cbe.sb); } func CBackend_Free(cbe: *CEmitter) { StringBuilder_Free(&cbe.sb); bux_free(cbe as *void); } }