1use std::collections::BTreeMap;
2
3use serde::{Deserialize, Serialize};
4use spade_common::{
5 id_tracker::ExprID,
6 loc_map::LocMap,
7 location_info::{Loc, WithLocation},
8 name::NameID,
9};
10
11use crate::{
12 expression::NamedArgument, ArgumentList, Binding, ConstGeneric, Enum, ExecutableItem, ExprKind,
13 Expression, ItemList, Pattern, PatternArgument, PatternKind, Register, Statement, Struct,
14 TypeDeclKind, TypeDeclaration, TypeExpression, TypeSpec,
15};
16
17#[derive(Debug, Serialize, Deserialize)]
18pub enum Thing {
19 Pattern(Pattern),
20 Expr(Expression),
21 Statement(Statement),
22 Executable(ExecutableItem),
23}
24
25#[derive(Serialize, Deserialize)]
26pub struct QueryCache {
27 things: LocMap<Thing>,
28 names: LocMap<NameID>,
29 ids: BTreeMap<ExprID, Loc<Expression>>,
31}
32
33impl QueryCache {
35 pub fn empty() -> Self {
36 QueryCache {
37 things: LocMap::new(),
38 names: LocMap::new(),
39 ids: BTreeMap::new(),
40 }
41 }
42
43 pub fn from_item_list(items: &ItemList) -> Self {
44 let mut result = QueryCache::empty();
45
46 for (_, item) in items.executables.iter() {
47 result.visit_executable(item.clone());
48 }
49
50 for (_, ty) in items.types.iter() {
51 result.visit_type_decl(ty)
52 }
53
54 result
55 }
56
57 pub fn things_around(&self, loc: &Loc<()>) -> Vec<Loc<&Thing>> {
58 self.things.around(loc)
59 }
60
61 pub fn names_around(&self, loc: &Loc<()>) -> Vec<Loc<&NameID>> {
62 self.names.around(loc)
63 }
64
65 pub fn id_to_expression(&self, id: ExprID) -> Option<&Loc<Expression>> {
66 self.ids.get(&id).map(|x| x)
67 }
68}
69
70impl<'a> QueryCache {
72 fn visit_executable(&mut self, item: ExecutableItem) {
73 match &item {
74 ExecutableItem::EnumInstance {
75 base_enum: _,
76 variant: _,
77 } => {
78 }
80 ExecutableItem::StructInstance => {}
82 ExecutableItem::Unit(unit) => {
83 self.things
84 .insert(unit.loc().map(|_| Thing::Executable(item.clone())));
85
86 self.visit_expression(&unit.body)
87 }
88 ExecutableItem::ExternUnit(_, unit) => {
89 self.things
90 .insert(unit.loc().map(|_| Thing::Executable(item.clone())));
91 }
92 }
93 }
94
95 fn visit_expr_kind(&mut self, kind: &Loc<&ExprKind>) {
96 match &kind.inner {
97 crate::ExprKind::Error => {}
98 crate::ExprKind::Identifier(ident) => self.names.insert(ident.clone().at_loc(kind)),
99 crate::ExprKind::IntLiteral(_, _) => {}
100 crate::ExprKind::BoolLiteral(_) => {}
101 crate::ExprKind::TriLiteral(_) => {}
102 crate::ExprKind::TypeLevelInteger(_) => {}
104 crate::ExprKind::CreatePorts => {}
105 crate::ExprKind::TupleLiteral(inner) | crate::ExprKind::ArrayLiteral(inner) => {
106 for expr in inner {
107 self.visit_expression(expr)
108 }
109 }
110 crate::ExprKind::ArrayShorthandLiteral(expr, _) => self.visit_expression(expr),
111 crate::ExprKind::Index(lhs, rhs) => {
112 self.visit_expression(lhs);
113 self.visit_expression(rhs);
114 }
115 crate::ExprKind::RangeIndex {
116 target,
117 start: _,
118 end: _,
119 } => self.visit_expression(target),
120 crate::ExprKind::TupleIndex(target, _) => self.visit_expression(target),
121 crate::ExprKind::FieldAccess(target, _) => self.visit_expression(target),
122 crate::ExprKind::MethodCall {
123 target,
124 name: _,
125 args,
126 call_kind: _,
127 turbofish: _,
128 safety: _,
129 } => {
130 self.visit_expression(target);
132 self.visit_arg_list(args)
133 }
134 crate::ExprKind::Call {
135 kind: _,
136 callee,
137 args,
138 turbofish: _turbofish,
139 safety: _,
140 } => {
141 self.names.insert(callee.clone());
142 self.visit_arg_list(args)
144 }
145 crate::ExprKind::LambdaDef {
146 unit_kind: _,
147 lambda_type: _,
148 type_params: _,
149 lambda_unit: _,
150 arguments: _,
151 outer_generic_params: _,
152 body,
153 captures: _,
154 clock: _,
155 } => {
156 self.visit_expression(body);
158 }
159 crate::ExprKind::BinaryOperator(lhs, _, rhs) => {
160 self.visit_expression(lhs);
161 self.visit_expression(rhs);
162 }
163 crate::ExprKind::UnaryOperator(_, operand) => self.visit_expression(operand),
164 crate::ExprKind::Match(cond, branches) => {
165 self.visit_expression(cond);
166
167 for (pattern, if_cond, expr) in branches {
168 self.visit_pattern(pattern);
169 if let Some(if_cond) = if_cond {
170 self.visit_expression(if_cond);
171 }
172 self.visit_expression(expr);
173 }
174 }
175 crate::ExprKind::Block(b) => {
176 for stmt in &b.statements {
177 self.visit_statements(&stmt)
178 }
179 if let Some(result) = &b.result {
180 self.visit_expression(result)
181 }
182 }
183 crate::ExprKind::If(cond, lhs, rhs) => {
184 self.visit_expression(cond);
185 self.visit_expression(lhs);
186 self.visit_expression(rhs);
187 }
188 crate::ExprKind::TypeLevelIf(_cond, lhs, rhs) => {
189 self.visit_expression(lhs);
191 self.visit_expression(rhs);
192 }
193 crate::ExprKind::PipelineRef {
194 stage: _,
195 name: _,
196 declares_name: _,
197 depth_typeexpr_id: _,
198 } => {}
199 crate::ExprKind::StageValid => {}
200 crate::ExprKind::StageReady => {}
201 crate::ExprKind::StaticUnreachable(_) | crate::ExprKind::Null => {}
202 }
203 }
204
205 fn visit_expression(&mut self, expr: &'a Loc<Expression>) {
206 self.things
207 .insert(expr.loc().map(|_| Thing::Expr(expr.inner.clone())));
208 self.ids.insert(expr.id, expr.clone());
209
210 self.visit_expr_kind(&Loc::new(&expr.kind, expr.span, expr.file_id));
211 }
212
213 fn visit_pattern(&mut self, pat: &'a Loc<Pattern>) {
214 self.things
215 .insert(pat.loc().map(|_| Thing::Pattern(pat.inner.clone())));
216 match &pat.inner.kind {
217 PatternKind::Integer(_) => {}
218 PatternKind::Bool(_) => {}
219 PatternKind::Name {
220 name,
221 pre_declared: _,
222 } => {
223 self.names.insert(name.clone());
224 }
225 PatternKind::Tuple(inner) => {
226 for pat in inner {
227 self.visit_pattern(&pat);
228 }
229 }
230 PatternKind::Array(inner) => {
231 for pat in inner {
232 self.visit_pattern(&pat);
233 }
234 }
235 PatternKind::Type(base, args) => {
236 self.names.insert(base.clone());
237 for PatternArgument {
238 target: _,
239 value,
240 kind: _,
241 } in args
242 {
243 self.visit_pattern(value);
244 }
245 }
246 }
247 }
248
249 fn visit_statements(&mut self, stmt: &'a Loc<Statement>) {
250 match &stmt.inner {
251 Statement::Error => {}
252 Statement::Binding(Binding {
253 pattern,
254 ty: _,
255 value,
256 wal_trace: _,
257 }) => {
258 self.visit_pattern(pattern);
259 self.visit_expression(value)
261 }
262 Statement::Register(Register {
263 pattern,
264 clock,
265 reset,
266 initial,
267 value,
268 value_type: _value_type,
269 attributes: _,
270 }) => {
271 self.visit_pattern(pattern);
272 self.visit_expression(clock);
274 if let Some((trig, val)) = reset {
275 self.visit_expression(trig);
276 self.visit_expression(val);
277 }
278 if let Some(initial) = initial {
279 self.visit_expression(initial)
280 }
281 self.visit_expression(value);
282 }
283 Statement::Expression(e) => {
284 self.visit_expression(e);
285 }
286 Statement::Declaration(names) => {
287 for name in names {
288 self.names.insert(name.clone());
289 }
290 }
291 Statement::PipelineRegMarker(_) => {}
292 Statement::Label(l) => {
293 self.names.insert(l.clone());
294 }
295 Statement::Assert(expr) => self.visit_expression(expr),
296 Statement::Set { target, value } => {
297 self.visit_expression(target);
298 self.visit_expression(value);
299 }
300 Statement::WalSuffixed {
301 suffix: _,
302 target: _,
303 } => {}
304 }
305 }
306
307 fn visit_arg_list(&mut self, args: &'a ArgumentList<Expression>) {
308 match args {
309 ArgumentList::Named(l) => {
310 for arg in l {
311 match arg {
312 NamedArgument::Full(_name, expr) => {
313 self.visit_expression(expr)
316 }
317 NamedArgument::Short(_, expr) => self.visit_expression(expr),
318 }
319 }
320 }
321 ArgumentList::Positional(args) => {
322 for arg in args {
323 self.visit_expression(arg)
324 }
325 }
326 }
327 }
328
329 fn visit_type_decl(&mut self, ty: &TypeDeclaration) {
330 self.names.insert(ty.name.clone());
331 match &ty.kind {
332 TypeDeclKind::Enum(e) => self.visit_enum_decl(e),
333 TypeDeclKind::Primitive(_) => {}
334 TypeDeclKind::Struct(s) => self.visit_struct(s),
335 }
336 }
337
338 fn visit_enum_decl(&mut self, e: &Loc<Enum>) {
339 for (_, params) in &e.options {
340 for param in ¶ms.0 {
341 self.visit_type_spec(¶m.ty);
342 }
343 }
344 }
345
346 fn visit_struct(&mut self, s: &Loc<Struct>) {
347 for member in &s.members.0 {
348 self.visit_type_spec(&member.ty);
349 }
350 }
351
352 fn visit_type_spec(&mut self, ts: &Loc<TypeSpec>) {
353 match &ts.inner {
354 TypeSpec::Declared(n, params) => {
355 self.names.insert(n.clone());
356 for param in params {
357 self.visit_type_expr(param);
358 }
359 }
360 TypeSpec::Generic(n) => self.names.insert(n.clone()),
361 TypeSpec::Tuple(inner) => {
362 for i in inner {
363 self.visit_type_spec(i);
364 }
365 }
366 TypeSpec::Array { inner, size } => {
367 self.visit_type_spec(inner);
368 self.visit_type_expr(size);
369 }
370 TypeSpec::Inverted(inner) => self.visit_type_spec(inner),
371 TypeSpec::Wire(inner) => self.visit_type_spec(inner),
372 TypeSpec::TraitSelf(_) => {}
373 TypeSpec::Wildcard(_) => {}
374 }
375 }
376
377 fn visit_type_expr(&mut self, te: &Loc<TypeExpression>) {
378 match &te.inner {
379 TypeExpression::Integer(_) => {}
380 TypeExpression::String(_) => {}
381 TypeExpression::TypeSpec(ts) => self.visit_type_spec(&ts.clone().at_loc(te)),
382 TypeExpression::ConstGeneric(cg) => {
383 self.visit_const_generic(cg);
384 }
385 }
386 }
387
388 fn visit_const_generic(&mut self, cg: &Loc<ConstGeneric>) {
389 match &cg.inner {
390 ConstGeneric::Name(n) => self.names.insert(n.clone()),
391 ConstGeneric::Int(_) => {}
392 ConstGeneric::Str(_) => {}
393 ConstGeneric::Add(lhs, rhs) => {
394 self.visit_const_generic(lhs);
395 self.visit_const_generic(rhs);
396 }
397 ConstGeneric::Sub(lhs, rhs) => {
398 self.visit_const_generic(lhs);
399 self.visit_const_generic(rhs);
400 }
401 ConstGeneric::Mul(lhs, rhs) => {
402 self.visit_const_generic(lhs);
403 self.visit_const_generic(rhs);
404 }
405 ConstGeneric::Div(lhs, rhs) => {
406 self.visit_const_generic(lhs);
407 self.visit_const_generic(rhs);
408 }
409 ConstGeneric::Mod(lhs, rhs) => {
410 self.visit_const_generic(lhs);
411 self.visit_const_generic(rhs);
412 }
413 ConstGeneric::Eq(lhs, rhs) => {
414 self.visit_const_generic(lhs);
415 self.visit_const_generic(rhs);
416 }
417 ConstGeneric::NotEq(lhs, rhs) => {
418 self.visit_const_generic(lhs);
419 self.visit_const_generic(rhs);
420 }
421 ConstGeneric::UintBitsToFit(inner) => self.visit_const_generic(inner),
422 }
423 }
424}