// ast.bux — AST node types (Expr, Stmt, Decl, Pattern, TypeExpr)
module Ast {

// ---------------------------------------------------------------------------
// SourceLocation (inline for convenience)
// ---------------------------------------------------------------------------
struct SourceLoc {
    line: uint32,
    column: uint32,
}

// ---------------------------------------------------------------------------
// Token (lightweight inline)
// ---------------------------------------------------------------------------
struct AstToken {
    kind: int,
    text: String,
    line: uint32,
    column: uint32,
}

// ---------------------------------------------------------------------------
// TypeExpr — type expressions
// ---------------------------------------------------------------------------
const tekNamed: int = 0;
const tekPath: int = 1;
const tekSlice: int = 2;
const tekPointer: int = 3;
const tekRef: int = 7;        // &T — shared reference
const tekMutRef: int = 8;     // &mut T — mutable reference
const tekTuple: int = 4;
const tekSelf: int = 5;
const tekFunc: int = 6;

struct TypeExprList {
    te: *TypeExpr,
    next: *TypeExprList,
}

struct TypeExpr {
    kind: int,
    line: uint32,
    column: uint32,
    typeName: String,         // for tekNamed / diagnostic name for tekFunc
    pathStr: String,          // for tekPath (segments joined with ::)
    pathCount: int,           // number of path segments
    typeArgName0: String,     // up to 2 type args
    typeArgName1: String,
    typeArgCount: int,
    sliceElement: *TypeExpr,  // for tekSlice
    pointerPointee: *TypeExpr, // for tekPointer
    funcParams: *TypeExprList, // for tekFunc
    funcRet: *TypeExpr,        // for tekFunc
    funcParamCount: int,       // for tekFunc
}

// ---------------------------------------------------------------------------
// Pattern — match patterns
// ---------------------------------------------------------------------------
const pkWildcard: int = 0;
const pkLiteral: int = 1;
const pkIdent: int = 2;
const pkRange: int = 3;
const pkEnum: int = 4;
const pkStruct: int = 5;
const pkTuple: int = 6;

struct Pattern {
    kind: int,
    line: uint32,
    column: uint32,
    patIdent: String,        // for pkIdent
    patLitKind: int,         // for pkLiteral (token kind)
    patLitText: String,      // for pkLiteral (token text)
    patRangeInclusive: bool, // for pkRange
    patEnumPath: String,     // for pkEnum (path joined)
    patStructName: String,   // for pkStruct
}

// ---------------------------------------------------------------------------
// Expr — expressions (tagged union)
// ---------------------------------------------------------------------------
const ekLiteral: int = 0;
const ekIdent: int = 1;
const ekSelf: int = 2;
const ekPath: int = 3;
const ekSizeOf: int = 4;
const ekUnary: int = 5;
const ekPostfix: int = 6;
const ekBinary: int = 7;
const ekAssign: int = 8;
const ekTernary: int = 9;
const ekRange: int = 10;
const ekCall: int = 11;
const ekGenericCall: int = 12;
const ekIndex: int = 13;
const ekField: int = 14;
const ekStructInit: int = 15;
const ekSlice: int = 16;
const ekTuple: int = 17;
const ekCast: int = 18;
const ekIs: int = 19;
const ekTry: int = 20;
const ekUnwrap: int = 23;
const ekBlock: int = 21;
const ekMatch: int = 22;
const ekSpawn: int = 24;
const ekAwait: int = 25;
const ekStringInterp: int = 26;
const ekClosure: int = 27;

struct ExprList {
    expr: *Expr,
    next: *ExprList,
    argName: String,
}

struct Expr {
    kind: int,
    line: uint32,
    column: uint32,
    // Common fields
    strValue: String,        // ident name, path segments, field name, callee
    intValue: int,           // operator kind, intrinsic kind
    boolValue: bool,         // range inclusive
    tokKind: int,            // literal token kind
    tokText: String,         // literal token text
    // Children (up to 3 sub-expressions)
    child1: *Expr,           // left, operand, callee, cond, subject
    child2: *Expr,           // right, index, then, value
    child3: *Expr,           // else, third
    // Extra references
    refType: *TypeExpr,      // cast type, is type, sizeof type
    refBlock: *Block,        // for ekBlock
    // Generic call
    genericCallee: String,
    genericTypeArg0: String,
    genericTypeArg1: String,
    genericTypeArgCount: int,
    // Struct init fields
    structName: String,
    structFieldCount: int,
    // Closure params (for ekClosure)
    closureParams: *Decl,
    // Captures (for ekClosure)
    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,
    // Call arguments (linked list for multi-arg support)
    callArgs: *ExprList,
    callArgCount: int,
}

// ---------------------------------------------------------------------------
// Block — sequence of statements
// ---------------------------------------------------------------------------
struct Block {
    line: uint32,
    column: uint32,
    stmtCount: int,
    firstStmt: *Stmt,
    lastStmt: *Stmt,
}

// ---------------------------------------------------------------------------
// Stmt — statements
// ---------------------------------------------------------------------------
const skExpr: int = 0;
const skLet: int = 1;
const skIf: int = 2;
const skWhile: int = 3;
const skDoWhile: int = 4;
const skLoop: int = 5;
const skFor: int = 6;
const skMatch: int = 7;
const skReturn: int = 8;
const skBreak: int = 9;
const skContinue: int = 10;
const skDecl: int = 11;
const skDefer: int = 12;
const skSwitch: int = 13;

struct ElseIf {
    line: uint32;
    column: uint32;
    cond: *Expr;
    block: *Block;
}

struct Stmt {
    kind: int,
    line: uint32,
    column: uint32,
    // Common fields
    strValue: String,        // let name, pattern ident, label, for var
    boolValue: bool,         // let mutable
    // Children
    child1: *Expr,           // init expr, condition, iter expr, return value
    child2: *Expr,           // match subject
    child3: *Expr,           // extra
    refStmtType: *TypeExpr,  // let type annotation
    refStmtPattern: *Pattern,// let pattern
    refStmtDecl: *Decl,     // for skDecl
    refStmtBlock: *Block,    // then/body block
    refStmtElse: *Block,     // else block
    // Else-if chain
    elseIfCount: int,
    // Linked list
    nextStmt: *Stmt,
}

// ---------------------------------------------------------------------------
// Decl — declarations
// ---------------------------------------------------------------------------
const dkFunc: int = 0;
const dkStruct: int = 1;
const dkEnum: int = 2;
const dkUnion: int = 3;
const dkInterface: int = 4;
const dkImpl: int = 5;
const dkModule: int = 6;
const dkUse: int = 7;
const dkConst: int = 8;
const dkTypeAlias: int = 9;
const dkExternFunc: int = 10;
const dkExternVar: int = 11;

struct Param {
    line: uint32;
    column: uint32;
    name: String;
    refParamType: *TypeExpr;
    isVariadic: bool;
    defaultExpr: *Expr;
}

struct StructField {
    line: uint32;
    column: uint32;
    isPublic: bool;
    name: String;
    refFieldType: *TypeExpr;
}

struct EnumVariant {
    line: uint32;
    column: uint32;
    name: String;
    fieldCount: int;
    fieldTypeName0: String;
    fieldTypeName1: String;
}

struct Decl {
    fieldCount: int,
    fields: *StructField,
    kind: int,
    line: uint32,
    column: uint32,
    isPublic: bool,
    isAsync: bool,
    isChecked: int,          // @[Checked] attribute (0/1)
    // Names
    strValue: String,        // decl name
    strValue2: String,       // interface name, dll name, module path
    // Type params (up to 2)
    typeParam0: String,
    typeParam1: String,
    typeParamCount: int,
    // Trait bounds for type params (e.g. <T: Comparable>)
    typeParam0Bound: String,
    typeParam1Bound: String,
    // Params (for functions)
    paramCount: int,
    param0: Param,
    param1: Param,
    param2: Param,
    param3: Param,
    param4: Param,
    param5: Param,
    param6: Param,
    param7: Param,
    param8: Param,
    retType: *TypeExpr,
    // Body
    refBody: *Block,
    // Enum variants (up to 8)
    variantCount: int,
    variant0: EnumVariant,
    variant1: EnumVariant,
    variant2: EnumVariant,
    variant3: EnumVariant,
    variant4: EnumVariant,
    variant5: EnumVariant,
    variant6: EnumVariant,
    variant7: EnumVariant,
    variant8: EnumVariant,
    // Impl methods (up to 4)
    methodCount: int,
    // Use/import
    useKind: int,
    usePath: String,
    useNames: String,        // joined names for multi-import
    // Const
    constType: *TypeExpr,
    constValue: *Expr,
    // Type alias
    aliasType: *TypeExpr,
    // Extern func
    extFuncDll: String,
    extFuncVariadic: bool,
    extFuncRetType: *TypeExpr,
    // Children
    childDecl1: *Decl,       // linked list of decls (for module items, impl methods)
    childDecl2: *Decl,
    // Struct fields (up to 256)
}

// ---------------------------------------------------------------------------
// Module — AST root
// ---------------------------------------------------------------------------
struct Module {
    name: String,
    path: String,            // path segments joined
    itemCount: int,
    firstItem: *Decl,
}

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

func Ast_MakeExpr(kind: int, line: uint32, col: uint32) -> Expr {
    return Expr { kind: kind, line: line, column: col,
        strValue: "", intValue: 0, boolValue: false,
        tokKind: 0, tokText: "",
        child1: null as *Expr, child2: null as *Expr, child3: null as *Expr,
        refType: null as *TypeExpr, refBlock: null as *Block,
        genericCallee: "", genericTypeArg0: "", genericTypeArg1: "", genericTypeArgCount: 0,
        structName: "", structFieldCount: 0,
        callArgs: null as *ExprList, callArgCount: 0 };
}

func Ast_MakeIdent(name: String, line: uint32, col: uint32) -> Expr {
    var e: Expr = Ast_MakeExpr(ekIdent, line, col);
    e.strValue = name;
    return e;
}

func Ast_MakeLiteral(tokKind: int, text: String, line: uint32, col: uint32) -> Expr {
    var e: Expr = Ast_MakeExpr(ekLiteral, line, col);
    e.tokKind = tokKind;
    e.tokText = text;
    return e;
}

func Ast_MakeBinary(op: int, left: *Expr, right: *Expr, line: uint32, col: uint32) -> Expr {
    var e: Expr = Ast_MakeExpr(ekBinary, line, col);
    e.intValue = op;
    e.child1 = left;
    e.child2 = right;
    return e;
}

func Ast_MakeCall(callee: *Expr, line: uint32, col: uint32) -> Expr {
    var e: Expr = Ast_MakeExpr(ekCall, line, col);
    e.child1 = callee;
    return e;
}

func Ast_MakeStmt(kind: int, line: uint32, col: uint32) -> Stmt {
    return Stmt { kind: kind, line: line, column: col,
        strValue: "", boolValue: false,
        child1: null as *Expr, child2: null as *Expr, child3: null as *Expr,
        refStmtType: null as *TypeExpr, refStmtPattern: null as *Pattern,
        refStmtDecl: null as *Decl, refStmtBlock: null as *Block, refStmtElse: null as *Block,
        elseIfCount: 0 };
}

func Ast_MakeDecl(kind: int, line: uint32, col: uint32) -> Decl {
    return Decl { kind: kind, line: line, column: col, isPublic: false,
        strValue: "", strValue2: "",
        typeParam0: "", typeParam1: "", typeParamCount: 0,
        typeParam0Bound: "", typeParam1Bound: ""
        ,
        paramCount: 0,
        retType: null as *TypeExpr,
        refBody: null as *Block,
        fieldCount: 0,
        variantCount: 0,
        methodCount: 0,
        useKind: 0, usePath: "", useNames: "",
        constType: null as *TypeExpr, constValue: null as *Expr,
        aliasType: null as *TypeExpr,
        extFuncDll: "", extFuncVariadic: false, extFuncRetType: null as *TypeExpr,
        childDecl1: null as *Decl, childDecl2: null as *Decl };
}
}
