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