lib/std/lang/ast.rad 23.3 KiB raw
1
//! Radiance AST modules.
2
export mod printer;
3
4
use std::io;
5
use std::fmt;
6
use std::lang::alloc;
7
use std::lang::types;
8
9
/// Maximum number of trait methods.
10
export constant MAX_TRAIT_METHODS: u32 = 8;
11
12
/// Arena for all parser allocations.
13
///
14
/// Uses a bump allocator for both AST nodes and node pointer arrays.
15
export record NodeArena: Copy {
16
    /// Bump allocator for all allocations.
17
    arena: alloc::Arena,
18
    /// Next node ID to assign. Incremented on each node allocation.
19
    nextId: u32,
20
}
21
22
/// Initialize a node arena backed by the given byte slice.
23
export fn nodeArena(data: *mut [u8]) -> NodeArena {
24
    return NodeArena {
25
        arena: alloc::new(data),
26
        nextId: 0,
27
    };
28
}
29
30
/// Create an empty `*mut [*Node]` slice with the given capacity.
31
export fn nodeSlice(arena: *mut NodeArena, capacity: u32) -> *mut [*Node] {
32
    if capacity == 0 {
33
        return &mut [];
34
    }
35
    let ptr = try! alloc::allocSlice(&mut arena.arena, @sizeOf(*Node), @alignOf(*Node), capacity);
36
37
    return @sliceOf(ptr.ptr as *mut *Node, 0, capacity);
38
}
39
40
/// Attribute bit set applied to declarations or fields.
41
export union Attribute: Copy {
42
    /// Public visibility attribute.
43
    Export = 0b1,
44
    /// Default implementation attribute.
45
    Default = 0b10,
46
    /// Extern linkage attribute.
47
    Extern = 0b100,
48
    /// Test-only declaration attribute.
49
    Test = 0b1000,
50
    /// Compiler intrinsic attribute.
51
    Intrinsic = 0b10000,
52
    /// Declaration may perform unsafe pointer operations.
53
    Unsafe = 0b100000,
54
}
55
56
/// Ordered collection of attribute nodes applied to a declaration.
57
export record Attributes: Copy {
58
    list: *mut [*Node],
59
}
60
61
/// Check if an attributes list contains an attribute.
62
export fn attributesContains(self: *Attributes, attr: Attribute) -> bool {
63
    for node in self.list {
64
        if let case NodeValue::Attribute(a) = node.value; a == attr {
65
            return true;
66
        }
67
    }
68
    return false;
69
}
70
71
/// Check if an attribute set includes the given attribute.
72
export fn hasAttribute(attrs: u32, attr: Attribute) -> bool {
73
    return (attrs & (attr as u32)) <> 0;
74
}
75
76
/// Signedness of an integer type.
77
export union Signedness: Copy {
78
    /// Signed, eg. `i8`.
79
    Signed,
80
    /// Unsigned, eg. `u32`.
81
    Unsigned,
82
}
83
84
/// Binary operator kinds used in numeric expressions.
85
export union BinaryOp: Copy {
86
    /// Addition (`+`).
87
    Add,
88
    /// Subtraction (`-`).
89
    Sub,
90
    /// Multiplication (`*`).
91
    Mul,
92
    /// Division (`/`).
93
    Div,
94
    /// Remainder (`%`).
95
    Mod,
96
    /// Bitwise AND (`&`).
97
    BitAnd,
98
    /// Bitwise OR (`|`).
99
    BitOr,
100
    /// Bitwise XOR (`^`).
101
    BitXor,
102
    /// Left shift (`<<`).
103
    Shl,
104
    /// Right shift (`>>`).
105
    Shr,
106
107
    /// Equality comparison (`==`).
108
    Eq,
109
    /// Inequality comparison (`<>`).
110
    Ne,
111
    /// Less-than comparison (`<`).
112
    Lt,
113
    /// Greater-than comparison (`>`).
114
    Gt,
115
    /// Less-than-or-equal comparison (`<=`).
116
    Lte,
117
    /// Greater-than-or-equal comparison (`>=`).
118
    Gte,
119
120
    /// Logical conjunction (`and`).
121
    And,
122
    /// Logical disjunction (`or`).
123
    Or,
124
    /// Logical exclusive disjunction (`xor`).
125
    Xor,
126
}
127
128
/// Unary operator kinds used in expressions.
129
export union UnaryOp: Copy {
130
    /// Logical negation (`not`).
131
    Not,
132
    /// Arithmetic negation (`-`).
133
    Neg,
134
    /// Bitwise NOT (`~`).
135
    BitNot,
136
}
137
138
/// Builtin function kind.
139
export union Builtin: Copy {
140
    /// Size of type in bytes (`@sizeOf`).
141
    SizeOf,
142
    /// Alignment requirement of type (`@alignOf`).
143
    AlignOf,
144
    /// Construct a slice from pointer, length, and optional capacity (`@sliceOf`).
145
    SliceOf,
146
}
147
148
/// Source extent for a node measured in bytes.
149
export record Span: Copy {
150
    /// Byte offset from the start of the source file.
151
    offset: u32,
152
    /// Length of the node in bytes.
153
    length: u32,
154
}
155
156
/// Type signature node.
157
export union TypeSig: Copy {
158
    /// Absence of type.
159
    Void,
160
    /// Opaque type.
161
    Opaque,
162
    /// Boolean type.
163
    Bool,
164
    /// Integer type.
165
    Integer {
166
        /// Size of values, in bytes.
167
        width: u8,
168
        /// Signedness of values.
169
        sign: Signedness,
170
    },
171
    /// Fixed-size array type, eg. `[i32; 16]`.
172
    Array {
173
        /// Array element type.
174
        itemType: *Node,
175
        /// Expression that evaluates to the array length.
176
        length: *Node,
177
    },
178
    /// Slice type, eg. `*[i32]`, `&[i32]`, or `*unsafe [i32]`.
179
    Slice {
180
        /// Ownership and safety class.
181
        class: types::PointerClass,
182
        /// Slice element type.
183
        itemType: *Node,
184
        /// Whether the slice is mutable.
185
        mutable: bool,
186
    },
187
    /// Pointer type, eg. `*i32`, `&i32`, or `*unsafe i32`.
188
    Pointer {
189
        /// Ownership and safety class.
190
        class: types::PointerClass,
191
        /// Pointer target type.
192
        valueType: *Node,
193
        /// Whether the pointer is mutable.
194
        mutable: bool,
195
    },
196
    /// Optional, eg. `?i32`.
197
    Optional {
198
        /// Underlying type.
199
        valueType: *Node,
200
    },
201
    /// Nominal type, points to identifier node.
202
    Nominal(*Node),
203
    /// Inline record type for union variant payloads.
204
    Record {
205
        /// Field declaration nodes.
206
        fields: *mut [*Node],
207
        /// Whether this record has labeled fields.
208
        labeled: bool,
209
    },
210
    /// Anonymous function type.
211
    Fn(FnSig),
212
    /// Trait object type, eg. `*opaque Allocator`, `&opaque Allocator`, or
213
    /// `*unsafe opaque Allocator`.
214
    TraitObject {
215
        /// Ownership and safety class.
216
        class: types::PointerClass,
217
        /// Trait name identifier.
218
        traitName: *Node,
219
        /// Whether the pointer is mutable.
220
        mutable: bool,
221
    },
222
}
223
224
/// Function signature.
225
export record FnSig: Copy {
226
    /// Parameter type nodes in declaration order.
227
    params: *mut [*Node],
228
    /// Optional return type node.
229
    returnType: ?*Node,
230
    /// Throwable type nodes declared in the signature.
231
    throwList: *mut [*Node],
232
}
233
234
/// Address-of expression metadata.
235
export record AddressOf: Copy {
236
    /// Target expression being referenced.
237
    target: *Node,
238
    /// Indicates whether the reference is mutable.
239
    mutable: bool,
240
}
241
242
/// Compound statement block with optional dedicated scope.
243
export record Block: Copy {
244
    /// Statements that belong to this block.
245
    statements: *mut [*Node],
246
}
247
248
/// Function call expression.
249
export record Call: Copy {
250
    /// Callee expression.
251
    callee: *Node,
252
    /// Argument expressions in source order.
253
    args: *mut [*Node],
254
}
255
256
/// Single argument to a function or record literal, optionally labeled.
257
export record Arg: Copy {
258
    /// Optional label applied to the argument.
259
    label: ?*Node,
260
    /// Expression supplying the argument value.
261
    value: *Node,
262
}
263
264
/// Assignment expression connecting a target and value.
265
export record Assign: Copy {
266
    /// Expression representing the assignment target.
267
    left: *Node,
268
    /// Expression providing the value being assigned.
269
    right: *Node,
270
}
271
272
/// While loop with an optional alternate branch.
273
export record While: Copy {
274
    /// Condition evaluated before each iteration.
275
    condition: *Node,
276
    /// Loop body executed while `condition` is true.
277
    body: *Node,
278
    /// Optional branch executed when the condition is false at entry.
279
    elseBranch: ?*Node,
280
}
281
282
/// `while let` loop binding metadata.
283
export record WhileLet: Copy {
284
    /// Pattern matching structure.
285
    pattern: PatternMatch,
286
    /// Loop body executed when the pattern matches.
287
    body: *Node,
288
    /// Optional branch executed when the match fails immediately.
289
    elseBranch: ?*Node,
290
}
291
292
/// Try expression metadata.
293
export record Try: Copy {
294
    /// Expression evaluated with implicit error propagation.
295
    expr: *Node,
296
    /// Catch clauses. Empty for propagation (`try`), `try!`, or `try?`.
297
    catches: *mut [*Node],
298
    /// Whether the try should panic instead of returning an error.
299
    shouldPanic: bool,
300
    /// Whether the try should return an optional instead of propagating error.
301
    returnsOptional: bool,
302
}
303
304
/// A single catch clause in a `try ... catch` expression.
305
export record CatchClause: Copy {
306
    /// Optional identifier binding for the error value (eg. `e`).
307
    binding: ?*Node,
308
    /// Optional type annotation after `as` (eg. `IoError`).
309
    typeNode: ?*Node,
310
    /// Block body executed when this clause matches.
311
    body: *Node,
312
}
313
314
/// `for` loop metadata.
315
export record For: Copy {
316
    /// Loop variable binding.
317
    binding: *Node,
318
    /// Optional index binding for enumeration loops.
319
    index: ?*Node,
320
    /// Expression producing the iterable value.
321
    iterable: *Node,
322
    /// Body executed for each element.
323
    body: *Node,
324
    /// Optional branch executed when the loop body never runs.
325
    elseBranch: ?*Node,
326
}
327
328
/// Conditional `if` statement metadata.
329
export record If: Copy {
330
    /// Condition controlling the branch.
331
    condition: *Node,
332
    /// Branch executed when `condition` is true.
333
    thenBranch: *Node,
334
    /// Optional branch executed when `condition` is false.
335
    elseBranch: ?*Node,
336
}
337
338
/// Conditional expression (`<true> if <condition> else <false>`).
339
export record CondExpr: Copy {
340
    /// Condition controlling which branch is evaluated.
341
    condition: *Node,
342
    /// Expression evaluated when `condition` is true.
343
    thenExpr: *Node,
344
    /// Expression evaluated when `condition` is false.
345
    elseExpr: *Node,
346
}
347
348
/// Classification of pattern matches (if-let, while-let, let-else).
349
export union PatternKind: Copy {
350
    /// Case pattern match.
351
    Case,
352
    /// Binding pattern match.
353
    Binding,
354
}
355
356
/// Prong arm.
357
export union ProngArm: Copy {
358
    /// Case arm with pattern list.
359
    Case(*mut [*Node]),
360
    /// Binding arm with single identifier or placeholder.
361
    Binding(*Node),
362
    /// Else arm.
363
    Else,
364
}
365
366
/// Common pattern matching structure used by `if let`, `while let`, and `let-else`.
367
export record PatternMatch: Copy {
368
    /// Pattern or binding to match against.
369
    pattern: *Node,
370
    /// Scrutinee expression to match against.
371
    scrutinee: *Node,
372
    /// Optional guard that must evaluate to `true`.
373
    guard: ?*Node,
374
    /// Whether this is a case pattern or binding.
375
    kind: PatternKind,
376
    /// Whether the binding is mutable.
377
    mutable: bool,
378
}
379
380
/// `if let` conditional binding metadata.
381
export record IfLet: Copy {
382
    /// Pattern matching structure.
383
    pattern: PatternMatch,
384
    /// Branch executed when the pattern matches.
385
    thenBranch: *Node,
386
    /// Optional branch executed when the match fails.
387
    elseBranch: ?*Node,
388
}
389
390
/// `let-else` statement metadata.
391
export record LetElse: Copy {
392
    /// Pattern matching structure.
393
    pattern: PatternMatch,
394
    /// Else branch executed if match fails (must diverge).
395
    elseBranch: *Node,
396
}
397
398
/// `match` statement metadata.
399
export record Match: Copy {
400
    /// Expression whose value controls the match.
401
    subject: *Node,
402
    /// Prong nodes evaluated in order.
403
    prongs: *mut [*Node],
404
}
405
406
/// `match` prong metadata.
407
export record MatchProng: Copy {
408
    /// Prong arm.
409
    arm: ProngArm,
410
    /// Optional guard that must evaluate to `true`.
411
    guard: ?*Node,
412
    /// Body executed when patterns match and guard passes.
413
    body: *Node,
414
}
415
416
/// `let` binding.
417
export record Let: Copy {
418
    /// Identifier bound by the declaration.
419
    ident: *Node,
420
    /// Declared type annotation.
421
    type: ?*Node,
422
    /// Initializer expression.
423
    value: *Node,
424
    /// Storage alignment.
425
    alignment: ?*Node,
426
    /// Whether the variable is mutable.
427
    mutable: bool,
428
}
429
430
/// Constant declaration.
431
export record ConstDecl: Copy {
432
    /// Identifier bound by the declaration.
433
    ident: *Node,
434
    /// Declared type annotation.
435
    type: *Node,
436
    /// Constant initializer expression.
437
    value: *Node,
438
    /// Optional attribute list applied to the constant.
439
    attrs: ?Attributes,
440
}
441
442
/// Static storage declaration.
443
export record StaticDecl: Copy {
444
    /// Identifier bound by the declaration.
445
    ident: *Node,
446
    /// Declared storage type.
447
    type: *Node,
448
    /// Initialization expression.
449
    value: *Node,
450
    /// Optional attribute list applied to the static.
451
    attrs: ?Attributes,
452
}
453
454
/// Function parameter declaration.
455
export record FnParam: Copy {
456
    /// Parameter identifier.
457
    name: *Node,
458
    /// Parameter type annotation.
459
    type: *Node,
460
}
461
462
/// Record literal expression metadata.
463
export record RecordLit: Copy {
464
    /// Type name associated with the literal.
465
    /// If `nil`, it's an anonymous record literal.
466
    typeName: ?*Node,
467
    /// Field initializer nodes.
468
    fields: *mut [*Node],
469
    /// When true, remaining fields are discarded (`{ x, .. }`).
470
    ignoreRest: bool,
471
}
472
473
/// Record declaration.
474
export record RecordDecl: Copy {
475
    /// Identifier naming the record.
476
    name: *Node,
477
    /// Field declaration nodes.
478
    fields: *mut [*Node],
479
    /// Optional attribute list applied to the record.
480
    attrs: ?Attributes,
481
    /// Trait derivations attached to the record.
482
    derives: *mut [*Node],
483
    /// Whether this record has labeled fields.
484
    labeled: bool,
485
}
486
487
/// Union declarations.
488
export record UnionDecl: Copy {
489
    /// Identifier naming the union.
490
    name: *Node,
491
    /// Variant nodes making up the union.
492
    variants: *mut [*Node],
493
    /// Optional attribute list applied to the union.
494
    attrs: ?Attributes,
495
    /// Trait derivations attached to the union.
496
    derives: *mut [*Node],
497
}
498
499
/// Union variant declaration.
500
export record UnionDeclVariant: Copy {
501
    /// Identifier naming the variant.
502
    name: *Node,
503
    /// Variant index.
504
    index: u32,
505
    /// Explicit discriminant value, if provided.
506
    value: ?*Node,
507
    /// Optional payload type.
508
    type: ?*Node,
509
}
510
511
/// Function declaration.
512
export record FnDecl: Copy {
513
    /// Identifier naming the function.
514
    name: *Node,
515
    /// Function type signature.
516
    sig: FnSig,
517
    /// Optional function body (`nil` for extern functions).
518
    body: ?*Node,
519
    /// Optional attribute list applied to the function.
520
    attrs: ?Attributes,
521
}
522
523
/// Array repeat literal metadata.
524
export record ArrayRepeatLit: Copy {
525
    /// Expression providing the repeated value.
526
    item: *Node,
527
    /// Expression providing the repetition count.
528
    count: *Node,
529
}
530
531
/// Module declaration.
532
export record Mod: Copy {
533
    /// Identifier naming the module.
534
    name: *Node,
535
    /// Optional attribute list applied to the module.
536
    attrs: ?Attributes,
537
}
538
539
/// Use declaration for importing modules.
540
export record Use: Copy {
541
    /// Access node identifying the imported module.
542
    path: *Node,
543
    /// Whether this is a wildcard import (e.g. `use ast::*`).
544
    wildcard: bool,
545
    /// Optional attribute list applied to the use declaration.
546
    attrs: ?Attributes,
547
}
548
549
/// Access expression used for field, scope, and index lookups.
550
export record Access: Copy {
551
    /// Expression providing the container or namespace.
552
    parent: *Node,
553
    /// Expression identifying the member, scope element, or index.
554
    child: *Node,
555
}
556
557
/// `as` cast expression metadata.
558
export record As: Copy {
559
    /// Expression being coerced.
560
    value: *Node,
561
    /// Target type annotation.
562
    type: *Node,
563
}
564
565
/// Range expression metadata.
566
export record Range: Copy {
567
    /// Optional inclusive start expression.
568
    start: ?*Node,
569
    /// Optional exclusive end expression.
570
    end: ?*Node,
571
}
572
573
/// Binary operation expression, eg. `x * y`.
574
export record BinOp: Copy {
575
    /// Operator applied to the operands.
576
    op: BinaryOp,
577
    /// Left-hand operand.
578
    left: *Node,
579
    /// Right-hand operand.
580
    right: *Node,
581
}
582
583
/// Unary operation expression, eg. `-x`.
584
export record UnOp: Copy {
585
    /// Operator applied to the operand.
586
    op: UnaryOp,
587
    /// Operand expression.
588
    value: *Node,
589
}
590
591
/// Tagged union describing every possible AST node payload.
592
export union NodeValue: Copy {
593
    /// Placeholder `_` expression.
594
    Placeholder,
595
    /// Nil literal (`nil`).
596
    Nil,
597
    /// Undefined literal (`undefined`).
598
    Undef,
599
    /// Boolean literal (`true` or `false`).
600
    Bool(bool),
601
    /// Character literal like `'x'`.
602
    Char(u8),
603
    /// String literal like `"Hello World!"`.
604
    String(*[u8]),
605
    /// Identifier expression.
606
    Ident(*[u8]),
607
    /// Numeric literal such as `42` or `0xFF`.
608
    Number(fmt::IntLiteral),
609
    /// Range expression such as `0..10` or `..`.
610
    Range(Range),
611
    /// Array literal expression.
612
    ArrayLit(*mut [*Node]),
613
    /// Array repeat literal expression.
614
    ArrayRepeatLit(ArrayRepeatLit),
615
    /// Array subscript expression.
616
    Subscript {
617
        /// Array or slice.
618
        container: *Node,
619
        /// Index expression.
620
        index: *Node
621
    },
622
    /// Binary operator expression.
623
    BinOp(BinOp),
624
    /// Unary operator expression.
625
    UnOp(UnOp),
626
    /// Builtin function call (e.g. `@sizeOf(T)`).
627
    BuiltinCall {
628
        /// Builtin function kind.
629
        kind: Builtin,
630
        /// Argument list.
631
        args: *mut [*Node],
632
    },
633
    /// Block expression or statement body.
634
    Block(Block),
635
    /// Call expression, eg. `f(x)`.
636
    Call(Call),
637
    /// Field access expression (e.g. `foo.bar`).
638
    FieldAccess(Access),
639
    /// Scope access expression (e.g. `foo::bar`).
640
    ScopeAccess(Access),
641
    /// Address of expression (e.g. `&mut x`).
642
    AddressOf(AddressOf),
643
    /// Dereference expression (e.g. `*ptr`).
644
    Deref(*Node),
645
    /// Cast expression using `as`.
646
    As(As),
647
    /// While loop statement.
648
    While(While),
649
    /// `while let` loop statement.
650
    WhileLet(WhileLet),
651
    /// `for` loop statement.
652
    For(For),
653
    /// Infinite loop statement.
654
    Loop {
655
        /// Body executed each iteration.
656
        body: *Node,
657
    },
658
    /// Break statement.
659
    Break,
660
    /// Continue statement.
661
    Continue,
662
    /// Return statement.
663
    Return {
664
        /// Expression returned by this statement, if any.
665
        value: ?*Node,
666
    },
667
    /// Throw statement.
668
    Throw {
669
        /// Expression to throw.
670
        expr: *Node,
671
    },
672
    /// Panic statement.
673
    Panic {
674
        /// Optional panic message expression.
675
        message: ?*Node,
676
    },
677
    /// Assert statement.
678
    Assert {
679
        /// Condition expression that must be true.
680
        condition: *Node,
681
        /// Optional assertion failure message.
682
        message: ?*Node,
683
    },
684
    /// Conditional statement.
685
    If(If),
686
    /// Conditional expression.
687
    CondExpr(CondExpr),
688
    /// `if let` conditional binding.
689
    IfLet(IfLet),
690
    /// `let-else` statement.
691
    LetElse(LetElse),
692
    /// Try expression.
693
    Try(Try),
694
    /// Match statement.
695
    Match(Match),
696
    /// Match prong.
697
    MatchProng(MatchProng),
698
    /// Function declaration.
699
    FnDecl(FnDecl),
700
    /// Function parameter declaration.
701
    FnParam(FnParam),
702
    /// `let binding.
703
    Let(Let),
704
    /// Constant declaration.
705
    ConstDecl(ConstDecl),
706
    /// Static storage declaration.
707
    StaticDecl(StaticDecl),
708
    /// Type signature node.
709
    TypeSig(TypeSig),
710
    /// Assignment statement.
711
    Assign(Assign),
712
    /// Expression statement.
713
    ExprStmt(*Node),
714
    /// Module declaration (`mod`).
715
    Mod(Mod),
716
    /// Parent module reference.
717
    Super,
718
    /// Module use declaration.
719
    Use(Use),
720
    /// Union type declaration.
721
    UnionDecl(UnionDecl),
722
    /// Union variant declaration.
723
    UnionDeclVariant(UnionDeclVariant),
724
    /// Attribute node.
725
    Attribute(Attribute),
726
    /// Record type declaration.
727
    RecordDecl(RecordDecl),
728
    /// Record field declaration.
729
    RecordField {
730
        /// Identifier bound by the declaration.
731
        field: ?*Node,
732
        /// Declared type annotation.
733
        type: *Node,
734
        /// Optional initializer expression.
735
        value: ?*Node,
736
    },
737
    /// Record literal expression.
738
    RecordLit(RecordLit),
739
    /// Record literal field initializer.
740
    RecordLitField(Arg),
741
    /// Alignment specifier.
742
    Align {
743
        /// Alignment value.
744
        value: *Node,
745
    },
746
    /// Catch clause within a try expression.
747
    CatchClause(CatchClause),
748
    /// Trait declaration.
749
    TraitDecl {
750
        /// Trait name identifier.
751
        name: *Node,
752
        /// Supertrait name nodes.
753
        supertraits: *mut [*Node],
754
        /// Method signature nodes ([`TraitMethodSig`]).
755
        methods: *mut [*Node],
756
        /// Optional attributes.
757
        attrs: ?Attributes,
758
    },
759
    /// Method signature inside a trait declaration.
760
    TraitMethodSig {
761
        /// Method name identifier.
762
        name: *Node,
763
        /// Receiver type node (eg. `*mut Allocator`).
764
        receiver: *Node,
765
        /// Function signature.
766
        sig: FnSig,
767
        /// Optional declaration modifiers.
768
        attrs: ?Attributes,
769
    },
770
    /// Instance block.
771
    InstanceDecl {
772
        /// Trait name identifier.
773
        traitName: *Node,
774
        /// Target type identifier.
775
        targetType: *Node,
776
        /// Method definition nodes ([`MethodDecl`]).
777
        methods: *mut [*Node],
778
    },
779
    /// Method definition with a receiver.
780
    /// Used both inside `instance` blocks and as standalone methods.
781
    MethodDecl {
782
        /// Method name identifier.
783
        name: *Node,
784
        /// Receiver binding name ([`Ident`] node).
785
        receiverName: *Node,
786
        /// Receiver type node (eg. `*mut Arena`).
787
        receiverType: *Node,
788
        /// Function signature.
789
        sig: FnSig,
790
        /// Method body.
791
        body: *Node,
792
        /// Optional attribute list.
793
        attrs: ?Attributes,
794
    },
795
}
796
797
/// Full AST node with shared metadata and variant-specific payload.
798
export record Node: Copy {
799
    /// Unique identifier for this node.
800
    id: u32,
801
    /// Source span describing where the node originated.
802
    span: Span,
803
    /// Variant-specific payload for the node.
804
    value: NodeValue,
805
}
806
807
/// Check whether a node is a place expression.
808
///
809
/// Place expressions have persistent storage and can appear on the left side
810
/// of `set` assignments.
811
export fn isPlaceExpr(node: *Node) -> bool {
812
    match node.value {
813
        case NodeValue::Ident(_),
814
             NodeValue::ScopeAccess(_),
815
             NodeValue::FieldAccess(_),
816
             NodeValue::Subscript { .. },
817
             NodeValue::Deref(_) => return true,
818
        else => return false,
819
    }
820
}
821
822
/// Allocate a new AST node from the arena with the given span and value.
823
export fn allocNode(arena: *mut NodeArena, span: Span, value: NodeValue) -> *mut Node {
824
    let p = try! alloc::alloc(&mut arena.arena, @sizeOf(Node), @alignOf(Node));
825
    let node = p as *mut Node;
826
    let nodeId = arena.nextId;
827
    set arena.nextId = nodeId + 1;
828
829
    set *node = Node { id: nodeId, span, value };
830
831
    return node;
832
}
833
834
/// Allocate a synthetic AST node with a zero-length span.
835
export fn synthNode(arena: *mut NodeArena, value: NodeValue) -> *mut Node {
836
    return allocNode(arena, Span { offset: 0, length: 0 }, value);
837
}
838
839
/// Synthetic module with a single function in it.
840
record SynthFnMod: Copy {
841
    /// The module block.
842
    modBody: *Node,
843
    /// The function block.
844
    fnBody: *Node
845
}
846
847
/// Synthesize a module with a function in it with the given name and statements.
848
export fn synthFnModule(
849
    arena: *mut NodeArena, name: *[u8], bodyStmts: *mut [*Node]
850
) -> SynthFnMod {
851
    let a = alloc::arenaAllocator(&mut arena.arena);
852
    let fnName = synthNode(arena, NodeValue::Ident(name));
853
    let params: *mut [*Node] = &mut [];
854
    let throwList: *mut [*Node] = &mut [];
855
    let fnSig = FnSig { params, returnType: nil, throwList };
856
    let fnBody = synthNode(arena, NodeValue::Block(Block { statements: bodyStmts }));
857
    let fnDecl = synthNode(arena, NodeValue::FnDecl(FnDecl {
858
        name: fnName, sig: fnSig, body: fnBody, attrs: nil,
859
    }));
860
    let mut rootStmts: *mut [*Node] = &mut [];
861
    rootStmts.append(fnDecl, a);
862
    let modBody = synthNode(arena, NodeValue::Block(Block { statements: rootStmts }));
863
864
    return SynthFnMod { modBody, fnBody };
865
}