lib/std/lang/resolver/printer.rad 23.0 KiB raw
1
//! Resolver scope printer.
2
use std::io;
3
use std::lang::ast;
4
use std::lang::scanner;
5
use std::lang::module;
6
7
/// Single indentation unit used when rendering nested scopes.
8
const INDENT_STEP: *[u8] = "  ";
9
10
/// Emit indentation for a given nesting depth.
11
fn printIndent(depth: u32) {
12
    for i in 0..depth {
13
        io::print(INDENT_STEP);
14
    }
15
}
16
17
/// Print a span in `@offset:length` form.
18
fn printSpan(span: ast::Span) {
19
    io::print("@");
20
    io::printU32(span.offset);
21
    io::print(":");
22
    io::printU32(span.length);
23
}
24
25
/// Print a resolved type in a textual form.
26
fn printType(ty: super::Type) {
27
    printTypeBody(ty, false);
28
}
29
30
/// Print just the type name without detailed structure info.
31
fn printTypeName(ty: super::Type) {
32
    printTypeBody(ty, true);
33
}
34
35
/// Print a resolved type, optionally abbreviated for function signatures.
36
fn printTypeBody(ty: super::Type, brief: bool) {
37
    match ty {
38
        case super::Type::Unknown => {
39
            io::print("<unknown>");
40
        }
41
        case super::Type::Undefined => {
42
            io::print("<undefined>");
43
        }
44
        case super::Type::Int => {
45
            io::print("<int>");
46
        }
47
        case super::Type::Nil => {
48
            io::print("<nil>");
49
        }
50
        case super::Type::Opaque => {
51
            io::print("opaque");
52
        }
53
        case super::Type::Never => {
54
            io::print("!");
55
        }
56
        case super::Type::Void => {
57
            io::print("void");
58
        }
59
        case super::Type::Bool => {
60
            io::print("bool");
61
        }
62
        case super::Type::U8 => {
63
            io::print("u8");
64
        }
65
        case super::Type::U16 => {
66
            io::print("u16");
67
        }
68
        case super::Type::U32 => {
69
            io::print("u32");
70
        }
71
        case super::Type::U64 => {
72
            io::print("u64");
73
        }
74
        case super::Type::I8 => {
75
            io::print("i8");
76
        }
77
        case super::Type::I16 => {
78
            io::print("i16");
79
        }
80
        case super::Type::I32 => {
81
            io::print("i32");
82
        }
83
        case super::Type::I64 => {
84
            io::print("i64");
85
        }
86
        case super::Type::Pointer { target, mutable } => {
87
            io::print("*");
88
            if mutable {
89
                io::print("mut ");
90
            }
91
            printTypeBody(*target, brief);
92
        }
93
        case super::Type::Slice { item, mutable } => {
94
            io::print("*");
95
            if mutable {
96
                io::print("mut ");
97
            }
98
            io::print("[");
99
            printTypeBody(*item, brief);
100
            io::print("]");
101
        }
102
        case super::Type::Array(array) => {
103
            io::print("[");
104
            printTypeBody(*array.item, brief);
105
            io::print("; ");
106
            io::printU32(array.length);
107
            io::print("]");
108
        }
109
        case super::Type::Optional(inner) => {
110
            io::print("?");
111
            printTypeBody(*inner, brief);
112
        }
113
        case super::Type::Fn(fnType) => {
114
            io::print("fn(");
115
            for paramType, i in fnType.paramTypes {
116
                if i > 0 {
117
                    io::print(", ");
118
                }
119
                printTypeName(*paramType);
120
            }
121
            io::print(")");
122
            io::print(" -> ");
123
            printTypeName(*fnType.returnType);
124
            if fnType.throwList.len > 0 {
125
                io::print(" throws ");
126
                for throwType, i in fnType.throwList {
127
                    if i > 0 {
128
                        io::print(", ");
129
                    }
130
                    printTypeName(*throwType);
131
                }
132
            }
133
        }
134
        case super::Type::Nominal(info) => {
135
            if brief {
136
                printNominalTypeName(info);
137
            } else {
138
                printNominalType(info);
139
            }
140
        }
141
        case super::Type::TraitObject { traitInfo, mutable } => {
142
            io::print("*");
143
            if mutable {
144
                io::print("mut ");
145
            }
146
            io::print("opaque ");
147
            io::print(traitInfo.name);
148
        }
149
        case super::Type::Range { start, end } => {
150
            if let s = start {
151
                printTypeBody(*s, brief);
152
            }
153
            io::print("..");
154
            if let e = end {
155
                printTypeBody(*e, brief);
156
            }
157
        }
158
    }
159
}
160
161
/// Print detailed information about a nominal type (record or union).
162
fn printNominalType(info: *super::NominalType) {
163
    match *info {
164
        case super::NominalType::Placeholder(_) => {
165
            io::print("<placeholder>");
166
        }
167
        case super::NominalType::Record(recordType) => {
168
            io::print("record {");
169
            if recordType.fields.len > 0 {
170
                io::print(" ");
171
                for i in 0..recordType.fields.len {
172
                    if i > 0 {
173
                        io::print(", ");
174
                    }
175
                    let field = &recordType.fields[i];
176
                    if let name = field.name {
177
                        io::print(name);
178
                        io::print(": ");
179
                    }
180
                    printTypeName(field.fieldType);
181
182
                    if i >= 4 and i < recordType.fields.len - 1 {
183
                        io::print(", ...");
184
                        break;
185
                    }
186
                }
187
                io::print(" ");
188
            }
189
            io::print("}");
190
        }
191
        case super::NominalType::Union(unionType) => {
192
            io::print("union {");
193
            if unionType.variants.len > 0 {
194
                io::print(" ");
195
                for i in 0..unionType.variants.len {
196
                    if i > 0 {
197
                        io::print(", ");
198
                    }
199
                    let variant = &unionType.variants[i];
200
                    io::print(variant.name);
201
                    io::print(": ");
202
                    printTypeName(variant.valueType);
203
204
                    if i >= 4 and i < unionType.variants.len - 1 {
205
                        io::print(", ...");
206
                        break;
207
                    }
208
                }
209
                io::print(" ");
210
            }
211
            io::print("}");
212
        }
213
    }
214
}
215
216
/// Print just the type kind for a nominal type, without detailed info.
217
fn printNominalTypeName(info: *super::NominalType) {
218
    match *info {
219
        case super::NominalType::Placeholder(_) => {
220
            io::print("<placeholder>");
221
        }
222
        case super::NominalType::Record(_) => {
223
            io::print("<record>");
224
        }
225
        case super::NominalType::Union(_) => {
226
            io::print("<union>");
227
        }
228
    }
229
}
230
231
/// Print a single symbol within a scope.
232
fn printSymbol(symbol: *super::Symbol, depth: u32) {
233
    printIndent(depth);
234
235
    io::print("`");
236
    io::print(symbol.name);
237
    io::print("` ");
238
239
    match symbol.data {
240
        case super::SymbolData::Variant { .. } => {
241
            io::print("variant");
242
        }
243
        case super::SymbolData::Value { .. } => {
244
            io::print("value");
245
        }
246
        case super::SymbolData::Constant { .. } => {
247
            io::print("constant");
248
        }
249
        case super::SymbolData::Type(_) => {
250
            io::print("type");
251
        }
252
        case super::SymbolData::Module { .. } => {
253
            io::print("module");
254
        }
255
        case super::SymbolData::Trait(_) => {
256
            io::print("trait");
257
        }
258
    }
259
260
    match symbol.data {
261
        case super::SymbolData::Value { mutable, type, .. } => {
262
            if mutable {
263
                io::print(" mut");
264
            }
265
            io::print(" ");
266
            io::print(symbol.name);
267
            io::print(" ");
268
            printSpan(symbol.node.span);
269
            io::print(" : ");
270
            printType(type);
271
            io::print("\n");
272
        }
273
        case super::SymbolData::Constant { type, .. } => {
274
            io::print(" ");
275
            io::print(symbol.name);
276
            io::print(" ");
277
            printSpan(symbol.node.span);
278
            io::print(" : ");
279
            printType(type);
280
            io::print("\n");
281
        }
282
        case super::SymbolData::Type(t) => {
283
            printType(super::Type::Nominal(t));
284
        }
285
        case super::SymbolData::Variant { .. } => {
286
            // TODO
287
        }
288
        case super::SymbolData::Module { .. } => {
289
            // TODO
290
        }
291
        case super::SymbolData::Trait(_) => {
292
            io::print(" ");
293
            io::print(symbol.name);
294
            io::print("\n");
295
        }
296
    }
297
}
298
299
/// Print a single diagnostic entry.
300
fn printError(err: *super::Error, res: *super::Resolver) {
301
    if let node = err.node {
302
        // Find the module containing this error.
303
        if let moduleEntry = module::get(res.moduleGraph, err.moduleId) {
304
            // Get the source text if available.
305
            if let source = moduleEntry.source {
306
                // Convert offset to location.
307
                if let loc = scanner::getLocation(scanner::SourceLoc::File(moduleEntry.filePath), source, node.span.offset) {
308
                    // Print: filename:line:col: error: message
309
                    if let case scanner::SourceLoc::File(path) = loc.source {
310
                        io::print(path);
311
                        io::print(":");
312
                    }
313
                    io::printU32(loc.line as u32);
314
                    io::print(":");
315
                    io::printU32(loc.col as u32);
316
                    io::print(": error: ");
317
                } else {
318
                    io::print("error ");
319
                    io::print(" ");
320
                    printSpan(node.span);
321
                    io::print(": ");
322
                }
323
            } else {
324
                io::print(moduleEntry.name);
325
                io::print(": ");
326
                io::print("error ");
327
                io::print(" ");
328
                printSpan(node.span);
329
                io::print(": ");
330
            }
331
        }
332
    } else {
333
        io::print("error: ");
334
    }
335
336
    // Print the error message.
337
    match err.kind {
338
        case super::ErrorKind::TypeMismatch(mismatch) => {
339
            io::print("type mismatch: expected ");
340
            printType(mismatch.expected);
341
            io::print(", got ");
342
            printType(mismatch.actual);
343
        }
344
        case super::ErrorKind::UnresolvedSymbol(name) => {
345
            io::print("unresolved symbol '");
346
            io::print(name);
347
            io::print("'");
348
        }
349
        case super::ErrorKind::DuplicateBinding(name) => {
350
            io::print("duplicate binding '");
351
            io::print(name);
352
            io::print("'");
353
        }
354
        case super::ErrorKind::FnArgCountMismatch(mismatch) => {
355
            io::print("function argument count mismatch: expected ");
356
            io::printU32(mismatch.expected);
357
            io::print(", got ");
358
            io::printU32(mismatch.actual);
359
        }
360
        case super::ErrorKind::FnThrowCountMismatch(mismatch) => {
361
            io::print("function throws count mismatch: expected ");
362
            io::printU32(mismatch.expected);
363
            io::print(", got ");
364
            io::printU32(mismatch.actual);
365
        }
366
        case super::ErrorKind::RecordFieldCountMismatch(mismatch) => {
367
            io::print("record field count mismatch: expected ");
368
            io::printU32(mismatch.expected);
369
            io::print(", got ");
370
            io::printU32(mismatch.actual);
371
        }
372
        case super::ErrorKind::RecordFieldMissing(name) => {
373
            io::print("record field missing: '");
374
            io::print(name);
375
            io::print("'");
376
        }
377
        case super::ErrorKind::RecordFieldUnknown(name) => {
378
            io::print("record field unknown: '");
379
            io::print(name);
380
            io::print("'");
381
        }
382
        case super::ErrorKind::InvalidAsCast(info) => {
383
            io::print("invalid cast: cannot cast ");
384
            printType(info.from);
385
            io::print(" to ");
386
            printType(info.to);
387
        }
388
        case super::ErrorKind::ExpectedIterable => {
389
            io::print("expected iterable type");
390
        }
391
        case super::ErrorKind::ElseBranchMustDiverge => {
392
            io::print("else branch must not fall through");
393
        }
394
        case super::ErrorKind::FnMissingReturn => {
395
            io::print("function must return a value on all paths");
396
        }
397
        case super::ErrorKind::UnionMatchNonExhaustive(name) => {
398
            io::print("union match non-exhaustive: missing case for variant '");
399
            io::print(name);
400
            io::print("'");
401
        }
402
        case super::ErrorKind::OptionalMatchMissingValue => {
403
            io::print("optional match non-exhaustive: missing value case");
404
        }
405
        case super::ErrorKind::OptionalMatchMissingNil => {
406
            io::print("optional match non-exhaustive: missing nil case");
407
        }
408
        case super::ErrorKind::BoolMatchMissing(val) => {
409
            io::print("bool match non-exhaustive: missing case for `");
410
            io::print("true" if val else "false");
411
            io::print("`");
412
        }
413
        case super::ErrorKind::MatchNonExhaustive => {
414
            io::print("match non-exhaustive: requires `else` or binding catch-all");
415
        }
416
        case super::ErrorKind::DuplicateCatchAll => {
417
            io::print("match has multiple catch-all prongs");
418
        }
419
        case super::ErrorKind::DuplicateMatchPattern => {
420
            io::print("match has duplicate pattern");
421
        }
422
        case super::ErrorKind::UnreachableElse => {
423
            io::print("match has unreachable `else`, all cases are already handled");
424
        }
425
        case super::ErrorKind::ImmutableBinding => {
426
            io::print("cannot assign to immutable binding");
427
        }
428
        case super::ErrorKind::ConstExprRequired => {
429
            io::print("expected compile-time constant expression");
430
        }
431
        case super::ErrorKind::ScopeOverflow => {
432
            io::print("scope stack overflow");
433
        }
434
        case super::ErrorKind::NodeOverflow => {
435
            io::print("node table overflow");
436
        }
437
        case super::ErrorKind::SymbolOverflow => {
438
            io::print("symbol arena overflow");
439
        }
440
        case super::ErrorKind::NumericLiteralOverflow => {
441
            io::print("numeric literal overflow");
442
        }
443
        case super::ErrorKind::RecordFieldStyleMismatch => {
444
            io::print("brace syntax not allowed for tuple-style records");
445
        }
446
        case super::ErrorKind::ExpectedIdentifier => {
447
            io::print("expected identifier");
448
        }
449
        case super::ErrorKind::ExpectedOptional => {
450
            io::print("expected optional type");
451
        }
452
        case super::ErrorKind::ExpectedNumeric => {
453
            io::print("expected numeric type");
454
        }
455
        case super::ErrorKind::ExpectedPointer => {
456
            io::print("expected pointer type");
457
        }
458
        case super::ErrorKind::ExpectedRecord => {
459
            io::print("expected record type");
460
        }
461
        case super::ErrorKind::ExpectedIndexable => {
462
            io::print("expected array or slice");
463
        }
464
        case super::ErrorKind::ExpectedBlock => {
465
            io::print("expected block");
466
        }
467
        case super::ErrorKind::InvalidAlignmentValue(val) => {
468
            io::print("invalid alignment value: ");
469
            io::printU32(val);
470
        }
471
        case super::ErrorKind::InvalidModulePath => {
472
            io::print("invalid module path");
473
        }
474
        case super::ErrorKind::InvalidIdentifier(_) => {
475
            io::print("invalid identifier");
476
        }
477
        case super::ErrorKind::InvalidScopeAccess => {
478
            io::print("invalid scope access");
479
        }
480
        case super::ErrorKind::ArrayFieldUnknown(name) => {
481
            io::print("array field unknown: '");
482
            io::print(name);
483
            io::print("'");
484
        }
485
        case super::ErrorKind::SliceFieldUnknown(name) => {
486
            io::print("slice field unknown: '");
487
            io::print(name);
488
            io::print("'");
489
        }
490
        case super::ErrorKind::SliceRequiresAddress => {
491
            io::print("slicing requires taking an address with '&'");
492
        }
493
        case super::ErrorKind::SliceRangeOutOfBounds => {
494
            io::print("slice bounds exceed array length");
495
        }
496
        case super::ErrorKind::UnexpectedReturn => {
497
            io::print("unexpected return statement");
498
        }
499
        case super::ErrorKind::UnexpectedNode(n) => {
500
            io::print("unexpected expression");
501
        }
502
        case super::ErrorKind::UnexpectedModuleName => {
503
            io::print("unexpected module name");
504
        }
505
        case super::ErrorKind::FnMissingBody => {
506
            io::print("function is missing a body");
507
        }
508
        case super::ErrorKind::FnUnexpectedBody => {
509
            io::print("function body is not expected");
510
        }
511
        case super::ErrorKind::IntrinsicRequiresExtern => {
512
            io::print("intrinsic function must be declared extern");
513
        }
514
        case super::ErrorKind::InvalidLoopControl => {
515
            io::print("loop control outside of a loop construct");
516
        }
517
        case super::ErrorKind::TryRequiresThrows => {
518
            io::print("try used when function does not declare throws");
519
        }
520
        case super::ErrorKind::TryIncompatibleError => {
521
            io::print("try propagates error not declared by function");
522
        }
523
        case super::ErrorKind::ThrowRequiresThrows => {
524
            io::print("throw used when function does not declare throws");
525
        }
526
        case super::ErrorKind::ThrowIncompatibleError => {
527
            io::print("throw uses error type not declared by function");
528
        }
529
        case super::ErrorKind::TryNonThrowing => {
530
            io::print("try applied to expression that cannot throw");
531
        }
532
        case super::ErrorKind::TryCatchMultiError => {
533
            io::print("catch with inferred binding requires single error type; use typed catches for multiple error types");
534
        }
535
        case super::ErrorKind::TryCatchDuplicateType => {
536
            io::print("duplicate error type in catch clauses");
537
        }
538
        case super::ErrorKind::TryCatchNonExhaustive => {
539
            io::print("catch clauses do not cover all error types");
540
        }
541
        case super::ErrorKind::MissingTry => {
542
            io::print("called fallible function without using try");
543
        }
544
        case super::ErrorKind::CannotInferType => {
545
            io::print("cannot infer type from context");
546
        }
547
        case super::ErrorKind::CannotAssignVoid => {
548
            io::print("cannot assign void value to a variable");
549
        }
550
        case super::ErrorKind::DefaultAttrOnlyOnFn => {
551
            io::print("default attribute can only be used on functions");
552
        }
553
        case super::ErrorKind::UnionVariantPayloadMissing(name) => {
554
            io::print("union variant '");
555
            io::print(name);
556
            io::print("' requires a payload");
557
        }
558
        case super::ErrorKind::UnionVariantPayloadUnexpected(name) => {
559
            io::print("union variant '");
560
            io::print(name);
561
            io::print("' does not expect a payload");
562
        }
563
        case super::ErrorKind::ReceiverMutabilityMismatch => {
564
            io::print("instance receiver mutability does not match trait declaration");
565
        }
566
        case super::ErrorKind::DuplicateInstance => {
567
            io::print("duplicate instance declaration for the same trait and type");
568
        }
569
        case super::ErrorKind::MissingTraitMethod(name) => {
570
            io::print("missing trait method '");
571
            io::print(name);
572
            io::print("'");
573
        }
574
        case super::ErrorKind::UnexpectedTraitName => {
575
            io::print("trait name cannot be used as a value");
576
        }
577
        case super::ErrorKind::TraitReceiverMismatch => {
578
            io::print("trait method receiver must be a pointer to the declaring trait");
579
        }
580
        case super::ErrorKind::FnParamOverflow(mismatch) => {
581
            io::print("too many function parameters: maximum ");
582
            io::printU32(mismatch.expected);
583
            io::print(", got ");
584
            io::printU32(mismatch.actual);
585
        }
586
        case super::ErrorKind::FnThrowOverflow(mismatch) => {
587
            io::print("too many function throws: maximum ");
588
            io::printU32(mismatch.expected);
589
            io::print(", got ");
590
            io::printU32(mismatch.actual);
591
        }
592
        case super::ErrorKind::TraitMethodOverflow(mismatch) => {
593
            io::print("too many trait methods: maximum ");
594
            io::printU32(mismatch.expected);
595
            io::print(", got ");
596
            io::printU32(mismatch.actual);
597
        }
598
        case super::ErrorKind::MissingSupertraitInstance(name) => {
599
            io::print("missing instance for supertrait '");
600
            io::print(name);
601
            io::print("'");
602
        }
603
        case super::ErrorKind::Internal => {
604
            io::print("internal compiler error");
605
        }
606
        case super::ErrorKind::RecordFieldOutOfOrder { .. } => {
607
            io::print("record field out of order");
608
        }
609
        case super::ErrorKind::OpaqueTypeNotAllowed => {
610
            io::print("opaque type not allowed");
611
        }
612
        case super::ErrorKind::OpaqueTypeDeref => {
613
            io::print("opaque types cannot be dereferenced");
614
        }
615
        case super::ErrorKind::OpaquePointerArithmetic => {
616
            io::print("opaque pointer arithmetic is not allowed");
617
        }
618
        case super::ErrorKind::CyclicTypeDependency(_) => {
619
            io::print("cyclic type dependency");
620
        }
621
        case super::ErrorKind::BuiltinArgCountMismatch { .. } => {
622
            io::print("built-in argument count mismatch");
623
        }
624
    }
625
    io::print("\n");
626
}
627
628
/// Recursively print a scope and its nested children.
629
fn printScopeTree(res: *super::Resolver, scope: *super::Scope, depth: u32) {
630
    printIndent(depth);
631
    io::print("Scope ");
632
633
    if let owner = scope.owner {
634
        printSpan(owner.span);
635
    } else {
636
        io::print("<root>");
637
    }
638
    io::print("\n");
639
    printScope(scope, depth);
640
641
    for entry in res.nodeData.entries {
642
        if let childScopePtr = entry.scope {
643
            if childScopePtr.parent != nil and childScopePtr.parent == scope {
644
                printScopeTree(res, childScopePtr, depth + 1);
645
            }
646
        }
647
    }
648
}
649
650
/// Entry point for printing the resolver scope tree.
651
pub fn printScopes(res: *super::Resolver, root: *ast::Node) {
652
    if let scope = super::scopeFor(res, root) {
653
        printScopeTree(res, scope, 0);
654
    }
655
    io::print("\n");
656
}
657
658
/// Print the given scope.
659
pub fn printScope(scope: *super::Scope, depth: u32) {
660
    for i in 0..scope.symbolsLen {
661
        let symbol = scope.symbols[i];
662
        printSymbol(symbol, depth);
663
        io::print("\n");
664
    }
665
}
666
667
/// Print the given scope, and all enclosing scopes.
668
pub fn printEnclosingScopes(res: *super::Resolver, scope: *super::Scope) {
669
    let mut curr = scope;
670
671
    loop {
672
        io::printLn("Scope");
673
        printScope(curr, 1);
674
675
        if let parent = curr.parent {
676
            curr = parent;
677
        } else {
678
            break;
679
        }
680
    }
681
}
682
683
/// Entry point for printing resolver diagnostics in vim quickfix format.
684
pub fn printDiagnostics(diag: *super::Diagnostics, res: *super::Resolver) {
685
    for i in 0..diag.errors.len {
686
        printError(&diag.errors[i], res);
687
    }
688
}