const std = @import("std"); pub const Span = struct { start: u32, end: u32, }; pub const Node = struct { span: Span, data: Data, source_file: ?[]const u8 = null, pub const Data = union(enum) { root: Root, fn_decl: FnDecl, block: Block, int_literal: IntLiteral, float_literal: FloatLiteral, bool_literal: BoolLiteral, string_literal: StringLiteral, identifier: Identifier, enum_literal: EnumLiteral, binary_op: BinaryOp, chained_comparison: ChainedComparison, unary_op: UnaryOp, call: Call, field_access: FieldAccess, if_expr: IfExpr, match_expr: MatchExpr, match_arm: MatchArm, const_decl: ConstDecl, var_decl: VarDecl, assignment: Assignment, multi_assign: MultiAssign, destructure_decl: DestructureDecl, enum_decl: EnumDecl, struct_decl: StructDecl, struct_literal: StructLiteral, union_decl: UnionDecl, lambda: Lambda, type_expr: TypeExpr, param: Param, defer_stmt: DeferStmt, push_stmt: PushStmt, comptime_expr: ComptimeExpr, insert_expr: InsertExpr, return_stmt: ReturnStmt, import_decl: ImportDecl, namespace_decl: NamespaceDecl, array_type_expr: ArrayTypeExpr, slice_type_expr: SliceTypeExpr, array_literal: ArrayLiteral, parameterized_type_expr: ParameterizedTypeExpr, index_expr: IndexExpr, slice_expr: SliceExpr, pointer_type_expr: PointerTypeExpr, many_pointer_type_expr: ManyPointerTypeExpr, optional_type_expr: OptionalTypeExpr, force_unwrap: ForceUnwrap, null_coalesce: NullCoalesce, deref_expr: DerefExpr, null_literal: void, while_expr: WhileExpr, for_expr: ForExpr, spread_expr: SpreadExpr, break_expr: void, continue_expr: void, undef_literal: void, inferred_type: void, builtin_expr: void, compiler_expr: void, foreign_expr: ForeignExpr, library_decl: LibraryDecl, framework_decl: FrameworkDecl, function_type_expr: FunctionTypeExpr, closure_type_expr: ClosureTypeExpr, tuple_type_expr: TupleTypeExpr, tuple_literal: TupleLiteral, ufcs_alias: UfcsAlias, c_import_decl: CImportDecl, protocol_decl: ProtocolDecl, impl_block: ImplBlock, pub fn declName(self: Data) ?[]const u8 { return switch (self) { .fn_decl => |d| d.name, .const_decl => |d| d.name, .var_decl => |d| d.name, .enum_decl => |d| d.name, .struct_decl => |d| d.name, .union_decl => |d| d.name, .namespace_decl => |d| d.name, .ufcs_alias => |d| d.name, .c_import_decl => |d| d.name, .protocol_decl => |d| d.name, else => null, }; } }; }; pub const Root = struct { decls: []const *Node, }; pub const CallingConvention = enum { default, c }; pub const FnDecl = struct { name: []const u8, params: []const Param, return_type: ?*Node, body: *Node, type_params: []const StructTypeParam = &.{}, is_arrow: bool = false, call_conv: CallingConvention = .default, }; pub const Param = struct { name: []const u8, name_span: Span, type_expr: *Node, is_variadic: bool = false, is_comptime: bool = false, }; pub const Block = struct { stmts: []const *Node, }; pub const IntLiteral = struct { value: i64, }; pub const FloatLiteral = struct { value: f64, }; pub const BoolLiteral = struct { value: bool, }; pub const StringLiteral = struct { raw: []const u8, is_raw: bool = false, }; pub const Identifier = struct { name: []const u8, }; pub const EnumLiteral = struct { name: []const u8, // without the leading dot }; pub const BinaryOp = struct { op: Op, lhs: *Node, rhs: *Node, pub const Op = enum { add, sub, mul, div, mod, eq, neq, lt, lte, gt, gte, and_op, or_op, bit_and, bit_or, bit_xor, shl, shr, in_op, }; }; pub const ChainedComparison = struct { operands: []const *Node, ops: []const BinaryOp.Op, }; pub const UnaryOp = struct { op: Op, operand: *Node, pub const Op = enum { negate, not, bit_not, xx, address_of, }; }; pub const Call = struct { callee: *Node, args: []const *Node, }; pub const FieldAccess = struct { object: *Node, field: []const u8, is_optional: bool = false, }; pub const IfExpr = struct { condition: *Node, then_branch: *Node, else_branch: ?*Node, is_inline: bool, // true for `if cond then a else b` is_comptime: bool = false, // true for `inline if` — compile-time branch elimination binding_name: ?[]const u8 = null, // for `if val := expr { ... }` optional binding }; pub const MatchExpr = struct { subject: *Node, arms: []const MatchArm, is_comptime: bool = false, }; pub const MatchArm = struct { pattern: ?*Node, // null = else (default) arm body: *Node, is_break: bool, capture: ?[]const u8 = null, // payload binding name: case .variant: (name) { ... } }; pub const ConstDecl = struct { name: []const u8, type_annotation: ?*Node, value: *Node, }; pub const VarDecl = struct { name: []const u8, type_annotation: ?*Node, value: ?*Node, is_foreign: bool = false, foreign_lib: ?[]const u8 = null, foreign_name: ?[]const u8 = null, }; pub const Assignment = struct { target: *Node, op: Op, value: *Node, pub const Op = enum { assign, add_assign, sub_assign, mul_assign, div_assign, mod_assign, and_assign, or_assign, xor_assign, shl_assign, shr_assign, }; }; pub const MultiAssign = struct { targets: []const *Node, values: []const *Node, }; pub const DestructureDecl = struct { names: []const []const u8, value: *Node, }; pub const EnumDecl = struct { name: []const u8, variant_names: []const []const u8, variant_types: []const ?*Node = &.{}, // null entries = no payload; empty = payload-less enum is_flags: bool = false, variant_values: []const ?*Node = &.{}, // explicit value per variant (null = auto), empty = all auto backing_type: ?*Node = null, // optional backing type: enum u8 { ... } }; pub const UnionDecl = struct { name: []const u8, field_names: []const []const u8, field_types: []const *Node, }; pub const StructTypeParam = struct { name: []const u8, // e.g. "N" or "T" (without $) constraint: *Node, // type_expr: "u32" for value param, "Type" for type param protocol_constraints: []const []const u8 = &.{}, // e.g. ["Eq", "Hashable"] for $T/Eq/Hashable }; pub const UsingEntry = struct { insert_index: u32, // position in field_names where used fields are spliced type_name: []const u8, // struct type to inline }; pub const StructDecl = struct { name: []const u8, field_names: []const []const u8, field_types: []const *Node, // type_expr nodes field_defaults: []const ?*Node, // default value per field, null if none type_params: []const StructTypeParam = &.{}, using_entries: []const UsingEntry = &.{}, methods: []const *Node = &.{}, // fn_decl nodes for struct methods constants: []const *Node = &.{}, // const_decl nodes for struct-level constants }; pub const StructFieldInit = struct { name: ?[]const u8, // null for positional, non-null for named/shorthand value: *Node, }; pub const StructLiteral = struct { struct_name: ?[]const u8, // null for anonymous `.{ ... }` type_expr: ?*Node = null, // for GenericType(args).{ ... } field_inits: []const StructFieldInit, init_block: ?*Node = null, // optional `{ stmts }` block after struct literal }; pub const Lambda = struct { params: []const Param, return_type: ?*Node, body: *Node, type_params: []const StructTypeParam = &.{}, call_conv: CallingConvention = .default, }; pub const TypeExpr = struct { name: []const u8, is_generic: bool = false, protocol_constraints: []const []const u8 = &.{}, // e.g. ["Eq", "Hashable"] for $T/Eq/Hashable }; pub const DeferStmt = struct { expr: *Node, }; pub const PushStmt = struct { context_expr: *Node, body: *Node, }; pub const ComptimeExpr = struct { expr: *Node, }; pub const InsertExpr = struct { expr: *Node, }; pub const ReturnStmt = struct { value: ?*Node, }; pub const ImportDecl = struct { path: []const u8, name: ?[]const u8, }; pub const ArrayTypeExpr = struct { length: *Node, // int_literal for the size element_type: *Node, // type_expr for the element type }; pub const SliceTypeExpr = struct { element_type: *Node, // type_expr for the element type }; pub const ArrayLiteral = struct { elements: []const *Node, type_expr: ?*Node = null, }; pub const ParameterizedTypeExpr = struct { name: []const u8, // e.g. "Vector", or later generic struct names args: []const *Node, // e.g. [int_literal(3), type_expr("f32")] }; pub const IndexExpr = struct { object: *Node, index: *Node, }; pub const SliceExpr = struct { object: *Node, start: ?*Node = null, end: ?*Node = null, }; pub const PointerTypeExpr = struct { pointee_type: *Node, }; pub const ManyPointerTypeExpr = struct { element_type: *Node, }; pub const OptionalTypeExpr = struct { inner_type: *Node, }; pub const ForceUnwrap = struct { operand: *Node, }; pub const NullCoalesce = struct { lhs: *Node, rhs: *Node, }; pub const DerefExpr = struct { operand: *Node, }; pub const WhileExpr = struct { condition: *Node, body: *Node, binding_name: ?[]const u8 = null, // for `while val := expr { ... }` optional binding }; pub const ForExpr = struct { iterable: *Node, body: *Node, capture_name: []const u8, index_name: ?[]const u8 = null, }; pub const SpreadExpr = struct { operand: *Node, }; pub const NamespaceDecl = struct { name: []const u8, decls: []const *Node, }; pub const ForeignExpr = struct { library_ref: ?[]const u8 = null, // identifier name of library constant c_name: ?[]const u8 = null, // C symbol name override }; pub const LibraryDecl = struct { lib_name: []const u8, name: []const u8, // sx-side constant name }; pub const FrameworkDecl = struct { name: []const u8, // framework name, e.g. "Foundation" }; pub const FunctionTypeExpr = struct { param_types: []const *Node, param_names: ?[]const ?[]const u8 = null, // optional documentation names return_type: ?*Node, // null = void return call_conv: CallingConvention = .default, }; pub const ClosureTypeExpr = struct { param_types: []const *Node, param_names: ?[]const ?[]const u8 = null, // optional documentation names return_type: ?*Node, // null = void return }; pub const TupleTypeExpr = struct { field_types: []const *Node, field_names: ?[]const []const u8, // null for positional }; pub const TupleLiteral = struct { elements: []const TupleElement, }; pub const TupleElement = struct { name: ?[]const u8, // null for positional value: *Node, }; pub const UfcsAlias = struct { name: []const u8, target: []const u8, }; pub const CImportDecl = struct { includes: []const []const u8, sources: []const []const u8, defines: []const []const u8, flags: []const []const u8, name: ?[]const u8 = null, bitcode_paths: []const []const u8 = &.{}, // populated during import resolution }; pub const ProtocolMethodDecl = struct { name: []const u8, params: []const *Node, // type_expr nodes for parameter types (excluding implicit self) param_names: []const []const u8, // parameter names (excluding implicit self) return_type: ?*Node, // null = void return default_body: ?*Node, // null = required method, non-null = default implementation }; pub const ProtocolDecl = struct { name: []const u8, methods: []const ProtocolMethodDecl, is_inline: bool = false, // #inline — embedded fn ptrs instead of vtable pointer type_params: []const StructTypeParam = &.{}, // for `protocol(Target: Type) { ... }` }; pub const ImplBlock = struct { protocol_name: []const u8, target_type: []const u8, target_type_params: []const StructTypeParam = &.{}, // for `impl P for List($T)` methods: []const *Node, // fn_decl nodes protocol_type_args: []const *Node = &.{}, // for `impl Into(Block) for Source` — type args on the protocol side target_type_expr: ?*Node = null, // populated for parameterised-protocol impls; carries non-identifier source spellings (e.g. `Closure() -> void`) };