GCC Code Coverage Report


src/
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
35 / 35
100.0%
Branches:
7 / 8, 2 excl
87.5%
Functions:
12 / 14
85.7%

exception/error-manager.spice
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 // Std imports
4 import "std/data/vector";
5
6 // Own imports
7 import "@/ast/ast-nodes";
8 import "@/exception/semantic-error";
9 import "@/reader/code-loc";
10
11 530 public type SoftError struct {
12 CodeLoc codeLoc
13 String message
14 }
15
16 265 public p SoftError.ctor(const CodeLoc& codeLoc, const String& message) {
17 265 this.codeLoc = codeLoc;
18 265 this.message = message;
19 265 }
20
21 /**
22 * Collects the errors of a compilation.
23 *
24 * Soft errors are collected and reported together at the end of the type checker (see SourceFile.checkForSoftErrors).
25 * Hard errors abort the compilation. Spice has no exceptions, so a hard error is recorded here and the pipeline aborts with it
26 * after the current stage (see SourceFile.checkForHardError). Only the first hard error is kept, since it ends the
27 * compilation. Recording instead of panicking also keeps hard errors testable.
28 */
29 1821 public type ErrorManager struct {
30 public Vector<SoftError> softErrors
31 1055 public bool hasHardError = false
32 public String hardErrorMessage
33 }
34
35 // Active error manager. Hard errors are raised from anywhere in the compiler, including places that have no access to the
36 // resource manager (e.g. the FunctionManager).
37 ErrorManager* ACTIVE_ERROR_MANAGER;
38
39 /**
40 * Make the given error manager the active one. throwSemanticError() records hard errors in it.
41 *
42 * @param errorManager Error manager
43 */
44 1055 public p setActiveErrorManager(ErrorManager* errorManager) {
45 1055 ACTIVE_ERROR_MANAGER = errorManager;
46 1055 }
47
48 /**
49 * Get the active error manager
50 *
51 * @return Active error manager
52 */
53 67 public f<ErrorManager*> getActiveErrorManager() {
54 67 assert ACTIVE_ERROR_MANAGER != nil<ErrorManager*>;
55 67 return ACTIVE_ERROR_MANAGER;
56 }
57
58 /**
59 * Record a hard error. Only the first hard error is kept, since it aborts the compilation.
60 *
61 * @param astNode AST node, where the error occurred
62 * @param errorType Type of the error
63 * @param message Error message suffix
64 * @param printErrorMessage Whether to append the code snippet of the node to the message
65 */
66 96 public p ErrorManager.addHardError(const ASTNode* astNode, SemanticErrorType errorType, const String& message, bool printErrorMessage = true) {
67
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 77 times.
96 if this.hasHardError {
68 12 return;
69 }
70 84 const SemanticError semanticError = SemanticError(astNode, errorType, message.getRaw(), printErrorMessage);
71 // Copy the message explicitly. Assigning the reference, returned by getMessage(), would alias the buffer of the
72 // SemanticError, which is freed at the end of this method (see https://github.com/spicelang/spice/issues/1460)
73 84 this.hardErrorMessage = String(semanticError.getMessage());
74 84 this.hasHardError = true;
75 84 }
76
77 /**
78 * Raise a hard error on the active error manager. The caller has to return afterwards, like after reporting a soft error.
79 *
80 * @param astNode AST node, where the error occurred
81 * @param errorType Type of the error
82 * @param message Error message suffix
83 * @param printErrorMessage Whether to append the code snippet of the node to the message
84 */
85 67 public p throwSemanticError(const ASTNode* astNode, SemanticErrorType errorType, const String& message, bool printErrorMessage = true) {
86 67 ErrorManager* errorManager = getActiveErrorManager();
87 67 errorManager.addHardError(astNode, errorType, message, printErrorMessage);
88 67 }
89
90 275 p ErrorManager.addSoftError(const CodeLoc& codeLoc, const String& message) {
91 // Avoid duplicate errors
92
2/2
✓ Branch 0 taken 278 times.
✓ Branch 1 taken 265 times.
543 foreach (const SoftError& error : this.softErrors) {
93
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 268 times.
278 if error.codeLoc == codeLoc {
94 10 return;
95 }
96 268 }
97 265 this.softErrors.pushBack(SoftError(codeLoc, message));
98 265 }
99
100 275 public p ErrorManager.addSoftError(const ASTNode* astNode, SemanticErrorType errorType, const String& message) {
101 // Build error message
102 275 SemanticError semanticError = SemanticError(astNode, errorType, message.getRaw());
103 // Add to soft errors list
104 275 this.addSoftError(astNode.codeLoc, semanticError.getMessage());
105 275 }
106