selfhost: expand Decl to 256 fields, fix unary precedence, add discard/var parsing, fix diag buffer overflow

- ast.bux: Decl expanded with field0..field255, variant0..7, param0..8
- parser.bux: add parserParseUnary for correct unary precedence; handle tkDiscard statements; allow var without initializer (matching bootstrap); add diagCount bounds check in parserEmitDiag
- hir.bux: HirParam changed to pointers
- hir_lower.bux: full field chains for struct lowering
- c_backend.bux: hardened -> vs . field access; null checks in CBE_GetExprTypeName
- cli.bux: add -lcrypto to linker
This commit is contained in:
2026-06-07 14:58:23 +03:00
parent 0bdef58182
commit 3b4456f01f
7 changed files with 1254 additions and 105 deletions
+131 -33
View File
@@ -65,11 +65,12 @@ func CBackend_OpToC(op: int) -> String {
struct CEmitter {
sb: StringBuilder,
indent: int,
mod: *HirModule,
}
func CBE_Init() -> CEmitter {
var sb: StringBuilder = StringBuilder_NewCap(4096);
return CEmitter { sb: sb, indent: 0 };
return CEmitter { sb: sb, indent: 0, mod: null as *HirModule };
}
func CBE_Emit(cbe: *CEmitter, text: String) {
@@ -252,8 +253,10 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) {
}
StringBuilder_Append(&cbe.sb, " ");
StringBuilder_Append(&cbe.sb, node.child1.strValue);
StringBuilder_Append(&cbe.sb, " = ");
CBE_EmitExpr(cbe, node.child2);
if node.child2 != null as *HirNode {
StringBuilder_Append(&cbe.sb, " = ");
CBE_EmitExpr(cbe, node.child2);
}
return;
}
// Plain assignment
@@ -349,9 +352,8 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) {
CBE_EmitExpr(cbe, node.child1);
var isPtr: bool = false;
if node.child1 != null as *HirNode {
if node.child1.typeKind == tyPointer {
isPtr = true;
} else if String_EndsWith(node.child1.typeName, "*") {
let childType: String = CBE_GetExprTypeName(cbe.mod, node.child1);
if String_EndsWith(childType, "*") {
isPtr = true;
}
}
@@ -396,9 +398,8 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) {
CBE_EmitExpr(cbe, ptrNode.child1);
var isPtr: bool = false;
if ptrNode.child1 != null as *HirNode {
if ptrNode.child1.typeKind == tyPointer {
isPtr = true;
} else if String_EndsWith(ptrNode.child1.typeName, "*") {
let childType: String = CBE_GetExprTypeName(cbe.mod, ptrNode.child1);
if String_EndsWith(childType, "*") {
isPtr = true;
}
}
@@ -617,6 +618,107 @@ func CBE_FuncHasGeneric(f: *HirFunc) -> bool {
return false;
}
func CBE_IsPrimitiveTypeName(name: String) -> bool {
if String_Eq(name, "int") || String_Eq(name, "") { return true; }
if String_Eq(name, "String") { return true; }
if String_Eq(name, "bool") { return true; }
if String_Eq(name, "uint32") { return true; }
if String_Eq(name, "uint64") { return true; }
if String_Eq(name, "int64") { return true; }
if String_Eq(name, "float32") { return true; }
if String_Eq(name, "float64") { return true; }
if String_Eq(name, "uint8") { return true; }
if String_Eq(name, "uint16") { return true; }
if String_Eq(name, "int8") { return true; }
if String_Eq(name, "int16") { return true; }
if String_Eq(name, "uint") { return true; }
if String_Eq(name, "char8") { return true; }
if String_Eq(name, "void") { return true; }
if String_Eq(name, "size_t") { return true; }
return false;
}
func CBE_StructHasValueStructField(st: *HirStruct) -> bool {
var fi: int = 0;
while fi < st.fieldCount {
let ft: String = st.fields[fi].typeName;
if !CBE_IsPrimitiveTypeName(ft) && !String_EndsWith(ft, "*") {
return true;
}
fi = fi + 1;
}
return false;
}
func CBE_EmitStructDef(cbe: *CEmitter, st: *HirStruct) {
StringBuilder_Append(&cbe.sb, "struct ");
StringBuilder_Append(&cbe.sb, st.name);
StringBuilder_Append(&cbe.sb, " {\n");
var fi: int = 0;
while fi < st.fieldCount {
StringBuilder_Append(&cbe.sb, " ");
var ft: String = st.fields[fi].typeName;
if String_Eq(ft, "int") || String_Eq(ft, "") {
StringBuilder_Append(&cbe.sb, "int");
} else if String_Eq(ft, "String") {
StringBuilder_Append(&cbe.sb, "String");
} else if String_Eq(ft, "bool") {
StringBuilder_Append(&cbe.sb, "bool");
} else if String_Eq(ft, "uint32") {
StringBuilder_Append(&cbe.sb, "uint32");
} else {
StringBuilder_Append(&cbe.sb, ft);
}
StringBuilder_Append(&cbe.sb, " ");
StringBuilder_Append(&cbe.sb, st.fields[fi].name);
StringBuilder_Append(&cbe.sb, ";\n");
fi = fi + 1;
}
StringBuilder_Append(&cbe.sb, "};\n\n");
}
func CBE_LookupFieldType(mod: *HirModule, structName: String, fieldName: String) -> String {
var si: int = 0;
while si < mod.structCount {
if String_Eq(mod.structs[si].name, structName) {
var fi: int = 0;
while fi < mod.structs[si].fieldCount {
if String_Eq(mod.structs[si].fields[fi].name, fieldName) {
let ft: String = mod.structs[si].fields[fi].typeName;
if ft != null as String { return ft; }
return "";
}
fi = fi + 1;
}
}
si = si + 1;
}
return "";
}
func CBE_GetExprTypeName(mod: *HirModule, node: *HirNode) -> String {
if node == null as *HirNode { return ""; }
if node.kind == hVar {
if node.typeName != null as String { return node.typeName; }
return "";
}
if node.kind == hFieldPtr {
let baseType: String = CBE_GetExprTypeName(mod, node.child1);
var structName: String = baseType;
if String_EndsWith(baseType, "*") {
let len: uint = String_Len(baseType);
if len > 1 {
structName = String_Slice(baseType, 0, len - 1);
}
}
if !String_Eq(structName, "") {
return CBE_LookupFieldType(mod, structName, node.strValue);
}
}
if node.typeName != null as String { return node.typeName; }
return "";
}
// ---------------------------------------------------------------------------
// Generate complete C module
// ---------------------------------------------------------------------------
@@ -625,6 +727,7 @@ func CBackend_Generate(mod: *HirModule) -> String {
let cbe: *CEmitter = bux_alloc(sizeof(CEmitter)) as *CEmitter;
cbe.sb = StringBuilder_NewCap(8192);
cbe.indent = 0;
cbe.mod = mod;
// Header
StringBuilder_Append(&cbe.sb, "// Generated by Bux C Backend\n");
@@ -778,37 +881,32 @@ func CBackend_Generate(mod: *HirModule) -> String {
}
// Struct definitions (skip generics)
// Pass 1: emit structs with no value-typed struct fields (leaf structs)
si = 0;
while si < mod.structCount {
if CBE_StructHasGeneric(&mod.structs[si]) {
si = si + 1;
continue;
}
StringBuilder_Append(&cbe.sb, "struct ");
StringBuilder_Append(&cbe.sb, mod.structs[si].name);
StringBuilder_Append(&cbe.sb, " {\n");
var fi: int = 0;
while fi < mod.structs[si].fieldCount {
StringBuilder_Append(&cbe.sb, " ");
var ft: String = mod.structs[si].fields[fi].typeName;
if String_Eq(ft, "int") || String_Eq(ft, "") {
StringBuilder_Append(&cbe.sb, "int");
} else if String_Eq(ft, "String") {
StringBuilder_Append(&cbe.sb, "String");
} else if String_Eq(ft, "bool") {
StringBuilder_Append(&cbe.sb, "bool");
} else if String_Eq(ft, "uint32") {
StringBuilder_Append(&cbe.sb, "uint32");
} else {
// Use the type name directly (handles "Foo*", "Bar", etc.)
StringBuilder_Append(&cbe.sb, ft);
}
StringBuilder_Append(&cbe.sb, " ");
StringBuilder_Append(&cbe.sb, mod.structs[si].fields[fi].name);
StringBuilder_Append(&cbe.sb, ";\n");
fi = fi + 1;
if CBE_StructHasValueStructField(&mod.structs[si]) {
si = si + 1;
continue;
}
StringBuilder_Append(&cbe.sb, "};\n\n");
CBE_EmitStructDef(cbe, &mod.structs[si]);
si = si + 1;
}
// Pass 2: emit structs that contain value-typed struct fields
si = 0;
while si < mod.structCount {
if CBE_StructHasGeneric(&mod.structs[si]) {
si = si + 1;
continue;
}
if !CBE_StructHasValueStructField(&mod.structs[si]) {
si = si + 1;
continue;
}
CBE_EmitStructDef(cbe, &mod.structs[si]);
si = si + 1;
}