Phase 7.9: Self-hosted compiler buxc2 builds and runs! 🎉

buxc (Nim bootstrap) successfully compiles buxc2 (Bux self-hosted compiler)
into a working 88KB ELF x86-64 binary.

Compiler fixes (Nim):
- duplicate symbol: user funcs shadow stdlib funcs via mergeDecls()
- forward declarations: func without body + definition (both orderings)
- extern func dedup: same extern in multiple files
- discard keyword: new language keyword, lowered to expr stmt or no-op
- parser: keywords as field names + advance-on-error safeguard
- parser: var without initializer (zero-init)
- parser: multi-line || && continuation expressions
- parser: else-if chain newline handling
- C backend: const declarations emitted as #define
- C backend: load(field_ptr) → base.field optimization (fixes lvalue errors)

Source fixes (src_bux/*.bux):
- types.bux: tk* → ty* prefix for type kind constants (avoid token conflict)
- sema.bux: remaining tk* → ty* references, StringMap → *void workaround
- hir_lower.bux: ekReturn removed, Lcx_LowerParam helper, *f dereference
- c_backend.bux: &mod.funcs[i] for pointer passing
- cli.bux: ReadFile/WriteFile → bux_read_file/bux_write_file wrappers
- parser.bux: pathStr.len → String_Len(pathStr)
- types.bux: "*" + x → String_Concat("*", x)

Build system:
- Makefile: added 4 missing examples + selfhost target
- PLAN.md: updated with actual project state, Phase 7.9 marked complete

All 18 examples pass, all unit tests pass.
This commit is contained in:
2026-05-31 16:34:36 +03:00
parent 166954204c
commit cb256397bd
31 changed files with 4603 additions and 284 deletions
+61 -61
View File
@@ -5,35 +5,35 @@ module Types {
// TypeKind constants
// ---------------------------------------------------------------------------
const tkUnknown: int = 0;
const tkVoid: int = 1;
const tkBool: int = 2;
const tkBool8: int = 3;
const tkBool16: int = 4;
const tkBool32: int = 5;
const tkChar8: int = 6;
const tkChar16: int = 7;
const tkChar32: int = 8;
const tkStr: int = 9;
const tkInt8: int = 10;
const tkInt16: int = 11;
const tkInt32: int = 12;
const tkInt64: int = 13;
const tkInt: int = 14;
const tkUInt8: int = 15;
const tkUInt16: int = 16;
const tkUInt32: int = 17;
const tkUInt64: int = 18;
const tkUInt: int = 19;
const tkFloat32: int = 20;
const tkFloat64: int = 21;
const tkPointer: int = 22;
const tkSlice: int = 23;
const tkRange: int = 24;
const tkTuple: int = 25;
const tkNamed: int = 26;
const tkTypeParam: int = 27;
const tkFunc: int = 28;
const tyUnknown: int = 0;
const tyVoid: int = 1;
const tyBool: int = 2;
const tyBool8: int = 3;
const tyBool16: int = 4;
const tyBool32: int = 5;
const tyChar8: int = 6;
const tyChar16: int = 7;
const tyChar32: int = 8;
const tyStr: int = 9;
const tyInt8: int = 10;
const tyInt16: int = 11;
const tyInt32: int = 12;
const tyInt64: int = 13;
const tyInt: int = 14;
const tyUInt8: int = 15;
const tyUInt16: int = 16;
const tyUInt32: int = 17;
const tyUInt64: int = 18;
const tyUInt: int = 19;
const tyFloat32: int = 20;
const tyFloat64: int = 21;
const tyPointer: int = 22;
const tySlice: int = 23;
const tyRange: int = 24;
const tyTuple: int = 25;
const tyNamed: int = 26;
const tyTypeParam: int = 27;
const tyFunc: int = 28;
// ---------------------------------------------------------------------------
// Type struct
@@ -57,67 +57,67 @@ struct Type {
// ---------------------------------------------------------------------------
func Type_MakeUnknown() -> Type {
return Type { kind: tkUnknown, name: "", innerCount: 0,
return Type { kind: tyUnknown, name: "", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeVoid() -> Type {
return Type { kind: tkVoid, name: "void", innerCount: 0,
return Type { kind: tyVoid, name: "void", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeBool() -> Type {
return Type { kind: tkBool, name: "bool", innerCount: 0,
return Type { kind: tyBool, name: "bool", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeInt() -> Type {
return Type { kind: tkInt, name: "int", innerCount: 0,
return Type { kind: tyInt, name: "int", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeInt64() -> Type {
return Type { kind: tkInt64, name: "int64", innerCount: 0,
return Type { kind: tyInt64, name: "int64", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeUInt() -> Type {
return Type { kind: tkUInt, name: "uint", innerCount: 0,
return Type { kind: tyUInt, name: "uint", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeFloat64() -> Type {
return Type { kind: tkFloat64, name: "float64", innerCount: 0,
return Type { kind: tyFloat64, name: "float64", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeStr() -> Type {
return Type { kind: tkStr, name: "String", innerCount: 0,
return Type { kind: tyStr, name: "String", innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakePointer(pointee: Type) -> Type {
return Type { kind: tkPointer, name: "", innerCount: 1,
return Type { kind: tyPointer, name: "", innerCount: 1,
innerKind1: pointee.kind, innerName1: pointee.name,
innerKind2: 0, innerName2: "", innerKind3: 0, innerName3: "" };
}
func Type_MakeNamed(name: String) -> Type {
return Type { kind: tkNamed, name: name, innerCount: 0,
return Type { kind: tyNamed, name: name, innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
func Type_MakeTypeParam(name: String) -> Type {
return Type { kind: tkTypeParam, name: name, innerCount: 0,
return Type { kind: tyTypeParam, name: name, innerCount: 0,
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
innerKind3: 0, innerName3: "" };
}
@@ -128,32 +128,32 @@ func Type_MakeTypeParam(name: String) -> Type {
func Type_IsNumeric(t: Type) -> bool {
let k: int = t.kind;
if k == tkInt8 || k == tkInt16 || k == tkInt32 || k == tkInt64 || k == tkInt { return true; }
if k == tkUInt8 || k == tkUInt16 || k == tkUInt32 || k == tkUInt64 || k == tkUInt { return true; }
if k == tkFloat32 || k == tkFloat64 { return true; }
if k == tkUnknown || k == tkNamed || k == tkTypeParam { return true; }
if k == tyInt8 || k == tyInt16 || k == tyInt32 || k == tyInt64 || k == tyInt { return true; }
if k == tyUInt8 || k == tyUInt16 || k == tyUInt32 || k == tyUInt64 || k == tyUInt { return true; }
if k == tyFloat32 || k == tyFloat64 { return true; }
if k == tyUnknown || k == tyNamed || k == tyTypeParam { return true; }
return false;
}
func Type_IsInteger(t: Type) -> bool {
let k: int = t.kind;
if k == tkInt8 || k == tkInt16 || k == tkInt32 || k == tkInt64 || k == tkInt { return true; }
if k == tkUInt8 || k == tkUInt16 || k == tkUInt32 || k == tkUInt64 || k == tkUInt { return true; }
if k == tkUnknown || k == tkNamed || k == tkTypeParam { return true; }
if k == tyInt8 || k == tyInt16 || k == tyInt32 || k == tyInt64 || k == tyInt { return true; }
if k == tyUInt8 || k == tyUInt16 || k == tyUInt32 || k == tyUInt64 || k == tyUInt { return true; }
if k == tyUnknown || k == tyNamed || k == tyTypeParam { return true; }
return false;
}
func Type_IsBool(t: Type) -> bool {
let k: int = t.kind;
return k == tkBool || k == tkBool8 || k == tkBool16 || k == tkBool32;
return k == tyBool || k == tyBool8 || k == tyBool16 || k == tyBool32;
}
func Type_IsPointer(t: Type) -> bool {
return t.kind == tkPointer;
return t.kind == tyPointer;
}
func Type_IsSlice(t: Type) -> bool {
return t.kind == tkSlice;
return t.kind == tySlice;
}
// ---------------------------------------------------------------------------
@@ -162,7 +162,7 @@ func Type_IsSlice(t: Type) -> bool {
func Type_Eq(a: Type, b: Type) -> bool {
if a.kind != b.kind { return false; }
if a.kind == tkNamed || a.kind == tkTypeParam {
if a.kind == tyNamed || a.kind == tyTypeParam {
return String_Eq(a.name, b.name);
}
return true;
@@ -173,16 +173,16 @@ func Type_Eq(a: Type, b: Type) -> bool {
// ---------------------------------------------------------------------------
func Type_ToString(t: Type) -> String {
if t.kind == tkVoid { return "void"; }
if t.kind == tkBool { return "bool"; }
if t.kind == tkStr { return "String"; }
if t.kind == tkInt { return "int"; }
if t.kind == tkInt64 { return "int64"; }
if t.kind == tkUInt { return "uint"; }
if t.kind == tkFloat64 { return "float64"; }
if t.kind == tkNamed { return t.name; }
if t.kind == tkTypeParam { return t.name; }
if t.kind == tkPointer { return "*" + t.innerName1; }
if t.kind == tyVoid { return "void"; }
if t.kind == tyBool { return "bool"; }
if t.kind == tyStr { return "String"; }
if t.kind == tyInt { return "int"; }
if t.kind == tyInt64 { return "int64"; }
if t.kind == tyUInt { return "uint"; }
if t.kind == tyFloat64 { return "float64"; }
if t.kind == tyNamed { return t.name; }
if t.kind == tyTypeParam { return t.name; }
if t.kind == tyPointer { return String_Concat("*", t.innerName1); }
return "?";
}
}