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