miden_assembly_syntax/sema/
errors.rs1use alloc::{sync::Arc, vec::Vec};
2use core::fmt;
3
4use miden_debug_types::{SourceFile, SourceSpan};
5use miden_utils_diagnostics::{Diagnostic, miette};
6
7#[derive(Debug, thiserror::Error, Diagnostic)]
18#[error("syntax error")]
19#[diagnostic(help("see emitted diagnostics for details"))]
20pub struct SyntaxError {
21 #[source_code]
22 pub source_file: Arc<SourceFile>,
23 #[related]
24 pub errors: Vec<SemanticAnalysisError>,
25}
26
27#[derive(Debug, thiserror::Error, Diagnostic)]
33#[error("one or more warnings were emitted")]
34#[diagnostic(help("see below for details"))]
35pub struct SyntaxWarning {
36 #[source_code]
37 pub source_file: Arc<SourceFile>,
38 #[related]
39 pub errors: Vec<SemanticAnalysisError>,
40}
41
42#[derive(Debug, thiserror::Error, Diagnostic)]
44pub enum SemanticAnalysisError {
45 #[error("invalid program: no entrypoint defined")]
46 #[diagnostic(help(
47 "ensure you define an entrypoint somewhere in the body with `begin`..`end`"
48 ))]
49 MissingEntrypoint,
50 #[error("invalid module: unexpected entrypoint definition")]
51 #[diagnostic(help("library modules cannot contain `begin`..`end` blocks"))]
52 UnexpectedEntrypoint {
53 #[label]
54 span: SourceSpan,
55 },
56 #[error("invalid module: multiple conflicting entrypoints defined")]
57 #[diagnostic(help("an executable module can only have a single `begin`..`end` block"))]
58 MultipleEntrypoints {
59 #[label]
60 span: SourceSpan,
61 #[label]
62 prev_span: SourceSpan,
63 },
64 #[error("invalid program: procedure exports are not allowed")]
65 #[diagnostic(help("perhaps you meant to use `proc` instead of `export`?"))]
66 UnexpectedExport {
67 #[label]
68 span: SourceSpan,
69 },
70 #[error("invalid enum type representation: underlying type must be an integral type")]
71 #[diagnostic()]
72 InvalidEnumRepr {
73 #[label]
74 span: SourceSpan,
75 },
76 #[error("symbol conflict: found duplicate definitions of the same name")]
77 #[diagnostic()]
78 SymbolConflict {
79 #[label("conflict occurs here")]
80 span: SourceSpan,
81 #[label("previously defined here")]
82 prev_span: SourceSpan,
83 },
84 #[error("symbol undefined: no such name found in scope")]
85 #[diagnostic(help("are you missing an import?"))]
86 SymbolUndefined {
87 #[label]
88 span: SourceSpan,
89 },
90 #[error("unused import")]
91 #[diagnostic(severity(Warning), help("this import is never used and can be safely removed"))]
92 UnusedImport {
93 #[label]
94 span: SourceSpan,
95 },
96 #[error("missing import: the referenced module has not been imported")]
97 #[diagnostic()]
98 MissingImport {
99 #[label("this reference is invalid without a corresponding import")]
100 span: SourceSpan,
101 },
102 #[error("symbol conflict: import would shadow a previous import of the same name")]
103 #[diagnostic(help(
104 "imports must have unique names within a module, \
105 try aliasing one of the imports if both are needed"
106 ))]
107 ImportConflict {
108 #[label("caused by this import")]
109 span: SourceSpan,
110 #[label("previously imported here")]
111 prev_span: SourceSpan,
112 },
113 #[error(
114 "invalid re-exported procedure: kernel modules may not re-export procedures from other modules"
115 )]
116 #[diagnostic()]
117 ReexportFromKernel {
118 #[label]
119 span: SourceSpan,
120 },
121 #[error("invalid syscall: cannot make a syscall from within the kernel")]
122 #[diagnostic(help("syscalls are only valid outside the kernel, you should use exec instead"))]
123 SyscallInKernel {
124 #[label]
125 span: SourceSpan,
126 },
127 #[error("invalid call: kernel modules cannot make calls to external procedures")]
128 #[diagnostic(help(
129 "this call is being made from a kernel module, and may only refer to local procedures"
130 ))]
131 CallInKernel {
132 #[label]
133 span: SourceSpan,
134 },
135 #[error("invalid instruction usage: 'caller' is only valid in kernel modules")]
136 #[diagnostic()]
137 CallerInKernel {
138 #[label]
139 span: SourceSpan,
140 },
141 #[error("invalid syscall: callee must be resolvable to kernel module")]
142 #[diagnostic()]
143 InvalidSyscallTarget {
144 #[label]
145 span: SourceSpan,
146 },
147 #[error("invalid recursive procedure call")]
148 #[diagnostic(help(
149 "this call induces a cycle that returns back to the caller, you must break that cycle"
150 ))]
151 InvalidRecursiveCall {
152 #[label("caused by this call")]
153 span: SourceSpan,
154 },
155 #[error("invalid recursive procedure call")]
156 #[diagnostic(help("this call is self-recursive, which is not allowed"))]
157 SelfRecursive {
158 #[label]
159 span: SourceSpan,
160 },
161 #[error("invalid immediate: value is larger than expected range")]
162 #[diagnostic()]
163 ImmediateOverflow {
164 #[label]
165 span: SourceSpan,
166 },
167 #[error("invalid module: {}", kind)]
168 #[diagnostic(help("try breaking this module up into submodules"))]
169 LimitExceeded {
170 #[label]
171 span: SourceSpan,
172 kind: LimitKind,
173 },
174 #[error("unused docstring")]
175 #[diagnostic(
176 severity(Warning),
177 help(
178 "this docstring is immediately followed by at least one empty line, then another docstring,\
179 if you intended these to be a single docstring, you should remove the empty lines"
180 )
181 )]
182 UnusedDocstring {
183 #[label]
184 span: SourceSpan,
185 },
186 #[error("unused docstring")]
187 #[diagnostic(
188 severity(Warning),
189 help(
190 "module imports cannot have docstrings, you should use line comment syntax here instead"
191 )
192 )]
193 ImportDocstring {
194 #[label]
195 span: SourceSpan,
196 },
197 #[error("invalid constant")]
198 #[diagnostic(help("this constant does not resolve to a value of the right type"))]
199 InvalidConstant {
200 #[label]
201 span: SourceSpan,
202 },
203 #[error("advmap key already defined")]
204 AdvMapKeyAlreadyDefined {
205 #[label]
206 span: SourceSpan,
207 },
208}
209
210#[derive(Debug, Copy, Clone, PartialEq, Eq)]
212pub enum LimitKind {
213 Procedures,
215 Locals,
217 Imports,
219 CalledImports,
223 Instructions,
225}
226
227impl fmt::Display for LimitKind {
228 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
229 match self {
230 Self::Procedures => f.write_str("too many procedures in module"),
231 Self::Locals => f.write_str("too many procedure locals"),
232 Self::Imports => f.write_str("too many imported procedures"),
233 Self::CalledImports => f.write_str("too many calls to imported procedures"),
234 Self::Instructions => f.write_str("too many instructions in block"),
235 }
236 }
237}