d517c62380
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled
- feat: generic enum support (parser, lowering, codegen — both selfhost + bootstrap)
- enum Result<T,E> { Ok(T), Err(E) } parsing + monomorphization
- tag constant mangling in monomorphized function bodies
- data field access (l-value + r-value) for generated enum instances
- multiple concrete instances in same file
- HIR walker for enum reference mangling (selfhost + bootstrap)
- feat: stdlib Result<T,E> and Option<T> made truly generic
- breaking: explicit type args required (Result<int, String>)
- fix: 'is' operator — lowering to hBinary tag comparison + C backend fallback
- fix: Type_Eq structural comparison (inner types for pointer/slice/tuple)
- fix: hardcoded limit diagnostics (>8 params/variants/captures now emit errors)
- docs: Iter<T> safety warning for dangling pointer
- docs: IMPROVEMENTS.md — comprehensive plan and changelog
- test: generic_enum example added to EXAMPLES
All tests pass (0 FAIL). Selfhost loop deterministic.
293 lines
12 KiB
Plaintext
293 lines
12 KiB
Plaintext
// types.bux — Type system definitions and factories
|
|
module Types {
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// TypeKind constants
|
|
// ---------------------------------------------------------------------------
|
|
|
|
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
|
|
// ---------------------------------------------------------------------------
|
|
|
|
struct Type {
|
|
kind: int;
|
|
name: String;
|
|
// inner types stored as array of pointers (simplified)
|
|
innerKind1: int;
|
|
innerName1: String;
|
|
innerKind2: int;
|
|
innerName2: String;
|
|
innerKind3: int;
|
|
innerName3: String;
|
|
innerCount: int;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Factories
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_MakeUnknown() -> Type {
|
|
return Type { kind: tyUnknown, name: "", innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeVoid() -> Type {
|
|
return Type { kind: tyVoid, name: "void", innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeBool() -> Type {
|
|
return Type { kind: tyBool, name: "bool", innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeInt() -> Type {
|
|
return Type { kind: tyInt, name: "int", innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeInt64() -> Type {
|
|
return Type { kind: tyInt64, name: "int64", innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeUInt() -> Type {
|
|
return Type { kind: tyUInt, name: "uint", innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeFloat64() -> Type {
|
|
return Type { kind: tyFloat64, name: "float64", innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeStr() -> Type {
|
|
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: 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: tyNamed, name: name, innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
func Type_MakeTypeParam(name: String) -> Type {
|
|
return Type { kind: tyTypeParam, name: name, innerCount: 0,
|
|
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
|
innerKind3: 0, innerName3: "" };
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Predicates
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_IsNumeric(t: Type) -> bool {
|
|
let k: int = t.kind;
|
|
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 == 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 == tyBool || k == tyBool8 || k == tyBool16 || k == tyBool32;
|
|
}
|
|
|
|
func Type_IsPointer(t: Type) -> bool {
|
|
return t.kind == tyPointer;
|
|
}
|
|
|
|
func Type_IsSlice(t: Type) -> bool {
|
|
return t.kind == tySlice;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Comparison (structural, limited to kind + name for simplicity)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_Eq(a: Type, b: Type) -> bool {
|
|
if a.kind != b.kind { return false; }
|
|
if a.kind == tyNamed || a.kind == tyTypeParam || a.kind == tyFunc {
|
|
return String_Eq(a.name, b.name);
|
|
}
|
|
if a.kind == tyPointer {
|
|
if a.innerKind1 != b.innerKind1 { return false; }
|
|
return String_Eq(a.innerName1, b.innerName1);
|
|
}
|
|
if a.kind == tySlice || a.kind == tyTuple {
|
|
if a.innerKind1 != b.innerKind1 { return false; }
|
|
if !String_Eq(a.innerName1, b.innerName1) { return false; }
|
|
if a.innerKind2 != b.innerKind2 { return false; }
|
|
if !String_Eq(a.innerName2, b.innerName2) { return false; }
|
|
if a.innerKind3 != b.innerKind3 { return false; }
|
|
if !String_Eq(a.innerName3, b.innerName3) { return false; }
|
|
return true;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// toString
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_ToString(t: Type) -> String {
|
|
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); }
|
|
if t.kind == tyFunc { return t.name; }
|
|
return "?";
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Type_FromName — central type-name → kind mapping (used by sema, hir_lower)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_FromName(name: String) -> int {
|
|
if String_Eq(name, "void") { return tyVoid; }
|
|
if String_Eq(name, "bool") { return tyBool; }
|
|
if String_Eq(name, "bool8") { return tyBool8; }
|
|
if String_Eq(name, "bool16") { return tyBool16; }
|
|
if String_Eq(name, "bool32") { return tyBool32; }
|
|
if String_Eq(name, "char8") { return tyChar8; }
|
|
if String_Eq(name, "char16") { return tyChar16; }
|
|
if String_Eq(name, "char32") { return tyChar32; }
|
|
if String_Eq(name, "String") { return tyStr; }
|
|
if String_Eq(name, "str") { return tyStr; }
|
|
if String_Eq(name, "int8") { return tyInt8; }
|
|
if String_Eq(name, "int16") { return tyInt16; }
|
|
if String_Eq(name, "int32") { return tyInt32; }
|
|
if String_Eq(name, "int64") { return tyInt64; }
|
|
if String_Eq(name, "int") { return tyInt; }
|
|
if String_Eq(name, "uint8") { return tyUInt8; }
|
|
if String_Eq(name, "uint16") { return tyUInt16; }
|
|
if String_Eq(name, "uint32") { return tyUInt32; }
|
|
if String_Eq(name, "uint64") { return tyUInt64; }
|
|
if String_Eq(name, "uint") { return tyUInt; }
|
|
if String_Eq(name, "float32") { return tyFloat32; }
|
|
if String_Eq(name, "float64") { return tyFloat64; }
|
|
if String_Eq(name, "float") { return tyFloat64; }
|
|
return tyNamed;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Type_ToCName — type kind → C type name (used by C backend)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_ToCName(kind: int) -> String {
|
|
if kind == tyVoid { return "void"; }
|
|
if kind == tyBool || kind == tyBool8 || kind == tyBool16 || kind == tyBool32 { return "bool"; }
|
|
if kind == tyChar8 { return "char"; }
|
|
if kind == tyChar16 { return "uint16"; }
|
|
if kind == tyChar32 { return "uint32"; }
|
|
if kind == tyStr { return "String"; }
|
|
if kind == tyInt8 { return "int8"; }
|
|
if kind == tyInt16 { return "int16"; }
|
|
if kind == tyInt32 { return "int32"; }
|
|
if kind == tyInt64 { return "int64"; }
|
|
if kind == tyInt { return "int"; }
|
|
if kind == tyUInt8 { return "uint8"; }
|
|
if kind == tyUInt16 { return "uint16"; }
|
|
if kind == tyUInt32 { return "uint32"; }
|
|
if kind == tyUInt64 { return "uint64"; }
|
|
if kind == tyUInt { return "uint"; }
|
|
if kind == tyFloat32 { return "float32"; }
|
|
if kind == tyFloat64 { return "float64"; }
|
|
if kind == tyPointer { return "void*"; }
|
|
// Fat function pointer — concrete BuxFn_* name comes from typeName field
|
|
if kind == tyFunc { return "BuxFn"; }
|
|
return "";
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Signed / Unsigned / Float predicates
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_IsSigned(kind: int) -> bool {
|
|
return kind == tyInt8 || kind == tyInt16 || kind == tyInt32 || kind == tyInt64 || kind == tyInt;
|
|
}
|
|
|
|
func Type_IsUnsigned(kind: int) -> bool {
|
|
return kind == tyUInt8 || kind == tyUInt16 || kind == tyUInt32 || kind == tyUInt64 || kind == tyUInt;
|
|
}
|
|
|
|
func Type_IsFloat(kind: int) -> bool {
|
|
return kind == tyFloat32 || kind == tyFloat64;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Type_SizeOf — byte size of a primitive type (0 for non-primitive)
|
|
// ---------------------------------------------------------------------------
|
|
|
|
func Type_SizeOf(kind: int) -> int {
|
|
if kind == tyBool || kind == tyBool8 || kind == tyChar8 || kind == tyInt8 || kind == tyUInt8 { return 1; }
|
|
if kind == tyBool16 || kind == tyChar16 || kind == tyInt16 || kind == tyUInt16 { return 2; }
|
|
if kind == tyBool32 || kind == tyChar32 || kind == tyInt32 || kind == tyUInt32 || kind == tyFloat32 { return 4; }
|
|
if kind == tyInt64 || kind == tyUInt64 || kind == tyFloat64 { return 8; }
|
|
if kind == tyInt || kind == tyUInt { return 8; }
|
|
if kind == tyPointer { return 8; }
|
|
return 0;
|
|
}
|
|
}
|