// hir.bux — HIR (High-level Intermediate Representation) node types
module Hir {

    // HIR node kinds
    const hLit: int = 0;
    const hVar: int = 1;
    const hSelf: int = 2;
    const hUnary: int = 3;
    const hBinary: int = 4;
    const hAssign: int = 5;
    const hIf: int = 6;
    const hWhile: int = 7;
    const hLoop: int = 8;
    const hBreak: int = 9;
    const hContinue: int = 10;
    const hReturn: int = 11;
    const hAlloca: int = 12;
    const hLoad: int = 13;
    const hStore: int = 14;
    const hFieldPtr: int = 15;
    const hFieldAccess: int = 16;
    const hArrowField: int = 17;
    const hIndexPtr: int = 18;
    const hCall: int = 32;
    const hCallIndirect: int = 33;
    const hCast: int = 34;
    const hIs: int = 35;
    const hSizeOf: int = 36;
    const hBlock: int = 37;
    const hStructInit: int = 38;
    const hSliceInit: int = 39;
    const hRange: int = 40;
    const hTupleInit: int = 41;
    const hMatch: int = 42;
    const hSpawn: int = 43;
    const hAwait: int = 44;
    const hDefer: int = 45;

    // ---------------------------------------------------------------------------
    // HirArgList — linked list for call arguments beyond 2
    // ---------------------------------------------------------------------------

    struct HirArgList {
        node: *HirNode,
        next: *HirArgList,
    }

    // ---------------------------------------------------------------------------
    // HirNode — unified struct with tagged union pattern
    // ---------------------------------------------------------------------------

    struct HirNode {
        kind: int;
        line: uint32;
        column: uint32;
        typeKind: int;
        typeName: String;
        // Common fields (used by multiple kinds)
        strValue: String;       // var name; callee name; field name; label
        intValue: int;          // token kind (for lit; unary op; binary op)
        boolValue: bool;        // range inclusive; isScope
        // Child nodes (up to 3)
        child1: *HirNode;       // left/operand/condition/base
        child2: *HirNode;       // right/value/then/body
        child3: *HirNode;       // else/third
        // Extra data pointer (for children arrays, field lists, etc.)
        extraData: *void;
        extraCount: int;
    }

    // ---------------------------------------------------------------------------
    // HirFunc
    // ---------------------------------------------------------------------------

    struct HirParam {
        name: String;
        typeKind: int;
        typeName: String;
    }

    struct HirFunc {
        name: String;
        paramCount: int;
        param0: *HirParam;
        param1: *HirParam;
        param2: *HirParam;
        param3: *HirParam;
        param4: *HirParam;
        param5: *HirParam;
        param6: *HirParam;
        param7: *HirParam;
        param8: *HirParam;
        retTypeKind: int;
        retTypeName: String;
        body: *HirNode;
        isPublic: bool;
        // Closure capture metadata
        captureCount: int;
        captureName0: String;
        captureName1: String;
        captureName2: String;
        captureName3: String;
        captureName4: String;
        captureName5: String;
        captureName6: String;
        captureName7: String;
        captureType0: int;
        captureType1: int;
        captureType2: int;
        captureType3: int;
        captureType4: int;
        captureType5: int;
        captureType6: int;
        captureType7: int;
        envStructName: String;
        envInstanceName: String;
        checkedFunc: bool;
    }

    // ---------------------------------------------------------------------------
    // HirEnumVariant
    // ---------------------------------------------------------------------------

    struct HirEnumVariant {
        name: String;
        fieldCount: int;
        fieldType0: int;
        fieldName0: String;
        fieldTypeName0: String;  // C type name (e.g. "int", "Tuple_int_int")
        fieldType1: int;
        fieldName1: String;
        fieldTypeName1: String;
    }

    // ---------------------------------------------------------------------------
    // HirModule
    // ---------------------------------------------------------------------------

    struct HirStructField {
        name: String;
        typeName: String;
    }

    struct HirStruct {
        name: String;
        fieldCount: int;
        fields: *HirStructField;
    }

    struct HirConst {
        name: String;
        value: int;
    }

    struct HirEnum {
        name: String;
        variantCount: int;
        variants: *HirEnumVariant;
    }

    struct HirModule {
        funcCount: int;
        funcs: *HirFunc;
        externCount: int;
        externFuncs: *HirFunc;
        structCount: int;
        structs: *HirStruct;
        enumCount: int;
        enums: *HirEnum;
        constCount: int;
        consts: *HirConst;
    }

    // ---------------------------------------------------------------------------
    // Constructor helpers
    // ---------------------------------------------------------------------------

    func Hir_MakeNode(kind: int, line: uint32, column: uint32) -> HirNode {
        return HirNode { kind: kind, line: line, column: column,
            typeKind: 0, typeName: "",
            strValue: "", intValue: 0, boolValue: false,
            child1: null as *HirNode, child2: null as *HirNode, child3: null as *HirNode,
            extraData: null as *void, extraCount: 0 };
    }

    func Hir_MakeLit(tokKind: int, tokText: String, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hLit, line, col);
        n.intValue = tokKind;
        n.strValue = tokText;
        return n;
    }

    func Hir_MakeVar(name: String, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hVar, line, col);
        n.strValue = name;
        return n;
    }

    func Hir_MakeBinary(op: int, left: *HirNode, right: *HirNode, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hBinary, line, col);
        n.intValue = op;
        n.child1 = left;
        n.child2 = right;
        return n;
    }

    func Hir_MakeCall(callee: String, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hCall, line, col);
        n.strValue = callee;
        return n;
    }

    func Hir_MakeReturn(value: *HirNode, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hReturn, line, col);
        n.child1 = value;
        return n;
    }

    func Hir_MakeBlock(line: uint32, col: uint32) -> HirNode {
        return Hir_MakeNode(hBlock, line, col);
    }

    func Hir_MakeIf(cond: *HirNode, thenBody: *HirNode, elseBody: *HirNode, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hIf, line, col);
        n.child1 = cond;
        n.child2 = thenBody;
        n.child3 = elseBody;
        return n;
    }

    func Hir_MakeWhile(cond: *HirNode, body: *HirNode, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hWhile, line, col);
        n.child1 = cond;
        n.child2 = body;
        return n;
    }

    func Hir_MakeAlloca(name: String, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hAlloca, line, col);
        n.strValue = name;
        return n;
    }

    func Hir_MakeLoad(ptr: *HirNode, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hLoad, line, col);
        n.child1 = ptr;
        return n;
    }

    func Hir_MakeStore(ptr: *HirNode, value: *HirNode, line: uint32, col: uint32) -> HirNode {
        var n: HirNode = Hir_MakeNode(hStore, line, col);
        n.child1 = ptr;
        n.child2 = value;
        return n;
    }
}
