lib/std/lang/parser/tests.rad 133.7 KiB raw
1
//! Parser tests.
2
3
use std::mem;
4
use std::fmt;
5
use std::testing;
6
use std::lang::ast;
7
use std::lang::alloc;
8
use std::lang::sexpr;
9
use std::lang::ast::printer;
10
use std::lang::scanner;
11
use std::lang::strings;
12
13
/// Allocated nodes publish immutable pointers with stable metadata and edges.
14
@test unsafe fn testAstNodePublication() throws (testing::TestError) {
15
    static STORAGE: [u8; 4096] = [0; 4096];
16
    let mut arena = ast::nodeArena(&mut STORAGE[..]);
17
    let allocate: unsafe fn(&mut ast::NodeArena, ast::Span, ast::NodeValue) -> *ast::Node = ast::allocNode;
18
    let synthesize: unsafe fn(&mut ast::NodeArena, ast::NodeValue) -> *ast::Node = ast::synthNode;
19
    let leaf = allocate(&mut arena, ast::Span { offset: 9, length: 4 }, ast::NodeValue::Bool(true));
20
    let root = synthesize(&mut arena, ast::NodeValue::ExprStmt(leaf));
21
    assert leaf.id == 0;
22
    assert leaf.span.offset == 9;
23
    assert leaf.span.length == 4;
24
    assert root.id == 1;
25
    assert root.span.offset == 0;
26
    assert root.span.length == 0;
27
    let case ast::NodeValue::ExprStmt(child) = root.value else throw testing::TestError::Failed;
28
    assert child == leaf;
29
    assert arena.nextId == 2;
30
}
31
32
/// Unified arena size.
33
constant ARENA_SIZE: u32 = 2097152;
34
/// Unified arena storage for all AST allocations.
35
static ARENA_STORAGE: [u8; ARENA_SIZE] = [0; ARENA_SIZE];
36
/// String pool.
37
unsafe static STRING_POOL: strings::Pool = strings::Pool { table: undefined, count: 0 };
38
39
/// Assert that a node is an identifier with the given name.
40
fn expectIdent(node: *ast::Node, name: *[u8])
41
    throws (testing::TestError)
42
{
43
    let case ast::NodeValue::Ident(n) = node.value
44
        if mem::eq(n, name)
45
        else throw testing::TestError::Failed;
46
}
47
48
/// Assert that a node is a type identifier with the given name.
49
fn expectTypeIdent(node: *ast::Node, name: *[u8])
50
    throws (testing::TestError)
51
{
52
    let case ast::NodeValue::TypeSig(ts) = node.value
53
        else throw testing::TestError::Failed;
54
    let case ast::TypeSig::Nominal(ident) = ts
55
        else throw testing::TestError::Failed;
56
57
    try expectIdent(ident, name);
58
}
59
60
/// Assert that a node is a number literal with the given text.
61
fn expectNumber(node: *ast::Node, text: *[u8])
62
    throws (testing::TestError)
63
{
64
    let case ast::NodeValue::Number(n) = node.value
65
        if mem::eq(n.text, text)
66
        else throw testing::TestError::Failed;
67
}
68
69
/// Assert that a node is a range literal with the given optional bounds.
70
fn expectRangeNumbers(node: *ast::Node, start: ?*[u8], end: ?*[u8])
71
    throws (testing::TestError)
72
{
73
    let case ast::NodeValue::Range(range) = node.value
74
        else throw testing::TestError::Failed;
75
76
    if let text = start {
77
        let startNode = range.start
78
            else throw testing::TestError::Failed;
79
        try expectNumber(startNode, text);
80
    } else {
81
        try testing::expect(range.start == nil);
82
    }
83
    if let text = end {
84
        let endNode = range.end
85
            else throw testing::TestError::Failed;
86
        try expectNumber(endNode, text);
87
    } else {
88
        try testing::expect(range.end == nil);
89
    }
90
}
91
92
/// Token operations use the parser's checked pool borrow.
93
fn checkTokenOperations 'pool (p: &mut super::Parser 'pool) throws (testing::TestError) {
94
    super::advance(p);
95
    let name = try super::expect(p, scanner::TokenKind::Ident, "expected name") catch {
96
        throw testing::TestError::Failed;
97
    };
98
    try testing::expectBytesEq(name, "alpha");
99
    try testing::expect(super::consume(p, scanner::TokenKind::Comma));
100
    try testing::expect(not super::consume(p, scanner::TokenKind::Comma));
101
    try testing::expect(super::check(p, scanner::TokenKind::Ident));
102
    super::advance(p);
103
    try testing::expect(super::check(p, scanner::TokenKind::Eof));
104
}
105
106
/// Scanner state can advance without an unsafe token operation.
107
@test unsafe fn testSafeTokenOperations() throws (testing::TestError) {
108
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
109
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
110
        let mut parser = super::mkParser(scanner::SourceLoc::String, "alpha, beta", arenaRef, poolRef);
111
        try checkTokenOperations(&mut parser);
112
    }
113
}
114
115
/// Parse multiple statements from a string.
116
unsafe fn parseStmtsStr(input: *[u8]) -> *ast::Node
117
    throws (testing::TestError)
118
{
119
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
120
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
121
        let mut parser = super::mkParser(scanner::SourceLoc::String, input, arenaRef, poolRef);
122
        return try super::parseModule(&mut parser) catch {
123
            throw testing::TestError::Failed;
124
        };
125
    }
126
}
127
128
/// Parse a single type from a string.
129
unsafe fn parseTypeStr(input: *[u8]) -> *ast::Node
130
    throws (super::ParseError)
131
{
132
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
133
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
134
        let mut parser = super::mkParser(scanner::SourceLoc::String, input, arenaRef, poolRef);
135
        super::advance(&mut parser);
136
        let root = try super::parseType(&mut parser);
137
        try super::expect(&mut parser, scanner::TokenKind::Eof, "expected end of type");
138
139
        return root;
140
    }
141
}
142
143
/// Parse a single expression from a string.
144
export unsafe fn parseExprStr(input: *[u8]) -> *ast::Node
145
    throws (super::ParseError)
146
{
147
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
148
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
149
        let mut parser = super::mkParser(scanner::SourceLoc::String, input, arenaRef, poolRef);
150
        super::advance(&mut parser);
151
        return try super::parseExpr(&mut parser);
152
    }
153
}
154
155
/// Parse a single statement from a string.
156
unsafe fn parseStmtStr(input: *[u8]) -> *ast::Node
157
    throws (super::ParseError)
158
{
159
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
160
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
161
        let mut parser = super::mkParser(scanner::SourceLoc::String, input, arenaRef, poolRef);
162
        super::advance(&mut parser);
163
        let root = try super::parseStmt(&mut parser);
164
        while super::consume(&mut parser, scanner::TokenKind::Semicolon) {}
165
        try super::expect(&mut parser, scanner::TokenKind::Eof, "expected end of statement");
166
167
        return root;
168
    }
169
}
170
171
/// Parse an expression expected to be a number literal and return its payload.
172
unsafe fn parseNumberLiteral(text: *[u8]) -> fmt::IntLiteral
173
    throws (testing::TestError)
174
{
175
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
176
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
177
        let mut parser = super::mkParser(scanner::SourceLoc::String, text, arenaRef, poolRef);
178
        super::advance(&mut parser);
179
180
        let node = try! super::parseExpr(&mut parser);
181
182
        if not super::check(&parser, scanner::TokenKind::Eof) {
183
            throw testing::TestError::Failed;
184
        }
185
        let case ast::NodeValue::Number(lit) = node.value
186
            else throw testing::TestError::Failed;
187
188
        return lit;
189
    }
190
}
191
192
/// Ensure that parsing the supplied literal source fails.
193
unsafe fn expectNumberLiteralFail(text: *[u8])
194
    throws (testing::TestError)
195
{
196
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
197
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
198
        let mut parser = super::mkParser(scanner::SourceLoc::String, text, arenaRef, poolRef);
199
        super::advance(&mut parser);
200
201
        try super::parseExpr(&mut parser) catch {
202
            return;
203
        };
204
        if not super::check(&parser, scanner::TokenKind::Eof) {
205
            return;
206
        }
207
        throw testing::TestError::Failed;
208
    }
209
}
210
211
/// Assert that a node is a type signature matching the expected type.
212
fn expectType(node: *ast::Node, type: ast::TypeSig)
213
    throws (testing::TestError)
214
{
215
    let case ast::NodeValue::TypeSig(t) = node.value
216
        if (t == type)
217
        else throw testing::TestError::Failed;
218
}
219
220
/// Assert that a node is an integer type with the expected width and sign.
221
fn expectIntType(node: *ast::Node, expectedWidth: u32, expectedSign: ast::Signedness)
222
    throws (testing::TestError)
223
{
224
    let case ast::NodeValue::TypeSig(sig) = node.value
225
        else throw testing::TestError::Failed;
226
227
    let case ast::TypeSig::Integer { width, sign } = sig
228
        else throw testing::TestError::Failed;
229
230
    try testing::expect(width == expectedWidth);
231
    try testing::expect(sign == expectedSign);
232
}
233
234
/// Extract a union variant and verify its name and index.
235
/// Returns the payload's fields slice for further checking with `expectField`.
236
fn expectVariant(varNode: *ast::Node, name: *[u8], index: u32) -> ?*[*ast::Node]
237
    throws (testing::TestError)
238
{
239
    let case ast::NodeValue::UnionDeclVariant(v) = varNode.value
240
        else throw testing::TestError::Failed;
241
    try expectIdent(v.name, name);
242
    try testing::expect(v.index == index);
243
    try testing::expect(v.value == nil);
244
245
    let payloadType = v.type else return nil;
246
    let case ast::NodeValue::TypeSig(sig) = payloadType.value
247
        else throw testing::TestError::Failed;
248
    let case ast::TypeSig::Record { fields, .. } = sig
249
        else throw testing::TestError::Failed;
250
251
    return fields;
252
}
253
254
/// Check a record field has the expected name and type signature.
255
fn expectFieldSig(
256
    fields: *[*ast::Node], index: u32, name: ?*[u8], sig: ast::TypeSig
257
) throws (testing::TestError) {
258
    let fieldNode = fields[index];
259
    let case ast::NodeValue::RecordField { field, type: fieldType, .. } = fieldNode.value
260
        else throw testing::TestError::Failed;
261
262
    if let expectedName = name {
263
        let actualName = field else throw testing::TestError::Failed;
264
        try expectIdent(actualName, expectedName);
265
    } else {
266
        try testing::expect(field == nil);
267
    }
268
    try expectType(fieldType, sig);
269
}
270
271
/// Assert that a block's first statement is an expression statement with the expected value.
272
fn expectBlockExprStmt(blk: *ast::Node, expected: ast::NodeValue)
273
    throws (testing::TestError)
274
{
275
    let stmt = try getBlockFirstStmt(blk);
276
    let case ast::NodeValue::ExprStmt(expr) = stmt.value
277
        else throw testing::TestError::Failed;
278
279
    if let case ast::NodeValue::Ident(e) = expected {
280
        if let case ast::NodeValue::Ident(a) = expr.value {
281
            if mem::eq(e, a) {
282
                return;
283
            } else {
284
                throw testing::TestError::Failed;
285
            }
286
        }
287
    }
288
    panic "expectBlockExprStmt: comparing values we don't know how to compare";
289
}
290
291
/// Get the first statement from a block node.
292
export fn getBlockFirstStmt(blk: *ast::Node) -> *ast::Node
293
    throws (testing::TestError)
294
{
295
    let case ast::NodeValue::Block(block) = blk.value
296
        else throw testing::TestError::Failed;
297
298
    if block.statements.len == 0 {
299
        throw testing::TestError::Failed;
300
    }
301
    return block.statements[0];
302
}
303
304
/// Get the last statement from a block node.
305
export fn getBlockLastStmt(blk: *ast::Node) -> *ast::Node
306
    throws (testing::TestError)
307
{
308
    let case ast::NodeValue::Block(block) = blk.value
309
        else throw testing::TestError::Failed;
310
311
    if block.statements.len == 0 {
312
        throw testing::TestError::Failed;
313
    }
314
    return block.statements[block.statements.len - 1];
315
}
316
317
/// Test parsing boolean literals (`true` and `false`).
318
@test unsafe fn testParseBool() throws (testing::TestError) {
319
    let r1 = try! parseExprStr("true");
320
    let case ast::NodeValue::Bool(v1) = r1.value if v1
321
        else throw testing::TestError::Failed;
322
323
    let r2 = try! parseExprStr("false");
324
    let case ast::NodeValue::Bool(v2) = r2.value if not v2
325
        else throw testing::TestError::Failed;
326
}
327
328
/// Test parsing number literals.
329
@test unsafe fn testParseNumber() throws (testing::TestError) {
330
    let r1 = try! parseExprStr("4519");
331
    try expectNumber(r1, "4519");
332
}
333
334
/// Verify that decimal literals record magnitude and base metadata.
335
@test unsafe fn testParseDecimalLiteralMetadata() throws (testing::TestError) {
336
    let lit = try parseNumberLiteral("1234");
337
    try testing::expect(lit.magnitude == 1234);
338
    try testing::expect(lit.radix == fmt::Radix::Decimal);
339
}
340
341
/// Verify that hexadecimal literals record magnitude and radix metadata.
342
@test unsafe fn testParseNumberMetadata() throws (testing::TestError) {
343
    let lit = try parseNumberLiteral("0xFF");
344
    try testing::expect(lit.magnitude == 0xFF);
345
    try testing::expect(lit.radix == fmt::Radix::Hex);
346
}
347
348
/// Verify that binary literals capture their radix.
349
@test unsafe fn testParseBinaryLiteralMetadata() throws (testing::TestError) {
350
    let lit = try parseNumberLiteral("0b1010");
351
    try testing::expect(lit.magnitude == 0b1010);
352
    try testing::expect(lit.radix == fmt::Radix::Binary);
353
}
354
355
/// Negative literals parse as unary negation of an unsigned number.
356
@test unsafe fn testParseNegativeLiteral() throws (testing::TestError) {
357
    let node = try! parseExprStr("-99");
358
    let case ast::NodeValue::UnOp(neg) = node.value
359
        else throw testing::TestError::Failed;
360
    try testing::expect(neg.op == ast::UnaryOp::Neg);
361
    let case ast::NodeValue::Number(lit) = neg.value.value
362
        else throw testing::TestError::Failed;
363
    try testing::expect(lit.magnitude == 99);
364
}
365
366
/// Unary plus is not part of the expression grammar.
367
@test unsafe fn testRejectUnaryPlus() throws (testing::TestError) {
368
    try expectNumberLiteralFail("+1");
369
    try expectNumberLiteralFail("+value");
370
    try expectNumberLiteralFail("+(value)");
371
}
372
373
/// Range expressions parse with explicit start and end bounds.
374
@test unsafe fn testParseRangeExpr() throws (testing::TestError) {
375
    let node = try! parseExprStr("0..5");
376
    try expectRangeNumbers(node, "0", "5");
377
}
378
379
/// Range expressions allow a missing end bound.
380
@test unsafe fn testParseRangeExprNoEnd() throws (testing::TestError) {
381
    let node = try! parseExprStr("0..");
382
    try expectRangeNumbers(node, "0", nil);
383
}
384
385
/// Range expressions allow a missing start bound.
386
@test unsafe fn testParseRangeExprNoStart() throws (testing::TestError) {
387
    let node = try! parseExprStr("..5");
388
    try expectRangeNumbers(node, nil, "5");
389
}
390
391
/// Literals with out-of-range digits for their base are rejected.
392
@test unsafe fn testParseInvalidIntLiteral() throws (testing::TestError) {
393
    // 2^64 overflows u64.
394
    try expectNumberLiteralFail("18446744073709551616");
395
    try expectNumberLiteralFail("0x10000000000000000");
396
    try expectNumberLiteralFail("0x1G");
397
    try expectNumberLiteralFail("0b102");
398
}
399
400
/// Test parsing nil literal.
401
@test unsafe fn testParseNil() throws (testing::TestError) {
402
    let r1 = try! parseExprStr("nil");
403
    let case ast::NodeValue::Nil = r1.value
404
        else throw testing::TestError::Failed;
405
}
406
407
/// Test parsing undefined literal.
408
@test unsafe fn testParseUndefined() throws (testing::TestError) {
409
    let r1 = try! parseExprStr("undefined");
410
    let case ast::NodeValue::Undef = r1.value
411
        else throw testing::TestError::Failed;
412
}
413
414
/// Test parsing character literals.
415
@test unsafe fn testParseChar() throws (testing::TestError) {
416
    let r1 = try! parseExprStr("'a'");
417
    let case ast::NodeValue::Char(c1) = r1.value if c1 == 'a'
418
        else throw testing::TestError::Failed;
419
420
    let r2 = try! parseExprStr("'\\n'");
421
    let case ast::NodeValue::Char(c2) = r2.value if c2 == '\n'
422
        else throw testing::TestError::Failed;
423
424
    let r3 = try! parseExprStr("'\\t'");
425
    let case ast::NodeValue::Char(c3) = r3.value if c3 == '\t'
426
        else throw testing::TestError::Failed;
427
}
428
429
/// Test parsing string literals.
430
@test unsafe fn testParseString() throws (testing::TestError) {
431
    let r1 = try! parseExprStr("\"hello\"");
432
    let case ast::NodeValue::String(s1) = r1.value if mem::eq(s1, "hello")
433
        else throw testing::TestError::Failed;
434
435
    let r2 = try! parseExprStr("\"\"");
436
    let case ast::NodeValue::String(s2) = r2.value if s2.len == 0
437
        else throw testing::TestError::Failed;
438
}
439
440
/// Test string escape sequence processing.
441
@test unsafe fn testParseStringEscape() throws (testing::TestError) {
442
    // Tab and newline.
443
    let r1 = try! parseExprStr("\"hello\\tworld\\n\"");
444
    let case ast::NodeValue::String(s1) = r1.value if s1.len == 12
445
        else throw testing::TestError::Failed;
446
    if s1[5] <> '\t' {
447
        throw testing::TestError::Failed;
448
    }
449
    if s1[11] <> '\n' {
450
        throw testing::TestError::Failed;
451
    }
452
453
    // Escaped quote.
454
    let r2 = try! parseExprStr("\"\\\"\"");
455
    let case ast::NodeValue::String(s2) = r2.value if s2.len == 1
456
        else throw testing::TestError::Failed;
457
    if s2[0] <> '"' {
458
        throw testing::TestError::Failed;
459
    }
460
461
    // Escaped backslash.
462
    let r3 = try! parseExprStr("\"\\\\\"");
463
    let case ast::NodeValue::String(s3) = r3.value if s3.len == 1
464
        else throw testing::TestError::Failed;
465
    if s3[0] <> '\\' {
466
        throw testing::TestError::Failed;
467
    }
468
469
    // Mixed escapes.
470
    let r4 = try! parseExprStr("\"a\\nb\\tc\"");
471
    let case ast::NodeValue::String(s4) = r4.value if s4.len == 5
472
        else throw testing::TestError::Failed;
473
    if s4[0] <> 'a' {
474
        throw testing::TestError::Failed;
475
    }
476
    if s4[1] <> '\n' {
477
        throw testing::TestError::Failed;
478
    }
479
    if s4[2] <> 'b' {
480
        throw testing::TestError::Failed;
481
    }
482
    if s4[3] <> '\t' {
483
        throw testing::TestError::Failed;
484
    }
485
    if s4[4] <> 'c' {
486
        throw testing::TestError::Failed;
487
    }
488
}
489
490
/// Test parsing placeholder/underscore.
491
@test unsafe fn testParsePlaceholder() throws (testing::TestError) {
492
    let r1 = try! parseExprStr("_");
493
    let case ast::NodeValue::Placeholder = r1.value
494
        else throw testing::TestError::Failed;
495
}
496
497
/// Test parsing array literals.
498
@test unsafe fn testParseArrayLiteral() throws (testing::TestError) {
499
    let r1 = try! parseExprStr("[]");
500
    let case ast::NodeValue::ArrayLit(items1) = r1.value if items1.len == 0
501
        else throw testing::TestError::Failed;
502
503
    let r2 = try! parseExprStr("[1]");
504
    let case ast::NodeValue::ArrayLit(items2) = r2.value if items2.len == 1
505
        else throw testing::TestError::Failed;
506
507
    let r3 = try! parseExprStr("[1, 2, 3]");
508
    let case ast::NodeValue::ArrayLit(items3) = r3.value if items3.len == 3
509
        else throw testing::TestError::Failed;
510
}
511
512
/// Test parsing array repeat literals.
513
@test unsafe fn testParseArrayRepeatLiteral() throws (testing::TestError) {
514
    let r1 = try! parseExprStr("[42; 10]");
515
    let case ast::NodeValue::ArrayRepeatLit(a) = r1.value
516
        else throw testing::TestError::Failed;
517
518
    try expectNumber(a.item, "42");
519
    try expectNumber(a.count, "10");
520
}
521
522
/// Test parsing a simple `if` statement without an `else` clause.
523
@test unsafe fn testParseIf() throws (testing::TestError) {
524
    let r1 = try parseStmtStr("if condition { body; }") catch {
525
        throw testing::TestError::Failed;
526
    };
527
    let case ast::NodeValue::If(n) = r1.value
528
        else throw testing::TestError::Failed;
529
530
    try expectIdent(n.condition, "condition");
531
    try expectBlockExprStmt(n.thenBranch, ast::NodeValue::Ident("body"));
532
    try testing::expect(n.elseBranch == nil);
533
}
534
535
/// Test parsing an `if-else` statement.
536
@test unsafe fn testParseIfElse() throws (testing::TestError) {
537
    let r1 = try! parseStmtStr("if condition { left; } else { right; }") catch {
538
        throw testing::TestError::Failed;
539
    };
540
    let case ast::NodeValue::If(n) = r1.value
541
        else throw testing::TestError::Failed;
542
543
    try expectIdent(n.condition, "condition");
544
    try expectBlockExprStmt(n.thenBranch, ast::NodeValue::Ident("left"));
545
546
    let elseBranch = n.elseBranch
547
        else throw testing::TestError::Failed;
548
549
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("right"));
550
}
551
552
/// Test parsing an `if-else if-else` chain.
553
@test unsafe fn testParseIfElseIf() throws (testing::TestError) {
554
    let root = try! parseStmtStr("if x { a; } else if y { b; } else { c; }") catch {
555
        throw testing::TestError::Failed;
556
    };
557
    let case ast::NodeValue::If(top) = root.value
558
        else throw testing::TestError::Failed;
559
560
    try expectIdent(top.condition, "x");
561
    try expectBlockExprStmt(top.thenBranch, ast::NodeValue::Ident("a"));
562
563
    let topElse = top.elseBranch
564
        else throw testing::TestError::Failed;
565
    let nested = try getBlockFirstStmt(topElse);
566
    let case ast::NodeValue::If(inner) = nested.value
567
        else throw testing::TestError::Failed;
568
569
    try expectIdent(inner.condition, "y");
570
    try expectBlockExprStmt(inner.thenBranch, ast::NodeValue::Ident("b"));
571
572
    let innerElse = inner.elseBranch
573
        else throw testing::TestError::Failed;
574
    try expectBlockExprStmt(innerElse, ast::NodeValue::Ident("c"));
575
}
576
577
/// Test parsing a block with multiple statements where the last lacks a semicolon.
578
@test unsafe fn testParseBlockMultiStmt() throws (testing::TestError) {
579
    let root = try! parseStmtStr("{ first; second; third }");
580
    let case ast::NodeValue::Block(body) = root.value
581
        else throw testing::TestError::Failed;
582
    try testing::expect(body.statements.len == 3);
583
584
    let firstStmt = body.statements[0];
585
    let case ast::NodeValue::ExprStmt(firstExpr) = firstStmt.value
586
        else throw testing::TestError::Failed;
587
    try expectIdent(firstExpr, "first");
588
589
    let secondStmt = body.statements[1];
590
    let case ast::NodeValue::ExprStmt(secondExpr) = secondStmt.value
591
        else throw testing::TestError::Failed;
592
    try expectIdent(secondExpr, "second");
593
594
    let thirdStmt = body.statements[2];
595
    let case ast::NodeValue::ExprStmt(thirdExpr) = thirdStmt.value
596
        else throw testing::TestError::Failed;
597
    try expectIdent(thirdExpr, "third");
598
}
599
600
/// Test parsing a block that keeps a trailing `;` delimiter.
601
@test unsafe fn testParseBlockTrailingSemicolon() throws (testing::TestError) {
602
    let root = try! parseStmtStr("if cond { only; }") catch {
603
        throw testing::TestError::Failed;
604
    };
605
    let case ast::NodeValue::If(node) = root.value
606
        else throw testing::TestError::Failed;
607
608
    let case ast::NodeValue::Block(body) = node.thenBranch.value
609
        else throw testing::TestError::Failed;
610
    try testing::expect(body.statements.len == 1);
611
612
    let stmt = body.statements[0];
613
    let case ast::NodeValue::ExprStmt(expr) = stmt.value
614
        else throw testing::TestError::Failed;
615
    try expectIdent(expr, "only");
616
}
617
618
/// Test that missing delimiters between block statements produce an error.
619
@test unsafe fn testParseBlockMissingDelimiter() throws (testing::TestError) {
620
    let parsed: ?*ast::Node =
621
        try? parseStmtStr("if cond { first second }");
622
    try testing::expect(parsed == nil);
623
}
624
625
/// Test parsing a `let` binding without a type annotation.
626
@test unsafe fn testParseLet() throws (testing::TestError) {
627
    let r1 = try! parseStmtStr("let x = y;") catch {
628
        throw testing::TestError::Failed;
629
    };
630
    let case ast::NodeValue::Let(n) = r1.value
631
        else throw testing::TestError::Failed;
632
633
    try expectIdent(n.ident, "x");
634
    try expectIdent(n.value, "y");
635
    try testing::expect(not n.mutable);
636
    try testing::expect(n.type == nil);
637
}
638
639
/// Test parsing a `let` binding with a type annotation.
640
@test unsafe fn testParseLetTyped() throws (testing::TestError) {
641
    let r1 = try! parseStmtStr("let x: i32 = y;");
642
    let case ast::NodeValue::Let(n) = r1.value
643
        else throw testing::TestError::Failed;
644
645
    try expectIdent(n.ident, "x");
646
    try expectIdent(n.value, "y");
647
    try testing::expect(not n.mutable);
648
649
    let type = n.type
650
        else throw testing::TestError::Failed;
651
    try expectType(type, ast::TypeSig::Integer {
652
        width: 4, sign: ast::Signedness::Signed
653
    });
654
}
655
656
/// Test parsing a `let` binding with alignment modifier.
657
@test unsafe fn testParseLetAlign() throws (testing::TestError) {
658
    let r1 = try! parseStmtStr("let x: i32 align(16) = 13;");
659
    let case ast::NodeValue::Let(n) = r1.value
660
        else throw testing::TestError::Failed;
661
662
    try expectIdent(n.ident, "x");
663
    try expectNumber(n.value, "13");
664
    try testing::expect(not n.mutable);
665
666
    let type = n.type
667
        else throw testing::TestError::Failed;
668
    try expectType(type, ast::TypeSig::Integer {
669
        width: 4, sign: ast::Signedness::Signed
670
    });
671
672
    let alignment = n.alignment
673
        else throw testing::TestError::Failed;
674
    let case ast::NodeValue::Align(a) = alignment.value
675
        else throw testing::TestError::Failed;
676
    try expectNumber(a, "16");
677
}
678
679
/// Test parsing let-else statement.
680
@test unsafe fn testParseLetElse() throws (testing::TestError) {
681
    let root = try! parseStmtStr("let x = opt else { return };");
682
    let case ast::NodeValue::LetElse(letElse) = root.value
683
        else throw testing::TestError::Failed;
684
685
    try expectIdent(letElse.pattern.pattern, "x");
686
687
    let case ast::NodeValue::Block(elseBlock) = letElse.elseBranch.value
688
        else throw testing::TestError::Failed;
689
    try testing::expect(elseBlock.statements.len == 1);
690
}
691
692
/// Test parsing let-else with single statement.
693
@test unsafe fn testParseLetElseSingleStmt() throws (testing::TestError) {
694
    let root = try! parseStmtStr("let y = val else return;");
695
    let case ast::NodeValue::LetElse(letElse) = root.value
696
        else throw testing::TestError::Failed;
697
698
    try expectIdent(letElse.pattern.pattern, "y");
699
700
    let case ast::NodeValue::Return(_) = letElse.elseBranch.value
701
        else throw testing::TestError::Failed;
702
}
703
704
/// Test parsing let-else with expression branch.
705
@test unsafe fn testParseLetElseExpr() throws (testing::TestError) {
706
    let root = try! parseStmtStr("let z = opt else y;");
707
    let case ast::NodeValue::LetElse(letElse) = root.value
708
        else throw testing::TestError::Failed;
709
710
    try expectIdent(letElse.pattern.pattern, "z");
711
    try expectIdent(letElse.elseBranch, "y");
712
}
713
714
/// Test parsing let-case-else statement.
715
@test unsafe fn testParseLetCaseElse() throws (testing::TestError) {
716
    let root = try! parseStmtStr("let case Variant(x) = opt else { return };");
717
    let case ast::NodeValue::LetElse(letElse) = root.value
718
        else throw testing::TestError::Failed;
719
720
    try testing::expect(letElse.pattern.guard == nil);
721
}
722
723
/// Test parsing let-case-else with guard.
724
@test unsafe fn testParseLetCaseElseWithGuard() throws (testing::TestError) {
725
    let root = try! parseStmtStr("let case Variant(x) = opt if x > 0 else { return };");
726
    let case ast::NodeValue::LetElse(letElse) = root.value
727
        else throw testing::TestError::Failed;
728
729
    try testing::expect(letElse.pattern.guard <> nil);
730
731
    let guardNode = letElse.pattern.guard else throw testing::TestError::Failed;
732
    let case ast::NodeValue::BinOp(cmp) = guardNode.value
733
        else throw testing::TestError::Failed;
734
    try testing::expect(cmp.op == ast::BinaryOp::Gt);
735
}
736
737
/// Test parsing a `let mut` declaration.
738
@test unsafe fn testParseMut() throws (testing::TestError) {
739
    let r1 = try! parseStmtStr("let mut x = 42;");
740
    let case ast::NodeValue::Let(n) = r1.value
741
        else throw testing::TestError::Failed;
742
743
    try expectIdent(n.ident, "x");
744
    try expectNumber(n.value, "42");
745
    try testing::expect(n.mutable);
746
    try testing::expect(n.type == nil);
747
}
748
749
/// Test parsing a `let mut` declaration with type annotation.
750
@test unsafe fn testParseMutTyped() throws (testing::TestError) {
751
    let r1 = try! parseStmtStr("let mut x: i32 = 42;");
752
    let case ast::NodeValue::Let(n) = r1.value
753
        else throw testing::TestError::Failed;
754
755
    try expectIdent(n.ident, "x");
756
    try expectNumber(n.value, "42");
757
    try testing::expect(n.mutable);
758
759
    let type = n.type
760
        else throw testing::TestError::Failed;
761
    try expectType(type, ast::TypeSig::Integer {
762
        width: 4, sign: ast::Signedness::Signed
763
    });
764
}
765
766
/// Test parsing a `constant` declaration.
767
@test unsafe fn testParseConst() throws (testing::TestError) {
768
    let node = try! parseStmtStr("constant ANSWER: i32 = 42;");
769
    let case ast::NodeValue::ConstDecl(decl) = node.value
770
        else throw testing::TestError::Failed;
771
772
    try expectIdent(decl.ident, "ANSWER");
773
    try expectType(decl.type, ast::TypeSig::Integer {
774
        width: 4, sign: ast::Signedness::Signed
775
    });
776
    try expectNumber(decl.value, "42");
777
}
778
779
/// Test parsing a `static` declaration.
780
@test unsafe fn testParseStatic() throws (testing::TestError) {
781
    let node = try! parseStmtStr("static COUNTER: i32 = 0;");
782
    let case ast::NodeValue::StaticDecl(decl) = node.value
783
        else throw testing::TestError::Failed;
784
785
    try expectIdent(decl.ident, "COUNTER");
786
    try expectType(decl.type, ast::TypeSig::Integer {
787
        width: 4, sign: ast::Signedness::Signed
788
    });
789
    try expectNumber(decl.value, "0");
790
}
791
792
/// Test parsing a `use` declaration.
793
@test unsafe fn testParseUse() throws (testing::TestError) {
794
    let node = try! parseStmtStr("use module::item;");
795
    let case ast::NodeValue::Use(decl) = node.value
796
        else throw testing::TestError::Failed;
797
798
    let case ast::NodeValue::ScopeAccess(scope) = decl.path.value
799
        else throw testing::TestError::Failed;
800
801
    try expectIdent(scope.parent, "module");
802
    try expectIdent(scope.child, "item");
803
}
804
805
/// Test parsing a `mod` declaration.
806
@test unsafe fn testParseMod() throws (testing::TestError) {
807
    let node = try! parseStmtStr("mod io;");
808
    let case ast::NodeValue::Mod(decl) = node.value
809
        else throw testing::TestError::Failed;
810
811
    try expectIdent(decl.name, "io");
812
    try testing::expect(decl.attrs == nil);
813
}
814
815
/// Test parsing a module declaration with attributes.
816
@test unsafe fn testParseModAttributes() throws (testing::TestError) {
817
    let node = try! parseStmtStr("export mod io;");
818
    let case ast::NodeValue::Mod(decl) = node.value
819
        else throw testing::TestError::Failed;
820
821
    try expectIdent(decl.name, "io");
822
    let attrs = decl.attrs
823
        else throw testing::TestError::Failed;
824
825
    try testing::expect(attrs.list.len == 1);
826
827
    let case ast::NodeValue::Attribute(attr) = attrs.list[0].value
828
        else throw testing::TestError::Failed;
829
830
    try testing::expect(attr == ast::Attribute::Export);
831
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Export));
832
}
833
834
/// Test parsing an optional type.
835
@test unsafe fn testParseTypeOptional() throws (testing::TestError) {
836
    let node = try! parseTypeStr("?i32");
837
    let case ast::NodeValue::TypeSig(optional) = node.value
838
        else throw testing::TestError::Failed;
839
    let case ast::TypeSig::Optional(opt) = optional
840
        else throw testing::TestError::Failed;
841
842
    try expectIntType(opt, 4, ast::Signedness::Signed);
843
}
844
845
/// Parse an `i32` pointer type and verify its class and mutability.
846
unsafe fn expectI32Pointer(
847
    source: *[u8],
848
    class: ast::PointerClass,
849
    mutable: bool,
850
) throws (testing::TestError) {
851
    let node = try! parseTypeStr(source);
852
    let case ast::NodeValue::TypeSig(sig) = node.value
853
        else throw testing::TestError::Failed;
854
    let case ast::TypeSig::Pointer {
855
        class: actualClass, valueType, mutable: actualMutable,
856
    } = sig else throw testing::TestError::Failed;
857
858
    assert actualClass == class;
859
    try expectIntType(valueType, 4, ast::Signedness::Signed);
860
    assert actualMutable == mutable;
861
}
862
863
/// Test parsing a mutable owned pointer.
864
@test unsafe fn testParseTypePointer() throws (testing::TestError) {
865
    try expectI32Pointer("*mut i32", ast::PointerClass::Owned, true);
866
}
867
868
/// Test parsing an immutable owned pointer.
869
@test unsafe fn testParseTypePointerImmutable() throws (testing::TestError) {
870
    try expectI32Pointer("*i32", ast::PointerClass::Owned, false);
871
}
872
873
/// Test parsing immutable and mutable references.
874
@test unsafe fn testParseTypeRef() throws (testing::TestError) {
875
    try expectI32Pointer("&i32", ast::PointerClass::Ref, false);
876
    try expectI32Pointer("&mut i32", ast::PointerClass::Ref, true);
877
}
878
879
/// Test parsing immutable and mutable unsafe pointers.
880
@test unsafe fn testParseTypeUnsafePointer() throws (testing::TestError) {
881
    try expectI32Pointer("*unsafe i32", ast::PointerClass::Unsafe, false);
882
    try expectI32Pointer("*unsafe mut i32", ast::PointerClass::Unsafe, true);
883
}
884
885
/// Test parsing a slice type.
886
@test unsafe fn testParseTypeSlice() throws (testing::TestError) {
887
    let node = try! parseTypeStr("*[u8]");
888
    let case ast::NodeValue::TypeSig(sig) = node.value
889
        else throw testing::TestError::Failed;
890
    let case ast::TypeSig::Slice { class, itemType, mutable } = sig
891
        else throw testing::TestError::Failed;
892
893
    assert class == ast::PointerClass::Owned;
894
    try expectIntType(itemType, 1, ast::Signedness::Unsigned);
895
    assert not mutable;
896
}
897
898
/// Test parsing a mutable slice type.
899
@test unsafe fn testParseTypeSliceMutable() throws (testing::TestError) {
900
    let node = try! parseTypeStr("*mut [u8]");
901
    let case ast::NodeValue::TypeSig(sig) = node.value
902
        else throw testing::TestError::Failed;
903
    let case ast::TypeSig::Slice { class, itemType, mutable } = sig
904
        else throw testing::TestError::Failed;
905
906
    assert class == ast::PointerClass::Owned;
907
    try expectIntType(itemType, 1, ast::Signedness::Unsigned);
908
    assert mutable;
909
}
910
911
/// Test parsing reference and unsafe slice classes.
912
@test unsafe fn testParseTypeSliceClasses() throws (testing::TestError) {
913
    let refNode = try! parseTypeStr("&[u8]");
914
    let case ast::NodeValue::TypeSig(ast::TypeSig::Slice {
915
        class: refClass, ..
916
    }) = refNode.value else throw testing::TestError::Failed;
917
    assert refClass == ast::PointerClass::Ref;
918
919
    let unsafeNode = try! parseTypeStr("*unsafe [u8]");
920
    let case ast::NodeValue::TypeSig(ast::TypeSig::Slice {
921
        class: unsafeClass, ..
922
    }) = unsafeNode.value else throw testing::TestError::Failed;
923
    assert unsafeClass == ast::PointerClass::Unsafe;
924
}
925
926
/// Test parsing trait object pointer classes.
927
@test unsafe fn testParseTypeTraitObjectClasses() throws (testing::TestError) {
928
    let ownedNode = try! parseTypeStr("*opaque Read");
929
    let case ast::NodeValue::TypeSig(ast::TypeSig::TraitObject {
930
        class: ownedClass, ..
931
    }) = ownedNode.value else throw testing::TestError::Failed;
932
    assert ownedClass == ast::PointerClass::Owned;
933
934
    let refNode = try! parseTypeStr("&opaque Read");
935
    let case ast::NodeValue::TypeSig(ast::TypeSig::TraitObject {
936
        class: refClass, ..
937
    }) = refNode.value else throw testing::TestError::Failed;
938
    assert refClass == ast::PointerClass::Ref;
939
940
    let unsafeNode = try! parseTypeStr("*unsafe opaque Read");
941
    let case ast::NodeValue::TypeSig(ast::TypeSig::TraitObject {
942
        class: unsafeClass, ..
943
    }) = unsafeNode.value else throw testing::TestError::Failed;
944
    assert unsafeClass == ast::PointerClass::Unsafe;
945
}
946
947
/// Test parsing an array type.
948
@test unsafe fn testParseTypeArray() throws (testing::TestError) {
949
    let node = try! parseTypeStr("[i32; 4]");
950
    let case ast::NodeValue::TypeSig(sig) = node.value
951
        else throw testing::TestError::Failed;
952
    let case ast::TypeSig::Array { itemType, length } = sig
953
        else throw testing::TestError::Failed;
954
955
    try expectIntType(itemType, 4, ast::Signedness::Signed);
956
    try expectNumber(length, "4");
957
}
958
959
/// Test parsing a named record declaration without derives.
960
@test unsafe fn testParseRecordDecl() throws (testing::TestError) {
961
    let node = try! parseStmtStr("record R { x: bool, y: i32 }");
962
    let case ast::NodeValue::RecordDecl(decl) = node.value
963
        else throw testing::TestError::Failed;
964
965
    try expectIdent(decl.name, "R");
966
    try testing::expect(decl.derives.len == 0);
967
    try testing::expect(decl.fields.len == 2);
968
969
    try expectFieldSig(decl.fields, 0, "x", ast::TypeSig::Bool);
970
    try expectFieldSig(decl.fields, 1, "y", ast::TypeSig::Integer {
971
        width: 4,
972
        sign: ast::Signedness::Signed,
973
    });
974
}
975
976
/// Test parsing a record declaration with derives.
977
@test unsafe fn testParseRecordDeclDerives() throws (testing::TestError) {
978
    let node = try! parseStmtStr("record R: Eq + Debug { field: i32 }");
979
    let case ast::NodeValue::RecordDecl(decl) = node.value
980
        else throw testing::TestError::Failed;
981
982
    try expectIdent(decl.name, "R");
983
    try testing::expect(decl.derives.len == 2);
984
    try expectIdent(decl.derives[0], "Eq");
985
    try expectIdent(decl.derives[1], "Debug");
986
}
987
988
/// Test parsing a record declaration with field initializers.
989
@test unsafe fn testParseRecordDeclFieldDefaults() throws (testing::TestError) {
990
    let node = try! parseStmtStr("record Config { size: opaque = 42, flag: bool = true }");
991
    let case ast::NodeValue::RecordDecl(decl) = node.value
992
        else throw testing::TestError::Failed;
993
994
    try expectIdent(decl.name, "Config");
995
    try testing::expect(decl.derives.len == 0);
996
    try testing::expect(decl.fields.len == 2);
997
998
    try expectFieldSig(decl.fields, 0, "size", ast::TypeSig::Opaque);
999
    try expectFieldSig(decl.fields, 1, "flag", ast::TypeSig::Bool);
1000
1001
    // Check default values.
1002
    let case ast::NodeValue::RecordField { value: val0, .. } = decl.fields[0].value
1003
        else throw testing::TestError::Failed;
1004
    let v0 = val0 else throw testing::TestError::Failed;
1005
    try expectNumber(v0, "42");
1006
1007
    let case ast::NodeValue::RecordField { value: val1, .. } = decl.fields[1].value
1008
        else throw testing::TestError::Failed;
1009
    let v1 = val1 else throw testing::TestError::Failed;
1010
    let case ast::NodeValue::Bool(flagValue) = v1.value
1011
        else throw testing::TestError::Failed;
1012
    try testing::expect(flagValue);
1013
}
1014
1015
/// Test parsing an unlabeled record declaration.
1016
@test unsafe fn testParseTupleRecordDecl() throws (testing::TestError) {
1017
    let node = try! parseStmtStr("record Pair(bool, i32);");
1018
    let case ast::NodeValue::RecordDecl(decl) = node.value
1019
        else throw testing::TestError::Failed;
1020
1021
    try expectIdent(decl.name, "Pair");
1022
    try testing::expect(not decl.labeled);
1023
    try testing::expect(decl.derives.len == 0);
1024
    try testing::expect(decl.fields.len == 2);
1025
1026
    try expectFieldSig(decl.fields, 0, nil, ast::TypeSig::Bool);
1027
    try expectFieldSig(decl.fields, 1, nil, ast::TypeSig::Integer {
1028
        width: 4,
1029
        sign: ast::Signedness::Signed,
1030
    });
1031
}
1032
1033
/// Test parsing a single-field unlabeled record.
1034
@test unsafe fn testParseTupleRecordSingleField() throws (testing::TestError) {
1035
    let node = try! parseStmtStr("record R(bool);");
1036
    let case ast::NodeValue::RecordDecl(decl) = node.value
1037
        else throw testing::TestError::Failed;
1038
1039
    try expectIdent(decl.name, "R");
1040
    try testing::expect(not decl.labeled);
1041
    try testing::expect(decl.fields.len == 1);
1042
1043
    try expectFieldSig(decl.fields, 0, nil, ast::TypeSig::Bool);
1044
}
1045
1046
/// Test parsing empty record literals.
1047
@test unsafe fn testParseEmptyRecordLiteral() throws (testing::TestError) {
1048
    let r1 = try! parseExprStr("{}");
1049
    let case ast::NodeValue::RecordLit(lit) = r1.value
1050
        else throw testing::TestError::Failed;
1051
1052
    try testing::expect(lit.typeName == nil);
1053
    try testing::expect(lit.fields.len == 0);
1054
1055
    let r2 = try! parseExprStr("Point {}");
1056
    let case ast::NodeValue::RecordLit(lit2) = r2.value
1057
        else throw testing::TestError::Failed;
1058
1059
    let typeName = lit2.typeName else throw testing::TestError::Failed;
1060
    try expectIdent(typeName, "Point");
1061
    try testing::expect(lit2.fields.len == 0);
1062
}
1063
1064
/// Test parsing a function type with parameters and return type.
1065
@test unsafe fn testParseTypeFn() throws (testing::TestError) {
1066
    let node = try! parseTypeStr("fn (i32, *u8) -> bool");
1067
    let case ast::NodeValue::TypeSig(sigValue) = node.value
1068
        else throw testing::TestError::Failed;
1069
    let case ast::TypeSig::Fn { sig, .. } = sigValue
1070
        else throw testing::TestError::Failed;
1071
1072
    try testing::expect(sig.params.len == 2);
1073
1074
    let param0 = sig.params[0];
1075
    try expectIntType(param0, 4, ast::Signedness::Signed);
1076
1077
    let param1 = sig.params[1];
1078
    let case ast::NodeValue::TypeSig(p1) = param1.value
1079
        else throw testing::TestError::Failed;
1080
    let case ast::TypeSig::Pointer { valueType: ptrTarget, .. } = p1
1081
        else throw testing::TestError::Failed;
1082
    try expectIntType(ptrTarget, 1, ast::Signedness::Unsigned);
1083
1084
    try testing::expect(sig.returnType <> nil);
1085
}
1086
1087
/// Test parsing a function type with a throws clause.
1088
@test unsafe fn testParseTypeFnThrows() throws (testing::TestError) {
1089
    let node = try! parseTypeStr("fn (i32) -> bool throws (Error, Other)");
1090
    let case ast::NodeValue::TypeSig(sigValue) = node.value
1091
        else throw testing::TestError::Failed;
1092
    let case ast::TypeSig::Fn { sig, .. } = sigValue
1093
        else throw testing::TestError::Failed;
1094
1095
    try testing::expect(sig.params.len == 1);
1096
    try expectIntType(sig.params[0], 4, ast::Signedness::Signed);
1097
1098
    try testing::expect(sig.throwList.len == 2);
1099
    try expectTypeIdent(sig.throwList[0], "Error");
1100
    try expectTypeIdent(sig.throwList[1], "Other");
1101
1102
    let returnType = sig.returnType
1103
        else throw testing::TestError::Failed;
1104
    try expectType(returnType, ast::TypeSig::Bool);
1105
}
1106
1107
/// Test parsing a function declaration without parameters.
1108
@test unsafe fn testParseFnDeclEmpty() throws (testing::TestError) {
1109
    let node = try! parseStmtStr("fn main() {}");
1110
    let case ast::NodeValue::FnDecl(decl) = node.value
1111
        else throw testing::TestError::Failed;
1112
1113
    try expectIdent(decl.name, "main");
1114
    try testing::expect(decl.sig.params.len == 0);
1115
    try testing::expect(decl.sig.returnType == nil);
1116
    try testing::expect(decl.attrs == nil);
1117
1118
    let body = decl.body else throw testing::TestError::Failed;
1119
    let case ast::NodeValue::Block(_) = body.value
1120
        else throw testing::TestError::Failed;
1121
}
1122
1123
/// Test parsing a function declaration with parameters and return type.
1124
@test unsafe fn testParseFnDeclParams() throws (testing::TestError) {
1125
    let node = try! parseStmtStr("fn add(x: i32, y: *u8) -> bool {}");
1126
    let case ast::NodeValue::FnDecl(decl) = node.value
1127
        else throw testing::TestError::Failed;
1128
1129
    try expectIdent(decl.name, "add");
1130
    try testing::expect(decl.sig.params.len == 2);
1131
1132
    {
1133
        let param0 = decl.sig.params[0];
1134
        let case ast::NodeValue::FnParam(p0) = param0.value
1135
            else throw testing::TestError::Failed;
1136
        try expectIdent(p0.name, "x");
1137
        try expectIntType(p0.type, 4, ast::Signedness::Signed);
1138
    }
1139
    {
1140
        let param1 = decl.sig.params[1];
1141
        let case ast::NodeValue::FnParam(p1) = param1.value
1142
            else throw testing::TestError::Failed;
1143
        try expectIdent(p1.name, "y");
1144
        let case ast::NodeValue::TypeSig(sig1) = p1.type.value
1145
            else throw testing::TestError::Failed;
1146
        let case ast::TypeSig::Pointer { valueType, .. } = sig1
1147
            else throw testing::TestError::Failed;
1148
        try expectIntType(valueType, 1, ast::Signedness::Unsigned);
1149
    }
1150
    {
1151
        let returnType = decl.sig.returnType
1152
            else throw testing::TestError::Failed;
1153
        try expectType(returnType, ast::TypeSig::Bool);
1154
1155
        let body = decl.body else throw testing::TestError::Failed;
1156
        let case ast::NodeValue::Block(_) = body.value
1157
            else throw testing::TestError::Failed;
1158
    }
1159
}
1160
1161
/// Test parsing a function declaration with a throws clause.
1162
@test unsafe fn testParseFnDeclThrows() throws (testing::TestError) {
1163
    let node = try! parseStmtStr("fn handle() throws (Error, Crash) {}");
1164
    let case ast::NodeValue::FnDecl(decl) = node.value
1165
        else throw testing::TestError::Failed;
1166
1167
    try expectIdent(decl.name, "handle");
1168
    try testing::expect(decl.sig.returnType == nil);
1169
1170
    try testing::expect(decl.sig.throwList.len == 2);
1171
    try expectTypeIdent(decl.sig.throwList[0], "Error");
1172
    try expectTypeIdent(decl.sig.throwList[1], "Crash");
1173
1174
    let body = decl.body else throw testing::TestError::Failed;
1175
    let case ast::NodeValue::Block(_) = body.value
1176
        else throw testing::TestError::Failed;
1177
}
1178
1179
/// Test scanning source-level `void` produces an identifier, not a type keyword.
1180
@test unsafe fn testParseTypeVoidRejected() throws (testing::TestError) {
1181
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
1182
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
1183
        let mut parser = super::mkParser(scanner::SourceLoc::String, "void", arenaRef, poolRef);
1184
        super::advance(&mut parser);
1185
        try testing::expect(super::check(&parser, scanner::TokenKind::Ident));
1186
    }
1187
}
1188
1189
/// Test parsing the unsafe function modifier.
1190
@test unsafe fn testParseUnsafeFnDecl() throws (testing::TestError) {
1191
    let node = try! parseStmtStr("unsafe fn run() {}");
1192
    let case ast::NodeValue::FnDecl(decl) = node.value
1193
        else throw testing::TestError::Failed;
1194
    let attrs = decl.attrs
1195
        else throw testing::TestError::Failed;
1196
1197
    try testing::expect(attrs.list.len == 1);
1198
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Unsafe));
1199
}
1200
1201
/// Test rejecting `unsafe` on declarations where it has no semantics.
1202
@test unsafe fn testParseUnsafeUnsupportedDecl() throws (testing::TestError) {
1203
    let recordDecl: ?*ast::Node = try? parseStmtStr("unsafe record R {}");
1204
    try testing::expect(recordDecl == nil);
1205
    let constDecl: ?*ast::Node = try? parseStmtStr("unsafe constant X = 1;");
1206
    try testing::expect(constDecl == nil);
1207
}
1208
1209
/// Test unsafe method declarations.
1210
@test unsafe fn testParseUnsafeMethods() throws (testing::TestError) {
1211
    let instanceNode = try! parseStmtStr(
1212
        "instance Read for Value { unsafe fn (value: &Value) get() {} }"
1213
    );
1214
    let case ast::NodeValue::InstanceDecl { methods, .. } = instanceNode.value
1215
        else throw testing::TestError::Failed;
1216
    try testing::expect(methods.len == 1);
1217
    let case ast::NodeValue::MethodDecl { modifiers, .. } = methods[0].value
1218
        else throw testing::TestError::Failed;
1219
    let attrs = modifiers.attrs;
1220
    let methodAttrs = attrs else throw testing::TestError::Failed;
1221
    assert ast::attributesContains(&methodAttrs, ast::Attribute::Unsafe);
1222
1223
    static printStorage: [u8; 4096] = undefined;
1224
    let mut printArena = alloc::new(&mut printStorage[..]);
1225
    let methodExpr = printer::toExpr(&mut printArena, methods[0]);
1226
    let case sexpr::Expr::Block { items: methodItems, .. } = methodExpr
1227
        else throw testing::TestError::Failed;
1228
    let case sexpr::Expr::List {
1229
        head: methodAttrsHead, tail: printedMethodAttrs, ..
1230
    } = methodItems[0] else throw testing::TestError::Failed;
1231
    assert mem::eq(methodAttrsHead, "attrs");
1232
    let case sexpr::Expr::Sym(methodAttr) = printedMethodAttrs[0]
1233
        else throw testing::TestError::Failed;
1234
    assert mem::eq(methodAttr, "@unsafe");
1235
1236
    let traitNode = try! parseStmtStr(
1237
        "trait Read { unsafe fn (&Read) get(); }"
1238
    );
1239
    let case ast::NodeValue::TraitDecl { methods: traitMethods, .. } = traitNode.value
1240
        else throw testing::TestError::Failed;
1241
    let case ast::NodeValue::TraitMethodSig {
1242
        modifiers: traitModifiers, ..
1243
    } = traitMethods[0].value else throw testing::TestError::Failed;
1244
    let traitAttrs = traitModifiers.attrs;
1245
    let traitMethodAttrs = traitAttrs else throw testing::TestError::Failed;
1246
    assert ast::attributesContains(&traitMethodAttrs, ast::Attribute::Unsafe);
1247
1248
    let traitMethodExpr = printer::toExpr(&mut printArena, traitMethods[0]);
1249
    let case sexpr::Expr::List { tail: traitMethodItems, .. } = traitMethodExpr
1250
        else throw testing::TestError::Failed;
1251
    let case sexpr::Expr::List {
1252
        head: traitAttrsHead, tail: printedTraitAttrs, ..
1253
    } = traitMethodItems[0] else throw testing::TestError::Failed;
1254
    assert mem::eq(traitAttrsHead, "attrs");
1255
    let case sexpr::Expr::Sym(traitAttr) = printedTraitAttrs[0]
1256
        else throw testing::TestError::Failed;
1257
    assert mem::eq(traitAttr, "@unsafe");
1258
}
1259
1260
/// Test region parameters on methods, trait methods, and instances.
1261
@test unsafe fn testParseRegionalMethods() throws (testing::TestError) {
1262
    let instanceNode = try! parseStmtStr(
1263
        "instance Read for View 'view { fn (view: &View 'view) get 'method () -> &'method u32 { panic; } }"
1264
    );
1265
    let case ast::NodeValue::InstanceDecl { regions, methods, .. } = instanceNode.value
1266
        else throw testing::TestError::Failed;
1267
    try testing::expect(regions.len == 1 and methods.len == 1);
1268
    let case ast::NodeValue::MethodDecl { modifiers, .. } = methods[0].value
1269
        else throw testing::TestError::Failed;
1270
    try testing::expect(modifiers.regions.len == 1);
1271
1272
    let traitNode = try! parseStmtStr(
1273
        "trait Read { fn (&Read) get 'method () -> &'method u32; }"
1274
    );
1275
    let case ast::NodeValue::TraitDecl { methods: traitMethods, .. } = traitNode.value
1276
        else throw testing::TestError::Failed;
1277
    let case ast::NodeValue::TraitMethodSig { modifiers: traitModifiers, .. } = traitMethods[0].value
1278
        else throw testing::TestError::Failed;
1279
    try testing::expect(traitModifiers.regions.len == 1);
1280
}
1281
1282
/// Test parsing a function declaration with attributes.
1283
@test unsafe fn testParseFnDeclAttributes() throws (testing::TestError) {
1284
    let node = try! parseStmtStr("export fn run();");
1285
    let case ast::NodeValue::FnDecl(decl) = node.value
1286
        else throw testing::TestError::Failed;
1287
1288
    try expectIdent(decl.name, "run");
1289
1290
    let attrs = decl.attrs
1291
        else throw testing::TestError::Failed;
1292
1293
    try testing::expect(attrs.list.len == 2);
1294
1295
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1296
        else throw testing::TestError::Failed;
1297
    try testing::expect(attr0 == ast::Attribute::Export);
1298
1299
    let case ast::NodeValue::Attribute(attr1) = attrs.list[1].value
1300
        else throw testing::TestError::Failed;
1301
    try testing::expect(attr1 == ast::Attribute::Extern);
1302
1303
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Export));
1304
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1305
    try testing::expect(decl.body == nil);
1306
}
1307
1308
/// Test parsing a top-level function declaration with inferred extern from `;`.
1309
@test unsafe fn testParseFnDeclInferredExtern() throws (testing::TestError) {
1310
    let node = try! parseStmtStr("fn run();");
1311
    let case ast::NodeValue::FnDecl(decl) = node.value
1312
        else throw testing::TestError::Failed;
1313
1314
    try expectIdent(decl.name, "run");
1315
1316
    let attrs = decl.attrs
1317
        else throw testing::TestError::Failed;
1318
1319
    try testing::expect(attrs.list.len == 1);
1320
1321
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1322
        else throw testing::TestError::Failed;
1323
    try testing::expect(attr0 == ast::Attribute::Extern);
1324
1325
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1326
    try testing::expect(decl.body == nil);
1327
}
1328
1329
/// Test parsing a top-level exported function declaration with inferred extern from `;`.
1330
@test unsafe fn testParseFnDeclExportInferredExtern() throws (testing::TestError) {
1331
    let node = try! parseStmtStr("export fn run();");
1332
    let case ast::NodeValue::FnDecl(decl) = node.value
1333
        else throw testing::TestError::Failed;
1334
1335
    try expectIdent(decl.name, "run");
1336
1337
    let attrs = decl.attrs
1338
        else throw testing::TestError::Failed;
1339
1340
    try testing::expect(attrs.list.len == 2);
1341
1342
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1343
        else throw testing::TestError::Failed;
1344
    try testing::expect(attr0 == ast::Attribute::Export);
1345
1346
    let case ast::NodeValue::Attribute(attr1) = attrs.list[1].value
1347
        else throw testing::TestError::Failed;
1348
    try testing::expect(attr1 == ast::Attribute::Extern);
1349
1350
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Export));
1351
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1352
    try testing::expect(decl.body == nil);
1353
}
1354
1355
/// Test parsing a scoped identifier type.
1356
@test unsafe fn testParseTypeScopedIdent() throws (testing::TestError) {
1357
    let node = try! parseTypeStr("module::Type");
1358
    let case ast::NodeValue::TypeSig(ts) = node.value
1359
        else throw testing::TestError::Failed;
1360
    let case ast::TypeSig::Nominal(name) = ts
1361
        else throw testing::TestError::Failed;
1362
    let case ast::NodeValue::ScopeAccess(access) = name.value
1363
        else throw testing::TestError::Failed;
1364
1365
    try expectIdent(access.parent, "module");
1366
    try expectIdent(access.child, "Type");
1367
}
1368
1369
/// Test parsing the `bool` type.
1370
@test unsafe fn testParseTypeBool() throws (testing::TestError) {
1371
    let node = try! parseTypeStr("bool");
1372
    try expectType(node, ast::TypeSig::Bool);
1373
}
1374
1375
/// Test parsing an unsigned integer type.
1376
@test unsafe fn testParseTypeUnsigned() throws (testing::TestError) {
1377
    let node = try! parseTypeStr("u8");
1378
    try expectType(node, ast::TypeSig::Integer {
1379
        width: 1,
1380
        sign: ast::Signedness::Unsigned,
1381
    });
1382
}
1383
1384
/// Test parsing a simple `if let` statement without guard or else.
1385
@test unsafe fn testParseIfLet() throws (testing::TestError) {
1386
    let root = try! parseStmtStr("if let value = opt { body; }");
1387
    let case ast::NodeValue::IfLet(node) = root.value
1388
        else throw testing::TestError::Failed;
1389
1390
    try expectIdent(node.pattern.pattern, "value");
1391
    try expectIdent(node.pattern.scrutinee, "opt");
1392
1393
    try testing::expect(node.pattern.guard == nil);
1394
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1395
    try testing::expect(node.elseBranch == nil);
1396
}
1397
1398
/// Test parsing an `if let` statement with guard and else branches.
1399
@test unsafe fn testParseIfLetGuardElse() throws (testing::TestError) {
1400
    let root = try! parseStmtStr(
1401
        "if let value = opt; guard { body; } else { alt; }"
1402
    );
1403
    let case ast::NodeValue::IfLet(node) = root.value
1404
        else throw testing::TestError::Failed;
1405
1406
    try expectIdent(node.pattern.pattern, "value");
1407
    try expectIdent(node.pattern.scrutinee, "opt");
1408
1409
    let guard = node.pattern.guard
1410
        else throw testing::TestError::Failed;
1411
    try expectIdent(guard, "guard");
1412
1413
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1414
1415
    let elseBranch = node.elseBranch
1416
        else throw testing::TestError::Failed;
1417
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1418
}
1419
1420
/// Test parsing an `if let` statement with an `else if` chain.
1421
@test unsafe fn testParseIfLetElseIf() throws (testing::TestError) {
1422
    let root = try! parseStmtStr(
1423
        "if let value = opt { body; } else if cond { alt; }"
1424
    );
1425
    let case ast::NodeValue::IfLet(node) = root.value
1426
        else throw testing::TestError::Failed;
1427
1428
    try expectIdent(node.pattern.pattern, "value");
1429
1430
    let elseBranch = node.elseBranch
1431
        else throw testing::TestError::Failed;
1432
1433
    let nested = try getBlockFirstStmt(elseBranch);
1434
    let case ast::NodeValue::If(inner) = nested.value
1435
        else throw testing::TestError::Failed;
1436
1437
    try expectIdent(inner.condition, "cond");
1438
    try expectBlockExprStmt(inner.thenBranch, ast::NodeValue::Ident("alt"));
1439
    try testing::expect(inner.elseBranch == nil);
1440
}
1441
1442
/// Test parsing `if let mut` binding.
1443
@test unsafe fn testParseIfLetMut() throws (testing::TestError) {
1444
    let root = try! parseStmtStr("if let mut value = opt { body; }");
1445
    let case ast::NodeValue::IfLet(node) = root.value
1446
        else throw testing::TestError::Failed;
1447
1448
    try expectIdent(node.pattern.pattern, "value");
1449
    try expectIdent(node.pattern.scrutinee, "opt");
1450
    try testing::expect(node.pattern.mutable);
1451
    try testing::expect(node.pattern.guard == nil);
1452
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1453
    try testing::expect(node.elseBranch == nil);
1454
}
1455
1456
/// Test parsing `let mut ... else` binding.
1457
@test unsafe fn testParseLetMutElse() throws (testing::TestError) {
1458
    let root = try! parseStmtStr("let mut x = opt else { return };");
1459
    let case ast::NodeValue::LetElse(letElse) = root.value
1460
        else throw testing::TestError::Failed;
1461
1462
    try expectIdent(letElse.pattern.pattern, "x");
1463
    try testing::expect(letElse.pattern.mutable);
1464
}
1465
1466
/// Test that `if let` without `mut` is not mutable.
1467
@test unsafe fn testParseIfLetNotMutable() throws (testing::TestError) {
1468
    let root = try! parseStmtStr("if let value = opt { body; }");
1469
    let case ast::NodeValue::IfLet(node) = root.value
1470
        else throw testing::TestError::Failed;
1471
1472
    try testing::expect(not node.pattern.mutable);
1473
}
1474
1475
/// Test that `let ... else` without `mut` is not mutable.
1476
@test unsafe fn testParseLetElseNotMutable() throws (testing::TestError) {
1477
    let root = try! parseStmtStr("let x = opt else { return };");
1478
    let case ast::NodeValue::LetElse(letElse) = root.value
1479
        else throw testing::TestError::Failed;
1480
1481
    try testing::expect(not letElse.pattern.mutable);
1482
}
1483
1484
/// Test parsing a simple `if let case` statement.
1485
@test unsafe fn testParseIfCase() throws (testing::TestError) {
1486
    let root = try! parseStmtStr("if let case pat = value { body; }");
1487
    let case ast::NodeValue::IfLet(node) = root.value
1488
        else throw testing::TestError::Failed;
1489
1490
    try expectIdent(node.pattern.pattern, "pat");
1491
    try expectIdent(node.pattern.scrutinee, "value");
1492
    try testing::expect(node.pattern.guard == nil);
1493
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1494
    try testing::expect(node.elseBranch == nil);
1495
}
1496
1497
/// Test parsing an `if let case` statement with guard and else branches.
1498
@test unsafe fn testParseIfCaseGuardElse() throws (testing::TestError) {
1499
    let root = try! parseStmtStr(
1500
        "if let case pat = value; guard { body; } else { alt; }"
1501
    );
1502
    let case ast::NodeValue::IfLet(node) = root.value
1503
        else throw testing::TestError::Failed;
1504
1505
    try expectIdent(node.pattern.pattern, "pat");
1506
    try expectIdent(node.pattern.scrutinee, "value");
1507
1508
    let guard = node.pattern.guard
1509
        else throw testing::TestError::Failed;
1510
    try expectIdent(guard, "guard");
1511
1512
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1513
1514
    let elseBranch = node.elseBranch
1515
        else throw testing::TestError::Failed;
1516
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1517
}
1518
1519
/// Test parsing an `if let case` statement with an `else if` chain.
1520
@test unsafe fn testParseIfCaseElseIf() throws (testing::TestError) {
1521
    let root = try! parseStmtStr(
1522
        "if let case pat = value { body; } else if cond { alt; }"
1523
    );
1524
    let case ast::NodeValue::IfLet(node) = root.value
1525
        else throw testing::TestError::Failed;
1526
1527
    let elseBranch = node.elseBranch
1528
        else throw testing::TestError::Failed;
1529
1530
    let nested = try getBlockFirstStmt(elseBranch);
1531
    let case ast::NodeValue::If(inner) = nested.value
1532
        else throw testing::TestError::Failed;
1533
1534
    try expectIdent(inner.condition, "cond");
1535
    try expectBlockExprStmt(inner.thenBranch, ast::NodeValue::Ident("alt"));
1536
    try testing::expect(inner.elseBranch == nil);
1537
}
1538
1539
/// Test parsing a simple `while` loop without an `else` branch.
1540
@test unsafe fn testParseWhile() throws (testing::TestError) {
1541
    let root = try! parseStmtStr("while cond { body; }");
1542
    let case ast::NodeValue::While(loopNode) = root.value
1543
        else throw testing::TestError::Failed;
1544
1545
    try expectIdent(loopNode.condition, "cond");
1546
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
1547
    try testing::expect(loopNode.elseBranch == nil);
1548
}
1549
1550
/// Test parsing a `while` loop with an `else` branch.
1551
@test unsafe fn testParseWhileElse() throws (testing::TestError) {
1552
    let root = try! parseStmtStr("while cond { body; } else { alt; }");
1553
    let case ast::NodeValue::While(loopNode) = root.value
1554
        else throw testing::TestError::Failed;
1555
1556
    try expectIdent(loopNode.condition, "cond");
1557
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
1558
1559
    let elseBranch = loopNode.elseBranch
1560
        else throw testing::TestError::Failed;
1561
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1562
}
1563
1564
/// Test parsing a simple `while let case` loop.
1565
@test unsafe fn testParseWhileCase() throws (testing::TestError) {
1566
    let root = try! parseStmtStr("while let case pat = value { body; }");
1567
    let case ast::NodeValue::WhileLet(node) = root.value
1568
        else throw testing::TestError::Failed;
1569
1570
    try expectIdent(node.pattern.pattern, "pat");
1571
    try expectIdent(node.pattern.scrutinee, "value");
1572
    try testing::expect(node.pattern.guard == nil);
1573
    try expectBlockExprStmt(node.body, ast::NodeValue::Ident("body"));
1574
    try testing::expect(node.elseBranch == nil);
1575
}
1576
1577
/// Test parsing a `while let case` loop with guard and else branches.
1578
@test unsafe fn testParseWhileCaseGuardElse() throws (testing::TestError) {
1579
    let root = try! parseStmtStr(
1580
        "while let case pat = value; guard { body; } else { alt; }"
1581
    );
1582
    let case ast::NodeValue::WhileLet(node) = root.value
1583
        else throw testing::TestError::Failed;
1584
1585
    let guard = node.pattern.guard
1586
        else throw testing::TestError::Failed;
1587
    try expectIdent(guard, "guard");
1588
1589
    try expectBlockExprStmt(node.body, ast::NodeValue::Ident("body"));
1590
1591
    let elseBranch = node.elseBranch
1592
        else throw testing::TestError::Failed;
1593
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1594
}
1595
1596
/// Test parsing a simple `try` expression without catch.
1597
@test unsafe fn testParseTry() throws (testing::TestError) {
1598
    let root = try! parseExprStr("try value");
1599
    let case ast::NodeValue::Try(node) = root.value
1600
        else throw testing::TestError::Failed;
1601
1602
    try expectIdent(node.expr, "value");
1603
    try testing::expect(node.catches.len == 0);
1604
    try testing::expect(not node.shouldPanic);
1605
}
1606
1607
/// Test that `try?` consumes a unary operand.
1608
@test unsafe fn testParseTryOptionalUnary() throws (testing::TestError) {
1609
    let root = try! parseExprStr("try? -value");
1610
    let case ast::NodeValue::Try(node) = root.value
1611
        else throw testing::TestError::Failed;
1612
    let case ast::NodeValue::UnOp(neg) = node.expr.value
1613
        else throw testing::TestError::Failed;
1614
    try testing::expect(neg.op == ast::UnaryOp::Neg);
1615
    try expectIdent(neg.value, "value");
1616
    try testing::expect(node.returnsOptional);
1617
}
1618
1619
/// Test parsing a `try!` expression that panics on error.
1620
@test unsafe fn testParseTryBang() throws (testing::TestError) {
1621
    let root = try! parseExprStr("try! value");
1622
    let case ast::NodeValue::Try(node) = root.value
1623
        else throw testing::TestError::Failed;
1624
1625
    try expectIdent(node.expr, "value");
1626
    try testing::expect(node.catches.len == 0);
1627
    try testing::expect(node.shouldPanic);
1628
}
1629
1630
/// Test parsing a `try` expression with a `catch` block.
1631
@test unsafe fn testParseTryCatchBlock() throws (testing::TestError) {
1632
    let root = try! parseExprStr("try value catch { alt; }");
1633
    let case ast::NodeValue::Try(node) = root.value
1634
        else throw testing::TestError::Failed;
1635
1636
    try expectIdent(node.expr, "value");
1637
    try testing::expect(node.catches.len == 1);
1638
1639
    let case ast::NodeValue::CatchClause(clause) = node.catches[0].value
1640
        else throw testing::TestError::Failed;
1641
    try testing::expect(clause.binding == nil);
1642
    try testing::expect(clause.typeNode == nil);
1643
    try expectBlockExprStmt(clause.body, ast::NodeValue::Ident("alt"));
1644
}
1645
1646
/// Test that `catch` without a block is rejected.
1647
@test unsafe fn testParseTryCatchExprRejected() throws (testing::TestError) {
1648
    let parsed: ?*ast::Node = try? parseExprStr("try value catch alternate");
1649
    try testing::expect(parsed == nil);
1650
}
1651
1652
/// Test parsing a `break` statement.
1653
@test unsafe fn testParseBreak() throws (testing::TestError) {
1654
    let root = try! parseStmtStr("break");
1655
    let case ast::NodeValue::Break= root.value
1656
        else throw testing::TestError::Failed;
1657
}
1658
1659
/// Test parsing a `continue` statement.
1660
@test unsafe fn testParseContinue() throws (testing::TestError) {
1661
    let root = try! parseStmtStr("continue");
1662
    let case ast::NodeValue::Continue= root.value
1663
        else throw testing::TestError::Failed;
1664
}
1665
1666
/// Test parsing a `return` statement without value.
1667
@test unsafe fn testParseReturnVoid() throws (testing::TestError) {
1668
    let root = try! parseStmtStr("return");
1669
    let case ast::NodeValue::Return(retValue) = root.value
1670
        else throw testing::TestError::Failed;
1671
1672
    try testing::expect(retValue == nil);
1673
}
1674
1675
/// Test parsing a `return` statement with a value.
1676
@test unsafe fn testParseReturnValue() throws (testing::TestError) {
1677
    let root = try! parseStmtStr("return result");
1678
    let case ast::NodeValue::Return(retValue) = root.value
1679
        else throw testing::TestError::Failed;
1680
1681
    let value = retValue
1682
        else throw testing::TestError::Failed;
1683
    try expectIdent(value, "result");
1684
}
1685
1686
/// Test parsing a `throw` statement.
1687
@test unsafe fn testParseThrow() throws (testing::TestError) {
1688
    let root = try! parseStmtStr("throw error");
1689
    let case ast::NodeValue::Throw(throwExpr) = root.value
1690
        else throw testing::TestError::Failed;
1691
1692
    try expectIdent(throwExpr, "error");
1693
}
1694
1695
/// Test parsing a `panic` statement without a message.
1696
@test unsafe fn testParsePanicEmpty() throws (testing::TestError) {
1697
    let root = try! parseStmtStr("panic");
1698
    let case ast::NodeValue::Panic(panicMsg) = root.value
1699
        else throw testing::TestError::Failed;
1700
1701
    try testing::expect(panicMsg == nil);
1702
}
1703
1704
/// Test parsing a `panic` statement with a message.
1705
@test unsafe fn testParsePanicMessage() throws (testing::TestError) {
1706
    let root = try! parseStmtStr("panic \"something went wrong\"");
1707
    let case ast::NodeValue::Panic(panicMsg) = root.value
1708
        else throw testing::TestError::Failed;
1709
1710
    let message = panicMsg
1711
        else throw testing::TestError::Failed;
1712
    let case ast::NodeValue::String(msgStr) = message.value if mem::eq(msgStr, "something went wrong")
1713
        else throw testing::TestError::Failed;
1714
}
1715
1716
/// Test parsing a `panic` statement with braces.
1717
@test unsafe fn testParsePanicBraces() throws (testing::TestError) {
1718
    let root = try! parseStmtStr("panic { \"error\" }");
1719
    let case ast::NodeValue::Panic(panicMsg) = root.value
1720
        else throw testing::TestError::Failed;
1721
1722
    let message = panicMsg
1723
        else throw testing::TestError::Failed;
1724
    let case ast::NodeValue::String(msgStr) = message.value if mem::eq(msgStr, "error")
1725
        else throw testing::TestError::Failed;
1726
}
1727
1728
/// Test parsing a simple `match` statement with one case.
1729
@test unsafe fn testParseMatchSingle() throws (testing::TestError) {
1730
    let root = try! parseStmtStr("match subject { case pattern => body }");
1731
    let case ast::NodeValue::Match(sw) = root.value
1732
        else throw testing::TestError::Failed;
1733
1734
    try expectIdent(sw.subject, "subject");
1735
    try testing::expect(sw.prongs.len == 1);
1736
1737
    let caseNode = sw.prongs[0];
1738
    let case ast::NodeValue::MatchProng(prong) = caseNode.value
1739
        else throw testing::TestError::Failed;
1740
1741
    let case ast::ProngArm::Case(patterns) = prong.arm
1742
        else throw testing::TestError::Failed;
1743
    try testing::expect(patterns.len == 1);
1744
    try expectIdent(patterns[0], "pattern");
1745
    try testing::expect(prong.guard == nil);
1746
1747
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1748
        else throw testing::TestError::Failed;
1749
    let case ast::NodeValue::Ident(name) = bodyStmt.value
1750
        if mem::eq(name, "body")
1751
        else throw testing::TestError::Failed;
1752
}
1753
1754
/// Test parsing a `match` case with guard and multiple patterns.
1755
@test unsafe fn testParseMatchGuard() throws (testing::TestError) {
1756
    let root = try! parseStmtStr(
1757
        "match subject { case left, right if cond => handle }"
1758
    );
1759
    let case ast::NodeValue::Match(sw) = root.value
1760
        else throw testing::TestError::Failed;
1761
1762
    try testing::expect(sw.prongs.len == 1);
1763
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1764
        else throw testing::TestError::Failed;
1765
1766
    let case ast::ProngArm::Case(patterns) = prong.arm
1767
        else throw testing::TestError::Failed;
1768
    try testing::expect(patterns.len == 2);
1769
    try expectIdent(patterns[0], "left");
1770
    try expectIdent(patterns[1], "right");
1771
1772
    let guard = prong.guard
1773
        else throw testing::TestError::Failed;
1774
    try expectIdent(guard, "cond");
1775
}
1776
1777
/// Test parsing `match` prongs whose bodies omit trailing semicolons.
1778
@test unsafe fn testParseMatchReturnNoSemicolon() throws (testing::TestError) {
1779
    let root = try! parseStmtStr(
1780
        "match subject { case First => return, case Second => return }"
1781
    );
1782
    let case ast::NodeValue::Match(sw) = root.value
1783
        else throw testing::TestError::Failed;
1784
1785
    try testing::expect(sw.prongs.len == 2);
1786
1787
    let firstCaseNode = sw.prongs[0];
1788
    let case ast::NodeValue::MatchProng(firstProng) = firstCaseNode.value
1789
        else throw testing::TestError::Failed;
1790
    let case ast::NodeValue::Return(firstRetVal) = firstProng.body.value
1791
        else throw testing::TestError::Failed;
1792
    try testing::expect(firstRetVal == nil);
1793
1794
    let secondCaseNode = sw.prongs[1];
1795
    let case ast::NodeValue::MatchProng(secondProng) = secondCaseNode.value
1796
        else throw testing::TestError::Failed;
1797
    let case ast::NodeValue::Return(secondRetVal) = secondProng.body.value
1798
        else throw testing::TestError::Failed;
1799
    try testing::expect(secondRetVal == nil);
1800
}
1801
1802
/// Test parsing a `match` statement with multiple branches.
1803
@test unsafe fn testParseMatchMultipleCases() throws (testing::TestError) {
1804
    let root = try! parseStmtStr(
1805
        "match subject { case First => first, case Second => second }"
1806
    );
1807
    let case ast::NodeValue::Match(sw) = root.value
1808
        else throw testing::TestError::Failed;
1809
1810
    try testing::expect(sw.prongs.len == 2);
1811
    {
1812
        let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1813
            else throw testing::TestError::Failed;
1814
        let case ast::ProngArm::Case(patterns) = prong.arm
1815
            else throw testing::TestError::Failed;
1816
        try testing::expect(patterns.len == 1);
1817
        try expectIdent(patterns[0], "First");
1818
        let case ast::NodeValue::ExprStmt(stmt) = prong.body.value
1819
            else throw testing::TestError::Failed;
1820
        let case ast::NodeValue::Ident(val) = stmt.value
1821
            if mem::eq(val, "first")
1822
            else throw testing::TestError::Failed;
1823
    } {
1824
        let case ast::NodeValue::MatchProng(prong) = sw.prongs[1].value
1825
            else throw testing::TestError::Failed;
1826
        let case ast::ProngArm::Case(pats) = prong.arm
1827
            else throw testing::TestError::Failed;
1828
1829
        try testing::expect(pats.len == 1);
1830
        try expectIdent(pats[0], "Second");
1831
1832
        let case ast::NodeValue::ExprStmt(stmt) = prong.body.value
1833
            else throw testing::TestError::Failed;
1834
        let case ast::NodeValue::Ident(val) = stmt.value
1835
            if mem::eq(val, "second")
1836
            else throw testing::TestError::Failed;
1837
    }
1838
}
1839
1840
/// Test parsing a `match` case whose body is a block.
1841
@test unsafe fn testParseMatchProngBlock() throws (testing::TestError) {
1842
    let root = try! parseStmtStr("match subject { case Pattern => { body; } }");
1843
    let case ast::NodeValue::Match(sw) = root.value
1844
        else throw testing::TestError::Failed;
1845
1846
    try testing::expect(sw.prongs.len == 1);
1847
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1848
        else throw testing::TestError::Failed;
1849
    try expectBlockExprStmt(prong.body, ast::NodeValue::Ident("body"));
1850
}
1851
1852
/// Test parsing a `match` statement with an `else` case.
1853
@test unsafe fn testParseMatchElse() throws (testing::TestError) {
1854
    let root = try! parseStmtStr("match subject { else => body }");
1855
    let case ast::NodeValue::Match(sw) = root.value
1856
        else throw testing::TestError::Failed;
1857
1858
    try testing::expect(sw.prongs.len == 1);
1859
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1860
        else throw testing::TestError::Failed;
1861
    // Else prong has no pattern.
1862
    let case ast::ProngArm::Else = prong.arm
1863
        else throw testing::TestError::Failed;
1864
    try testing::expect(prong.guard == nil);
1865
1866
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1867
        else throw testing::TestError::Failed;
1868
    let case ast::NodeValue::Ident(name) = bodyStmt.value
1869
        if mem::eq(name, "body")
1870
        else throw testing::TestError::Failed;
1871
}
1872
1873
/// Test parsing a `match` statement with a binding prong.
1874
@test unsafe fn testParseMatchBinding() throws (testing::TestError) {
1875
    let root = try! parseStmtStr("match subject { x => body }");
1876
    let case ast::NodeValue::Match(sw) = root.value
1877
        else throw testing::TestError::Failed;
1878
1879
    try testing::expect(sw.prongs.len == 1);
1880
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1881
        else throw testing::TestError::Failed;
1882
    // Binding prong has single identifier pattern.
1883
    let case ast::ProngArm::Binding(pat) = prong.arm
1884
        else throw testing::TestError::Failed;
1885
    try expectIdent(pat, "x");
1886
    try testing::expect(prong.guard == nil);
1887
1888
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1889
        else throw testing::TestError::Failed;
1890
    try expectIdent(bodyStmt, "body");
1891
}
1892
1893
/// Test parsing a `match` statement with a guarded binding prong.
1894
@test unsafe fn testParseMatchBindingGuard() throws (testing::TestError) {
1895
    let root = try! parseStmtStr("match subject { x if x > 0 => body }");
1896
    let case ast::NodeValue::Match(sw) = root.value
1897
        else throw testing::TestError::Failed;
1898
1899
    try testing::expect(sw.prongs.len == 1);
1900
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1901
        else throw testing::TestError::Failed;
1902
    // Binding prong has single identifier pattern.
1903
    let case ast::ProngArm::Binding(pat) = prong.arm
1904
        else throw testing::TestError::Failed;
1905
    try expectIdent(pat, "x");
1906
1907
    let guard = prong.guard else throw testing::TestError::Failed;
1908
    let case ast::NodeValue::BinOp(binop) = guard.value
1909
        else throw testing::TestError::Failed;
1910
    try testing::expect(binop.op == ast::BinaryOp::Gt);
1911
}
1912
1913
/// Test parsing a `match` statement with a `_` wildcard.
1914
@test unsafe fn testParseMatchWildcard() throws (testing::TestError) {
1915
    let root = try! parseStmtStr("match subject { _ => body }");
1916
    let case ast::NodeValue::Match(sw) = root.value
1917
        else throw testing::TestError::Failed;
1918
1919
    try testing::expect(sw.prongs.len == 1);
1920
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1921
        else throw testing::TestError::Failed;
1922
    // Wildcard binding prong has single placeholder pattern.
1923
    let case ast::ProngArm::Binding(pat) = prong.arm
1924
        else throw testing::TestError::Failed;
1925
    let case ast::NodeValue::Placeholder = pat.value
1926
        else throw testing::TestError::Failed;
1927
    try testing::expect(prong.guard == nil);
1928
1929
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1930
        else throw testing::TestError::Failed;
1931
    try expectIdent(bodyStmt, "body");
1932
}
1933
1934
/// Test parsing a `match` statement with a guarded `_` wildcard.
1935
@test unsafe fn testParseMatchWildcardGuard() throws (testing::TestError) {
1936
    let root = try! parseStmtStr("match subject { _ if cond => body }");
1937
    let case ast::NodeValue::Match(sw) = root.value
1938
        else throw testing::TestError::Failed;
1939
1940
    try testing::expect(sw.prongs.len == 1);
1941
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1942
        else throw testing::TestError::Failed;
1943
    // Guarded wildcard binding prong has single placeholder pattern.
1944
    let case ast::ProngArm::Binding(pat) = prong.arm
1945
        else throw testing::TestError::Failed;
1946
    let case ast::NodeValue::Placeholder = pat.value
1947
        else throw testing::TestError::Failed;
1948
1949
    let guard = prong.guard else throw testing::TestError::Failed;
1950
    try expectIdent(guard, "cond");
1951
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1952
        else throw testing::TestError::Failed;
1953
    try expectIdent(bodyStmt, "body");
1954
}
1955
1956
/// Test parsing a `while let` loop with guard and else branches.
1957
@test unsafe fn testParseWhileLet() throws (testing::TestError) {
1958
    let root = try! parseStmtStr(
1959
        "while let value = opt; guard { body; } else { alt; }"
1960
    );
1961
    let case ast::NodeValue::WhileLet(loopNode) = root.value
1962
        else throw testing::TestError::Failed;
1963
1964
    try expectIdent(loopNode.pattern.pattern, "value");
1965
    try expectIdent(loopNode.pattern.scrutinee, "opt");
1966
1967
    let guard = loopNode.pattern.guard
1968
        else throw testing::TestError::Failed;
1969
    try expectIdent(guard, "guard");
1970
1971
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
1972
1973
    let elseBranch = loopNode.elseBranch
1974
        else throw testing::TestError::Failed;
1975
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1976
}
1977
1978
/// Test parsing a simple `loop` statement.
1979
@test unsafe fn testParseLoop() throws (testing::TestError) {
1980
    let root = try! parseStmtStr("loop { body; }");
1981
    let case ast::NodeValue::Loop(loopBody) = root.value
1982
        else throw testing::TestError::Failed;
1983
1984
    try expectBlockExprStmt(loopBody, ast::NodeValue::Ident("body"));
1985
}
1986
1987
/// Test parsing a `for` loop without index or else branches.
1988
@test unsafe fn testParseFor() throws (testing::TestError) {
1989
    let root = try! parseStmtStr("for item in items { body; }");
1990
    let case ast::NodeValue::For(loopNode) = root.value
1991
        else throw testing::TestError::Failed;
1992
1993
    try expectIdent(loopNode.binding, "item");
1994
    try testing::expect(loopNode.index == nil);
1995
1996
    try expectIdent(loopNode.iterable, "items");
1997
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
1998
    try testing::expect(loopNode.elseBranch == nil);
1999
}
2000
2001
/// Test parsing a `for` loop over a range expression.
2002
@test unsafe fn testParseForRangeIterable() throws (testing::TestError) {
2003
    let root = try! parseStmtStr("for item in 0..5 {}");
2004
    let case ast::NodeValue::For(loopNode) = root.value
2005
        else throw testing::TestError::Failed;
2006
2007
    try expectIdent(loopNode.binding, "item");
2008
    try testing::expect(loopNode.index == nil);
2009
    try expectRangeNumbers(loopNode.iterable, "0", "5");
2010
2011
    let case ast::NodeValue::Block(body) = loopNode.body.value
2012
        else throw testing::TestError::Failed;
2013
    try testing::expect(body.statements.len == 0);
2014
    try testing::expect(loopNode.elseBranch == nil);
2015
}
2016
2017
/// Test parsing a `for` loop with index and else branches.
2018
@test unsafe fn testParseForIndexElse() throws (testing::TestError) {
2019
    let root = try! parseStmtStr(
2020
        "for value, idx in items { body; } else { alt; }"
2021
    );
2022
    let case ast::NodeValue::For(loopNode) = root.value
2023
        else throw testing::TestError::Failed;
2024
2025
    try expectIdent(loopNode.binding, "value");
2026
2027
    let index = loopNode.index
2028
        else throw testing::TestError::Failed;
2029
    try expectIdent(index, "idx");
2030
2031
    try expectIdent(loopNode.iterable, "items");
2032
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
2033
2034
    let elseBranch = loopNode.elseBranch
2035
        else throw testing::TestError::Failed;
2036
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
2037
}
2038
2039
/// Test parsing field access expression.
2040
@test unsafe fn testParseFieldAccess() throws (testing::TestError) {
2041
    let root = try! parseExprStr("obj.field");
2042
    let case ast::NodeValue::FieldAccess(access) = root.value
2043
        else throw testing::TestError::Failed;
2044
2045
    try expectIdent(access.parent, "obj");
2046
    try expectIdent(access.child, "field");
2047
}
2048
2049
/// Test parsing scope access expression.
2050
@test unsafe fn testParseScopeAccess() throws (testing::TestError) {
2051
    let root = try! parseExprStr("module::item");
2052
    let case ast::NodeValue::ScopeAccess(access) = root.value
2053
        else throw testing::TestError::Failed;
2054
2055
    try expectIdent(access.parent, "module");
2056
    try expectIdent(access.child, "item");
2057
}
2058
2059
/// Test parsing array subscript expression.
2060
@test unsafe fn testParseArraySubscript() throws (testing::TestError) {
2061
    let root = try! parseExprStr("array[index]");
2062
    let case ast::NodeValue::Subscript { container, index } = root.value
2063
        else throw testing::TestError::Failed;
2064
2065
    try expectIdent(container, "array");
2066
    try expectIdent(index, "index");
2067
}
2068
2069
/// Test parsing array slicing expressions.
2070
@test unsafe fn testParseArraySlicing() throws (testing::TestError) {
2071
    // Test `array[start..end]`.
2072
    {
2073
        let expr = try! parseExprStr("array[1..10]");
2074
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2075
            else throw testing::TestError::Failed;
2076
        try expectIdent(subContainer, "array");
2077
2078
        let case ast::NodeValue::Range(range) = subIndex.value
2079
            else throw testing::TestError::Failed;
2080
        let start = range.start
2081
            else throw testing::TestError::Failed;
2082
        let end = range.end
2083
            else throw testing::TestError::Failed;
2084
        try expectNumber(start, "1");
2085
        try expectNumber(end, "10");
2086
    }
2087
    // Test `array[start..]`.
2088
    {
2089
        let expr = try! parseExprStr("array[5..]");
2090
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2091
            else throw testing::TestError::Failed;
2092
        try expectIdent(subContainer, "array");
2093
2094
        let case ast::NodeValue::Range(range) = subIndex.value
2095
            else throw testing::TestError::Failed;
2096
        let start = range.start
2097
            else throw testing::TestError::Failed;
2098
        try expectNumber(start, "5");
2099
        try testing::expect(range.end == nil);
2100
    }
2101
    // Test `array[..end]`.
2102
    {
2103
        let expr = try! parseExprStr("array[..10]");
2104
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2105
            else throw testing::TestError::Failed;
2106
        try expectIdent(subContainer, "array");
2107
2108
        let case ast::NodeValue::Range(range) = subIndex.value
2109
            else throw testing::TestError::Failed;
2110
        try testing::expect(range.start == nil);
2111
        let end = range.end
2112
            else throw testing::TestError::Failed;
2113
        try expectNumber(end, "10");
2114
    }
2115
    // Test `array[..]`.
2116
    {
2117
        let expr = try! parseExprStr("array[..]");
2118
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2119
            else throw testing::TestError::Failed;
2120
        try expectIdent(subContainer, "array");
2121
2122
        let case ast::NodeValue::Range(range) = subIndex.value
2123
            else throw testing::TestError::Failed;
2124
        try testing::expect(range.start == nil);
2125
        try testing::expect(range.end == nil);
2126
    }
2127
}
2128
2129
/// Test parsing function call expression.
2130
@test unsafe fn testParseFunctionCall() throws (testing::TestError) {
2131
    let root = try! parseExprStr("func(x, y)");
2132
    let case ast::NodeValue::Call(call) = root.value
2133
        else throw testing::TestError::Failed;
2134
2135
    try expectIdent(call.callee, "func");
2136
    try testing::expect(call.args.len == 2);
2137
    try expectIdent(call.args[0], "x");
2138
    try expectIdent(call.args[1], "y");
2139
}
2140
2141
/// Test parsing chained postfix operators.
2142
@test unsafe fn testParseChainedPostfix() throws (testing::TestError) {
2143
    let root = try! parseExprStr("obj.method(arg)[0]");
2144
    let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = root.value
2145
        else throw testing::TestError::Failed;
2146
2147
    let case ast::NodeValue::Call(call) = subContainer.value
2148
        else throw testing::TestError::Failed;
2149
2150
    let case ast::NodeValue::FieldAccess(fieldAccess) = call.callee.value
2151
        else throw testing::TestError::Failed;
2152
2153
    try expectIdent(fieldAccess.parent, "obj");
2154
    try expectIdent(fieldAccess.child, "method");
2155
    try testing::expect(call.args.len == 1);
2156
    try expectIdent(call.args[0], "arg");
2157
}
2158
2159
/// Test parsing a literal cast using `as`.
2160
@test unsafe fn testParseAsCastLiteral() throws (testing::TestError) {
2161
    let root = try! parseExprStr("1 as i32");
2162
    let case ast::NodeValue::As(asExpr) = root.value
2163
        else throw testing::TestError::Failed;
2164
2165
    let case ast::NodeValue::Number(_) = asExpr.value.value
2166
        else throw testing::TestError::Failed;
2167
2168
    try expectIntType(asExpr.type, 4, ast::Signedness::Signed);
2169
}
2170
2171
/// Test parsing a cast following chained postfix expressions.
2172
@test unsafe fn testParseAsCastWithPostfix() throws (testing::TestError) {
2173
    let root = try! parseExprStr("value.method(arg) as u32");
2174
    let case ast::NodeValue::As(asExpr) = root.value
2175
        else throw testing::TestError::Failed;
2176
2177
    let case ast::NodeValue::Call(call) = asExpr.value.value
2178
        else throw testing::TestError::Failed;
2179
2180
    let case ast::NodeValue::FieldAccess(access) = call.callee.value
2181
        else throw testing::TestError::Failed;
2182
2183
    try expectIdent(access.parent, "value");
2184
    try expectIdent(access.child, "method");
2185
    try testing::expect(call.args.len == 1);
2186
    try expectIdent(call.args[0], "arg");
2187
    try expectIntType(asExpr.type, 4, ast::Signedness::Unsigned);
2188
}
2189
2190
/// Test parsing @sizeOf builtin.
2191
@test unsafe fn testParseBuiltinSizeOf() throws (testing::TestError) {
2192
    let expr = try! parseExprStr("@sizeOf(i32)");
2193
    let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2194
        else throw testing::TestError::Failed;
2195
2196
    try testing::expect(builtinKind == ast::Builtin::SizeOf);
2197
    try testing::expect(builtinArgs.len == 1);
2198
    try expectType(builtinArgs[0], ast::TypeSig::Integer {
2199
        width: 4,
2200
        sign: ast::Signedness::Signed,
2201
    });
2202
}
2203
2204
/// Test parsing @alignOf builtin.
2205
@test unsafe fn testParseBuiltinAlignOf() throws (testing::TestError) {
2206
    let expr = try! parseExprStr("@alignOf(i32)");
2207
    let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2208
        else throw testing::TestError::Failed;
2209
2210
    try testing::expect(builtinKind == ast::Builtin::AlignOf);
2211
    try testing::expect(builtinArgs.len == 1);
2212
    try expectType(builtinArgs[0], ast::TypeSig::Integer {
2213
        width: 4,
2214
        sign: ast::Signedness::Signed,
2215
    });
2216
}
2217
2218
/// Test parsing @sliceOf with varying argument counts.
2219
@test unsafe fn testParseBuiltinSliceOf() throws (testing::TestError) {
2220
    // Two arguments.
2221
    {
2222
        let expr = try! parseExprStr("@sliceOf(ptr, len)");
2223
        let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2224
            else throw testing::TestError::Failed;
2225
        try testing::expect(builtinKind == ast::Builtin::SliceOf);
2226
        try testing::expect(builtinArgs.len == 2);
2227
    }
2228
    // One argument.
2229
    {
2230
        let expr = try! parseExprStr("@sliceOf(ptr)");
2231
        let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2232
            else throw testing::TestError::Failed;
2233
        try testing::expect(builtinKind == ast::Builtin::SliceOf);
2234
        try testing::expect(builtinArgs.len == 1);
2235
    }
2236
    // Three arguments.
2237
    {
2238
        let expr = try! parseExprStr("@sliceOf(ptr, len, extra)");
2239
        let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2240
            else throw testing::TestError::Failed;
2241
        try testing::expect(builtinKind == ast::Builtin::SliceOf);
2242
        try testing::expect(builtinArgs.len == 3);
2243
    }
2244
}
2245
2246
/// Test parsing prefix unary operators.
2247
@test unsafe fn testParseUnaryOperators() throws (testing::TestError) {
2248
    {
2249
        let notExpr = try! parseExprStr("not flag");
2250
        let case ast::NodeValue::UnOp(notNode) = notExpr.value
2251
            else throw testing::TestError::Failed;
2252
        try testing::expect(notNode.op == ast::UnaryOp::Not);
2253
        try expectIdent(notNode.value, "flag");
2254
    }
2255
    {
2256
        let negExpr = try! parseExprStr("-value");
2257
        let case ast::NodeValue::UnOp(negNode) = negExpr.value
2258
            else throw testing::TestError::Failed;
2259
        try testing::expect(negNode.op == ast::UnaryOp::Neg);
2260
        try expectIdent(negNode.value, "value");
2261
    }
2262
    {
2263
        let bitNotExpr = try! parseExprStr("~mask");
2264
        let case ast::NodeValue::UnOp(bitNotNode) = bitNotExpr.value
2265
            else throw testing::TestError::Failed;
2266
        try testing::expect(bitNotNode.op == ast::UnaryOp::BitNot);
2267
        try expectIdent(bitNotNode.value, "mask");
2268
    }
2269
}
2270
2271
/// Test parsing dereference expressions.
2272
@test unsafe fn testParseDereference() throws (testing::TestError) {
2273
    {
2274
        let derefExpr = try! parseExprStr("*ptr");
2275
        let case ast::NodeValue::Deref(target) = derefExpr.value
2276
            else throw testing::TestError::Failed;
2277
        try expectIdent(target, "ptr");
2278
    }
2279
    {
2280
        let derefField = try! parseExprStr("*ptr.field");
2281
        let case ast::NodeValue::Deref(target) = derefField.value
2282
            else throw testing::TestError::Failed;
2283
        let case ast::NodeValue::FieldAccess(access) = target.value
2284
            else throw testing::TestError::Failed;
2285
        try expectIdent(access.parent, "ptr");
2286
        try expectIdent(access.child, "field");
2287
    }
2288
}
2289
2290
/// Test parsing reference (address-of) expressions.
2291
@test unsafe fn testParseRefs() throws (testing::TestError) {
2292
    {
2293
        let expr = try! parseExprStr("&cell obj.field");
2294
        let case ast::NodeValue::AddressOf(address) = expr.value
2295
            else throw testing::TestError::Failed;
2296
        try testing::expect(address.kind == ast::AddressKind::Cell);
2297
        let case ast::NodeValue::FieldAccess(access) = address.target.value
2298
            else throw testing::TestError::Failed;
2299
        try expectIdent(access.parent, "obj");
2300
        try expectIdent(access.child, "field");
2301
    }
2302
    {
2303
        let refExpr = try! parseExprStr("&foo");
2304
        let case ast::NodeValue::AddressOf(refNode) = refExpr.value
2305
            else throw testing::TestError::Failed;
2306
        try testing::expect(refNode.kind == ast::AddressKind::Shared);
2307
        try expectIdent(refNode.target, "foo");
2308
    }
2309
    {
2310
        let mutRefExpr = try! parseExprStr("&mut bar");
2311
        let case ast::NodeValue::AddressOf(mutRefNode) = mutRefExpr.value
2312
            else throw testing::TestError::Failed;
2313
        try testing::expect(mutRefNode.kind == ast::AddressKind::Mutable);
2314
        try expectIdent(mutRefNode.target, "bar");
2315
    }
2316
    {
2317
        let refFieldExpr = try! parseExprStr("&obj.field");
2318
        let case ast::NodeValue::AddressOf(refFieldNode) = refFieldExpr.value
2319
            else throw testing::TestError::Failed;
2320
        try testing::expect(refFieldNode.kind == ast::AddressKind::Shared);
2321
        let case ast::NodeValue::FieldAccess(access) = refFieldNode.target.value
2322
            else throw testing::TestError::Failed;
2323
        try expectIdent(access.parent, "obj");
2324
        try expectIdent(access.child, "field");
2325
    }
2326
    {
2327
        let mutRefFieldExpr = try! parseExprStr("&mut obj.field");
2328
        let case ast::NodeValue::AddressOf(mutRefFieldNode) = mutRefFieldExpr.value
2329
            else throw testing::TestError::Failed;
2330
        try testing::expect(mutRefFieldNode.kind == ast::AddressKind::Mutable);
2331
        let case ast::NodeValue::FieldAccess(access) = mutRefFieldNode.target.value
2332
            else throw testing::TestError::Failed;
2333
        try expectIdent(access.parent, "obj");
2334
        try expectIdent(access.child, "field");
2335
    }
2336
}
2337
2338
/// Test unary operator precedence relative to binary and postfix expressions.
2339
@test unsafe fn testParseUnaryPrecedence() throws (testing::TestError) {
2340
    {
2341
        let expr = try! parseExprStr("not a and b");
2342
        let case ast::NodeValue::BinOp(bin) = expr.value
2343
            else throw testing::TestError::Failed;
2344
        try testing::expect(bin.op == ast::BinaryOp::And);
2345
        let case ast::NodeValue::UnOp(leftUnary) = bin.left.value
2346
            else throw testing::TestError::Failed;
2347
        try testing::expect(leftUnary.op == ast::UnaryOp::Not);
2348
        try expectIdent(leftUnary.value, "a");
2349
        try expectIdent(bin.right, "b");
2350
    }
2351
    {
2352
        let mulExpr = try! parseExprStr("-x * y");
2353
        let case ast::NodeValue::BinOp(mul) = mulExpr.value
2354
            else throw testing::TestError::Failed;
2355
        try testing::expect(mul.op == ast::BinaryOp::Mul);
2356
        let case ast::NodeValue::UnOp(leftNeg) = mul.left.value
2357
            else throw testing::TestError::Failed;
2358
        try testing::expect(leftNeg.op == ast::UnaryOp::Neg);
2359
        try expectIdent(leftNeg.value, "x");
2360
        try expectIdent(mul.right, "y");
2361
    }
2362
    {
2363
        let callExpr = try! parseExprStr("not func()");
2364
        let case ast::NodeValue::UnOp(callNot) = callExpr.value
2365
            else throw testing::TestError::Failed;
2366
        try testing::expect(callNot.op == ast::UnaryOp::Not);
2367
        let case ast::NodeValue::Call(call) = callNot.value.value
2368
            else throw testing::TestError::Failed;
2369
        try expectIdent(call.callee, "func");
2370
    }
2371
}
2372
2373
/// Test parsing assignment expressions.
2374
@test unsafe fn testParseAssignment() throws (testing::TestError) {
2375
    {
2376
        let assign = try! parseStmtStr("set x = 1;");
2377
        let case ast::NodeValue::Assign(node) = assign.value
2378
            else throw testing::TestError::Failed;
2379
        try expectIdent(node.left, "x");
2380
        let case ast::NodeValue::Number(_) = node.right.value
2381
            else throw testing::TestError::Failed;
2382
    }
2383
    {
2384
        let assign = try! parseStmtStr("set obj.field = value;");
2385
        let case ast::NodeValue::Assign(node) = assign.value
2386
            else throw testing::TestError::Failed;
2387
        let case ast::NodeValue::FieldAccess(access) = node.left.value
2388
            else throw testing::TestError::Failed;
2389
        try expectIdent(access.parent, "obj");
2390
        try expectIdent(access.child, "field");
2391
        try expectIdent(node.right, "value");
2392
    }
2393
    {
2394
        let assign = try! parseStmtStr("set *ptr = rhs;");
2395
        let case ast::NodeValue::Assign(node) = assign.value
2396
            else throw testing::TestError::Failed;
2397
        let case ast::NodeValue::Deref(target) = node.left.value
2398
            else throw testing::TestError::Failed;
2399
        try expectIdent(target, "ptr");
2400
        try expectIdent(node.right, "rhs");
2401
    }
2402
    {
2403
        let assign = try! parseStmtStr("set x = 1 + 2;");
2404
        let case ast::NodeValue::Assign(node) = assign.value
2405
            else throw testing::TestError::Failed;
2406
        let case ast::NodeValue::BinOp(bin) = node.right.value
2407
            else throw testing::TestError::Failed;
2408
        try testing::expect(bin.op == ast::BinaryOp::Add);
2409
    }
2410
    {
2411
        let assign = try! parseStmtStr("set module::VAR = 1;");
2412
        let case ast::NodeValue::Assign(node) = assign.value
2413
            else throw testing::TestError::Failed;
2414
        let case ast::NodeValue::ScopeAccess(access) = node.left.value
2415
            else throw testing::TestError::Failed;
2416
        try expectIdent(access.parent, "module");
2417
        try expectIdent(access.child, "VAR");
2418
    }
2419
}
2420
2421
/// Test that assignment syntax requires the `set` statement.
2422
@test unsafe fn testAssignmentRequiresSetKeyword() throws (testing::TestError) {
2423
    let assign: ?*ast::Node = try? parseStmtStr("x = 1;");
2424
    try testing::expect(assign == nil);
2425
2426
    let compoundAssign: ?*ast::Node = try? parseStmtStr("x += 1;");
2427
    try testing::expect(compoundAssign == nil);
2428
}
2429
2430
/// Test that `set` requires an assignable target.
2431
@test unsafe fn testSetRequiresAssignableTarget() throws (testing::TestError) {
2432
    let binTarget: ?*ast::Node = try? parseStmtStr("set x + y = 1;");
2433
    try testing::expect(binTarget == nil);
2434
2435
    let condTarget: ?*ast::Node = try? parseStmtStr("set x if ok else y = 1;");
2436
    try testing::expect(condTarget == nil);
2437
}
2438
2439
/// Test parsing basic arithmetic binary operators (+, -, *, /, %).
2440
@test unsafe fn testParseBinOpArithmetic() throws (testing::TestError) {
2441
    let add = try! parseExprStr("a + b");
2442
    let case ast::NodeValue::BinOp(op1) = add.value
2443
        else throw testing::TestError::Failed;
2444
    try testing::expect(op1.op == ast::BinaryOp::Add);
2445
    try expectIdent(op1.left, "a");
2446
    try expectIdent(op1.right, "b");
2447
2448
    let sub = try! parseExprStr("x - y");
2449
    let case ast::NodeValue::BinOp(op2) = sub.value
2450
        else throw testing::TestError::Failed;
2451
    try testing::expect(op2.op == ast::BinaryOp::Sub);
2452
2453
    let mul = try! parseExprStr("a * b");
2454
    let case ast::NodeValue::BinOp(op3) = mul.value
2455
        else throw testing::TestError::Failed;
2456
    try testing::expect(op3.op == ast::BinaryOp::Mul);
2457
2458
    let div = try! parseExprStr("x / y");
2459
    let case ast::NodeValue::BinOp(op4) = div.value
2460
        else throw testing::TestError::Failed;
2461
    try testing::expect(op4.op == ast::BinaryOp::Div);
2462
2463
    let modOp = try! parseExprStr("a % b");
2464
    let case ast::NodeValue::BinOp(op5) = modOp.value
2465
        else throw testing::TestError::Failed;
2466
    try testing::expect(op5.op == ast::BinaryOp::Mod);
2467
}
2468
2469
/// Test parsing comparison binary operators (==, <>).
2470
@test unsafe fn testParseBinOpEq() throws (testing::TestError) {
2471
    let eq = try! parseExprStr("a == b");
2472
    let case ast::NodeValue::BinOp(op1) = eq.value
2473
        else throw testing::TestError::Failed;
2474
    try testing::expect(op1.op == ast::BinaryOp::Eq);
2475
2476
    let ne = try! parseExprStr("x <> y");
2477
    let case ast::NodeValue::BinOp(op2) = ne.value
2478
        else throw testing::TestError::Failed;
2479
    try testing::expect(op2.op == ast::BinaryOp::Ne);
2480
}
2481
2482
/// Test parsing comparison binary operators.
2483
@test unsafe fn testParseBinOpGtLt() throws (testing::TestError) {
2484
    let lt = try! parseExprStr("a < b");
2485
    let case ast::NodeValue::BinOp(op1) = lt.value
2486
        else throw testing::TestError::Failed;
2487
    try testing::expect(op1.op == ast::BinaryOp::Lt);
2488
2489
    let gt = try! parseExprStr("x > y");
2490
    let case ast::NodeValue::BinOp(op2) = gt.value
2491
        else throw testing::TestError::Failed;
2492
    try testing::expect(op2.op == ast::BinaryOp::Gt);
2493
2494
    let lte = try! parseExprStr("a <= b");
2495
    let case ast::NodeValue::BinOp(op3) = lte.value
2496
        else throw testing::TestError::Failed;
2497
    try testing::expect(op3.op == ast::BinaryOp::Lte);
2498
2499
    let gte = try! parseExprStr("x >= y");
2500
    let case ast::NodeValue::BinOp(op4) = gte.value
2501
        else throw testing::TestError::Failed;
2502
    try testing::expect(op4.op == ast::BinaryOp::Gte);
2503
}
2504
2505
/// Test parsing bitwise binary operators (&, |, ^, <<, >>).
2506
@test unsafe fn testParseBinOpBitwise() throws (testing::TestError) {
2507
    let bitAnd = try! parseExprStr("a & b");
2508
    let case ast::NodeValue::BinOp(op1) = bitAnd.value
2509
        else throw testing::TestError::Failed;
2510
    try testing::expect(op1.op == ast::BinaryOp::BitAnd);
2511
2512
    let bitOr = try! parseExprStr("x | y");
2513
    let case ast::NodeValue::BinOp(op2) = bitOr.value
2514
        else throw testing::TestError::Failed;
2515
    try testing::expect(op2.op == ast::BinaryOp::BitOr);
2516
2517
    let bitXor = try! parseExprStr("a ^ b");
2518
    let case ast::NodeValue::BinOp(op3) = bitXor.value
2519
        else throw testing::TestError::Failed;
2520
    try testing::expect(op3.op == ast::BinaryOp::BitXor);
2521
2522
    let shl = try! parseExprStr("x << y");
2523
    let case ast::NodeValue::BinOp(op4) = shl.value
2524
        else throw testing::TestError::Failed;
2525
    try testing::expect(op4.op == ast::BinaryOp::Shl);
2526
2527
    let shr = try! parseExprStr("a >> b");
2528
    let case ast::NodeValue::BinOp(op5) = shr.value
2529
        else throw testing::TestError::Failed;
2530
    try testing::expect(op5.op == ast::BinaryOp::Shr);
2531
}
2532
2533
/// Test parsing logical binary operators (and, or).
2534
@test unsafe fn testParseBinOpLogical() throws (testing::TestError) {
2535
    let andOp = try! parseExprStr("a and b");
2536
    let case ast::NodeValue::BinOp(op1) = andOp.value
2537
        else throw testing::TestError::Failed;
2538
    try testing::expect(op1.op == ast::BinaryOp::And);
2539
    try expectIdent(op1.left, "a");
2540
    try expectIdent(op1.right, "b");
2541
2542
    let orOp = try! parseExprStr("x or y");
2543
    let case ast::NodeValue::BinOp(op2) = orOp.value
2544
        else throw testing::TestError::Failed;
2545
    try testing::expect(op2.op == ast::BinaryOp::Or);
2546
    try expectIdent(op2.left, "x");
2547
    try expectIdent(op2.right, "y");
2548
}
2549
2550
/// Test operator precedence: multiplication before addition.
2551
@test unsafe fn testParseBinOpPrecedenceMulAdd() throws (testing::TestError) {
2552
    let root = try! parseExprStr("a + b * c");
2553
    let case ast::NodeValue::BinOp(add) = root.value
2554
        else throw testing::TestError::Failed;
2555
2556
    try testing::expect(add.op == ast::BinaryOp::Add);
2557
    try expectIdent(add.left, "a");
2558
2559
    let case ast::NodeValue::BinOp(mul) = add.right.value
2560
        else throw testing::TestError::Failed;
2561
2562
    try testing::expect(mul.op == ast::BinaryOp::Mul);
2563
    try expectIdent(mul.left, "b");
2564
    try expectIdent(mul.right, "c");
2565
}
2566
2567
/// Test operator precedence: shifts before bitwise operations.
2568
@test unsafe fn testParseBinOpPrecedenceShiftBitwise() throws (testing::TestError) {
2569
    let root = try! parseExprStr("a & b << c");
2570
    let case ast::NodeValue::BinOp(bitAnd) = root.value
2571
        else throw testing::TestError::Failed;
2572
2573
    try testing::expect(bitAnd.op == ast::BinaryOp::BitAnd);
2574
    try expectIdent(bitAnd.left, "a");
2575
2576
    let case ast::NodeValue::BinOp(shl) = bitAnd.right.value
2577
        else throw testing::TestError::Failed;
2578
2579
    try testing::expect(shl.op == ast::BinaryOp::Shl);
2580
    try expectIdent(shl.left, "b");
2581
    try expectIdent(shl.right, "c");
2582
}
2583
2584
/// Test operator precedence: comparison before logical AND.
2585
@test unsafe fn testParseBinOpPrecedenceCompareLogical() throws (testing::TestError) {
2586
    let root = try! parseExprStr("a < b and c > d");
2587
    let case ast::NodeValue::BinOp(andOp) = root.value
2588
        else throw testing::TestError::Failed;
2589
2590
    try testing::expect(andOp.op == ast::BinaryOp::And);
2591
2592
    let case ast::NodeValue::BinOp(lt) = andOp.left.value
2593
        else throw testing::TestError::Failed;
2594
    try testing::expect(lt.op == ast::BinaryOp::Lt);
2595
    try expectIdent(lt.left, "a");
2596
    try expectIdent(lt.right, "b");
2597
2598
    let case ast::NodeValue::BinOp(gt) = andOp.right.value
2599
        else throw testing::TestError::Failed;
2600
    try testing::expect(gt.op == ast::BinaryOp::Gt);
2601
    try expectIdent(gt.left, "c");
2602
    try expectIdent(gt.right, "d");
2603
}
2604
2605
/// Test left associativity of addition.
2606
@test unsafe fn testParseBinOpAssociativityAdd() throws (testing::TestError) {
2607
    let root = try! parseExprStr("a + b + c");
2608
    let case ast::NodeValue::BinOp(add2) = root.value
2609
        else throw testing::TestError::Failed;
2610
2611
    try testing::expect(add2.op == ast::BinaryOp::Add);
2612
    try expectIdent(add2.right, "c");
2613
2614
    let case ast::NodeValue::BinOp(add1) = add2.left.value
2615
        else throw testing::TestError::Failed;
2616
    try testing::expect(add1.op == ast::BinaryOp::Add);
2617
    try expectIdent(add1.left, "a");
2618
    try expectIdent(add1.right, "b");
2619
}
2620
2621
/// Test complex expression with multiple operators and precedence.
2622
@test unsafe fn testParseBinOpComplex() throws (testing::TestError) {
2623
    let root = try! parseExprStr("a + b * c - d / e");
2624
    let case ast::NodeValue::BinOp(sub) = root.value
2625
        else throw testing::TestError::Failed;
2626
2627
    try testing::expect(sub.op == ast::BinaryOp::Sub);
2628
2629
    let case ast::NodeValue::BinOp(add) = sub.left.value
2630
        else throw testing::TestError::Failed;
2631
    try testing::expect(add.op == ast::BinaryOp::Add);
2632
    try expectIdent(add.left, "a");
2633
2634
    let case ast::NodeValue::BinOp(mul) = add.right.value
2635
        else throw testing::TestError::Failed;
2636
    try testing::expect(mul.op == ast::BinaryOp::Mul);
2637
2638
    let case ast::NodeValue::BinOp(div) = sub.right.value
2639
        else throw testing::TestError::Failed;
2640
    try testing::expect(div.op == ast::BinaryOp::Div);
2641
}
2642
2643
/// Test binary operators with parentheses override precedence.
2644
@test unsafe fn testParseBinOpParentheses() throws (testing::TestError) {
2645
    let root = try! parseExprStr("(a + b) * c");
2646
    let case ast::NodeValue::BinOp(mul) = root.value
2647
        else throw testing::TestError::Failed;
2648
2649
    try testing::expect(mul.op == ast::BinaryOp::Mul);
2650
    try expectIdent(mul.right, "c");
2651
2652
    let case ast::NodeValue::BinOp(add) = mul.left.value
2653
        else throw testing::TestError::Failed;
2654
    try testing::expect(add.op == ast::BinaryOp::Add);
2655
    try expectIdent(add.left, "a");
2656
    try expectIdent(add.right, "b");
2657
}
2658
2659
/// Test parsing a simple union without payloads.
2660
@test unsafe fn testParseEnumSimple() throws (testing::TestError) {
2661
    let node = try! parseStmtStr("union Color { Red, Green, Blue }");
2662
    let case ast::NodeValue::UnionDecl(decl) = node.value
2663
        else throw testing::TestError::Failed;
2664
2665
    try expectIdent(decl.name, "Color");
2666
    try testing::expect(decl.derives.len == 0);
2667
2668
    let variants = decl.variants;
2669
    try testing::expect(variants.len == 3);
2670
2671
    let v0 = variants[0];
2672
    let case ast::NodeValue::UnionDeclVariant(var0) = v0.value
2673
        else throw testing::TestError::Failed;
2674
    try expectIdent(var0.name, "Red");
2675
    try testing::expect(var0.index == 0);
2676
    try testing::expect(var0.type == nil);
2677
    try testing::expect(var0.value == nil);
2678
2679
    let v1 = variants[1];
2680
    let case ast::NodeValue::UnionDeclVariant(var1) = v1.value
2681
        else throw testing::TestError::Failed;
2682
    try expectIdent(var1.name, "Green");
2683
    try testing::expect(var1.index == 1);
2684
    try testing::expect(var1.type == nil);
2685
    try testing::expect(var1.value == nil);
2686
2687
    let v2 = variants[2];
2688
    let case ast::NodeValue::UnionDeclVariant(var2) = v2.value
2689
        else throw testing::TestError::Failed;
2690
    try expectIdent(var2.name, "Blue");
2691
    try testing::expect(var2.index == 2);
2692
    try testing::expect(var2.type == nil);
2693
    try testing::expect(var2.value == nil);
2694
}
2695
2696
/// Test parsing a union with trailing comma.
2697
@test unsafe fn testParseEnumTrailingComma() throws (testing::TestError) {
2698
    let node = try! parseStmtStr("union Letter { A, B, C, }");
2699
    let case ast::NodeValue::UnionDecl(decl) = node.value
2700
        else throw testing::TestError::Failed;
2701
2702
    try expectIdent(decl.name, "Letter");
2703
    try testing::expect(decl.variants.len == 3);
2704
}
2705
2706
/// Test parsing a union with explicit values.
2707
@test unsafe fn testParseEnumExplicitValues() throws (testing::TestError) {
2708
    let node = try! parseStmtStr("union Status { Ok = 0, Error = 1, Pending = 5 }");
2709
    let case ast::NodeValue::UnionDecl(decl) = node.value
2710
        else throw testing::TestError::Failed;
2711
2712
    try expectIdent(decl.name, "Status");
2713
2714
    let variants = decl.variants;
2715
    try testing::expect(variants.len == 3);
2716
2717
    let v0 = variants[0];
2718
    let case ast::NodeValue::UnionDeclVariant(var0) = v0.value
2719
        else throw testing::TestError::Failed;
2720
    try expectIdent(var0.name, "Ok");
2721
    try testing::expect(var0.index == 0);
2722
    try testing::expect(var0.type == nil);
2723
    try testing::expect(var0.value <> nil);
2724
2725
    let v1 = variants[1];
2726
    let case ast::NodeValue::UnionDeclVariant(var1) = v1.value
2727
        else throw testing::TestError::Failed;
2728
    try expectIdent(var1.name, "Error");
2729
    try testing::expect(var1.index == 1);
2730
    try testing::expect(var1.value <> nil);
2731
2732
    let v2 = variants[2];
2733
    let case ast::NodeValue::UnionDeclVariant(var2) = v2.value
2734
        else throw testing::TestError::Failed;
2735
    try expectIdent(var2.name, "Pending");
2736
    try testing::expect(var2.index == 2);
2737
    try testing::expect(var2.value <> nil);
2738
}
2739
2740
/// Test parsing a union with payload and tag-only variants.
2741
@test unsafe fn testParseEnumWithPayloads() throws (testing::TestError) {
2742
    let node = try! parseStmtStr("union Result { Ok(bool), Error }");
2743
    let case ast::NodeValue::UnionDecl(decl) = node.value
2744
        else throw testing::TestError::Failed;
2745
2746
    try expectIdent(decl.name, "Result");
2747
    try testing::expect(decl.variants.len == 2);
2748
2749
    let okFields = try expectVariant(decl.variants[0], "Ok", 0)
2750
        else throw testing::TestError::Failed;
2751
    try testing::expect(okFields.len == 1);
2752
    try expectFieldSig(okFields, 0, nil, ast::TypeSig::Bool);
2753
2754
    let errFields = try expectVariant(decl.variants[1], "Error", 1);
2755
    try testing::expect(errFields == nil);
2756
}
2757
2758
/// Test parsing a union with derives.
2759
@test unsafe fn testParseEnumWithDerives() throws (testing::TestError) {
2760
    let node = try! parseStmtStr("union Option: Debug + Eq { None, Some(i32) }");
2761
    let case ast::NodeValue::UnionDecl(decl) = node.value
2762
        else throw testing::TestError::Failed;
2763
2764
    try expectIdent(decl.name, "Option");
2765
    try testing::expect(decl.derives.len == 2);
2766
    try expectIdent(decl.derives[0], "Debug");
2767
    try expectIdent(decl.derives[1], "Eq");
2768
2769
    let variants = decl.variants;
2770
    try testing::expect(variants.len == 2);
2771
2772
    let v0 = variants[0];
2773
    let case ast::NodeValue::UnionDeclVariant(var0) = v0.value
2774
        else throw testing::TestError::Failed;
2775
    try expectIdent(var0.name, "None");
2776
    try testing::expect(var0.type == nil);
2777
2778
    let v1 = variants[1];
2779
    let case ast::NodeValue::UnionDeclVariant(var1) = v1.value
2780
        else throw testing::TestError::Failed;
2781
    try expectIdent(var1.name, "Some");
2782
    try testing::expect(var1.type <> nil);
2783
}
2784
2785
/// Test parsing named record literals with named fields.
2786
@test unsafe fn testParseNamedRecordLiteralNamed() throws (testing::TestError) {
2787
    let r1 = try! parseExprStr("Point { x: 5, y: 10 }");
2788
    let case ast::NodeValue::RecordLit(lit) = r1.value
2789
        else throw testing::TestError::Failed;
2790
2791
    let typeName = lit.typeName else throw testing::TestError::Failed;
2792
    try expectIdent(typeName, "Point");
2793
    try testing::expect(lit.fields.len == 2);
2794
2795
    let field0 = lit.fields[0];
2796
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2797
        else throw testing::TestError::Failed;
2798
    let label0 = arg0.label else throw testing::TestError::Failed;
2799
    try expectIdent(label0, "x");
2800
    try expectNumber(arg0.value, "5");
2801
}
2802
2803
/// Test parsing anonymous record literals with named fields.
2804
@test unsafe fn testParseAnonymousRecordLiteralNamed() throws (testing::TestError) {
2805
    let r1 = try! parseExprStr("{ x: 10, y: 20 }");
2806
    let case ast::NodeValue::RecordLit(lit) = r1.value
2807
        else throw testing::TestError::Failed;
2808
2809
    try testing::expect(lit.typeName == nil);
2810
    try testing::expect(lit.fields.len == 2);
2811
2812
    let field0 = lit.fields[0];
2813
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2814
        else throw testing::TestError::Failed;
2815
    let label0 = arg0.label else throw testing::TestError::Failed;
2816
    try expectIdent(label0, "x");
2817
    try expectNumber(arg0.value, "10");
2818
2819
    let field1 = lit.fields[1];
2820
    let case ast::NodeValue::RecordLitField(arg1) = field1.value
2821
        else throw testing::TestError::Failed;
2822
    let label1 = arg1.label else throw testing::TestError::Failed;
2823
    try expectIdent(label1, "y");
2824
    try expectNumber(arg1.value, "20");
2825
}
2826
2827
/// Test parsing record literals with shorthand field syntax.
2828
/// `{ x, y }` is equivalent to `{ x: x, y: y }`.
2829
@test unsafe fn testParseRecordLiteralShorthand() throws (testing::TestError) {
2830
    let r1 = try! parseExprStr("Point { x, y }");
2831
    let case ast::NodeValue::RecordLit(lit) = r1.value
2832
        else throw testing::TestError::Failed;
2833
2834
    let typeName = lit.typeName else throw testing::TestError::Failed;
2835
    try expectIdent(typeName, "Point");
2836
    try testing::expect(lit.fields.len == 2);
2837
2838
    // First field: shorthand `x`.
2839
    let field0 = lit.fields[0];
2840
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2841
        else throw testing::TestError::Failed;
2842
    let label0 = arg0.label else throw testing::TestError::Failed;
2843
    try expectIdent(label0, "x");
2844
    try expectIdent(arg0.value, "x");
2845
    // Label and value should point to the same node.
2846
    try testing::expect(label0 == arg0.value);
2847
2848
    // Second field: shorthand `y`.
2849
    let field1 = lit.fields[1];
2850
    let case ast::NodeValue::RecordLitField(arg1) = field1.value
2851
        else throw testing::TestError::Failed;
2852
    let label1 = arg1.label else throw testing::TestError::Failed;
2853
    try expectIdent(label1, "y");
2854
    try expectIdent(arg1.value, "y");
2855
    try testing::expect(label1 == arg1.value);
2856
}
2857
2858
/// Test parsing record literals with mixed shorthand and explicit fields.
2859
@test unsafe fn testParseRecordLiteralMixedShorthand() throws (testing::TestError) {
2860
    let r1 = try! parseExprStr("Point { x, y: 10 }");
2861
    let case ast::NodeValue::RecordLit(lit) = r1.value
2862
        else throw testing::TestError::Failed;
2863
2864
    try testing::expect(lit.fields.len == 2);
2865
2866
    // First field: shorthand `x`.
2867
    let field0 = lit.fields[0];
2868
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2869
        else throw testing::TestError::Failed;
2870
    let label0 = arg0.label else throw testing::TestError::Failed;
2871
    try expectIdent(label0, "x");
2872
    try expectIdent(arg0.value, "x");
2873
2874
    // Second field: explicit `y: 10`.
2875
    let field1 = lit.fields[1];
2876
    let case ast::NodeValue::RecordLitField(arg1) = field1.value
2877
        else throw testing::TestError::Failed;
2878
    let label1 = arg1.label else throw testing::TestError::Failed;
2879
    try expectIdent(label1, "y");
2880
    try expectNumber(arg1.value, "10");
2881
}
2882
2883
/// Test that positional brace initializers are rejected: `{ 1, 2 }`.
2884
@test unsafe fn testParsePositionalBraceInitializerAnonymous() throws (testing::TestError) {
2885
    let parsed: ?*ast::Node = try? parseExprStr("{ 1, 2 }");
2886
    try testing::expect(parsed == nil);
2887
}
2888
2889
/// Test that positional brace initializers are rejected: `Point { 1, 2 }`.
2890
@test unsafe fn testParsePositionalBraceInitializerNamed() throws (testing::TestError) {
2891
    let parsed: ?*ast::Node = try? parseExprStr("Point { 1, 2 }");
2892
    try testing::expect(parsed == nil);
2893
}
2894
2895
/// Test that mixed labeled/positional brace initializers are rejected: `Pt { x: 1, 2 }`.
2896
@test unsafe fn testParseMixedBraceInitializer() throws (testing::TestError) {
2897
    let parsed: ?*ast::Node = try? parseExprStr("Pt { x: 1, 2 }");
2898
    try testing::expect(parsed == nil);
2899
}
2900
2901
/// Unsafe statements have a block body.
2902
@test unsafe fn testParseUnsafeBlock() throws (testing::TestError) {
2903
    let parsed = try? parseStmtsStr("fn run() { unsafe { return; } }");
2904
    let root = parsed else throw testing::TestError::Failed;
2905
    let case ast::NodeValue::Block(module) = root.value
2906
        else throw testing::TestError::Failed;
2907
    let case ast::NodeValue::FnDecl(decl) = module.statements[0].value
2908
        else throw testing::TestError::Failed;
2909
    let fnBody = decl.body else throw testing::TestError::Failed;
2910
    let case ast::NodeValue::Block(body) = fnBody.value
2911
        else throw testing::TestError::Failed;
2912
    let case ast::NodeValue::Block(inner) = body.statements[0].value
2913
        else throw testing::TestError::Failed;
2914
    try testing::expect(not body.isUnsafe);
2915
    try testing::expect(inner.isUnsafe);
2916
}
2917
2918
/// Unsafe blocks do not accept declaration attributes.
2919
@test unsafe fn testUnsafeBlockAttributesRejected() throws (testing::TestError) {
2920
    let parsed = try? parseStmtsStr("fn run() { export unsafe {} }");
2921
    try testing::expect(parsed == nil);
2922
}
2923
2924
/// Unsafe static declarations carry an explicit access requirement.
2925
@test unsafe fn testParseUnsafeStatic() throws (testing::TestError) {
2926
    let parsed = try? parseStmtsStr("export unsafe static DATA: [u8; 4] = undefined;");
2927
    try testing::expect(parsed <> nil);
2928
}
2929
2930
@test unsafe fn testParseModule() throws (testing::TestError) {
2931
    let r = try! parseStmtsStr("fn f() {} fn g() {}");
2932
2933
    let case ast::NodeValue::Block(module) = r.value
2934
        else throw testing::TestError::Failed;
2935
    try testing::expect(module.statements.len == 2);
2936
2937
    let first = module.statements[0];
2938
    let case ast::NodeValue::FnDecl(fDecl) = first.value
2939
        else throw testing::TestError::Failed;
2940
    try expectIdent(fDecl.name, "f");
2941
2942
    let second = module.statements[1];
2943
    let case ast::NodeValue::FnDecl(gDecl) = second.value
2944
        else throw testing::TestError::Failed;
2945
    try expectIdent(gDecl.name, "g");
2946
}
2947
2948
/// Test parsing a simple conditional expression.
2949
@test unsafe fn testParseCondExpr() throws (testing::TestError) {
2950
    let r = try! parseExprStr("a if cond else b") catch {
2951
        throw testing::TestError::Failed;
2952
    };
2953
    let case ast::NodeValue::CondExpr(cond) = r.value
2954
        else throw testing::TestError::Failed;
2955
2956
    try expectIdent(cond.thenExpr, "a");
2957
    try expectIdent(cond.condition, "cond");
2958
    try expectIdent(cond.elseExpr, "b");
2959
}
2960
2961
/// Test parsing a conditional expression with `as` casts.
2962
@test unsafe fn testParseCondExprWithAsCast() throws (testing::TestError) {
2963
    let r = try! parseExprStr("x as i32 if cond else y as i32") catch {
2964
        throw testing::TestError::Failed;
2965
    };
2966
    let case ast::NodeValue::CondExpr(cond) = r.value
2967
        else throw testing::TestError::Failed;
2968
2969
    // Check thenExpr is an `as` cast.
2970
    let case ast::NodeValue::As(thenAs) = cond.thenExpr.value
2971
        else throw testing::TestError::Failed;
2972
    try expectIdent(thenAs.value, "x");
2973
    try expectIntType(thenAs.type, 4, ast::Signedness::Signed);
2974
2975
    // Check condition.
2976
    try expectIdent(cond.condition, "cond");
2977
2978
    // Check elseExpr is an `as` cast.
2979
    let case ast::NodeValue::As(elseAs) = cond.elseExpr.value
2980
        else throw testing::TestError::Failed;
2981
    try expectIdent(elseAs.value, "y");
2982
    try expectIntType(elseAs.type, 4, ast::Signedness::Signed);
2983
}
2984
2985
/// Test parsing a nested conditional expression (right-associative).
2986
@test unsafe fn testParseCondExprNested() throws (testing::TestError) {
2987
    let r = try! parseExprStr("a if x else b if y else c") catch {
2988
        throw testing::TestError::Failed;
2989
    };
2990
    let case ast::NodeValue::CondExpr(outer) = r.value
2991
        else throw testing::TestError::Failed;
2992
2993
    try expectIdent(outer.thenExpr, "a");
2994
    try expectIdent(outer.condition, "x");
2995
2996
    // The else branch should be another conditional expression.
2997
    let case ast::NodeValue::CondExpr(inner) = outer.elseExpr.value
2998
        else throw testing::TestError::Failed;
2999
3000
    try expectIdent(inner.thenExpr, "b");
3001
    try expectIdent(inner.condition, "y");
3002
    try expectIdent(inner.elseExpr, "c");
3003
}
3004
3005
/// Test that trailing commas are allowed in all comma-separated lists.
3006
@test unsafe fn testTrailingCommas() throws (testing::TestError) {
3007
    // Function call arguments.
3008
    let call = try! parseExprStr("f(1, 2, 3,)");
3009
    let case ast::NodeValue::Call(c) = call.value else throw testing::TestError::Failed;
3010
    try testing::expect(c.args.len == 3);
3011
3012
    // Function parameters.
3013
    let fnNode = try! parseStmtStr("fn add(x: i32, y: i32,) {}");
3014
    let case ast::NodeValue::FnDecl(fnDecl) = fnNode.value else throw testing::TestError::Failed;
3015
    try testing::expect(fnDecl.sig.params.len == 2);
3016
3017
    // Record declarations.
3018
    let recNode = try! parseStmtStr("record R { x: i32, y: bool, }");
3019
    let case ast::NodeValue::RecordDecl(recDecl) = recNode.value else throw testing::TestError::Failed;
3020
    try testing::expect(recDecl.fields.len == 2);
3021
3022
    // Tuple record declarations.
3023
    let tupNode = try! parseStmtStr("record R(i32, bool,);");
3024
    let case ast::NodeValue::RecordDecl(tupDecl) = tupNode.value else throw testing::TestError::Failed;
3025
    try testing::expect(tupDecl.fields.len == 2);
3026
3027
    // Record literals.
3028
    let litNode = try! parseExprStr("Point { x: 1, y: 2, }");
3029
    let case ast::NodeValue::RecordLit(lit) = litNode.value else throw testing::TestError::Failed;
3030
    try testing::expect(lit.fields.len == 2);
3031
3032
    // Union declarations.
3033
    let unionNode = try! parseStmtStr("union Color { Red, Green, Blue, }");
3034
    let case ast::NodeValue::UnionDecl(unionDecl) = unionNode.value else throw testing::TestError::Failed;
3035
    try testing::expect(unionDecl.variants.len == 3);
3036
3037
    // Array literals.
3038
    let arrNode = try! parseExprStr("[1, 2, 3,]");
3039
    let case ast::NodeValue::ArrayLit(items) = arrNode.value else throw testing::TestError::Failed;
3040
    try testing::expect(items.len == 3);
3041
3042
    // Function type parameters.
3043
    let fnType = try! parseTypeStr("fn (i32, bool,)");
3044
    let case ast::NodeValue::TypeSig(sigValue) = fnType.value else throw testing::TestError::Failed;
3045
    let case ast::TypeSig::Fn { sig, .. } = sigValue else throw testing::TestError::Failed;
3046
    try testing::expect(sig.params.len == 2);
3047
    try testing::expect(sig.returnType == nil);
3048
3049
    // Throws lists.
3050
    let throwsNode = try! parseStmtStr("fn handle() throws (Error, Other,) {}");
3051
    let case ast::NodeValue::FnDecl(throwsDecl) = throwsNode.value else throw testing::TestError::Failed;
3052
    try testing::expect(throwsDecl.sig.throwList.len == 2);
3053
}
3054
3055
/// Function declarations and function types accept never return annotations.
3056
@test unsafe fn testParseNeverReturn() throws (testing::TestError) {
3057
    let declNode = try! parseStmtStr("fn stop() -> ! { panic; }");
3058
    let case ast::NodeValue::FnDecl(decl) = declNode.value else throw testing::TestError::Failed;
3059
    let ret = decl.sig.returnType else throw testing::TestError::Failed;
3060
    assert ret.value == ast::NodeValue::TypeSig(ast::TypeSig::Never);
3061
    let fnNode = try! parseTypeStr("unsafe fn(u64) -> ! throws (Error)");
3062
    let case ast::NodeValue::TypeSig(ast::TypeSig::Fn { sig, isUnsafe }) = fnNode.value
3063
        else throw testing::TestError::Failed;
3064
    let fnRet = sig.returnType else throw testing::TestError::Failed;
3065
    assert isUnsafe and sig.params.len == 1 and sig.throwList.len == 1;
3066
    assert fnRet.value == ast::NodeValue::TypeSig(ast::TypeSig::Never);
3067
}
3068
3069
/// Unsafe function types preserve their call requirement and signature.
3070
@test unsafe fn testParseUnsafeFunctionType() throws (testing::TestError) {
3071
    let node = try! parseTypeStr("unsafe fn(&u32) -> u32 throws (Error)");
3072
    let case ast::NodeValue::TypeSig(ast::TypeSig::Fn { sig, isUnsafe }) = node.value
3073
        else throw testing::TestError::Failed;
3074
    assert isUnsafe;
3075
    assert sig.params.len == 1;
3076
    assert sig.returnType <> nil;
3077
    assert sig.throwList.len == 1;
3078
}
3079
3080
/// Region arguments on an inner type remain distinct from a reference region.
3081
@test unsafe fn testRegionReferenceTypes() throws (testing::TestError) {
3082
    let root = try! parseTypeStr("&'short mut Node 'arena");
3083
    let case ast::NodeValue::TypeSig(ast::TypeSig::RegionRef { region, type }) = root.value
3084
        else throw testing::TestError::Failed;
3085
    let case ast::NodeValue::Region { name, parent: nil } = region.value
3086
        else throw testing::TestError::Failed;
3087
    try testing::expect(mem::eq(name, "'short"));
3088
    let case ast::NodeValue::TypeSig(ast::TypeSig::Pointer { class, valueType, mutable }) = type.value
3089
        else throw testing::TestError::Failed;
3090
    try testing::expect(class == ast::PointerClass::Ref and mutable);
3091
    let case ast::NodeValue::TypeSig(ast::TypeSig::Applied { name: nominal, regions }) = valueType.value
3092
        else throw testing::TestError::Failed;
3093
    try expectIdent(nominal, "Node");
3094
    try testing::expect(regions.len == 1);
3095
    let case ast::NodeValue::Region { name: argument, .. } = regions[0].value
3096
        else throw testing::TestError::Failed;
3097
    try testing::expect(mem::eq(argument, "'arena"));
3098
    let slice = try! parseTypeStr("&'r [View 'a 'b]");
3099
    let case ast::NodeValue::TypeSig(ast::TypeSig::RegionRef { type: sliceType, .. }) = slice.value
3100
        else throw testing::TestError::Failed;
3101
    let case ast::NodeValue::TypeSig(ast::TypeSig::Slice { .. }) = sliceType.value
3102
        else throw testing::TestError::Failed;
3103
}
3104
3105
/// Declaration lists accept regions, parent relations, and ownership derives.
3106
@test unsafe fn testRegionDeclarations() throws (testing::TestError) {
3107
    let parsedRecord = try! parseStmtStr("record View: 'a + 'b + Copy where 'a: 'b { item: &'b u8 }");
3108
    let case ast::NodeValue::RecordDecl(decl) = parsedRecord.value
3109
        else throw testing::TestError::Failed;
3110
    try testing::expect(decl.regions.len == 2 and decl.derives.len == 1);
3111
    let case ast::NodeValue::Region { parent: parent, .. } = decl.regions[1].value
3112
        else throw testing::TestError::Failed;
3113
    try testing::expect(parent <> nil);
3114
    let func = try! parseStmtStr(
3115
        "fn read 'long 'short (input: &'short u8) -> &'short u8 throws (ReadError) where 'long: 'short { return input; }"
3116
    );
3117
    let case ast::NodeValue::FnDecl(f) = func.value else throw testing::TestError::Failed;
3118
    try testing::expect(f.regions.len == 2 and f.sig.throwList.len == 1);
3119
    let case ast::NodeValue::Region { name: shortName, parent: shortParent } = f.regions[1].value
3120
        else throw testing::TestError::Failed;
3121
    try testing::expect(mem::eq(shortName, "'short") and shortParent <> nil);
3122
    let parentNode = shortParent else throw testing::TestError::Failed;
3123
    let case ast::NodeValue::Region { name: parentName, parent: nil } = parentNode.value
3124
        else throw testing::TestError::Failed;
3125
    try testing::expect(mem::eq(parentName, "'long"));
3126
    let parsedUnion = try! parseStmtStr("union Result: 'x { Value(&'x u8), Empty }");
3127
    let case ast::NodeValue::UnionDecl(u) = parsedUnion.value else throw testing::TestError::Failed;
3128
    try testing::expect(u.regions.len == 1 and u.derives.len == 0);
3129
}
3130
3131
/// Regional blocks retain their source bindings and derived session region.
3132
@test unsafe fn testRegionBlocks() throws (testing::TestError) {
3133
    let root = try! parseStmtStr("let left: 'r = &mut state.left, right = &state.right in { useView(left); }");
3134
    let case ast::NodeValue::RegionBlock { bindings, isSession, .. } = root.value
3135
        else throw testing::TestError::Failed;
3136
    try testing::expect(not isSession and bindings.len == 2);
3137
    let nested = try! parseStmtStr("let view: 'inner = &value where 'outer: 'inner in {}");
3138
    let case ast::NodeValue::RegionBlock { region: nestedRegion, .. } = nested.value
3139
        else throw testing::TestError::Failed;
3140
    let case ast::NodeValue::Region { name: nestedName, parent: nestedParent } = nestedRegion.value
3141
        else throw testing::TestError::Failed;
3142
    let parent = nestedParent else throw testing::TestError::Failed;
3143
    let case ast::NodeValue::Region { name: parentName, parent: nil } = parent.value
3144
        else throw testing::TestError::Failed;
3145
    try testing::expect(mem::eq(nestedName, "'inner") and mem::eq(parentName, "'outer"));
3146
    let arena = try! parseStmtStr("use arena as objects in { make(objects); }");
3147
    let case ast::NodeValue::RegionBlock {
3148
        region: arenaRegion, bindings: arenaBindings, isSession: arenaSession, ..
3149
    } = arena.value
3150
        else throw testing::TestError::Failed;
3151
    let case ast::NodeValue::Region { name: arenaRegionName, parent: nil } = arenaRegion.value
3152
        else throw testing::TestError::Failed;
3153
    let case ast::NodeValue::RegionBinding(arenaBinding) = arenaBindings[0].value
3154
        else throw testing::TestError::Failed;
3155
    let arenaLabel = arenaBinding.label else throw testing::TestError::Failed;
3156
    let case ast::NodeValue::Ident(arenaLabelName) = arenaLabel.value
3157
        else throw testing::TestError::Failed;
3158
    let case ast::NodeValue::AddressOf({ target: arenaTarget, kind: ast::AddressKind::Mutable }) = arenaBinding.value.value
3159
        else throw testing::TestError::Failed;
3160
    let case ast::NodeValue::Ident(arenaTargetName) = arenaTarget.value
3161
        else throw testing::TestError::Failed;
3162
    try testing::expect(
3163
        arenaSession and arenaBindings.len == 1
3164
        and mem::eq(arenaRegionName, "'objects")
3165
        and mem::eq(arenaLabelName, "objects")
3166
        and mem::eq(arenaTargetName, "arena")
3167
    );
3168
}
3169
3170
/// Region grammar rejects incomplete lists and invalid allocation headers.
3171
@test unsafe fn testMalformedRegionSyntax() throws (testing::TestError) {
3172
    for source in [
3173
        "fn bad: Copy () {}",
3174
        "record Bad: 'r + {}",
3175
        "let 'r  in {}",
3176
        "let p: 'r = value in {}",
3177
        "let 'r p = &value in {}",
3178
        "let 'child < 'parent p = &value in {}",
3179
        "let 'parent as p = &value in {}",
3180
        "let value: 'child = &source where 'parent: 'other in {}",
3181
        "use arena in {}",
3182
        "use arena as in {}",
3183
        "use arena as first, second in {}",
3184
        "use 'r a = &mut arena in {}",
3185
        "use 'r a as &mut arena in {}",
3186
    ] {
3187
        let parsed = try? parseStmtStr(source);
3188
        try testing::expect(parsed == nil);
3189
    }
3190
    for source in ["&'x' u8", "&mut 'x u8", "View '", "&'r"] {
3191
        let parsed = try? parseTypeStr(source);
3192
        try testing::expect(parsed == nil);
3193
    }
3194
}
3195
3196
/// Ordinary identifiers remain available beside regional block syntax.
3197
@test unsafe fn testRegionContextualKeywords() throws (testing::TestError) {
3198
    for source in [
3199
        "let borrow = 1;",
3200
        "let session = 2;",
3201
        "borrow(value);",
3202
        "session(value);",
3203
        "record Context { borrow: u32, session: u32 }",
3204
    ] {
3205
        let parsed = try? parseStmtStr(source);
3206
        try testing::expect(parsed <> nil);
3207
    }
3208
}
3209
3210
/// The AST printer retains region parameters and qualified reference types.
3211
@test unsafe fn testPrintRegionSignature() throws (testing::TestError) {
3212
    let root = try! parseStmtStr("fn read 'r (input: &'r u8) -> &'r u8 { return input; }");
3213
    static PRINT_STORAGE: [u8; 4096] = [0; 4096];
3214
    let mut arena = alloc::new(&mut PRINT_STORAGE[..]);
3215
    let printed = printer::toExpr(&mut arena, root);
3216
    let case sexpr::Expr::Block { items, .. } = printed
3217
        else throw testing::TestError::Failed;
3218
    try testing::expect(items.len == 4);
3219
    let case sexpr::Expr::List { head, tail, .. } = items[1]
3220
        else throw testing::TestError::Failed;
3221
    try testing::expect(mem::eq(head, "regions") and tail.len == 1);
3222
    let case sexpr::Expr::Sym(name) = tail[0] else throw testing::TestError::Failed;
3223
    try testing::expect(mem::eq(name, "'r"));
3224
    let case sexpr::Expr::List { head: refHead, tail: refTail, .. } = items[3]
3225
        else throw testing::TestError::Failed;
3226
    try testing::expect(mem::eq(refHead, "region-ref") and refTail.len == 2);
3227
}
3228
3229
/// Explicit function region arguments precede ordinary call arguments.
3230
@test unsafe fn testFunctionRegionApplication() throws (testing::TestError) {
3231
    let expr = try! parseExprStr("read 'a 'b (p)");
3232
    let case ast::NodeValue::Call(call) = expr.value else throw testing::TestError::Failed;
3233
    let case ast::NodeValue::RegionApply { value, regions } = call.callee.value
3234
        else throw testing::TestError::Failed;
3235
    try expectIdent(value, "read");
3236
    try testing::expect(regions.len == 2 and call.args.len == 1);
3237
}
3238
3239
/// Concrete region headers can name a parent and end without a semicolon.
3240
@test unsafe fn testRegionParentSyntax() throws (testing::TestError) {
3241
    let parsed = try? parseStmtsStr("fn f 'a (p: &'a u32) { let q: 'b = &*p where 'a: 'b in {} return; }");
3242
    try testing::expect(parsed <> nil);
3243
}
3244
3245
/// Cell qualifiers retain pointer ownership and payload syntax.
3246
@test unsafe fn testCellPointerType() throws (testing::TestError) {
3247
    let root = try! parseTypeStr("*cell u32");
3248
    let case ast::NodeValue::TypeSig(ast::TypeSig::Cell { class, payload }) = root.value
3249
        else throw testing::TestError::Failed;
3250
    try testing::expect(class == ast::PointerClass::Owned);
3251
    let case ast::NodeValue::TypeSig(ast::TypeSig::Integer { width: 4, .. }) = payload.value
3252
        else throw testing::TestError::Failed;
3253
    let borrowed = try! parseTypeStr("&'r cell Pair 's");
3254
    let case ast::NodeValue::TypeSig(ast::TypeSig::RegionRef { type, .. }) = borrowed.value
3255
        else throw testing::TestError::Failed;
3256
    let case ast::NodeValue::TypeSig(ast::TypeSig::Cell { class: refClass, payload: inner }) = type.value
3257
        else throw testing::TestError::Failed;
3258
    try testing::expect(refClass == ast::PointerClass::Ref);
3259
    let case ast::NodeValue::TypeSig(ast::TypeSig::Applied { regions, .. }) = inner.value
3260
        else throw testing::TestError::Failed;
3261
    try testing::expect(regions.len == 1);
3262
}
3263
3264
3265
/// Measure committed storage for a statement after an existing node.
3266
unsafe fn statementStorageUsed(source: *[u8]) -> u32 {
3267
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
3268
    ast::allocNode(&mut arena, ast::Span { offset: 0, length: 0 }, ast::NodeValue::Bool(true));
3269
    let start = alloc::used(&arena.arena);
3270
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
3271
        let mut parser = super::mkParser(scanner::SourceLoc::String, source, arenaRef, poolRef);
3272
        super::advance(&mut parser);
3273
        try! super::parseStmt(&mut parser);
3274
        return alloc::used(&parser.arena.arena) - start;
3275
    }
3276
}
3277
3278
/// Rewinding a failed expression preserves published nodes and source tokens.
3279
@test unsafe fn testSpeculativeRestoreStorage() throws (testing::TestError) {
3280
    let expectedBytes = statementStorageUsed("return");
3281
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
3282
    let retained = ast::allocNode(&mut arena, ast::Span { offset: 3, length: 1 }, ast::NodeValue::Bool(true));
3283
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
3284
        let mut parser = super::mkParser(scanner::SourceLoc::String,
3285
            "return [speculativeRestoreIdentifier, 1 +", arenaRef, poolRef);
3286
        super::advance(&mut parser);
3287
        try super::expect(&mut parser, scanner::TokenKind::Eof, "retained diagnostic") catch {
3288
        };
3289
        let mut expectedScanner = parser.scanner;
3290
        let expectedCurrent = scanner::next(&mut expectedScanner, parser.pool);
3291
        let expectedPrevious = parser.current;
3292
        let expectedContext = parser.context;
3293
        let startOffset = alloc::used(&parser.arena.arena);
3294
        let startId = parser.arena.nextId;
3295
        let statement = try! super::parseStmt(&mut parser);
3296
        let case ast::NodeValue::Return { value } = statement.value else throw testing::TestError::Failed;
3297
        try testing::expect(value == nil);
3298
        try testing::expect(statement.id == startId);
3299
        try testing::expect(alloc::used(&parser.arena.arena) == startOffset + expectedBytes);
3300
        try testing::expect(parser.arena.nextId == startId + 1);
3301
        try testing::expect(parser.scanner.cursor == expectedScanner.cursor);
3302
        try testing::expect(parser.scanner.token == expectedScanner.token);
3303
        try testing::expect(parser.current.kind == expectedCurrent.kind);
3304
        try testing::expect(parser.current.offset == expectedCurrent.offset);
3305
        try testing::expect(parser.previous.kind == expectedPrevious.kind);
3306
        try testing::expect(parser.previous.offset == expectedPrevious.offset);
3307
        try testing::expect(parser.context == expectedContext);
3308
        try testing::expect(parser.errors.count == 1);
3309
        for i in alloc::used(&parser.arena.arena)..ARENA_STORAGE.len {
3310
            set ARENA_STORAGE[i] = 0xA5;
3311
        }
3312
        let case ast::NodeValue::Bool(true) = retained.value else throw testing::TestError::Failed;
3313
        try testing::expect(retained.span.offset == 3);
3314
        try testing::expect(retained.span.length == 1);
3315
        try testing::expect(mem::eq(parser.errors.list[0].message, "retained diagnostic"));
3316
        try testing::expect(mem::eq(parser.errors.list[0].token.source, "return"));
3317
        let interned = strings::find(parser.pool, "speculativeRestoreIdentifier") else throw testing::TestError::Failed;
3318
        try testing::expect(mem::eq(interned, "speculativeRestoreIdentifier"));
3319
        let replacement = ast::allocNode(parser.arena, ast::Span { offset: 0, length: 0 }, ast::NodeValue::Bool(false));
3320
        try testing::expect(replacement.id == startId + 1);
3321
        let case ast::NodeValue::Bool(true) = retained.value else throw testing::TestError::Failed;
3322
    }
3323
}
3324
3325
/// Optional return and panic expressions publish only their wrapper after failure.
3326
@test unsafe fn testSpeculativeStatementPublication() throws (testing::TestError) {
3327
    let expectedBytes = statementStorageUsed("return");
3328
    for source in ["return (speculativeReturnIdentifier +", "panic (speculativePanicIdentifier +"] {
3329
        let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
3330
        ast::allocNode(&mut arena, ast::Span { offset: 0, length: 0 }, ast::NodeValue::Bool(true));
3331
        let startOffset = alloc::used(&arena.arena);
3332
        let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
3333
            let mut parser = super::mkParser(scanner::SourceLoc::String, source, arenaRef, poolRef);
3334
            super::advance(&mut parser);
3335
            let startId = parser.arena.nextId;
3336
            let statement = try! super::parseStmt(&mut parser);
3337
            try testing::expect(statement.id == startId);
3338
            try testing::expect(parser.arena.nextId == startId + 1);
3339
            try testing::expect(alloc::used(&parser.arena.arena) == startOffset + expectedBytes);
3340
            try testing::expect(parser.errors.count == 0);
3341
            try testing::expect(parser.current.kind == scanner::TokenKind::LParen);
3342
            match statement.value {
3343
                case ast::NodeValue::Return { value } => try testing::expect(value == nil),
3344
                case ast::NodeValue::Panic { message } => try testing::expect(message == nil),
3345
                else => throw testing::TestError::Failed,
3346
            }
3347
        }
3348
    }
3349
}