lib/std/lang/parser/tests.rad 138.8 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
/// Opaque record modifiers preserve exports, regions, and ownership markers.
961
@test unsafe fn testParseOpaqueRecord() throws (testing::TestError) {
962
    for source, i in [
963
        "opaque record R { value: u32 }",
964
        "export opaque record R: 'r + Copy { value: &'r u32 }",
965
        "opaque record R: Copy(u32);",
966
    ] {
967
        let node = try! parseStmtStr(source);
968
        let case ast::NodeValue::RecordDecl(decl) = node.value else throw testing::TestError::Failed;
969
        let attrs = decl.attrs else throw testing::TestError::Failed;
970
        assert ast::attributesContains(&attrs, ast::Attribute::Opaque);
971
        assert ast::attributesContains(&attrs, ast::Attribute::Export) == (i == 1);
972
        assert decl.labeled == (i <> 2);
973
        assert decl.fields.len == 1;
974
        assert decl.regions.len == (1 if i == 1 else 0);
975
        assert decl.derives.len == (0 if i == 0 else 1);
976
        static PRINT_STORAGE: [u8; 4096] = [0; 4096];
977
        let mut printArena = alloc::new(&mut PRINT_STORAGE[..]);
978
        let printed = printer::toExpr(&mut printArena, node);
979
        let case sexpr::Expr::Block { name, .. } = printed else throw testing::TestError::Failed;
980
        assert name == "opaque-record";
981
    }
982
    for source in [
983
        "opaque fn f() {}",
984
        "opaque union R { Value }",
985
        "opaque opaque record R {}",
986
        "opaque export record R {}",
987
    ] {
988
        let parsed = try? parseStmtStr(source);
989
        assert parsed == nil;
990
    }
991
}
992
993
@test unsafe fn testParseRecordDecl() throws (testing::TestError) {
994
    let node = try! parseStmtStr("record R { x: bool, y: i32 }");
995
    let case ast::NodeValue::RecordDecl(decl) = node.value
996
        else throw testing::TestError::Failed;
997
998
    try expectIdent(decl.name, "R");
999
    try testing::expect(decl.derives.len == 0);
1000
    try testing::expect(decl.fields.len == 2);
1001
1002
    try expectFieldSig(decl.fields, 0, "x", ast::TypeSig::Bool);
1003
    try expectFieldSig(decl.fields, 1, "y", ast::TypeSig::Integer {
1004
        width: 4,
1005
        sign: ast::Signedness::Signed,
1006
    });
1007
}
1008
1009
/// Test parsing a record declaration with derives.
1010
@test unsafe fn testParseRecordDeclDerives() throws (testing::TestError) {
1011
    let node = try! parseStmtStr("record R: Eq + Debug { field: i32 }");
1012
    let case ast::NodeValue::RecordDecl(decl) = node.value
1013
        else throw testing::TestError::Failed;
1014
1015
    try expectIdent(decl.name, "R");
1016
    try testing::expect(decl.derives.len == 2);
1017
    try expectIdent(decl.derives[0], "Eq");
1018
    try expectIdent(decl.derives[1], "Debug");
1019
}
1020
1021
/// Test parsing a record declaration with field initializers.
1022
@test unsafe fn testParseRecordDeclFieldDefaults() throws (testing::TestError) {
1023
    let node = try! parseStmtStr("record Config { size: opaque = 42, flag: bool = true }");
1024
    let case ast::NodeValue::RecordDecl(decl) = node.value
1025
        else throw testing::TestError::Failed;
1026
1027
    try expectIdent(decl.name, "Config");
1028
    try testing::expect(decl.derives.len == 0);
1029
    try testing::expect(decl.fields.len == 2);
1030
1031
    try expectFieldSig(decl.fields, 0, "size", ast::TypeSig::Opaque);
1032
    try expectFieldSig(decl.fields, 1, "flag", ast::TypeSig::Bool);
1033
1034
    // Check default values.
1035
    let case ast::NodeValue::RecordField { value: val0, .. } = decl.fields[0].value
1036
        else throw testing::TestError::Failed;
1037
    let v0 = val0 else throw testing::TestError::Failed;
1038
    try expectNumber(v0, "42");
1039
1040
    let case ast::NodeValue::RecordField { value: val1, .. } = decl.fields[1].value
1041
        else throw testing::TestError::Failed;
1042
    let v1 = val1 else throw testing::TestError::Failed;
1043
    let case ast::NodeValue::Bool(flagValue) = v1.value
1044
        else throw testing::TestError::Failed;
1045
    try testing::expect(flagValue);
1046
}
1047
1048
/// Test parsing an unlabeled record declaration.
1049
@test unsafe fn testParseTupleRecordDecl() throws (testing::TestError) {
1050
    let node = try! parseStmtStr("record Pair(bool, i32);");
1051
    let case ast::NodeValue::RecordDecl(decl) = node.value
1052
        else throw testing::TestError::Failed;
1053
1054
    try expectIdent(decl.name, "Pair");
1055
    try testing::expect(not decl.labeled);
1056
    try testing::expect(decl.derives.len == 0);
1057
    try testing::expect(decl.fields.len == 2);
1058
1059
    try expectFieldSig(decl.fields, 0, nil, ast::TypeSig::Bool);
1060
    try expectFieldSig(decl.fields, 1, nil, ast::TypeSig::Integer {
1061
        width: 4,
1062
        sign: ast::Signedness::Signed,
1063
    });
1064
}
1065
1066
/// Test parsing a single-field unlabeled record.
1067
@test unsafe fn testParseTupleRecordSingleField() throws (testing::TestError) {
1068
    let node = try! parseStmtStr("record R(bool);");
1069
    let case ast::NodeValue::RecordDecl(decl) = node.value
1070
        else throw testing::TestError::Failed;
1071
1072
    try expectIdent(decl.name, "R");
1073
    try testing::expect(not decl.labeled);
1074
    try testing::expect(decl.fields.len == 1);
1075
1076
    try expectFieldSig(decl.fields, 0, nil, ast::TypeSig::Bool);
1077
}
1078
1079
/// Test parsing empty record literals.
1080
@test unsafe fn testParseEmptyRecordLiteral() throws (testing::TestError) {
1081
    let r1 = try! parseExprStr("{}");
1082
    let case ast::NodeValue::RecordLit(lit) = r1.value
1083
        else throw testing::TestError::Failed;
1084
1085
    try testing::expect(lit.typeName == nil);
1086
    try testing::expect(lit.fields.len == 0);
1087
1088
    let r2 = try! parseExprStr("Point {}");
1089
    let case ast::NodeValue::RecordLit(lit2) = r2.value
1090
        else throw testing::TestError::Failed;
1091
1092
    let typeName = lit2.typeName else throw testing::TestError::Failed;
1093
    try expectIdent(typeName, "Point");
1094
    try testing::expect(lit2.fields.len == 0);
1095
}
1096
1097
/// Test parsing a function type with parameters and return type.
1098
@test unsafe fn testParseTypeFn() throws (testing::TestError) {
1099
    let node = try! parseTypeStr("fn (i32, *u8) -> bool");
1100
    let case ast::NodeValue::TypeSig(sigValue) = node.value
1101
        else throw testing::TestError::Failed;
1102
    let case ast::TypeSig::Fn { sig, .. } = sigValue
1103
        else throw testing::TestError::Failed;
1104
1105
    try testing::expect(sig.params.len == 2);
1106
1107
    let param0 = sig.params[0];
1108
    try expectIntType(param0, 4, ast::Signedness::Signed);
1109
1110
    let param1 = sig.params[1];
1111
    let case ast::NodeValue::TypeSig(p1) = param1.value
1112
        else throw testing::TestError::Failed;
1113
    let case ast::TypeSig::Pointer { valueType: ptrTarget, .. } = p1
1114
        else throw testing::TestError::Failed;
1115
    try expectIntType(ptrTarget, 1, ast::Signedness::Unsigned);
1116
1117
    try testing::expect(sig.returnType <> nil);
1118
}
1119
1120
/// Test parsing a function type with a throws clause.
1121
@test unsafe fn testParseTypeFnThrows() throws (testing::TestError) {
1122
    let node = try! parseTypeStr("fn (i32) -> bool throws (Error, Other)");
1123
    let case ast::NodeValue::TypeSig(sigValue) = node.value
1124
        else throw testing::TestError::Failed;
1125
    let case ast::TypeSig::Fn { sig, .. } = sigValue
1126
        else throw testing::TestError::Failed;
1127
1128
    try testing::expect(sig.params.len == 1);
1129
    try expectIntType(sig.params[0], 4, ast::Signedness::Signed);
1130
1131
    try testing::expect(sig.throwList.len == 2);
1132
    try expectTypeIdent(sig.throwList[0], "Error");
1133
    try expectTypeIdent(sig.throwList[1], "Other");
1134
1135
    let returnType = sig.returnType
1136
        else throw testing::TestError::Failed;
1137
    try expectType(returnType, ast::TypeSig::Bool);
1138
}
1139
1140
/// Test parsing a function declaration without parameters.
1141
@test unsafe fn testParseFnDeclEmpty() throws (testing::TestError) {
1142
    let node = try! parseStmtStr("fn main() {}");
1143
    let case ast::NodeValue::FnDecl(decl) = node.value
1144
        else throw testing::TestError::Failed;
1145
1146
    try expectIdent(decl.name, "main");
1147
    try testing::expect(decl.sig.params.len == 0);
1148
    try testing::expect(decl.sig.returnType == nil);
1149
    try testing::expect(decl.attrs == nil);
1150
1151
    let body = decl.body else throw testing::TestError::Failed;
1152
    let case ast::NodeValue::Block(_) = body.value
1153
        else throw testing::TestError::Failed;
1154
}
1155
1156
/// Test parsing a function declaration with parameters and return type.
1157
@test unsafe fn testParseFnDeclParams() throws (testing::TestError) {
1158
    let node = try! parseStmtStr("fn add(x: i32, y: *u8) -> bool {}");
1159
    let case ast::NodeValue::FnDecl(decl) = node.value
1160
        else throw testing::TestError::Failed;
1161
1162
    try expectIdent(decl.name, "add");
1163
    try testing::expect(decl.sig.params.len == 2);
1164
1165
    {
1166
        let param0 = decl.sig.params[0];
1167
        let case ast::NodeValue::FnParam(p0) = param0.value
1168
            else throw testing::TestError::Failed;
1169
        try expectIdent(p0.name, "x");
1170
        try expectIntType(p0.type, 4, ast::Signedness::Signed);
1171
    }
1172
    {
1173
        let param1 = decl.sig.params[1];
1174
        let case ast::NodeValue::FnParam(p1) = param1.value
1175
            else throw testing::TestError::Failed;
1176
        try expectIdent(p1.name, "y");
1177
        let case ast::NodeValue::TypeSig(sig1) = p1.type.value
1178
            else throw testing::TestError::Failed;
1179
        let case ast::TypeSig::Pointer { valueType, .. } = sig1
1180
            else throw testing::TestError::Failed;
1181
        try expectIntType(valueType, 1, ast::Signedness::Unsigned);
1182
    }
1183
    {
1184
        let returnType = decl.sig.returnType
1185
            else throw testing::TestError::Failed;
1186
        try expectType(returnType, ast::TypeSig::Bool);
1187
1188
        let body = decl.body else throw testing::TestError::Failed;
1189
        let case ast::NodeValue::Block(_) = body.value
1190
            else throw testing::TestError::Failed;
1191
    }
1192
}
1193
1194
/// Test parsing a function declaration with a throws clause.
1195
@test unsafe fn testParseFnDeclThrows() throws (testing::TestError) {
1196
    let node = try! parseStmtStr("fn handle() throws (Error, Crash) {}");
1197
    let case ast::NodeValue::FnDecl(decl) = node.value
1198
        else throw testing::TestError::Failed;
1199
1200
    try expectIdent(decl.name, "handle");
1201
    try testing::expect(decl.sig.returnType == nil);
1202
1203
    try testing::expect(decl.sig.throwList.len == 2);
1204
    try expectTypeIdent(decl.sig.throwList[0], "Error");
1205
    try expectTypeIdent(decl.sig.throwList[1], "Crash");
1206
1207
    let body = decl.body else throw testing::TestError::Failed;
1208
    let case ast::NodeValue::Block(_) = body.value
1209
        else throw testing::TestError::Failed;
1210
}
1211
1212
/// Test scanning source-level `void` produces an identifier, not a type keyword.
1213
@test unsafe fn testParseTypeVoidRejected() throws (testing::TestError) {
1214
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
1215
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
1216
        let mut parser = super::mkParser(scanner::SourceLoc::String, "void", arenaRef, poolRef);
1217
        super::advance(&mut parser);
1218
        try testing::expect(super::check(&parser, scanner::TokenKind::Ident));
1219
    }
1220
}
1221
1222
/// Test parsing the unsafe function modifier.
1223
@test unsafe fn testParseUnsafeFnDecl() throws (testing::TestError) {
1224
    let node = try! parseStmtStr("unsafe fn run() {}");
1225
    let case ast::NodeValue::FnDecl(decl) = node.value
1226
        else throw testing::TestError::Failed;
1227
    let attrs = decl.attrs
1228
        else throw testing::TestError::Failed;
1229
1230
    try testing::expect(attrs.list.len == 1);
1231
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Unsafe));
1232
}
1233
1234
/// Test rejecting `unsafe` on declarations where it has no semantics.
1235
@test unsafe fn testParseUnsafeUnsupportedDecl() throws (testing::TestError) {
1236
    let recordDecl: ?*ast::Node = try? parseStmtStr("unsafe record R {}");
1237
    try testing::expect(recordDecl == nil);
1238
    let constDecl: ?*ast::Node = try? parseStmtStr("unsafe constant X = 1;");
1239
    try testing::expect(constDecl == nil);
1240
}
1241
1242
/// Test unsafe method declarations.
1243
@test unsafe fn testParseUnsafeMethods() throws (testing::TestError) {
1244
    let instanceNode = try! parseStmtStr(
1245
        "instance Read for Value { unsafe fn (value: &Value) get() {} }"
1246
    );
1247
    let case ast::NodeValue::InstanceDecl { methods, .. } = instanceNode.value
1248
        else throw testing::TestError::Failed;
1249
    try testing::expect(methods.len == 1);
1250
    let case ast::NodeValue::MethodDecl { modifiers, .. } = methods[0].value
1251
        else throw testing::TestError::Failed;
1252
    let attrs = modifiers.attrs;
1253
    let methodAttrs = attrs else throw testing::TestError::Failed;
1254
    assert ast::attributesContains(&methodAttrs, ast::Attribute::Unsafe);
1255
1256
    static printStorage: [u8; 4096] = undefined;
1257
    let mut printArena = alloc::new(&mut printStorage[..]);
1258
    let methodExpr = printer::toExpr(&mut printArena, methods[0]);
1259
    let case sexpr::Expr::Block { items: methodItems, .. } = methodExpr
1260
        else throw testing::TestError::Failed;
1261
    let case sexpr::Expr::List {
1262
        head: methodAttrsHead, tail: printedMethodAttrs, ..
1263
    } = methodItems[0] else throw testing::TestError::Failed;
1264
    assert mem::eq(methodAttrsHead, "attrs");
1265
    let case sexpr::Expr::Sym(methodAttr) = printedMethodAttrs[0]
1266
        else throw testing::TestError::Failed;
1267
    assert mem::eq(methodAttr, "@unsafe");
1268
1269
    let traitNode = try! parseStmtStr(
1270
        "trait Read { unsafe fn (&Read) get(); }"
1271
    );
1272
    let case ast::NodeValue::TraitDecl { methods: traitMethods, .. } = traitNode.value
1273
        else throw testing::TestError::Failed;
1274
    let case ast::NodeValue::TraitMethodSig {
1275
        modifiers: traitModifiers, ..
1276
    } = traitMethods[0].value else throw testing::TestError::Failed;
1277
    let traitAttrs = traitModifiers.attrs;
1278
    let traitMethodAttrs = traitAttrs else throw testing::TestError::Failed;
1279
    assert ast::attributesContains(&traitMethodAttrs, ast::Attribute::Unsafe);
1280
1281
    let traitMethodExpr = printer::toExpr(&mut printArena, traitMethods[0]);
1282
    let case sexpr::Expr::List { tail: traitMethodItems, .. } = traitMethodExpr
1283
        else throw testing::TestError::Failed;
1284
    let case sexpr::Expr::List {
1285
        head: traitAttrsHead, tail: printedTraitAttrs, ..
1286
    } = traitMethodItems[0] else throw testing::TestError::Failed;
1287
    assert mem::eq(traitAttrsHead, "attrs");
1288
    let case sexpr::Expr::Sym(traitAttr) = printedTraitAttrs[0]
1289
        else throw testing::TestError::Failed;
1290
    assert mem::eq(traitAttr, "@unsafe");
1291
}
1292
1293
/// Test region parameters on methods, trait methods, and instances.
1294
@test unsafe fn testParseRegionalMethods() throws (testing::TestError) {
1295
    let instanceNode = try! parseStmtStr(
1296
        "instance Read for View 'view { fn (view: &View 'view) get 'method () -> &'method u32 { panic; } }"
1297
    );
1298
    let case ast::NodeValue::InstanceDecl { regions, methods, .. } = instanceNode.value
1299
        else throw testing::TestError::Failed;
1300
    try testing::expect(regions.len == 1 and methods.len == 1);
1301
    let case ast::NodeValue::MethodDecl { modifiers, .. } = methods[0].value
1302
        else throw testing::TestError::Failed;
1303
    try testing::expect(modifiers.regions.len == 1);
1304
1305
    let traitNode = try! parseStmtStr(
1306
        "trait Read { fn (&Read) get 'method () -> &'method u32; }"
1307
    );
1308
    let case ast::NodeValue::TraitDecl { methods: traitMethods, .. } = traitNode.value
1309
        else throw testing::TestError::Failed;
1310
    let case ast::NodeValue::TraitMethodSig { modifiers: traitModifiers, .. } = traitMethods[0].value
1311
        else throw testing::TestError::Failed;
1312
    try testing::expect(traitModifiers.regions.len == 1);
1313
}
1314
1315
/// Test parsing a function declaration with attributes.
1316
@test unsafe fn testParseFnDeclAttributes() throws (testing::TestError) {
1317
    let node = try! parseStmtStr("export fn run();");
1318
    let case ast::NodeValue::FnDecl(decl) = node.value
1319
        else throw testing::TestError::Failed;
1320
1321
    try expectIdent(decl.name, "run");
1322
1323
    let attrs = decl.attrs
1324
        else throw testing::TestError::Failed;
1325
1326
    try testing::expect(attrs.list.len == 2);
1327
1328
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1329
        else throw testing::TestError::Failed;
1330
    try testing::expect(attr0 == ast::Attribute::Export);
1331
1332
    let case ast::NodeValue::Attribute(attr1) = attrs.list[1].value
1333
        else throw testing::TestError::Failed;
1334
    try testing::expect(attr1 == ast::Attribute::Extern);
1335
1336
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Export));
1337
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1338
    try testing::expect(decl.body == nil);
1339
}
1340
1341
/// Test parsing a top-level function declaration with inferred extern from `;`.
1342
@test unsafe fn testParseFnDeclInferredExtern() throws (testing::TestError) {
1343
    let node = try! parseStmtStr("fn run();");
1344
    let case ast::NodeValue::FnDecl(decl) = node.value
1345
        else throw testing::TestError::Failed;
1346
1347
    try expectIdent(decl.name, "run");
1348
1349
    let attrs = decl.attrs
1350
        else throw testing::TestError::Failed;
1351
1352
    try testing::expect(attrs.list.len == 1);
1353
1354
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1355
        else throw testing::TestError::Failed;
1356
    try testing::expect(attr0 == ast::Attribute::Extern);
1357
1358
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1359
    try testing::expect(decl.body == nil);
1360
}
1361
1362
/// Test parsing a top-level exported function declaration with inferred extern from `;`.
1363
@test unsafe fn testParseFnDeclExportInferredExtern() throws (testing::TestError) {
1364
    let node = try! parseStmtStr("export fn run();");
1365
    let case ast::NodeValue::FnDecl(decl) = node.value
1366
        else throw testing::TestError::Failed;
1367
1368
    try expectIdent(decl.name, "run");
1369
1370
    let attrs = decl.attrs
1371
        else throw testing::TestError::Failed;
1372
1373
    try testing::expect(attrs.list.len == 2);
1374
1375
    let case ast::NodeValue::Attribute(attr0) = attrs.list[0].value
1376
        else throw testing::TestError::Failed;
1377
    try testing::expect(attr0 == ast::Attribute::Export);
1378
1379
    let case ast::NodeValue::Attribute(attr1) = attrs.list[1].value
1380
        else throw testing::TestError::Failed;
1381
    try testing::expect(attr1 == ast::Attribute::Extern);
1382
1383
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Export));
1384
    try testing::expect(ast::attributesContains(&attrs, ast::Attribute::Extern));
1385
    try testing::expect(decl.body == nil);
1386
}
1387
1388
/// Test parsing a scoped identifier type.
1389
@test unsafe fn testParseTypeScopedIdent() throws (testing::TestError) {
1390
    let node = try! parseTypeStr("module::Type");
1391
    let case ast::NodeValue::TypeSig(ts) = node.value
1392
        else throw testing::TestError::Failed;
1393
    let case ast::TypeSig::Nominal(name) = ts
1394
        else throw testing::TestError::Failed;
1395
    let case ast::NodeValue::ScopeAccess(access) = name.value
1396
        else throw testing::TestError::Failed;
1397
1398
    try expectIdent(access.parent, "module");
1399
    try expectIdent(access.child, "Type");
1400
}
1401
1402
/// Test parsing the `bool` type.
1403
@test unsafe fn testParseTypeBool() throws (testing::TestError) {
1404
    let node = try! parseTypeStr("bool");
1405
    try expectType(node, ast::TypeSig::Bool);
1406
}
1407
1408
/// Test parsing an unsigned integer type.
1409
@test unsafe fn testParseTypeUnsigned() throws (testing::TestError) {
1410
    let node = try! parseTypeStr("u8");
1411
    try expectType(node, ast::TypeSig::Integer {
1412
        width: 1,
1413
        sign: ast::Signedness::Unsigned,
1414
    });
1415
}
1416
1417
/// Test parsing a simple `if let` statement without guard or else.
1418
@test unsafe fn testParseIfLet() throws (testing::TestError) {
1419
    let root = try! parseStmtStr("if let value = opt { body; }");
1420
    let case ast::NodeValue::IfLet(node) = root.value
1421
        else throw testing::TestError::Failed;
1422
1423
    try expectIdent(node.pattern.pattern, "value");
1424
    try expectIdent(node.pattern.scrutinee, "opt");
1425
1426
    try testing::expect(node.pattern.guard == nil);
1427
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1428
    try testing::expect(node.elseBranch == nil);
1429
}
1430
1431
/// Test parsing an `if let` statement with guard and else branches.
1432
@test unsafe fn testParseIfLetGuardElse() throws (testing::TestError) {
1433
    let root = try! parseStmtStr(
1434
        "if let value = opt; guard { body; } else { alt; }"
1435
    );
1436
    let case ast::NodeValue::IfLet(node) = root.value
1437
        else throw testing::TestError::Failed;
1438
1439
    try expectIdent(node.pattern.pattern, "value");
1440
    try expectIdent(node.pattern.scrutinee, "opt");
1441
1442
    let guard = node.pattern.guard
1443
        else throw testing::TestError::Failed;
1444
    try expectIdent(guard, "guard");
1445
1446
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1447
1448
    let elseBranch = node.elseBranch
1449
        else throw testing::TestError::Failed;
1450
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1451
}
1452
1453
/// Test parsing an `if let` statement with an `else if` chain.
1454
@test unsafe fn testParseIfLetElseIf() throws (testing::TestError) {
1455
    let root = try! parseStmtStr(
1456
        "if let value = opt { body; } else if cond { alt; }"
1457
    );
1458
    let case ast::NodeValue::IfLet(node) = root.value
1459
        else throw testing::TestError::Failed;
1460
1461
    try expectIdent(node.pattern.pattern, "value");
1462
1463
    let elseBranch = node.elseBranch
1464
        else throw testing::TestError::Failed;
1465
1466
    let nested = try getBlockFirstStmt(elseBranch);
1467
    let case ast::NodeValue::If(inner) = nested.value
1468
        else throw testing::TestError::Failed;
1469
1470
    try expectIdent(inner.condition, "cond");
1471
    try expectBlockExprStmt(inner.thenBranch, ast::NodeValue::Ident("alt"));
1472
    try testing::expect(inner.elseBranch == nil);
1473
}
1474
1475
/// Test parsing `if let mut` binding.
1476
@test unsafe fn testParseIfLetMut() throws (testing::TestError) {
1477
    let root = try! parseStmtStr("if let mut value = opt { body; }");
1478
    let case ast::NodeValue::IfLet(node) = root.value
1479
        else throw testing::TestError::Failed;
1480
1481
    try expectIdent(node.pattern.pattern, "value");
1482
    try expectIdent(node.pattern.scrutinee, "opt");
1483
    try testing::expect(node.pattern.mutable);
1484
    try testing::expect(node.pattern.guard == nil);
1485
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1486
    try testing::expect(node.elseBranch == nil);
1487
}
1488
1489
/// Test parsing `let mut ... else` binding.
1490
@test unsafe fn testParseLetMutElse() throws (testing::TestError) {
1491
    let root = try! parseStmtStr("let mut x = opt else { return };");
1492
    let case ast::NodeValue::LetElse(letElse) = root.value
1493
        else throw testing::TestError::Failed;
1494
1495
    try expectIdent(letElse.pattern.pattern, "x");
1496
    try testing::expect(letElse.pattern.mutable);
1497
}
1498
1499
/// Test that `if let` without `mut` is not mutable.
1500
@test unsafe fn testParseIfLetNotMutable() throws (testing::TestError) {
1501
    let root = try! parseStmtStr("if let value = opt { body; }");
1502
    let case ast::NodeValue::IfLet(node) = root.value
1503
        else throw testing::TestError::Failed;
1504
1505
    try testing::expect(not node.pattern.mutable);
1506
}
1507
1508
/// Test that `let ... else` without `mut` is not mutable.
1509
@test unsafe fn testParseLetElseNotMutable() throws (testing::TestError) {
1510
    let root = try! parseStmtStr("let x = opt else { return };");
1511
    let case ast::NodeValue::LetElse(letElse) = root.value
1512
        else throw testing::TestError::Failed;
1513
1514
    try testing::expect(not letElse.pattern.mutable);
1515
}
1516
1517
/// Test parsing a simple `if let case` statement.
1518
@test unsafe fn testParseIfCase() throws (testing::TestError) {
1519
    let root = try! parseStmtStr("if let case pat = value { body; }");
1520
    let case ast::NodeValue::IfLet(node) = root.value
1521
        else throw testing::TestError::Failed;
1522
1523
    try expectIdent(node.pattern.pattern, "pat");
1524
    try expectIdent(node.pattern.scrutinee, "value");
1525
    try testing::expect(node.pattern.guard == nil);
1526
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1527
    try testing::expect(node.elseBranch == nil);
1528
}
1529
1530
/// Test parsing an `if let case` statement with guard and else branches.
1531
@test unsafe fn testParseIfCaseGuardElse() throws (testing::TestError) {
1532
    let root = try! parseStmtStr(
1533
        "if let case pat = value; guard { body; } else { alt; }"
1534
    );
1535
    let case ast::NodeValue::IfLet(node) = root.value
1536
        else throw testing::TestError::Failed;
1537
1538
    try expectIdent(node.pattern.pattern, "pat");
1539
    try expectIdent(node.pattern.scrutinee, "value");
1540
1541
    let guard = node.pattern.guard
1542
        else throw testing::TestError::Failed;
1543
    try expectIdent(guard, "guard");
1544
1545
    try expectBlockExprStmt(node.thenBranch, ast::NodeValue::Ident("body"));
1546
1547
    let elseBranch = node.elseBranch
1548
        else throw testing::TestError::Failed;
1549
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1550
}
1551
1552
/// Test parsing an `if let case` statement with an `else if` chain.
1553
@test unsafe fn testParseIfCaseElseIf() throws (testing::TestError) {
1554
    let root = try! parseStmtStr(
1555
        "if let case pat = value { body; } else if cond { alt; }"
1556
    );
1557
    let case ast::NodeValue::IfLet(node) = root.value
1558
        else throw testing::TestError::Failed;
1559
1560
    let elseBranch = node.elseBranch
1561
        else throw testing::TestError::Failed;
1562
1563
    let nested = try getBlockFirstStmt(elseBranch);
1564
    let case ast::NodeValue::If(inner) = nested.value
1565
        else throw testing::TestError::Failed;
1566
1567
    try expectIdent(inner.condition, "cond");
1568
    try expectBlockExprStmt(inner.thenBranch, ast::NodeValue::Ident("alt"));
1569
    try testing::expect(inner.elseBranch == nil);
1570
}
1571
1572
/// Test parsing a simple `while` loop without an `else` branch.
1573
@test unsafe fn testParseWhile() throws (testing::TestError) {
1574
    let root = try! parseStmtStr("while cond { body; }");
1575
    let case ast::NodeValue::While(loopNode) = root.value
1576
        else throw testing::TestError::Failed;
1577
1578
    try expectIdent(loopNode.condition, "cond");
1579
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
1580
    try testing::expect(loopNode.elseBranch == nil);
1581
}
1582
1583
/// Test parsing a `while` loop with an `else` branch.
1584
@test unsafe fn testParseWhileElse() throws (testing::TestError) {
1585
    let root = try! parseStmtStr("while cond { body; } else { alt; }");
1586
    let case ast::NodeValue::While(loopNode) = root.value
1587
        else throw testing::TestError::Failed;
1588
1589
    try expectIdent(loopNode.condition, "cond");
1590
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
1591
1592
    let elseBranch = loopNode.elseBranch
1593
        else throw testing::TestError::Failed;
1594
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1595
}
1596
1597
/// Test parsing a simple `while let case` loop.
1598
@test unsafe fn testParseWhileCase() throws (testing::TestError) {
1599
    let root = try! parseStmtStr("while let case pat = value { body; }");
1600
    let case ast::NodeValue::WhileLet(node) = root.value
1601
        else throw testing::TestError::Failed;
1602
1603
    try expectIdent(node.pattern.pattern, "pat");
1604
    try expectIdent(node.pattern.scrutinee, "value");
1605
    try testing::expect(node.pattern.guard == nil);
1606
    try expectBlockExprStmt(node.body, ast::NodeValue::Ident("body"));
1607
    try testing::expect(node.elseBranch == nil);
1608
}
1609
1610
/// Test parsing a `while let case` loop with guard and else branches.
1611
@test unsafe fn testParseWhileCaseGuardElse() throws (testing::TestError) {
1612
    let root = try! parseStmtStr(
1613
        "while let case pat = value; guard { body; } else { alt; }"
1614
    );
1615
    let case ast::NodeValue::WhileLet(node) = root.value
1616
        else throw testing::TestError::Failed;
1617
1618
    let guard = node.pattern.guard
1619
        else throw testing::TestError::Failed;
1620
    try expectIdent(guard, "guard");
1621
1622
    try expectBlockExprStmt(node.body, ast::NodeValue::Ident("body"));
1623
1624
    let elseBranch = node.elseBranch
1625
        else throw testing::TestError::Failed;
1626
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
1627
}
1628
1629
/// Test parsing a simple `try` expression without catch.
1630
@test unsafe fn testParseTry() throws (testing::TestError) {
1631
    let root = try! parseExprStr("try value");
1632
    let case ast::NodeValue::Try(node) = root.value
1633
        else throw testing::TestError::Failed;
1634
1635
    try expectIdent(node.expr, "value");
1636
    try testing::expect(node.catches.len == 0);
1637
    try testing::expect(not node.shouldPanic);
1638
}
1639
1640
/// Test that `try?` consumes a unary operand.
1641
@test unsafe fn testParseTryOptionalUnary() throws (testing::TestError) {
1642
    let root = try! parseExprStr("try? -value");
1643
    let case ast::NodeValue::Try(node) = root.value
1644
        else throw testing::TestError::Failed;
1645
    let case ast::NodeValue::UnOp(neg) = node.expr.value
1646
        else throw testing::TestError::Failed;
1647
    try testing::expect(neg.op == ast::UnaryOp::Neg);
1648
    try expectIdent(neg.value, "value");
1649
    try testing::expect(node.returnsOptional);
1650
}
1651
1652
/// Test parsing a `try!` expression that panics on error.
1653
@test unsafe fn testParseTryBang() throws (testing::TestError) {
1654
    let root = try! parseExprStr("try! value");
1655
    let case ast::NodeValue::Try(node) = root.value
1656
        else throw testing::TestError::Failed;
1657
1658
    try expectIdent(node.expr, "value");
1659
    try testing::expect(node.catches.len == 0);
1660
    try testing::expect(node.shouldPanic);
1661
}
1662
1663
/// Test parsing a `try` expression with a `catch` block.
1664
@test unsafe fn testParseTryCatchBlock() throws (testing::TestError) {
1665
    let root = try! parseExprStr("try value catch { alt; }");
1666
    let case ast::NodeValue::Try(node) = root.value
1667
        else throw testing::TestError::Failed;
1668
1669
    try expectIdent(node.expr, "value");
1670
    try testing::expect(node.catches.len == 1);
1671
1672
    let case ast::NodeValue::CatchClause(clause) = node.catches[0].value
1673
        else throw testing::TestError::Failed;
1674
    try testing::expect(clause.binding == nil);
1675
    try testing::expect(clause.typeNode == nil);
1676
    try expectBlockExprStmt(clause.body, ast::NodeValue::Ident("alt"));
1677
}
1678
1679
/// Test that `catch` without a block is rejected.
1680
@test unsafe fn testParseTryCatchExprRejected() throws (testing::TestError) {
1681
    let parsed: ?*ast::Node = try? parseExprStr("try value catch alternate");
1682
    try testing::expect(parsed == nil);
1683
}
1684
1685
/// Test parsing a `break` statement.
1686
@test unsafe fn testParseBreak() throws (testing::TestError) {
1687
    let root = try! parseStmtStr("break");
1688
    let case ast::NodeValue::Break= root.value
1689
        else throw testing::TestError::Failed;
1690
}
1691
1692
/// Test parsing a `continue` statement.
1693
@test unsafe fn testParseContinue() throws (testing::TestError) {
1694
    let root = try! parseStmtStr("continue");
1695
    let case ast::NodeValue::Continue= root.value
1696
        else throw testing::TestError::Failed;
1697
}
1698
1699
/// Test parsing a `return` statement without value.
1700
@test unsafe fn testParseReturnVoid() throws (testing::TestError) {
1701
    let root = try! parseStmtStr("return");
1702
    let case ast::NodeValue::Return(retValue) = root.value
1703
        else throw testing::TestError::Failed;
1704
1705
    try testing::expect(retValue == nil);
1706
}
1707
1708
/// Test parsing a `return` statement with a value.
1709
@test unsafe fn testParseReturnValue() throws (testing::TestError) {
1710
    let root = try! parseStmtStr("return result");
1711
    let case ast::NodeValue::Return(retValue) = root.value
1712
        else throw testing::TestError::Failed;
1713
1714
    let value = retValue
1715
        else throw testing::TestError::Failed;
1716
    try expectIdent(value, "result");
1717
}
1718
1719
/// Test parsing a `throw` statement.
1720
@test unsafe fn testParseThrow() throws (testing::TestError) {
1721
    let root = try! parseStmtStr("throw error");
1722
    let case ast::NodeValue::Throw(throwExpr) = root.value
1723
        else throw testing::TestError::Failed;
1724
1725
    try expectIdent(throwExpr, "error");
1726
}
1727
1728
/// Test parsing a `panic` statement without a message.
1729
@test unsafe fn testParsePanicEmpty() throws (testing::TestError) {
1730
    let root = try! parseStmtStr("panic");
1731
    let case ast::NodeValue::Panic(panicMsg) = root.value
1732
        else throw testing::TestError::Failed;
1733
1734
    try testing::expect(panicMsg == nil);
1735
}
1736
1737
/// Test parsing a `panic` statement with a message.
1738
@test unsafe fn testParsePanicMessage() throws (testing::TestError) {
1739
    let root = try! parseStmtStr("panic \"something went wrong\"");
1740
    let case ast::NodeValue::Panic(panicMsg) = root.value
1741
        else throw testing::TestError::Failed;
1742
1743
    let message = panicMsg
1744
        else throw testing::TestError::Failed;
1745
    let case ast::NodeValue::String(msgStr) = message.value if mem::eq(msgStr, "something went wrong")
1746
        else throw testing::TestError::Failed;
1747
}
1748
1749
/// Test parsing a `panic` statement with braces.
1750
@test unsafe fn testParsePanicBraces() throws (testing::TestError) {
1751
    let root = try! parseStmtStr("panic { \"error\" }");
1752
    let case ast::NodeValue::Panic(panicMsg) = root.value
1753
        else throw testing::TestError::Failed;
1754
1755
    let message = panicMsg
1756
        else throw testing::TestError::Failed;
1757
    let case ast::NodeValue::String(msgStr) = message.value if mem::eq(msgStr, "error")
1758
        else throw testing::TestError::Failed;
1759
}
1760
1761
/// Test parsing a simple `match` statement with one case.
1762
@test unsafe fn testParseMatchSingle() throws (testing::TestError) {
1763
    let root = try! parseStmtStr("match subject { case pattern => body }");
1764
    let case ast::NodeValue::Match(sw) = root.value
1765
        else throw testing::TestError::Failed;
1766
1767
    try expectIdent(sw.subject, "subject");
1768
    try testing::expect(sw.prongs.len == 1);
1769
1770
    let caseNode = sw.prongs[0];
1771
    let case ast::NodeValue::MatchProng(prong) = caseNode.value
1772
        else throw testing::TestError::Failed;
1773
1774
    let case ast::ProngArm::Case(patterns) = prong.arm
1775
        else throw testing::TestError::Failed;
1776
    try testing::expect(patterns.len == 1);
1777
    try expectIdent(patterns[0], "pattern");
1778
    try testing::expect(prong.guard == nil);
1779
1780
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1781
        else throw testing::TestError::Failed;
1782
    let case ast::NodeValue::Ident(name) = bodyStmt.value
1783
        if mem::eq(name, "body")
1784
        else throw testing::TestError::Failed;
1785
}
1786
1787
/// Test parsing a `match` case with guard and multiple patterns.
1788
@test unsafe fn testParseMatchGuard() throws (testing::TestError) {
1789
    let root = try! parseStmtStr(
1790
        "match subject { case left, right if cond => handle }"
1791
    );
1792
    let case ast::NodeValue::Match(sw) = root.value
1793
        else throw testing::TestError::Failed;
1794
1795
    try testing::expect(sw.prongs.len == 1);
1796
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1797
        else throw testing::TestError::Failed;
1798
1799
    let case ast::ProngArm::Case(patterns) = prong.arm
1800
        else throw testing::TestError::Failed;
1801
    try testing::expect(patterns.len == 2);
1802
    try expectIdent(patterns[0], "left");
1803
    try expectIdent(patterns[1], "right");
1804
1805
    let guard = prong.guard
1806
        else throw testing::TestError::Failed;
1807
    try expectIdent(guard, "cond");
1808
}
1809
1810
/// Test parsing `match` prongs whose bodies omit trailing semicolons.
1811
@test unsafe fn testParseMatchReturnNoSemicolon() throws (testing::TestError) {
1812
    let root = try! parseStmtStr(
1813
        "match subject { case First => return, case Second => return }"
1814
    );
1815
    let case ast::NodeValue::Match(sw) = root.value
1816
        else throw testing::TestError::Failed;
1817
1818
    try testing::expect(sw.prongs.len == 2);
1819
1820
    let firstCaseNode = sw.prongs[0];
1821
    let case ast::NodeValue::MatchProng(firstProng) = firstCaseNode.value
1822
        else throw testing::TestError::Failed;
1823
    let case ast::NodeValue::Return(firstRetVal) = firstProng.body.value
1824
        else throw testing::TestError::Failed;
1825
    try testing::expect(firstRetVal == nil);
1826
1827
    let secondCaseNode = sw.prongs[1];
1828
    let case ast::NodeValue::MatchProng(secondProng) = secondCaseNode.value
1829
        else throw testing::TestError::Failed;
1830
    let case ast::NodeValue::Return(secondRetVal) = secondProng.body.value
1831
        else throw testing::TestError::Failed;
1832
    try testing::expect(secondRetVal == nil);
1833
}
1834
1835
/// Test parsing a `match` statement with multiple branches.
1836
@test unsafe fn testParseMatchMultipleCases() throws (testing::TestError) {
1837
    let root = try! parseStmtStr(
1838
        "match subject { case First => first, case Second => second }"
1839
    );
1840
    let case ast::NodeValue::Match(sw) = root.value
1841
        else throw testing::TestError::Failed;
1842
1843
    try testing::expect(sw.prongs.len == 2);
1844
    {
1845
        let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1846
            else throw testing::TestError::Failed;
1847
        let case ast::ProngArm::Case(patterns) = prong.arm
1848
            else throw testing::TestError::Failed;
1849
        try testing::expect(patterns.len == 1);
1850
        try expectIdent(patterns[0], "First");
1851
        let case ast::NodeValue::ExprStmt(stmt) = prong.body.value
1852
            else throw testing::TestError::Failed;
1853
        let case ast::NodeValue::Ident(val) = stmt.value
1854
            if mem::eq(val, "first")
1855
            else throw testing::TestError::Failed;
1856
    } {
1857
        let case ast::NodeValue::MatchProng(prong) = sw.prongs[1].value
1858
            else throw testing::TestError::Failed;
1859
        let case ast::ProngArm::Case(pats) = prong.arm
1860
            else throw testing::TestError::Failed;
1861
1862
        try testing::expect(pats.len == 1);
1863
        try expectIdent(pats[0], "Second");
1864
1865
        let case ast::NodeValue::ExprStmt(stmt) = prong.body.value
1866
            else throw testing::TestError::Failed;
1867
        let case ast::NodeValue::Ident(val) = stmt.value
1868
            if mem::eq(val, "second")
1869
            else throw testing::TestError::Failed;
1870
    }
1871
}
1872
1873
/// Test parsing a `match` case whose body is a block.
1874
@test unsafe fn testParseMatchProngBlock() throws (testing::TestError) {
1875
    let root = try! parseStmtStr("match subject { case Pattern => { 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
    try expectBlockExprStmt(prong.body, ast::NodeValue::Ident("body"));
1883
}
1884
1885
/// Test parsing a `match` statement with an `else` case.
1886
@test unsafe fn testParseMatchElse() throws (testing::TestError) {
1887
    let root = try! parseStmtStr("match subject { else => body }");
1888
    let case ast::NodeValue::Match(sw) = root.value
1889
        else throw testing::TestError::Failed;
1890
1891
    try testing::expect(sw.prongs.len == 1);
1892
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1893
        else throw testing::TestError::Failed;
1894
    // Else prong has no pattern.
1895
    let case ast::ProngArm::Else = prong.arm
1896
        else throw testing::TestError::Failed;
1897
    try testing::expect(prong.guard == nil);
1898
1899
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1900
        else throw testing::TestError::Failed;
1901
    let case ast::NodeValue::Ident(name) = bodyStmt.value
1902
        if mem::eq(name, "body")
1903
        else throw testing::TestError::Failed;
1904
}
1905
1906
/// Test parsing a `match` statement with a binding prong.
1907
@test unsafe fn testParseMatchBinding() throws (testing::TestError) {
1908
    let root = try! parseStmtStr("match subject { x => body }");
1909
    let case ast::NodeValue::Match(sw) = root.value
1910
        else throw testing::TestError::Failed;
1911
1912
    try testing::expect(sw.prongs.len == 1);
1913
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1914
        else throw testing::TestError::Failed;
1915
    // Binding prong has single identifier pattern.
1916
    let case ast::ProngArm::Binding(pat) = prong.arm
1917
        else throw testing::TestError::Failed;
1918
    try expectIdent(pat, "x");
1919
    try testing::expect(prong.guard == nil);
1920
1921
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1922
        else throw testing::TestError::Failed;
1923
    try expectIdent(bodyStmt, "body");
1924
}
1925
1926
/// Test parsing a `match` statement with a guarded binding prong.
1927
@test unsafe fn testParseMatchBindingGuard() throws (testing::TestError) {
1928
    let root = try! parseStmtStr("match subject { x if x > 0 => body }");
1929
    let case ast::NodeValue::Match(sw) = root.value
1930
        else throw testing::TestError::Failed;
1931
1932
    try testing::expect(sw.prongs.len == 1);
1933
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1934
        else throw testing::TestError::Failed;
1935
    // Binding prong has single identifier pattern.
1936
    let case ast::ProngArm::Binding(pat) = prong.arm
1937
        else throw testing::TestError::Failed;
1938
    try expectIdent(pat, "x");
1939
1940
    let guard = prong.guard else throw testing::TestError::Failed;
1941
    let case ast::NodeValue::BinOp(binop) = guard.value
1942
        else throw testing::TestError::Failed;
1943
    try testing::expect(binop.op == ast::BinaryOp::Gt);
1944
}
1945
1946
/// Test parsing a `match` statement with a `_` wildcard.
1947
@test unsafe fn testParseMatchWildcard() throws (testing::TestError) {
1948
    let root = try! parseStmtStr("match subject { _ => body }");
1949
    let case ast::NodeValue::Match(sw) = root.value
1950
        else throw testing::TestError::Failed;
1951
1952
    try testing::expect(sw.prongs.len == 1);
1953
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1954
        else throw testing::TestError::Failed;
1955
    // Wildcard binding prong has single placeholder pattern.
1956
    let case ast::ProngArm::Binding(pat) = prong.arm
1957
        else throw testing::TestError::Failed;
1958
    let case ast::NodeValue::Placeholder = pat.value
1959
        else throw testing::TestError::Failed;
1960
    try testing::expect(prong.guard == nil);
1961
1962
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1963
        else throw testing::TestError::Failed;
1964
    try expectIdent(bodyStmt, "body");
1965
}
1966
1967
/// Test parsing a `match` statement with a guarded `_` wildcard.
1968
@test unsafe fn testParseMatchWildcardGuard() throws (testing::TestError) {
1969
    let root = try! parseStmtStr("match subject { _ if cond => body }");
1970
    let case ast::NodeValue::Match(sw) = root.value
1971
        else throw testing::TestError::Failed;
1972
1973
    try testing::expect(sw.prongs.len == 1);
1974
    let case ast::NodeValue::MatchProng(prong) = sw.prongs[0].value
1975
        else throw testing::TestError::Failed;
1976
    // Guarded wildcard binding prong has single placeholder pattern.
1977
    let case ast::ProngArm::Binding(pat) = prong.arm
1978
        else throw testing::TestError::Failed;
1979
    let case ast::NodeValue::Placeholder = pat.value
1980
        else throw testing::TestError::Failed;
1981
1982
    let guard = prong.guard else throw testing::TestError::Failed;
1983
    try expectIdent(guard, "cond");
1984
    let case ast::NodeValue::ExprStmt(bodyStmt) = prong.body.value
1985
        else throw testing::TestError::Failed;
1986
    try expectIdent(bodyStmt, "body");
1987
}
1988
1989
/// Test parsing a `while let` loop with guard and else branches.
1990
@test unsafe fn testParseWhileLet() throws (testing::TestError) {
1991
    let root = try! parseStmtStr(
1992
        "while let value = opt; guard { body; } else { alt; }"
1993
    );
1994
    let case ast::NodeValue::WhileLet(loopNode) = root.value
1995
        else throw testing::TestError::Failed;
1996
1997
    try expectIdent(loopNode.pattern.pattern, "value");
1998
    try expectIdent(loopNode.pattern.scrutinee, "opt");
1999
2000
    let guard = loopNode.pattern.guard
2001
        else throw testing::TestError::Failed;
2002
    try expectIdent(guard, "guard");
2003
2004
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
2005
2006
    let elseBranch = loopNode.elseBranch
2007
        else throw testing::TestError::Failed;
2008
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
2009
}
2010
2011
/// Test parsing a simple `loop` statement.
2012
@test unsafe fn testParseLoop() throws (testing::TestError) {
2013
    let root = try! parseStmtStr("loop { body; }");
2014
    let case ast::NodeValue::Loop(loopBody) = root.value
2015
        else throw testing::TestError::Failed;
2016
2017
    try expectBlockExprStmt(loopBody, ast::NodeValue::Ident("body"));
2018
}
2019
2020
/// Test parsing a `for` loop without index or else branches.
2021
@test unsafe fn testParseFor() throws (testing::TestError) {
2022
    let root = try! parseStmtStr("for item in items { body; }");
2023
    let case ast::NodeValue::For(loopNode) = root.value
2024
        else throw testing::TestError::Failed;
2025
2026
    try expectIdent(loopNode.binding, "item");
2027
    try testing::expect(loopNode.index == nil);
2028
2029
    try expectIdent(loopNode.iterable, "items");
2030
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
2031
    try testing::expect(loopNode.elseBranch == nil);
2032
}
2033
2034
/// Test parsing a `for` loop over a range expression.
2035
@test unsafe fn testParseForRangeIterable() throws (testing::TestError) {
2036
    let root = try! parseStmtStr("for item in 0..5 {}");
2037
    let case ast::NodeValue::For(loopNode) = root.value
2038
        else throw testing::TestError::Failed;
2039
2040
    try expectIdent(loopNode.binding, "item");
2041
    try testing::expect(loopNode.index == nil);
2042
    try expectRangeNumbers(loopNode.iterable, "0", "5");
2043
2044
    let case ast::NodeValue::Block(body) = loopNode.body.value
2045
        else throw testing::TestError::Failed;
2046
    try testing::expect(body.statements.len == 0);
2047
    try testing::expect(loopNode.elseBranch == nil);
2048
}
2049
2050
/// Test parsing a `for` loop with index and else branches.
2051
@test unsafe fn testParseForIndexElse() throws (testing::TestError) {
2052
    let root = try! parseStmtStr(
2053
        "for value, idx in items { body; } else { alt; }"
2054
    );
2055
    let case ast::NodeValue::For(loopNode) = root.value
2056
        else throw testing::TestError::Failed;
2057
2058
    try expectIdent(loopNode.binding, "value");
2059
2060
    let index = loopNode.index
2061
        else throw testing::TestError::Failed;
2062
    try expectIdent(index, "idx");
2063
2064
    try expectIdent(loopNode.iterable, "items");
2065
    try expectBlockExprStmt(loopNode.body, ast::NodeValue::Ident("body"));
2066
2067
    let elseBranch = loopNode.elseBranch
2068
        else throw testing::TestError::Failed;
2069
    try expectBlockExprStmt(elseBranch, ast::NodeValue::Ident("alt"));
2070
}
2071
2072
/// Test parsing field access expression.
2073
@test unsafe fn testParseFieldAccess() throws (testing::TestError) {
2074
    let root = try! parseExprStr("obj.field");
2075
    let case ast::NodeValue::FieldAccess(access) = root.value
2076
        else throw testing::TestError::Failed;
2077
2078
    try expectIdent(access.parent, "obj");
2079
    try expectIdent(access.child, "field");
2080
}
2081
2082
/// Test parsing scope access expression.
2083
@test unsafe fn testParseScopeAccess() throws (testing::TestError) {
2084
    let root = try! parseExprStr("module::item");
2085
    let case ast::NodeValue::ScopeAccess(access) = root.value
2086
        else throw testing::TestError::Failed;
2087
2088
    try expectIdent(access.parent, "module");
2089
    try expectIdent(access.child, "item");
2090
}
2091
2092
/// Test parsing array subscript expression.
2093
@test unsafe fn testParseArraySubscript() throws (testing::TestError) {
2094
    let root = try! parseExprStr("array[index]");
2095
    let case ast::NodeValue::Subscript { container, index } = root.value
2096
        else throw testing::TestError::Failed;
2097
2098
    try expectIdent(container, "array");
2099
    try expectIdent(index, "index");
2100
}
2101
2102
/// Test parsing array slicing expressions.
2103
@test unsafe fn testParseArraySlicing() throws (testing::TestError) {
2104
    // Test `array[start..end]`.
2105
    {
2106
        let expr = try! parseExprStr("array[1..10]");
2107
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2108
            else throw testing::TestError::Failed;
2109
        try expectIdent(subContainer, "array");
2110
2111
        let case ast::NodeValue::Range(range) = subIndex.value
2112
            else throw testing::TestError::Failed;
2113
        let start = range.start
2114
            else throw testing::TestError::Failed;
2115
        let end = range.end
2116
            else throw testing::TestError::Failed;
2117
        try expectNumber(start, "1");
2118
        try expectNumber(end, "10");
2119
    }
2120
    // Test `array[start..]`.
2121
    {
2122
        let expr = try! parseExprStr("array[5..]");
2123
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2124
            else throw testing::TestError::Failed;
2125
        try expectIdent(subContainer, "array");
2126
2127
        let case ast::NodeValue::Range(range) = subIndex.value
2128
            else throw testing::TestError::Failed;
2129
        let start = range.start
2130
            else throw testing::TestError::Failed;
2131
        try expectNumber(start, "5");
2132
        try testing::expect(range.end == nil);
2133
    }
2134
    // Test `array[..end]`.
2135
    {
2136
        let expr = try! parseExprStr("array[..10]");
2137
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2138
            else throw testing::TestError::Failed;
2139
        try expectIdent(subContainer, "array");
2140
2141
        let case ast::NodeValue::Range(range) = subIndex.value
2142
            else throw testing::TestError::Failed;
2143
        try testing::expect(range.start == nil);
2144
        let end = range.end
2145
            else throw testing::TestError::Failed;
2146
        try expectNumber(end, "10");
2147
    }
2148
    // Test `array[..]`.
2149
    {
2150
        let expr = try! parseExprStr("array[..]");
2151
        let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = expr.value
2152
            else throw testing::TestError::Failed;
2153
        try expectIdent(subContainer, "array");
2154
2155
        let case ast::NodeValue::Range(range) = subIndex.value
2156
            else throw testing::TestError::Failed;
2157
        try testing::expect(range.start == nil);
2158
        try testing::expect(range.end == nil);
2159
    }
2160
}
2161
2162
/// Test parsing function call expression.
2163
@test unsafe fn testParseFunctionCall() throws (testing::TestError) {
2164
    let root = try! parseExprStr("func(x, y)");
2165
    let case ast::NodeValue::Call(call) = root.value
2166
        else throw testing::TestError::Failed;
2167
2168
    try expectIdent(call.callee, "func");
2169
    try testing::expect(call.args.len == 2);
2170
    try expectIdent(call.args[0], "x");
2171
    try expectIdent(call.args[1], "y");
2172
}
2173
2174
/// Test parsing chained postfix operators.
2175
@test unsafe fn testParseChainedPostfix() throws (testing::TestError) {
2176
    let root = try! parseExprStr("obj.method(arg)[0]");
2177
    let case ast::NodeValue::Subscript { container: subContainer, index: subIndex } = root.value
2178
        else throw testing::TestError::Failed;
2179
2180
    let case ast::NodeValue::Call(call) = subContainer.value
2181
        else throw testing::TestError::Failed;
2182
2183
    let case ast::NodeValue::FieldAccess(fieldAccess) = call.callee.value
2184
        else throw testing::TestError::Failed;
2185
2186
    try expectIdent(fieldAccess.parent, "obj");
2187
    try expectIdent(fieldAccess.child, "method");
2188
    try testing::expect(call.args.len == 1);
2189
    try expectIdent(call.args[0], "arg");
2190
}
2191
2192
/// Test parsing a literal cast using `as`.
2193
@test unsafe fn testParseAsCastLiteral() throws (testing::TestError) {
2194
    let root = try! parseExprStr("1 as i32");
2195
    let case ast::NodeValue::As(asExpr) = root.value
2196
        else throw testing::TestError::Failed;
2197
2198
    let case ast::NodeValue::Number(_) = asExpr.value.value
2199
        else throw testing::TestError::Failed;
2200
2201
    try expectIntType(asExpr.type, 4, ast::Signedness::Signed);
2202
}
2203
2204
/// Test parsing a cast following chained postfix expressions.
2205
@test unsafe fn testParseAsCastWithPostfix() throws (testing::TestError) {
2206
    let root = try! parseExprStr("value.method(arg) as u32");
2207
    let case ast::NodeValue::As(asExpr) = root.value
2208
        else throw testing::TestError::Failed;
2209
2210
    let case ast::NodeValue::Call(call) = asExpr.value.value
2211
        else throw testing::TestError::Failed;
2212
2213
    let case ast::NodeValue::FieldAccess(access) = call.callee.value
2214
        else throw testing::TestError::Failed;
2215
2216
    try expectIdent(access.parent, "value");
2217
    try expectIdent(access.child, "method");
2218
    try testing::expect(call.args.len == 1);
2219
    try expectIdent(call.args[0], "arg");
2220
    try expectIntType(asExpr.type, 4, ast::Signedness::Unsigned);
2221
}
2222
2223
/// Test parsing @sizeOf builtin.
2224
@test unsafe fn testParseBuiltinSizeOf() throws (testing::TestError) {
2225
    let expr = try! parseExprStr("@sizeOf(i32)");
2226
    let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2227
        else throw testing::TestError::Failed;
2228
2229
    try testing::expect(builtinKind == ast::Builtin::SizeOf);
2230
    try testing::expect(builtinArgs.len == 1);
2231
    try expectType(builtinArgs[0], ast::TypeSig::Integer {
2232
        width: 4,
2233
        sign: ast::Signedness::Signed,
2234
    });
2235
}
2236
2237
/// Test parsing @alignOf builtin.
2238
@test unsafe fn testParseBuiltinAlignOf() throws (testing::TestError) {
2239
    let expr = try! parseExprStr("@alignOf(i32)");
2240
    let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2241
        else throw testing::TestError::Failed;
2242
2243
    try testing::expect(builtinKind == ast::Builtin::AlignOf);
2244
    try testing::expect(builtinArgs.len == 1);
2245
    try expectType(builtinArgs[0], ast::TypeSig::Integer {
2246
        width: 4,
2247
        sign: ast::Signedness::Signed,
2248
    });
2249
}
2250
2251
/// Test parsing @sliceOf with varying argument counts.
2252
@test unsafe fn testParseBuiltinSliceOf() throws (testing::TestError) {
2253
    // Two arguments.
2254
    {
2255
        let expr = try! parseExprStr("@sliceOf(ptr, len)");
2256
        let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2257
            else throw testing::TestError::Failed;
2258
        try testing::expect(builtinKind == ast::Builtin::SliceOf);
2259
        try testing::expect(builtinArgs.len == 2);
2260
    }
2261
    // One argument.
2262
    {
2263
        let expr = try! parseExprStr("@sliceOf(ptr)");
2264
        let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2265
            else throw testing::TestError::Failed;
2266
        try testing::expect(builtinKind == ast::Builtin::SliceOf);
2267
        try testing::expect(builtinArgs.len == 1);
2268
    }
2269
    // Three arguments.
2270
    {
2271
        let expr = try! parseExprStr("@sliceOf(ptr, len, extra)");
2272
        let case ast::NodeValue::BuiltinCall { kind: builtinKind, args: builtinArgs } = expr.value
2273
            else throw testing::TestError::Failed;
2274
        try testing::expect(builtinKind == ast::Builtin::SliceOf);
2275
        try testing::expect(builtinArgs.len == 3);
2276
    }
2277
}
2278
2279
/// Test parsing prefix unary operators.
2280
@test unsafe fn testParseUnaryOperators() throws (testing::TestError) {
2281
    {
2282
        let notExpr = try! parseExprStr("not flag");
2283
        let case ast::NodeValue::UnOp(notNode) = notExpr.value
2284
            else throw testing::TestError::Failed;
2285
        try testing::expect(notNode.op == ast::UnaryOp::Not);
2286
        try expectIdent(notNode.value, "flag");
2287
    }
2288
    {
2289
        let negExpr = try! parseExprStr("-value");
2290
        let case ast::NodeValue::UnOp(negNode) = negExpr.value
2291
            else throw testing::TestError::Failed;
2292
        try testing::expect(negNode.op == ast::UnaryOp::Neg);
2293
        try expectIdent(negNode.value, "value");
2294
    }
2295
    {
2296
        let bitNotExpr = try! parseExprStr("~mask");
2297
        let case ast::NodeValue::UnOp(bitNotNode) = bitNotExpr.value
2298
            else throw testing::TestError::Failed;
2299
        try testing::expect(bitNotNode.op == ast::UnaryOp::BitNot);
2300
        try expectIdent(bitNotNode.value, "mask");
2301
    }
2302
}
2303
2304
/// Test parsing dereference expressions.
2305
@test unsafe fn testParseDereference() throws (testing::TestError) {
2306
    {
2307
        let derefExpr = try! parseExprStr("*ptr");
2308
        let case ast::NodeValue::Deref(target) = derefExpr.value
2309
            else throw testing::TestError::Failed;
2310
        try expectIdent(target, "ptr");
2311
    }
2312
    {
2313
        let derefField = try! parseExprStr("*ptr.field");
2314
        let case ast::NodeValue::Deref(target) = derefField.value
2315
            else throw testing::TestError::Failed;
2316
        let case ast::NodeValue::FieldAccess(access) = target.value
2317
            else throw testing::TestError::Failed;
2318
        try expectIdent(access.parent, "ptr");
2319
        try expectIdent(access.child, "field");
2320
    }
2321
}
2322
2323
/// Test parsing reference (address-of) expressions.
2324
@test unsafe fn testParseRefs() throws (testing::TestError) {
2325
    {
2326
        let expr = try! parseExprStr("&cell obj.field");
2327
        let case ast::NodeValue::AddressOf(address) = expr.value
2328
            else throw testing::TestError::Failed;
2329
        try testing::expect(
2330
            address.kind == ast::AddressKind::Cell and address.permission == nil
2331
        );
2332
        let case ast::NodeValue::FieldAccess(access) = address.target.value
2333
            else throw testing::TestError::Failed;
2334
        try expectIdent(access.parent, "obj");
2335
        try expectIdent(access.child, "field");
2336
    }
2337
    {
2338
        let expr = try! parseExprStr("&cell 'permission obj.field");
2339
        let case ast::NodeValue::AddressOf(address) = expr.value
2340
            else throw testing::TestError::Failed;
2341
        let permission = address.permission else throw testing::TestError::Failed;
2342
        let case ast::NodeValue::Region { name, parent: nil } = permission.value
2343
            else throw testing::TestError::Failed;
2344
        try testing::expect(
2345
            address.kind == ast::AddressKind::Cell and mem::eq(name, "'permission")
2346
        );
2347
        let case ast::NodeValue::FieldAccess(access) = address.target.value
2348
            else throw testing::TestError::Failed;
2349
        try expectIdent(access.parent, "obj");
2350
        try expectIdent(access.child, "field");
2351
    }
2352
    {
2353
        let refExpr = try! parseExprStr("&foo");
2354
        let case ast::NodeValue::AddressOf(refNode) = refExpr.value
2355
            else throw testing::TestError::Failed;
2356
        try testing::expect(
2357
            refNode.kind == ast::AddressKind::Shared and refNode.permission == nil
2358
        );
2359
        try expectIdent(refNode.target, "foo");
2360
    }
2361
    {
2362
        let mutRefExpr = try! parseExprStr("&mut bar");
2363
        let case ast::NodeValue::AddressOf(mutRefNode) = mutRefExpr.value
2364
            else throw testing::TestError::Failed;
2365
        try testing::expect(
2366
            mutRefNode.kind == ast::AddressKind::Mutable and mutRefNode.permission == nil
2367
        );
2368
        try expectIdent(mutRefNode.target, "bar");
2369
    }
2370
    {
2371
        let refFieldExpr = try! parseExprStr("&obj.field");
2372
        let case ast::NodeValue::AddressOf(refFieldNode) = refFieldExpr.value
2373
            else throw testing::TestError::Failed;
2374
        try testing::expect(
2375
            refFieldNode.kind == ast::AddressKind::Shared and refFieldNode.permission == nil
2376
        );
2377
        let case ast::NodeValue::FieldAccess(access) = refFieldNode.target.value
2378
            else throw testing::TestError::Failed;
2379
        try expectIdent(access.parent, "obj");
2380
        try expectIdent(access.child, "field");
2381
    }
2382
    {
2383
        let mutRefFieldExpr = try! parseExprStr("&mut obj.field");
2384
        let case ast::NodeValue::AddressOf(mutRefFieldNode) = mutRefFieldExpr.value
2385
            else throw testing::TestError::Failed;
2386
        try testing::expect(
2387
            mutRefFieldNode.kind == ast::AddressKind::Mutable
2388
            and mutRefFieldNode.permission == nil
2389
        );
2390
        let case ast::NodeValue::FieldAccess(access) = mutRefFieldNode.target.value
2391
            else throw testing::TestError::Failed;
2392
        try expectIdent(access.parent, "obj");
2393
        try expectIdent(access.child, "field");
2394
    }
2395
    for source in ["&'permission obj.field", "&mut 'permission obj.field"] {
2396
        let parsed = try? parseExprStr(source);
2397
        try testing::expect(parsed == nil);
2398
    }
2399
}
2400
2401
/// Test unary operator precedence relative to binary and postfix expressions.
2402
@test unsafe fn testParseUnaryPrecedence() throws (testing::TestError) {
2403
    {
2404
        let expr = try! parseExprStr("not a and b");
2405
        let case ast::NodeValue::BinOp(bin) = expr.value
2406
            else throw testing::TestError::Failed;
2407
        try testing::expect(bin.op == ast::BinaryOp::And);
2408
        let case ast::NodeValue::UnOp(leftUnary) = bin.left.value
2409
            else throw testing::TestError::Failed;
2410
        try testing::expect(leftUnary.op == ast::UnaryOp::Not);
2411
        try expectIdent(leftUnary.value, "a");
2412
        try expectIdent(bin.right, "b");
2413
    }
2414
    {
2415
        let mulExpr = try! parseExprStr("-x * y");
2416
        let case ast::NodeValue::BinOp(mul) = mulExpr.value
2417
            else throw testing::TestError::Failed;
2418
        try testing::expect(mul.op == ast::BinaryOp::Mul);
2419
        let case ast::NodeValue::UnOp(leftNeg) = mul.left.value
2420
            else throw testing::TestError::Failed;
2421
        try testing::expect(leftNeg.op == ast::UnaryOp::Neg);
2422
        try expectIdent(leftNeg.value, "x");
2423
        try expectIdent(mul.right, "y");
2424
    }
2425
    {
2426
        let callExpr = try! parseExprStr("not func()");
2427
        let case ast::NodeValue::UnOp(callNot) = callExpr.value
2428
            else throw testing::TestError::Failed;
2429
        try testing::expect(callNot.op == ast::UnaryOp::Not);
2430
        let case ast::NodeValue::Call(call) = callNot.value.value
2431
            else throw testing::TestError::Failed;
2432
        try expectIdent(call.callee, "func");
2433
    }
2434
}
2435
2436
/// Test parsing assignment expressions.
2437
@test unsafe fn testParseAssignment() throws (testing::TestError) {
2438
    {
2439
        let assign = try! parseStmtStr("set x = 1;");
2440
        let case ast::NodeValue::Assign(node) = assign.value
2441
            else throw testing::TestError::Failed;
2442
        try expectIdent(node.left, "x");
2443
        let case ast::NodeValue::Number(_) = node.right.value
2444
            else throw testing::TestError::Failed;
2445
    }
2446
    {
2447
        let assign = try! parseStmtStr("set obj.field = value;");
2448
        let case ast::NodeValue::Assign(node) = assign.value
2449
            else throw testing::TestError::Failed;
2450
        let case ast::NodeValue::FieldAccess(access) = node.left.value
2451
            else throw testing::TestError::Failed;
2452
        try expectIdent(access.parent, "obj");
2453
        try expectIdent(access.child, "field");
2454
        try expectIdent(node.right, "value");
2455
    }
2456
    {
2457
        let assign = try! parseStmtStr("set *ptr = rhs;");
2458
        let case ast::NodeValue::Assign(node) = assign.value
2459
            else throw testing::TestError::Failed;
2460
        let case ast::NodeValue::Deref(target) = node.left.value
2461
            else throw testing::TestError::Failed;
2462
        try expectIdent(target, "ptr");
2463
        try expectIdent(node.right, "rhs");
2464
    }
2465
    {
2466
        let assign = try! parseStmtStr("set x = 1 + 2;");
2467
        let case ast::NodeValue::Assign(node) = assign.value
2468
            else throw testing::TestError::Failed;
2469
        let case ast::NodeValue::BinOp(bin) = node.right.value
2470
            else throw testing::TestError::Failed;
2471
        try testing::expect(bin.op == ast::BinaryOp::Add);
2472
    }
2473
    {
2474
        let assign = try! parseStmtStr("set module::VAR = 1;");
2475
        let case ast::NodeValue::Assign(node) = assign.value
2476
            else throw testing::TestError::Failed;
2477
        let case ast::NodeValue::ScopeAccess(access) = node.left.value
2478
            else throw testing::TestError::Failed;
2479
        try expectIdent(access.parent, "module");
2480
        try expectIdent(access.child, "VAR");
2481
    }
2482
}
2483
2484
/// Test that assignment syntax requires the `set` statement.
2485
@test unsafe fn testAssignmentRequiresSetKeyword() throws (testing::TestError) {
2486
    let assign: ?*ast::Node = try? parseStmtStr("x = 1;");
2487
    try testing::expect(assign == nil);
2488
2489
    let compoundAssign: ?*ast::Node = try? parseStmtStr("x += 1;");
2490
    try testing::expect(compoundAssign == nil);
2491
}
2492
2493
/// Test that `set` requires an assignable target.
2494
@test unsafe fn testSetRequiresAssignableTarget() throws (testing::TestError) {
2495
    let binTarget: ?*ast::Node = try? parseStmtStr("set x + y = 1;");
2496
    try testing::expect(binTarget == nil);
2497
2498
    let condTarget: ?*ast::Node = try? parseStmtStr("set x if ok else y = 1;");
2499
    try testing::expect(condTarget == nil);
2500
}
2501
2502
/// Test parsing basic arithmetic binary operators (+, -, *, /, %).
2503
@test unsafe fn testParseBinOpArithmetic() throws (testing::TestError) {
2504
    let add = try! parseExprStr("a + b");
2505
    let case ast::NodeValue::BinOp(op1) = add.value
2506
        else throw testing::TestError::Failed;
2507
    try testing::expect(op1.op == ast::BinaryOp::Add);
2508
    try expectIdent(op1.left, "a");
2509
    try expectIdent(op1.right, "b");
2510
2511
    let sub = try! parseExprStr("x - y");
2512
    let case ast::NodeValue::BinOp(op2) = sub.value
2513
        else throw testing::TestError::Failed;
2514
    try testing::expect(op2.op == ast::BinaryOp::Sub);
2515
2516
    let mul = try! parseExprStr("a * b");
2517
    let case ast::NodeValue::BinOp(op3) = mul.value
2518
        else throw testing::TestError::Failed;
2519
    try testing::expect(op3.op == ast::BinaryOp::Mul);
2520
2521
    let div = try! parseExprStr("x / y");
2522
    let case ast::NodeValue::BinOp(op4) = div.value
2523
        else throw testing::TestError::Failed;
2524
    try testing::expect(op4.op == ast::BinaryOp::Div);
2525
2526
    let modOp = try! parseExprStr("a % b");
2527
    let case ast::NodeValue::BinOp(op5) = modOp.value
2528
        else throw testing::TestError::Failed;
2529
    try testing::expect(op5.op == ast::BinaryOp::Mod);
2530
}
2531
2532
/// Test parsing comparison binary operators (==, <>).
2533
@test unsafe fn testParseBinOpEq() throws (testing::TestError) {
2534
    let eq = try! parseExprStr("a == b");
2535
    let case ast::NodeValue::BinOp(op1) = eq.value
2536
        else throw testing::TestError::Failed;
2537
    try testing::expect(op1.op == ast::BinaryOp::Eq);
2538
2539
    let ne = try! parseExprStr("x <> y");
2540
    let case ast::NodeValue::BinOp(op2) = ne.value
2541
        else throw testing::TestError::Failed;
2542
    try testing::expect(op2.op == ast::BinaryOp::Ne);
2543
}
2544
2545
/// Test parsing comparison binary operators.
2546
@test unsafe fn testParseBinOpGtLt() throws (testing::TestError) {
2547
    let lt = try! parseExprStr("a < b");
2548
    let case ast::NodeValue::BinOp(op1) = lt.value
2549
        else throw testing::TestError::Failed;
2550
    try testing::expect(op1.op == ast::BinaryOp::Lt);
2551
2552
    let gt = try! parseExprStr("x > y");
2553
    let case ast::NodeValue::BinOp(op2) = gt.value
2554
        else throw testing::TestError::Failed;
2555
    try testing::expect(op2.op == ast::BinaryOp::Gt);
2556
2557
    let lte = try! parseExprStr("a <= b");
2558
    let case ast::NodeValue::BinOp(op3) = lte.value
2559
        else throw testing::TestError::Failed;
2560
    try testing::expect(op3.op == ast::BinaryOp::Lte);
2561
2562
    let gte = try! parseExprStr("x >= y");
2563
    let case ast::NodeValue::BinOp(op4) = gte.value
2564
        else throw testing::TestError::Failed;
2565
    try testing::expect(op4.op == ast::BinaryOp::Gte);
2566
}
2567
2568
/// Test parsing bitwise binary operators (&, |, ^, <<, >>).
2569
@test unsafe fn testParseBinOpBitwise() throws (testing::TestError) {
2570
    let bitAnd = try! parseExprStr("a & b");
2571
    let case ast::NodeValue::BinOp(op1) = bitAnd.value
2572
        else throw testing::TestError::Failed;
2573
    try testing::expect(op1.op == ast::BinaryOp::BitAnd);
2574
2575
    let bitOr = try! parseExprStr("x | y");
2576
    let case ast::NodeValue::BinOp(op2) = bitOr.value
2577
        else throw testing::TestError::Failed;
2578
    try testing::expect(op2.op == ast::BinaryOp::BitOr);
2579
2580
    let bitXor = try! parseExprStr("a ^ b");
2581
    let case ast::NodeValue::BinOp(op3) = bitXor.value
2582
        else throw testing::TestError::Failed;
2583
    try testing::expect(op3.op == ast::BinaryOp::BitXor);
2584
2585
    let shl = try! parseExprStr("x << y");
2586
    let case ast::NodeValue::BinOp(op4) = shl.value
2587
        else throw testing::TestError::Failed;
2588
    try testing::expect(op4.op == ast::BinaryOp::Shl);
2589
2590
    let shr = try! parseExprStr("a >> b");
2591
    let case ast::NodeValue::BinOp(op5) = shr.value
2592
        else throw testing::TestError::Failed;
2593
    try testing::expect(op5.op == ast::BinaryOp::Shr);
2594
}
2595
2596
/// Test parsing logical binary operators (and, or).
2597
@test unsafe fn testParseBinOpLogical() throws (testing::TestError) {
2598
    let andOp = try! parseExprStr("a and b");
2599
    let case ast::NodeValue::BinOp(op1) = andOp.value
2600
        else throw testing::TestError::Failed;
2601
    try testing::expect(op1.op == ast::BinaryOp::And);
2602
    try expectIdent(op1.left, "a");
2603
    try expectIdent(op1.right, "b");
2604
2605
    let orOp = try! parseExprStr("x or y");
2606
    let case ast::NodeValue::BinOp(op2) = orOp.value
2607
        else throw testing::TestError::Failed;
2608
    try testing::expect(op2.op == ast::BinaryOp::Or);
2609
    try expectIdent(op2.left, "x");
2610
    try expectIdent(op2.right, "y");
2611
}
2612
2613
/// Test operator precedence: multiplication before addition.
2614
@test unsafe fn testParseBinOpPrecedenceMulAdd() throws (testing::TestError) {
2615
    let root = try! parseExprStr("a + b * c");
2616
    let case ast::NodeValue::BinOp(add) = root.value
2617
        else throw testing::TestError::Failed;
2618
2619
    try testing::expect(add.op == ast::BinaryOp::Add);
2620
    try expectIdent(add.left, "a");
2621
2622
    let case ast::NodeValue::BinOp(mul) = add.right.value
2623
        else throw testing::TestError::Failed;
2624
2625
    try testing::expect(mul.op == ast::BinaryOp::Mul);
2626
    try expectIdent(mul.left, "b");
2627
    try expectIdent(mul.right, "c");
2628
}
2629
2630
/// Test operator precedence: shifts before bitwise operations.
2631
@test unsafe fn testParseBinOpPrecedenceShiftBitwise() throws (testing::TestError) {
2632
    let root = try! parseExprStr("a & b << c");
2633
    let case ast::NodeValue::BinOp(bitAnd) = root.value
2634
        else throw testing::TestError::Failed;
2635
2636
    try testing::expect(bitAnd.op == ast::BinaryOp::BitAnd);
2637
    try expectIdent(bitAnd.left, "a");
2638
2639
    let case ast::NodeValue::BinOp(shl) = bitAnd.right.value
2640
        else throw testing::TestError::Failed;
2641
2642
    try testing::expect(shl.op == ast::BinaryOp::Shl);
2643
    try expectIdent(shl.left, "b");
2644
    try expectIdent(shl.right, "c");
2645
}
2646
2647
/// Test operator precedence: comparison before logical AND.
2648
@test unsafe fn testParseBinOpPrecedenceCompareLogical() throws (testing::TestError) {
2649
    let root = try! parseExprStr("a < b and c > d");
2650
    let case ast::NodeValue::BinOp(andOp) = root.value
2651
        else throw testing::TestError::Failed;
2652
2653
    try testing::expect(andOp.op == ast::BinaryOp::And);
2654
2655
    let case ast::NodeValue::BinOp(lt) = andOp.left.value
2656
        else throw testing::TestError::Failed;
2657
    try testing::expect(lt.op == ast::BinaryOp::Lt);
2658
    try expectIdent(lt.left, "a");
2659
    try expectIdent(lt.right, "b");
2660
2661
    let case ast::NodeValue::BinOp(gt) = andOp.right.value
2662
        else throw testing::TestError::Failed;
2663
    try testing::expect(gt.op == ast::BinaryOp::Gt);
2664
    try expectIdent(gt.left, "c");
2665
    try expectIdent(gt.right, "d");
2666
}
2667
2668
/// Test left associativity of addition.
2669
@test unsafe fn testParseBinOpAssociativityAdd() throws (testing::TestError) {
2670
    let root = try! parseExprStr("a + b + c");
2671
    let case ast::NodeValue::BinOp(add2) = root.value
2672
        else throw testing::TestError::Failed;
2673
2674
    try testing::expect(add2.op == ast::BinaryOp::Add);
2675
    try expectIdent(add2.right, "c");
2676
2677
    let case ast::NodeValue::BinOp(add1) = add2.left.value
2678
        else throw testing::TestError::Failed;
2679
    try testing::expect(add1.op == ast::BinaryOp::Add);
2680
    try expectIdent(add1.left, "a");
2681
    try expectIdent(add1.right, "b");
2682
}
2683
2684
/// Test complex expression with multiple operators and precedence.
2685
@test unsafe fn testParseBinOpComplex() throws (testing::TestError) {
2686
    let root = try! parseExprStr("a + b * c - d / e");
2687
    let case ast::NodeValue::BinOp(sub) = root.value
2688
        else throw testing::TestError::Failed;
2689
2690
    try testing::expect(sub.op == ast::BinaryOp::Sub);
2691
2692
    let case ast::NodeValue::BinOp(add) = sub.left.value
2693
        else throw testing::TestError::Failed;
2694
    try testing::expect(add.op == ast::BinaryOp::Add);
2695
    try expectIdent(add.left, "a");
2696
2697
    let case ast::NodeValue::BinOp(mul) = add.right.value
2698
        else throw testing::TestError::Failed;
2699
    try testing::expect(mul.op == ast::BinaryOp::Mul);
2700
2701
    let case ast::NodeValue::BinOp(div) = sub.right.value
2702
        else throw testing::TestError::Failed;
2703
    try testing::expect(div.op == ast::BinaryOp::Div);
2704
}
2705
2706
/// Test binary operators with parentheses override precedence.
2707
@test unsafe fn testParseBinOpParentheses() throws (testing::TestError) {
2708
    let root = try! parseExprStr("(a + b) * c");
2709
    let case ast::NodeValue::BinOp(mul) = root.value
2710
        else throw testing::TestError::Failed;
2711
2712
    try testing::expect(mul.op == ast::BinaryOp::Mul);
2713
    try expectIdent(mul.right, "c");
2714
2715
    let case ast::NodeValue::BinOp(add) = mul.left.value
2716
        else throw testing::TestError::Failed;
2717
    try testing::expect(add.op == ast::BinaryOp::Add);
2718
    try expectIdent(add.left, "a");
2719
    try expectIdent(add.right, "b");
2720
}
2721
2722
/// Test parsing a simple union without payloads.
2723
@test unsafe fn testParseEnumSimple() throws (testing::TestError) {
2724
    let node = try! parseStmtStr("union Color { Red, Green, Blue }");
2725
    let case ast::NodeValue::UnionDecl(decl) = node.value
2726
        else throw testing::TestError::Failed;
2727
2728
    try expectIdent(decl.name, "Color");
2729
    try testing::expect(decl.derives.len == 0);
2730
2731
    let variants = decl.variants;
2732
    try testing::expect(variants.len == 3);
2733
2734
    let v0 = variants[0];
2735
    let case ast::NodeValue::UnionDeclVariant(var0) = v0.value
2736
        else throw testing::TestError::Failed;
2737
    try expectIdent(var0.name, "Red");
2738
    try testing::expect(var0.index == 0);
2739
    try testing::expect(var0.type == nil);
2740
    try testing::expect(var0.value == nil);
2741
2742
    let v1 = variants[1];
2743
    let case ast::NodeValue::UnionDeclVariant(var1) = v1.value
2744
        else throw testing::TestError::Failed;
2745
    try expectIdent(var1.name, "Green");
2746
    try testing::expect(var1.index == 1);
2747
    try testing::expect(var1.type == nil);
2748
    try testing::expect(var1.value == nil);
2749
2750
    let v2 = variants[2];
2751
    let case ast::NodeValue::UnionDeclVariant(var2) = v2.value
2752
        else throw testing::TestError::Failed;
2753
    try expectIdent(var2.name, "Blue");
2754
    try testing::expect(var2.index == 2);
2755
    try testing::expect(var2.type == nil);
2756
    try testing::expect(var2.value == nil);
2757
}
2758
2759
/// Test parsing a union with trailing comma.
2760
@test unsafe fn testParseEnumTrailingComma() throws (testing::TestError) {
2761
    let node = try! parseStmtStr("union Letter { A, B, C, }");
2762
    let case ast::NodeValue::UnionDecl(decl) = node.value
2763
        else throw testing::TestError::Failed;
2764
2765
    try expectIdent(decl.name, "Letter");
2766
    try testing::expect(decl.variants.len == 3);
2767
}
2768
2769
/// Test parsing a union with explicit values.
2770
@test unsafe fn testParseEnumExplicitValues() throws (testing::TestError) {
2771
    let node = try! parseStmtStr("union Status { Ok = 0, Error = 1, Pending = 5 }");
2772
    let case ast::NodeValue::UnionDecl(decl) = node.value
2773
        else throw testing::TestError::Failed;
2774
2775
    try expectIdent(decl.name, "Status");
2776
2777
    let variants = decl.variants;
2778
    try testing::expect(variants.len == 3);
2779
2780
    let v0 = variants[0];
2781
    let case ast::NodeValue::UnionDeclVariant(var0) = v0.value
2782
        else throw testing::TestError::Failed;
2783
    try expectIdent(var0.name, "Ok");
2784
    try testing::expect(var0.index == 0);
2785
    try testing::expect(var0.type == nil);
2786
    try testing::expect(var0.value <> nil);
2787
2788
    let v1 = variants[1];
2789
    let case ast::NodeValue::UnionDeclVariant(var1) = v1.value
2790
        else throw testing::TestError::Failed;
2791
    try expectIdent(var1.name, "Error");
2792
    try testing::expect(var1.index == 1);
2793
    try testing::expect(var1.value <> nil);
2794
2795
    let v2 = variants[2];
2796
    let case ast::NodeValue::UnionDeclVariant(var2) = v2.value
2797
        else throw testing::TestError::Failed;
2798
    try expectIdent(var2.name, "Pending");
2799
    try testing::expect(var2.index == 2);
2800
    try testing::expect(var2.value <> nil);
2801
}
2802
2803
/// Test parsing a union with payload and tag-only variants.
2804
@test unsafe fn testParseEnumWithPayloads() throws (testing::TestError) {
2805
    let node = try! parseStmtStr("union Result { Ok(bool), Error }");
2806
    let case ast::NodeValue::UnionDecl(decl) = node.value
2807
        else throw testing::TestError::Failed;
2808
2809
    try expectIdent(decl.name, "Result");
2810
    try testing::expect(decl.variants.len == 2);
2811
2812
    let okFields = try expectVariant(decl.variants[0], "Ok", 0)
2813
        else throw testing::TestError::Failed;
2814
    try testing::expect(okFields.len == 1);
2815
    try expectFieldSig(okFields, 0, nil, ast::TypeSig::Bool);
2816
2817
    let errFields = try expectVariant(decl.variants[1], "Error", 1);
2818
    try testing::expect(errFields == nil);
2819
}
2820
2821
/// Test parsing a union with derives.
2822
@test unsafe fn testParseEnumWithDerives() throws (testing::TestError) {
2823
    let node = try! parseStmtStr("union Option: Debug + Eq { None, Some(i32) }");
2824
    let case ast::NodeValue::UnionDecl(decl) = node.value
2825
        else throw testing::TestError::Failed;
2826
2827
    try expectIdent(decl.name, "Option");
2828
    try testing::expect(decl.derives.len == 2);
2829
    try expectIdent(decl.derives[0], "Debug");
2830
    try expectIdent(decl.derives[1], "Eq");
2831
2832
    let variants = decl.variants;
2833
    try testing::expect(variants.len == 2);
2834
2835
    let v0 = variants[0];
2836
    let case ast::NodeValue::UnionDeclVariant(var0) = v0.value
2837
        else throw testing::TestError::Failed;
2838
    try expectIdent(var0.name, "None");
2839
    try testing::expect(var0.type == nil);
2840
2841
    let v1 = variants[1];
2842
    let case ast::NodeValue::UnionDeclVariant(var1) = v1.value
2843
        else throw testing::TestError::Failed;
2844
    try expectIdent(var1.name, "Some");
2845
    try testing::expect(var1.type <> nil);
2846
}
2847
2848
/// Test parsing named record literals with named fields.
2849
@test unsafe fn testParseNamedRecordLiteralNamed() throws (testing::TestError) {
2850
    let r1 = try! parseExprStr("Point { x: 5, y: 10 }");
2851
    let case ast::NodeValue::RecordLit(lit) = r1.value
2852
        else throw testing::TestError::Failed;
2853
2854
    let typeName = lit.typeName else throw testing::TestError::Failed;
2855
    try expectIdent(typeName, "Point");
2856
    try testing::expect(lit.fields.len == 2);
2857
2858
    let field0 = lit.fields[0];
2859
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2860
        else throw testing::TestError::Failed;
2861
    let label0 = arg0.label else throw testing::TestError::Failed;
2862
    try expectIdent(label0, "x");
2863
    try expectNumber(arg0.value, "5");
2864
}
2865
2866
/// Test parsing anonymous record literals with named fields.
2867
@test unsafe fn testParseAnonymousRecordLiteralNamed() throws (testing::TestError) {
2868
    let r1 = try! parseExprStr("{ x: 10, y: 20 }");
2869
    let case ast::NodeValue::RecordLit(lit) = r1.value
2870
        else throw testing::TestError::Failed;
2871
2872
    try testing::expect(lit.typeName == nil);
2873
    try testing::expect(lit.fields.len == 2);
2874
2875
    let field0 = lit.fields[0];
2876
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2877
        else throw testing::TestError::Failed;
2878
    let label0 = arg0.label else throw testing::TestError::Failed;
2879
    try expectIdent(label0, "x");
2880
    try expectNumber(arg0.value, "10");
2881
2882
    let field1 = lit.fields[1];
2883
    let case ast::NodeValue::RecordLitField(arg1) = field1.value
2884
        else throw testing::TestError::Failed;
2885
    let label1 = arg1.label else throw testing::TestError::Failed;
2886
    try expectIdent(label1, "y");
2887
    try expectNumber(arg1.value, "20");
2888
}
2889
2890
/// Test parsing record literals with shorthand field syntax.
2891
/// `{ x, y }` is equivalent to `{ x: x, y: y }`.
2892
@test unsafe fn testParseRecordLiteralShorthand() throws (testing::TestError) {
2893
    let r1 = try! parseExprStr("Point { x, y }");
2894
    let case ast::NodeValue::RecordLit(lit) = r1.value
2895
        else throw testing::TestError::Failed;
2896
2897
    let typeName = lit.typeName else throw testing::TestError::Failed;
2898
    try expectIdent(typeName, "Point");
2899
    try testing::expect(lit.fields.len == 2);
2900
2901
    // First field: shorthand `x`.
2902
    let field0 = lit.fields[0];
2903
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2904
        else throw testing::TestError::Failed;
2905
    let label0 = arg0.label else throw testing::TestError::Failed;
2906
    try expectIdent(label0, "x");
2907
    try expectIdent(arg0.value, "x");
2908
    // Label and value should point to the same node.
2909
    try testing::expect(label0 == arg0.value);
2910
2911
    // Second field: shorthand `y`.
2912
    let field1 = lit.fields[1];
2913
    let case ast::NodeValue::RecordLitField(arg1) = field1.value
2914
        else throw testing::TestError::Failed;
2915
    let label1 = arg1.label else throw testing::TestError::Failed;
2916
    try expectIdent(label1, "y");
2917
    try expectIdent(arg1.value, "y");
2918
    try testing::expect(label1 == arg1.value);
2919
}
2920
2921
/// Test parsing record literals with mixed shorthand and explicit fields.
2922
@test unsafe fn testParseRecordLiteralMixedShorthand() throws (testing::TestError) {
2923
    let r1 = try! parseExprStr("Point { x, y: 10 }");
2924
    let case ast::NodeValue::RecordLit(lit) = r1.value
2925
        else throw testing::TestError::Failed;
2926
2927
    try testing::expect(lit.fields.len == 2);
2928
2929
    // First field: shorthand `x`.
2930
    let field0 = lit.fields[0];
2931
    let case ast::NodeValue::RecordLitField(arg0) = field0.value
2932
        else throw testing::TestError::Failed;
2933
    let label0 = arg0.label else throw testing::TestError::Failed;
2934
    try expectIdent(label0, "x");
2935
    try expectIdent(arg0.value, "x");
2936
2937
    // Second field: explicit `y: 10`.
2938
    let field1 = lit.fields[1];
2939
    let case ast::NodeValue::RecordLitField(arg1) = field1.value
2940
        else throw testing::TestError::Failed;
2941
    let label1 = arg1.label else throw testing::TestError::Failed;
2942
    try expectIdent(label1, "y");
2943
    try expectNumber(arg1.value, "10");
2944
}
2945
2946
/// Test that positional brace initializers are rejected: `{ 1, 2 }`.
2947
@test unsafe fn testParsePositionalBraceInitializerAnonymous() throws (testing::TestError) {
2948
    let parsed: ?*ast::Node = try? parseExprStr("{ 1, 2 }");
2949
    try testing::expect(parsed == nil);
2950
}
2951
2952
/// Test that positional brace initializers are rejected: `Point { 1, 2 }`.
2953
@test unsafe fn testParsePositionalBraceInitializerNamed() throws (testing::TestError) {
2954
    let parsed: ?*ast::Node = try? parseExprStr("Point { 1, 2 }");
2955
    try testing::expect(parsed == nil);
2956
}
2957
2958
/// Test that mixed labeled/positional brace initializers are rejected: `Pt { x: 1, 2 }`.
2959
@test unsafe fn testParseMixedBraceInitializer() throws (testing::TestError) {
2960
    let parsed: ?*ast::Node = try? parseExprStr("Pt { x: 1, 2 }");
2961
    try testing::expect(parsed == nil);
2962
}
2963
2964
/// Unsafe statements have a block body.
2965
@test unsafe fn testParseUnsafeBlock() throws (testing::TestError) {
2966
    let parsed = try? parseStmtsStr("fn run() { unsafe { return; } }");
2967
    let root = parsed else throw testing::TestError::Failed;
2968
    let case ast::NodeValue::Block(module) = root.value
2969
        else throw testing::TestError::Failed;
2970
    let case ast::NodeValue::FnDecl(decl) = module.statements[0].value
2971
        else throw testing::TestError::Failed;
2972
    let fnBody = decl.body else throw testing::TestError::Failed;
2973
    let case ast::NodeValue::Block(body) = fnBody.value
2974
        else throw testing::TestError::Failed;
2975
    let case ast::NodeValue::Block(inner) = body.statements[0].value
2976
        else throw testing::TestError::Failed;
2977
    try testing::expect(not body.isUnsafe);
2978
    try testing::expect(inner.isUnsafe);
2979
}
2980
2981
/// Unsafe blocks do not accept declaration attributes.
2982
@test unsafe fn testUnsafeBlockAttributesRejected() throws (testing::TestError) {
2983
    let parsed = try? parseStmtsStr("fn run() { export unsafe {} }");
2984
    try testing::expect(parsed == nil);
2985
}
2986
2987
/// Unsafe static declarations carry an explicit access requirement.
2988
@test unsafe fn testParseUnsafeStatic() throws (testing::TestError) {
2989
    let parsed = try? parseStmtsStr("export unsafe static DATA: [u8; 4] = undefined;");
2990
    try testing::expect(parsed <> nil);
2991
}
2992
2993
@test unsafe fn testParseModule() throws (testing::TestError) {
2994
    let r = try! parseStmtsStr("fn f() {} fn g() {}");
2995
2996
    let case ast::NodeValue::Block(module) = r.value
2997
        else throw testing::TestError::Failed;
2998
    try testing::expect(module.statements.len == 2);
2999
3000
    let first = module.statements[0];
3001
    let case ast::NodeValue::FnDecl(fDecl) = first.value
3002
        else throw testing::TestError::Failed;
3003
    try expectIdent(fDecl.name, "f");
3004
3005
    let second = module.statements[1];
3006
    let case ast::NodeValue::FnDecl(gDecl) = second.value
3007
        else throw testing::TestError::Failed;
3008
    try expectIdent(gDecl.name, "g");
3009
}
3010
3011
/// Test parsing a simple conditional expression.
3012
@test unsafe fn testParseCondExpr() throws (testing::TestError) {
3013
    let r = try! parseExprStr("a if cond else b") catch {
3014
        throw testing::TestError::Failed;
3015
    };
3016
    let case ast::NodeValue::CondExpr(cond) = r.value
3017
        else throw testing::TestError::Failed;
3018
3019
    try expectIdent(cond.thenExpr, "a");
3020
    try expectIdent(cond.condition, "cond");
3021
    try expectIdent(cond.elseExpr, "b");
3022
}
3023
3024
/// Test parsing a conditional expression with `as` casts.
3025
@test unsafe fn testParseCondExprWithAsCast() throws (testing::TestError) {
3026
    let r = try! parseExprStr("x as i32 if cond else y as i32") catch {
3027
        throw testing::TestError::Failed;
3028
    };
3029
    let case ast::NodeValue::CondExpr(cond) = r.value
3030
        else throw testing::TestError::Failed;
3031
3032
    // Check thenExpr is an `as` cast.
3033
    let case ast::NodeValue::As(thenAs) = cond.thenExpr.value
3034
        else throw testing::TestError::Failed;
3035
    try expectIdent(thenAs.value, "x");
3036
    try expectIntType(thenAs.type, 4, ast::Signedness::Signed);
3037
3038
    // Check condition.
3039
    try expectIdent(cond.condition, "cond");
3040
3041
    // Check elseExpr is an `as` cast.
3042
    let case ast::NodeValue::As(elseAs) = cond.elseExpr.value
3043
        else throw testing::TestError::Failed;
3044
    try expectIdent(elseAs.value, "y");
3045
    try expectIntType(elseAs.type, 4, ast::Signedness::Signed);
3046
}
3047
3048
/// Test parsing a nested conditional expression (right-associative).
3049
@test unsafe fn testParseCondExprNested() throws (testing::TestError) {
3050
    let r = try! parseExprStr("a if x else b if y else c") catch {
3051
        throw testing::TestError::Failed;
3052
    };
3053
    let case ast::NodeValue::CondExpr(outer) = r.value
3054
        else throw testing::TestError::Failed;
3055
3056
    try expectIdent(outer.thenExpr, "a");
3057
    try expectIdent(outer.condition, "x");
3058
3059
    // The else branch should be another conditional expression.
3060
    let case ast::NodeValue::CondExpr(inner) = outer.elseExpr.value
3061
        else throw testing::TestError::Failed;
3062
3063
    try expectIdent(inner.thenExpr, "b");
3064
    try expectIdent(inner.condition, "y");
3065
    try expectIdent(inner.elseExpr, "c");
3066
}
3067
3068
/// Test that trailing commas are allowed in all comma-separated lists.
3069
@test unsafe fn testTrailingCommas() throws (testing::TestError) {
3070
    // Function call arguments.
3071
    let call = try! parseExprStr("f(1, 2, 3,)");
3072
    let case ast::NodeValue::Call(c) = call.value else throw testing::TestError::Failed;
3073
    try testing::expect(c.args.len == 3);
3074
3075
    // Function parameters.
3076
    let fnNode = try! parseStmtStr("fn add(x: i32, y: i32,) {}");
3077
    let case ast::NodeValue::FnDecl(fnDecl) = fnNode.value else throw testing::TestError::Failed;
3078
    try testing::expect(fnDecl.sig.params.len == 2);
3079
3080
    // Record declarations.
3081
    let recNode = try! parseStmtStr("record R { x: i32, y: bool, }");
3082
    let case ast::NodeValue::RecordDecl(recDecl) = recNode.value else throw testing::TestError::Failed;
3083
    try testing::expect(recDecl.fields.len == 2);
3084
3085
    // Tuple record declarations.
3086
    let tupNode = try! parseStmtStr("record R(i32, bool,);");
3087
    let case ast::NodeValue::RecordDecl(tupDecl) = tupNode.value else throw testing::TestError::Failed;
3088
    try testing::expect(tupDecl.fields.len == 2);
3089
3090
    // Record literals.
3091
    let litNode = try! parseExprStr("Point { x: 1, y: 2, }");
3092
    let case ast::NodeValue::RecordLit(lit) = litNode.value else throw testing::TestError::Failed;
3093
    try testing::expect(lit.fields.len == 2);
3094
3095
    // Union declarations.
3096
    let unionNode = try! parseStmtStr("union Color { Red, Green, Blue, }");
3097
    let case ast::NodeValue::UnionDecl(unionDecl) = unionNode.value else throw testing::TestError::Failed;
3098
    try testing::expect(unionDecl.variants.len == 3);
3099
3100
    // Array literals.
3101
    let arrNode = try! parseExprStr("[1, 2, 3,]");
3102
    let case ast::NodeValue::ArrayLit(items) = arrNode.value else throw testing::TestError::Failed;
3103
    try testing::expect(items.len == 3);
3104
3105
    // Function type parameters.
3106
    let fnType = try! parseTypeStr("fn (i32, bool,)");
3107
    let case ast::NodeValue::TypeSig(sigValue) = fnType.value else throw testing::TestError::Failed;
3108
    let case ast::TypeSig::Fn { sig, .. } = sigValue else throw testing::TestError::Failed;
3109
    try testing::expect(sig.params.len == 2);
3110
    try testing::expect(sig.returnType == nil);
3111
3112
    // Throws lists.
3113
    let throwsNode = try! parseStmtStr("fn handle() throws (Error, Other,) {}");
3114
    let case ast::NodeValue::FnDecl(throwsDecl) = throwsNode.value else throw testing::TestError::Failed;
3115
    try testing::expect(throwsDecl.sig.throwList.len == 2);
3116
}
3117
3118
/// Function declarations and function types accept never return annotations.
3119
@test unsafe fn testParseNeverReturn() throws (testing::TestError) {
3120
    let declNode = try! parseStmtStr("fn stop() -> ! { panic; }");
3121
    let case ast::NodeValue::FnDecl(decl) = declNode.value else throw testing::TestError::Failed;
3122
    let ret = decl.sig.returnType else throw testing::TestError::Failed;
3123
    assert ret.value == ast::NodeValue::TypeSig(ast::TypeSig::Never);
3124
    let fnNode = try! parseTypeStr("unsafe fn(u64) -> ! throws (Error)");
3125
    let case ast::NodeValue::TypeSig(ast::TypeSig::Fn { sig, isUnsafe }) = fnNode.value
3126
        else throw testing::TestError::Failed;
3127
    let fnRet = sig.returnType else throw testing::TestError::Failed;
3128
    assert isUnsafe and sig.params.len == 1 and sig.throwList.len == 1;
3129
    assert fnRet.value == ast::NodeValue::TypeSig(ast::TypeSig::Never);
3130
}
3131
3132
/// Unsafe function types preserve their call requirement and signature.
3133
@test unsafe fn testParseUnsafeFunctionType() throws (testing::TestError) {
3134
    let node = try! parseTypeStr("unsafe fn(&u32) -> u32 throws (Error)");
3135
    let case ast::NodeValue::TypeSig(ast::TypeSig::Fn { sig, isUnsafe }) = node.value
3136
        else throw testing::TestError::Failed;
3137
    assert isUnsafe;
3138
    assert sig.params.len == 1;
3139
    assert sig.returnType <> nil;
3140
    assert sig.throwList.len == 1;
3141
}
3142
3143
/// Region arguments on an inner type remain distinct from a reference region.
3144
@test unsafe fn testRegionReferenceTypes() throws (testing::TestError) {
3145
    let root = try! parseTypeStr("&'short mut Node 'arena");
3146
    let case ast::NodeValue::TypeSig(ast::TypeSig::RegionRef { region, type }) = root.value
3147
        else throw testing::TestError::Failed;
3148
    let case ast::NodeValue::Region { name, parent: nil } = region.value
3149
        else throw testing::TestError::Failed;
3150
    try testing::expect(mem::eq(name, "'short"));
3151
    let case ast::NodeValue::TypeSig(ast::TypeSig::Pointer { class, valueType, mutable }) = type.value
3152
        else throw testing::TestError::Failed;
3153
    try testing::expect(class == ast::PointerClass::Ref and mutable);
3154
    let case ast::NodeValue::TypeSig(ast::TypeSig::Applied { name: nominal, regions }) = valueType.value
3155
        else throw testing::TestError::Failed;
3156
    try expectIdent(nominal, "Node");
3157
    try testing::expect(regions.len == 1);
3158
    let case ast::NodeValue::Region { name: argument, .. } = regions[0].value
3159
        else throw testing::TestError::Failed;
3160
    try testing::expect(mem::eq(argument, "'arena"));
3161
    let slice = try! parseTypeStr("&'r [View 'a 'b]");
3162
    let case ast::NodeValue::TypeSig(ast::TypeSig::RegionRef { type: sliceType, .. }) = slice.value
3163
        else throw testing::TestError::Failed;
3164
    let case ast::NodeValue::TypeSig(ast::TypeSig::Slice { .. }) = sliceType.value
3165
        else throw testing::TestError::Failed;
3166
}
3167
3168
/// Declaration lists accept regions, parent relations, and ownership derives.
3169
@test unsafe fn testRegionDeclarations() throws (testing::TestError) {
3170
    let parsedRecord = try! parseStmtStr("record View: 'a + 'b + Copy where 'a: 'b { item: &'b u8 }");
3171
    let case ast::NodeValue::RecordDecl(decl) = parsedRecord.value
3172
        else throw testing::TestError::Failed;
3173
    try testing::expect(decl.regions.len == 2 and decl.derives.len == 1);
3174
    let case ast::NodeValue::Region { parent: parent, .. } = decl.regions[1].value
3175
        else throw testing::TestError::Failed;
3176
    try testing::expect(parent <> nil);
3177
    let func = try! parseStmtStr(
3178
        "fn read 'long 'short (input: &'short u8) -> &'short u8 throws (ReadError) where 'long: 'short { return input; }"
3179
    );
3180
    let case ast::NodeValue::FnDecl(f) = func.value else throw testing::TestError::Failed;
3181
    try testing::expect(f.regions.len == 2 and f.sig.throwList.len == 1);
3182
    let case ast::NodeValue::Region { name: shortName, parent: shortParent } = f.regions[1].value
3183
        else throw testing::TestError::Failed;
3184
    try testing::expect(mem::eq(shortName, "'short") and shortParent <> nil);
3185
    let parentNode = shortParent else throw testing::TestError::Failed;
3186
    let case ast::NodeValue::Region { name: parentName, parent: nil } = parentNode.value
3187
        else throw testing::TestError::Failed;
3188
    try testing::expect(mem::eq(parentName, "'long"));
3189
    let parsedUnion = try! parseStmtStr("union Result: 'x { Value(&'x u8), Empty }");
3190
    let case ast::NodeValue::UnionDecl(u) = parsedUnion.value else throw testing::TestError::Failed;
3191
    try testing::expect(u.regions.len == 1 and u.derives.len == 0);
3192
}
3193
3194
/// Regional blocks retain their source bindings and derived session region.
3195
@test unsafe fn testRegionBlocks() throws (testing::TestError) {
3196
    let root = try! parseStmtStr("let left: 'r = &mut state.left, right = &state.right in { useView(left); }");
3197
    let case ast::NodeValue::RegionBlock { bindings, isSession, .. } = root.value
3198
        else throw testing::TestError::Failed;
3199
    try testing::expect(not isSession and bindings.len == 2);
3200
    let nested = try! parseStmtStr("let view: 'inner = &value where 'outer: 'inner in {}");
3201
    let case ast::NodeValue::RegionBlock { region: nestedRegion, .. } = nested.value
3202
        else throw testing::TestError::Failed;
3203
    let case ast::NodeValue::Region { name: nestedName, parent: nestedParent } = nestedRegion.value
3204
        else throw testing::TestError::Failed;
3205
    let parent = nestedParent else throw testing::TestError::Failed;
3206
    let case ast::NodeValue::Region { name: parentName, parent: nil } = parent.value
3207
        else throw testing::TestError::Failed;
3208
    try testing::expect(mem::eq(nestedName, "'inner") and mem::eq(parentName, "'outer"));
3209
    let arena = try! parseStmtStr("use arena as objects in { make(objects); }");
3210
    let case ast::NodeValue::RegionBlock {
3211
        region: arenaRegion, bindings: arenaBindings, isSession: arenaSession, ..
3212
    } = arena.value
3213
        else throw testing::TestError::Failed;
3214
    let case ast::NodeValue::Region { name: arenaRegionName, parent: nil } = arenaRegion.value
3215
        else throw testing::TestError::Failed;
3216
    let case ast::NodeValue::RegionBinding(arenaBinding) = arenaBindings[0].value
3217
        else throw testing::TestError::Failed;
3218
    let arenaLabel = arenaBinding.label else throw testing::TestError::Failed;
3219
    let case ast::NodeValue::Ident(arenaLabelName) = arenaLabel.value
3220
        else throw testing::TestError::Failed;
3221
    let case ast::NodeValue::AddressOf({
3222
        target: arenaTarget, kind: ast::AddressKind::Mutable, permission: nil,
3223
    }) = arenaBinding.value.value
3224
        else throw testing::TestError::Failed;
3225
    let case ast::NodeValue::Ident(arenaTargetName) = arenaTarget.value
3226
        else throw testing::TestError::Failed;
3227
    try testing::expect(
3228
        arenaSession and arenaBindings.len == 1
3229
        and mem::eq(arenaRegionName, "'objects")
3230
        and mem::eq(arenaLabelName, "objects")
3231
        and mem::eq(arenaTargetName, "arena")
3232
    );
3233
}
3234
3235
/// Region grammar rejects incomplete lists and invalid allocation headers.
3236
@test unsafe fn testMalformedRegionSyntax() throws (testing::TestError) {
3237
    for source in [
3238
        "fn bad: Copy () {}",
3239
        "record Bad: 'r + {}",
3240
        "let 'r  in {}",
3241
        "let p: 'r = value in {}",
3242
        "let 'r p = &value in {}",
3243
        "let 'child < 'parent p = &value in {}",
3244
        "let 'parent as p = &value in {}",
3245
        "let value: 'child = &source where 'parent: 'other in {}",
3246
        "use arena in {}",
3247
        "use arena as in {}",
3248
        "use arena as first, second in {}",
3249
        "use 'r a = &mut arena in {}",
3250
        "use 'r a as &mut arena in {}",
3251
    ] {
3252
        let parsed = try? parseStmtStr(source);
3253
        try testing::expect(parsed == nil);
3254
    }
3255
    for source in ["&'x' u8", "&mut 'x u8", "View '", "&'r"] {
3256
        let parsed = try? parseTypeStr(source);
3257
        try testing::expect(parsed == nil);
3258
    }
3259
}
3260
3261
/// Ordinary identifiers remain available beside regional block syntax.
3262
@test unsafe fn testRegionContextualKeywords() throws (testing::TestError) {
3263
    for source in [
3264
        "let borrow = 1;",
3265
        "let session = 2;",
3266
        "borrow(value);",
3267
        "session(value);",
3268
        "record Context { borrow: u32, session: u32 }",
3269
    ] {
3270
        let parsed = try? parseStmtStr(source);
3271
        try testing::expect(parsed <> nil);
3272
    }
3273
}
3274
3275
/// The AST printer retains region parameters and qualified reference types.
3276
@test unsafe fn testPrintRegionSignature() throws (testing::TestError) {
3277
    let root = try! parseStmtStr("fn read 'r (input: &'r u8) -> &'r u8 { return input; }");
3278
    static PRINT_STORAGE: [u8; 4096] = [0; 4096];
3279
    let mut arena = alloc::new(&mut PRINT_STORAGE[..]);
3280
    let printed = printer::toExpr(&mut arena, root);
3281
    let case sexpr::Expr::Block { items, .. } = printed
3282
        else throw testing::TestError::Failed;
3283
    try testing::expect(items.len == 4);
3284
    let case sexpr::Expr::List { head, tail, .. } = items[1]
3285
        else throw testing::TestError::Failed;
3286
    try testing::expect(mem::eq(head, "regions") and tail.len == 1);
3287
    let case sexpr::Expr::Sym(name) = tail[0] else throw testing::TestError::Failed;
3288
    try testing::expect(mem::eq(name, "'r"));
3289
    let case sexpr::Expr::List { head: refHead, tail: refTail, .. } = items[3]
3290
        else throw testing::TestError::Failed;
3291
    try testing::expect(mem::eq(refHead, "region-ref") and refTail.len == 2);
3292
}
3293
3294
/// Explicit function region arguments precede ordinary call arguments.
3295
@test unsafe fn testFunctionRegionApplication() throws (testing::TestError) {
3296
    let expr = try! parseExprStr("read 'a 'b (p)");
3297
    let case ast::NodeValue::Call(call) = expr.value else throw testing::TestError::Failed;
3298
    let case ast::NodeValue::RegionApply { value, regions } = call.callee.value
3299
        else throw testing::TestError::Failed;
3300
    try expectIdent(value, "read");
3301
    try testing::expect(regions.len == 2 and call.args.len == 1);
3302
}
3303
3304
/// Concrete region headers can name a parent and end without a semicolon.
3305
@test unsafe fn testRegionParentSyntax() throws (testing::TestError) {
3306
    let parsed = try? parseStmtsStr("fn f 'a (p: &'a u32) { let q: 'b = &*p where 'a: 'b in {} return; }");
3307
    try testing::expect(parsed <> nil);
3308
}
3309
3310
/// Cell qualifiers retain pointer ownership and payload syntax.
3311
@test unsafe fn testCellPointerType() throws (testing::TestError) {
3312
    let root = try! parseTypeStr("*cell u32");
3313
    let case ast::NodeValue::TypeSig(ast::TypeSig::Cell {
3314
        class, payload, permission,
3315
    }) = root.value else throw testing::TestError::Failed;
3316
    try testing::expect(class == ast::PointerClass::Owned and permission == nil);
3317
    let case ast::NodeValue::TypeSig(ast::TypeSig::Integer { width: 4, .. }) = payload.value
3318
        else throw testing::TestError::Failed;
3319
3320
    let ownedAssociated = try! parseTypeStr("*cell 'permission u32");
3321
    let case ast::NodeValue::TypeSig(ast::TypeSig::Cell {
3322
        class: ownedClass, payload: ownedPayload, permission: ownedPermission,
3323
    }) = ownedAssociated.value else throw testing::TestError::Failed;
3324
    let ownedPermissionRegion = ownedPermission else throw testing::TestError::Failed;
3325
    let case ast::NodeValue::Region { name: ownedPermissionName, parent: nil } =
3326
        ownedPermissionRegion.value
3327
        else throw testing::TestError::Failed;
3328
    let case ast::NodeValue::TypeSig(ast::TypeSig::Integer { width: 4, .. }) =
3329
        ownedPayload.value
3330
        else throw testing::TestError::Failed;
3331
    try testing::expect(
3332
        ownedClass == ast::PointerClass::Owned
3333
        and mem::eq(ownedPermissionName, "'permission")
3334
    );
3335
3336
    let borrowed = try! parseTypeStr("&'r cell Pair 's");
3337
    let case ast::NodeValue::TypeSig(ast::TypeSig::RegionRef { type, .. }) = borrowed.value
3338
        else throw testing::TestError::Failed;
3339
    let case ast::NodeValue::TypeSig(ast::TypeSig::Cell {
3340
        class: refClass, payload: inner, permission: refPermission,
3341
    }) = type.value else throw testing::TestError::Failed;
3342
    try testing::expect(refClass == ast::PointerClass::Ref and refPermission == nil);
3343
    let case ast::NodeValue::TypeSig(ast::TypeSig::Applied { regions, .. }) = inner.value
3344
        else throw testing::TestError::Failed;
3345
    try testing::expect(regions.len == 1);
3346
3347
    let associated = try! parseTypeStr("&'storage cell 'permission Pair 'payload");
3348
    let case ast::NodeValue::TypeSig(ast::TypeSig::RegionRef {
3349
        region: storage, type: associatedType,
3350
    }) = associated.value else throw testing::TestError::Failed;
3351
    let case ast::NodeValue::Region { name: storageName, parent: nil } = storage.value
3352
        else throw testing::TestError::Failed;
3353
    let case ast::NodeValue::TypeSig(ast::TypeSig::Cell {
3354
        class: associatedClass,
3355
        payload: associatedPayload,
3356
        permission: associatedPermission,
3357
    }) = associatedType.value else throw testing::TestError::Failed;
3358
    let permissionRegion = associatedPermission else throw testing::TestError::Failed;
3359
    let case ast::NodeValue::Region { name: permissionName, parent: nil } =
3360
        permissionRegion.value
3361
        else throw testing::TestError::Failed;
3362
    let case ast::NodeValue::TypeSig(ast::TypeSig::Applied {
3363
        name: payloadName, regions: payloadRegions,
3364
    }) = associatedPayload.value else throw testing::TestError::Failed;
3365
    try expectIdent(payloadName, "Pair");
3366
    try testing::expect(payloadRegions.len == 1);
3367
    let case ast::NodeValue::Region { name: payloadRegionName, parent: nil } =
3368
        payloadRegions[0].value
3369
        else throw testing::TestError::Failed;
3370
    try testing::expect(
3371
        associatedClass == ast::PointerClass::Ref
3372
        and mem::eq(storageName, "'storage")
3373
        and mem::eq(permissionName, "'permission")
3374
        and mem::eq(payloadRegionName, "'payload")
3375
    );
3376
3377
}
3378
3379
/// Measure committed storage for a statement after an existing node.
3380
unsafe fn statementStorageUsed(source: *[u8]) -> u32 {
3381
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
3382
    ast::allocNode(&mut arena, ast::Span { offset: 0, length: 0 }, ast::NodeValue::Bool(true));
3383
    let start = alloc::used(&arena.arena);
3384
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
3385
        let mut parser = super::mkParser(scanner::SourceLoc::String, source, arenaRef, poolRef);
3386
        super::advance(&mut parser);
3387
        try! super::parseStmt(&mut parser);
3388
        return alloc::used(&parser.arena.arena) - start;
3389
    }
3390
}
3391
3392
/// Rewinding a failed expression preserves published nodes and source tokens.
3393
@test unsafe fn testSpeculativeRestoreStorage() throws (testing::TestError) {
3394
    let expectedBytes = statementStorageUsed("return");
3395
    let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
3396
    let retained = ast::allocNode(&mut arena, ast::Span { offset: 3, length: 1 }, ast::NodeValue::Bool(true));
3397
    let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
3398
        let mut parser = super::mkParser(scanner::SourceLoc::String,
3399
            "return [speculativeRestoreIdentifier, 1 +", arenaRef, poolRef);
3400
        super::advance(&mut parser);
3401
        try super::expect(&mut parser, scanner::TokenKind::Eof, "retained diagnostic") catch {
3402
        };
3403
        let mut expectedScanner = parser.scanner;
3404
        let expectedCurrent = scanner::next(&mut expectedScanner, parser.pool);
3405
        let expectedPrevious = parser.current;
3406
        let expectedContext = parser.context;
3407
        let startOffset = alloc::used(&parser.arena.arena);
3408
        let startId = parser.arena.nextId;
3409
        let statement = try! super::parseStmt(&mut parser);
3410
        let case ast::NodeValue::Return { value } = statement.value else throw testing::TestError::Failed;
3411
        try testing::expect(value == nil);
3412
        try testing::expect(statement.id == startId);
3413
        try testing::expect(alloc::used(&parser.arena.arena) == startOffset + expectedBytes);
3414
        try testing::expect(parser.arena.nextId == startId + 1);
3415
        try testing::expect(parser.scanner.cursor == expectedScanner.cursor);
3416
        try testing::expect(parser.scanner.token == expectedScanner.token);
3417
        try testing::expect(parser.current.kind == expectedCurrent.kind);
3418
        try testing::expect(parser.current.offset == expectedCurrent.offset);
3419
        try testing::expect(parser.previous.kind == expectedPrevious.kind);
3420
        try testing::expect(parser.previous.offset == expectedPrevious.offset);
3421
        try testing::expect(parser.context == expectedContext);
3422
        try testing::expect(parser.errors.count == 1);
3423
        for i in alloc::used(&parser.arena.arena)..ARENA_STORAGE.len {
3424
            set ARENA_STORAGE[i] = 0xA5;
3425
        }
3426
        let case ast::NodeValue::Bool(true) = retained.value else throw testing::TestError::Failed;
3427
        try testing::expect(retained.span.offset == 3);
3428
        try testing::expect(retained.span.length == 1);
3429
        try testing::expect(mem::eq(parser.errors.list[0].message, "retained diagnostic"));
3430
        try testing::expect(mem::eq(parser.errors.list[0].token.source, "return"));
3431
        let interned = strings::find(parser.pool, "speculativeRestoreIdentifier") else throw testing::TestError::Failed;
3432
        try testing::expect(mem::eq(interned, "speculativeRestoreIdentifier"));
3433
        let replacement = ast::allocNode(parser.arena, ast::Span { offset: 0, length: 0 }, ast::NodeValue::Bool(false));
3434
        try testing::expect(replacement.id == startId + 1);
3435
        let case ast::NodeValue::Bool(true) = retained.value else throw testing::TestError::Failed;
3436
    }
3437
}
3438
3439
/// Optional return and panic expressions publish only their wrapper after failure.
3440
@test unsafe fn testSpeculativeStatementPublication() throws (testing::TestError) {
3441
    let expectedBytes = statementStorageUsed("return");
3442
    for source in ["return (speculativeReturnIdentifier +", "panic (speculativePanicIdentifier +"] {
3443
        let mut arena = ast::nodeArena(&mut ARENA_STORAGE[..]);
3444
        ast::allocNode(&mut arena, ast::Span { offset: 0, length: 0 }, ast::NodeValue::Bool(true));
3445
        let startOffset = alloc::used(&arena.arena);
3446
        let poolRef: 'pool = &mut STRING_POOL, arenaRef = &mut arena in {
3447
            let mut parser = super::mkParser(scanner::SourceLoc::String, source, arenaRef, poolRef);
3448
            super::advance(&mut parser);
3449
            let startId = parser.arena.nextId;
3450
            let statement = try! super::parseStmt(&mut parser);
3451
            try testing::expect(statement.id == startId);
3452
            try testing::expect(parser.arena.nextId == startId + 1);
3453
            try testing::expect(alloc::used(&parser.arena.arena) == startOffset + expectedBytes);
3454
            try testing::expect(parser.errors.count == 0);
3455
            try testing::expect(parser.current.kind == scanner::TokenKind::LParen);
3456
            match statement.value {
3457
                case ast::NodeValue::Return { value } => try testing::expect(value == nil),
3458
                case ast::NodeValue::Panic { message } => try testing::expect(message == nil),
3459
                else => throw testing::TestError::Failed,
3460
            }
3461
        }
3462
    }
3463
}