spade_hir/
query.rs

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