Skip to main content

spade_hir/
query.rs

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    // FIXME: To support patterns, this needs to not be just Loc<Expression> anymore
30    ids: BTreeMap<ExprID, Loc<Expression>>,
31}
32
33// Public functions
34impl 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
70// Visitors
71impl<'a> QueryCache {
72    fn visit_executable(&mut self, item: ExecutableItem) {
73        match &item {
74            ExecutableItem::EnumInstance {
75                base_enum: _,
76                variant: _,
77            } => {
78                // FIXME: Map this loc
79            }
80            // Structs are stored as types rather than struct instances
81            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            // FIXME Visit types
103            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                // FIXME: handle name and turbofish
131                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                // FIXME: handle callee and turbofish
143                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                // FIXME: Handle arguments
157                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                // FIXME: Visit cond
190                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                // FIXME: Handle ty
260                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                // FIXME: Handle value_type
273                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                            // FIXME: Handle name
314
315                            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 &params.0 {
341                self.visit_type_spec(&param.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}