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