veryl_simulator/
simulator_error.rs1use miette::{Diagnostic, SourceSpan};
2use thiserror::Error;
3use veryl_analyzer::multi_sources::{MultiSources, Source};
4use veryl_parser::token_range::TokenRange;
5use veryl_parser::veryl_token::TokenSource;
6
7#[derive(Error, Diagnostic, Debug)]
8pub enum SimulatorError {
9 #[diagnostic(severity(Error), code(top_module_not_found))]
10 #[error("top module \"{module_name}\" not found")]
11 TopModuleNotFound { module_name: String },
12
13 #[diagnostic(severity(Error), code(no_initial_block))]
14 #[error("no initial block found in module \"{module_name}\"")]
15 NoInitialBlock {
16 module_name: String,
17 #[source_code]
18 input: MultiSources,
19 #[label("this module has no initial block")]
20 error_location: SourceSpan,
21 token_source: TokenSource,
22 },
23
24 #[diagnostic(severity(Error), code(test_failed))]
25 #[error("{message}")]
26 TestFailed { message: String },
27
28 #[diagnostic(severity(Error), code(io_error))]
29 #[error("{message}")]
30 IoError { message: String },
31
32 #[diagnostic(severity(Error), code(unresolved_expression))]
33 #[error("unresolved expression")]
34 UnresolvedExpression {
35 #[source_code]
36 input: MultiSources,
37 #[label("could not resolve this expression")]
38 error_location: SourceSpan,
39 token_source: TokenSource,
40 },
41
42 #[diagnostic(severity(Error), code(recursive_function))]
43 #[error("recursive function \"{function_name}\" cannot be inlined")]
44 RecursiveFunction {
45 function_name: String,
46 #[source_code]
47 input: MultiSources,
48 #[label("recursive call here")]
49 error_location: SourceSpan,
50 token_source: TokenSource,
51 },
52
53 #[diagnostic(severity(Error), code(unsupported_description))]
54 #[error("unsupported description")]
55 UnsupportedDescription {
56 #[source_code]
57 input: MultiSources,
58 #[label("this description is not supported by the simulator")]
59 error_location: SourceSpan,
60 token_source: TokenSource,
61 },
62
63 #[diagnostic(severity(Error), code(combinational_loop))]
64 #[error("combinational loop detected")]
65 CombinationalLoop {
66 #[source_code]
67 input: MultiSources,
68 #[label("Error location")]
69 error_location: SourceSpan,
70 #[label(collection, "involved in loop")]
71 loop_participants: Vec<SourceSpan>,
72 token_source: TokenSource,
73 },
74}
75
76fn source_with_context(
77 token: &TokenRange,
78 context: &[TokenRange],
79) -> (MultiSources, Vec<SourceSpan>) {
80 let path = token.beg.source.to_string();
81 let text = token.beg.source.get_text();
82
83 let mut base = text.len();
84 let mut ranges = Vec::new();
85 let mut sources = Vec::new();
86
87 sources.push(Source { path, text });
88
89 for x in context.iter().rev() {
90 let path = x.beg.source.to_string();
91 let text = x.beg.source.get_text();
92
93 let mut range = *x;
94 range.offset(base as u32);
95 ranges.push(range.into());
96
97 base += text.len();
98
99 sources.push(Source { path, text });
100 }
101
102 let sources = MultiSources { sources };
103 (sources, ranges)
104}
105
106impl SimulatorError {
107 pub fn no_initial_block(module_name: &str, token: &TokenRange) -> Self {
108 let path = token.beg.source.to_string();
109 let text = token.beg.source.get_text();
110 let input = MultiSources {
111 sources: vec![Source { path, text }],
112 };
113 SimulatorError::NoInitialBlock {
114 module_name: module_name.to_string(),
115 input,
116 error_location: (*token).into(),
117 token_source: token.beg.source,
118 }
119 }
120
121 pub fn unresolved_expression(token: &TokenRange) -> Self {
122 let path = token.beg.source.to_string();
123 let text = token.beg.source.get_text();
124 let input = MultiSources {
125 sources: vec![Source { path, text }],
126 };
127 SimulatorError::UnresolvedExpression {
128 input,
129 error_location: (*token).into(),
130 token_source: token.beg.source,
131 }
132 }
133
134 pub fn unsupported_description(token: &TokenRange) -> Self {
135 let path = token.beg.source.to_string();
136 let text = token.beg.source.get_text();
137 let input = MultiSources {
138 sources: vec![Source { path, text }],
139 };
140 SimulatorError::UnsupportedDescription {
141 input,
142 error_location: (*token).into(),
143 token_source: token.beg.source,
144 }
145 }
146
147 pub fn recursive_function(function_name: &str, token: &TokenRange) -> Self {
148 let path = token.beg.source.to_string();
149 let text = token.beg.source.get_text();
150 let input = MultiSources {
151 sources: vec![Source { path, text }],
152 };
153 SimulatorError::RecursiveFunction {
154 function_name: function_name.to_string(),
155 input,
156 error_location: (*token).into(),
157 token_source: token.beg.source,
158 }
159 }
160
161 pub fn combinational_loop(token: &TokenRange, participants: &[TokenRange]) -> Self {
162 let (input, loop_participants) = source_with_context(token, participants);
163 SimulatorError::CombinationalLoop {
164 input,
165 error_location: (*token).into(),
166 loop_participants,
167 token_source: token.beg.source,
168 }
169 }
170}