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