microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.25.1

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/compiler/qsc_ast/src/visit.rs

430lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::ast::{
5 Attr, Block, CallableBody, CallableDecl, Expr, ExprKind, FieldAccess, FieldAssign, FieldDef,
6 FunctorExpr, FunctorExprKind, Ident, ImportKind, ImportOrExportItem, Item, ItemKind, Namespace,
7 Package, Pat, PatKind, Path, PathKind, QubitInit, QubitInitKind, SpecBody, SpecDecl, Stmt,
8 StmtKind, StringComponent, StructDecl, TopLevelNode, Ty, TyDef, TyDefKind, TyKind,
9 TypeParameter,
10};
11
12pub trait Visitor<'a>: Sized {
13 fn visit_package(&mut self, package: &'a Package) {
14 walk_package(self, package);
15 }
16
17 fn visit_namespace(&mut self, namespace: &'a Namespace) {
18 walk_namespace(self, namespace);
19 }
20
21 fn visit_item(&mut self, item: &'a Item) {
22 walk_item(self, item);
23 }
24
25 fn visit_attr(&mut self, attr: &'a Attr) {
26 walk_attr(self, attr);
27 }
28
29 fn visit_ty_def(&mut self, def: &'a TyDef) {
30 walk_ty_def(self, def);
31 }
32
33 fn visit_callable_decl(&mut self, decl: &'a CallableDecl) {
34 walk_callable_decl(self, decl);
35 }
36
37 fn visit_struct_decl(&mut self, decl: &'a StructDecl) {
38 walk_struct_decl(self, decl);
39 }
40
41 fn visit_import_or_export(&mut self, item: &'a ImportOrExportItem) {
42 walk_import_or_export(self, item);
43 }
44
45 fn visit_field_def(&mut self, def: &'a FieldDef) {
46 walk_field_def(self, def);
47 }
48
49 fn visit_spec_decl(&mut self, decl: &'a SpecDecl) {
50 walk_spec_decl(self, decl);
51 }
52
53 fn visit_functor_expr(&mut self, expr: &'a FunctorExpr) {
54 walk_functor_expr(self, expr);
55 }
56
57 fn visit_ty(&mut self, ty: &'a Ty) {
58 walk_ty(self, ty);
59 }
60
61 fn visit_block(&mut self, block: &'a Block) {
62 walk_block(self, block);
63 }
64
65 fn visit_stmt(&mut self, stmt: &'a Stmt) {
66 walk_stmt(self, stmt);
67 }
68
69 fn visit_expr(&mut self, expr: &'a Expr) {
70 walk_expr(self, expr);
71 }
72
73 fn visit_field_assign(&mut self, assign: &'a FieldAssign) {
74 walk_field_assign(self, assign);
75 }
76
77 fn visit_pat(&mut self, pat: &'a Pat) {
78 walk_pat(self, pat);
79 }
80
81 fn visit_qubit_init(&mut self, init: &'a QubitInit) {
82 walk_qubit_init(self, init);
83 }
84
85 fn visit_path(&mut self, path: &'a Path) {
86 walk_path(self, path);
87 }
88
89 fn visit_path_kind(&mut self, path: &'a PathKind) {
90 walk_path_kind(self, path);
91 }
92
93 fn visit_ident(&mut self, _: &'a Ident) {}
94
95 fn visit_idents(&mut self, idents: &'a [Ident]) {
96 walk_idents(self, idents);
97 }
98}
99
100pub fn walk_package<'a>(vis: &mut impl Visitor<'a>, package: &'a Package) {
101 package.nodes.iter().for_each(|n| match n {
102 TopLevelNode::Namespace(ns) => vis.visit_namespace(ns),
103 TopLevelNode::Stmt(stmt) => vis.visit_stmt(stmt),
104 });
105 package.entry.iter().for_each(|e| vis.visit_expr(e));
106}
107
108pub fn walk_namespace<'a>(vis: &mut impl Visitor<'a>, namespace: &'a Namespace) {
109 vis.visit_idents(&namespace.name);
110 namespace.items.iter().for_each(|i| vis.visit_item(i));
111}
112
113pub fn walk_item<'a>(vis: &mut impl Visitor<'a>, item: &'a Item) {
114 item.attrs.iter().for_each(|a| vis.visit_attr(a));
115 match &*item.kind {
116 ItemKind::Err => {}
117 ItemKind::Callable(decl) => vis.visit_callable_decl(decl),
118 ItemKind::Open(ns, alias) => {
119 vis.visit_path_kind(ns);
120 if let Some(a) = alias.as_ref() {
121 vis.visit_ident(a);
122 }
123 }
124 ItemKind::Ty(ident, def) => {
125 vis.visit_ident(ident);
126 vis.visit_ty_def(def);
127 }
128 ItemKind::Struct(decl) => vis.visit_struct_decl(decl),
129 ItemKind::ImportOrExport(decl) => {
130 decl.items
131 .iter()
132 .for_each(|item| vis.visit_import_or_export(item));
133 }
134 }
135}
136pub fn walk_attr<'a>(vis: &mut impl Visitor<'a>, attr: &'a Attr) {
137 vis.visit_ident(&attr.name);
138 vis.visit_expr(&attr.arg);
139}
140
141pub fn walk_ty_def<'a>(vis: &mut impl Visitor<'a>, def: &'a TyDef) {
142 match &*def.kind {
143 TyDefKind::Field(name, ty) => {
144 if let Some(n) = name.as_ref() {
145 vis.visit_ident(n);
146 }
147 vis.visit_ty(ty);
148 }
149 TyDefKind::Paren(def) => vis.visit_ty_def(def),
150 TyDefKind::Tuple(defs) => defs.iter().for_each(|d| vis.visit_ty_def(d)),
151 TyDefKind::Err => {}
152 }
153}
154
155pub fn walk_callable_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a CallableDecl) {
156 vis.visit_ident(&decl.name);
157 decl.generics.iter().for_each(|p| {
158 vis.visit_ident(&p.ty);
159 p.constraints.0.iter().for_each(|b| {
160 vis.visit_ident(&b.name);
161 b.parameters
162 .iter()
163 .for_each(|crate::ast::ConstraintParameter { ty, .. }| {
164 vis.visit_ty(ty);
165 });
166 });
167 });
168 vis.visit_pat(&decl.input);
169 vis.visit_ty(&decl.output);
170 decl.functors.iter().for_each(|f| vis.visit_functor_expr(f));
171 match &*decl.body {
172 CallableBody::Block(block) => vis.visit_block(block),
173 CallableBody::Specs(specs) => specs.iter().for_each(|s| vis.visit_spec_decl(s)),
174 }
175}
176
177pub fn walk_struct_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a StructDecl) {
178 vis.visit_ident(&decl.name);
179 decl.fields.iter().for_each(|f| vis.visit_field_def(f));
180}
181
182pub fn walk_import_or_export<'a>(vis: &mut impl Visitor<'a>, item: &'a ImportOrExportItem) {
183 vis.visit_path_kind(&item.path);
184 if let ImportKind::Direct {
185 alias: Some(ref alias),
186 } = item.kind
187 {
188 vis.visit_ident(alias);
189 }
190}
191
192pub fn walk_field_def<'a>(vis: &mut impl Visitor<'a>, def: &'a FieldDef) {
193 vis.visit_ident(&def.name);
194 vis.visit_ty(&def.ty);
195}
196
197pub fn walk_spec_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a SpecDecl) {
198 match &decl.body {
199 SpecBody::Gen(_) => {}
200 SpecBody::Impl(pat, block) => {
201 vis.visit_pat(pat);
202 vis.visit_block(block);
203 }
204 }
205}
206
207pub fn walk_functor_expr<'a>(vis: &mut impl Visitor<'a>, expr: &'a FunctorExpr) {
208 match &*expr.kind {
209 FunctorExprKind::BinOp(_, lhs, rhs) => {
210 vis.visit_functor_expr(lhs);
211 vis.visit_functor_expr(rhs);
212 }
213 FunctorExprKind::Lit(_) => {}
214 FunctorExprKind::Paren(expr) => vis.visit_functor_expr(expr),
215 }
216}
217
218pub fn walk_ty<'a>(vis: &mut impl Visitor<'a>, ty: &'a Ty) {
219 match &*ty.kind {
220 TyKind::Array(item) => vis.visit_ty(item),
221 TyKind::Arrow(_, lhs, rhs, functors) => {
222 vis.visit_ty(lhs);
223 vis.visit_ty(rhs);
224 if let Some(f) = functors.as_ref() {
225 vis.visit_functor_expr(f);
226 }
227 }
228 TyKind::Hole | TyKind::Err => {}
229 TyKind::Paren(ty) => vis.visit_ty(ty),
230 TyKind::Path(path) => vis.visit_path_kind(path),
231 TyKind::Param(TypeParameter {
232 ty,
233 constraints: bounds,
234 ..
235 }) => {
236 for bound in &bounds.0 {
237 vis.visit_ident(&bound.name);
238
239 bound.parameters.iter().for_each(
240 |crate::ast::ConstraintParameter { ty, .. }| {
241 vis.visit_ty(ty);
242 },
243 );
244 }
245 vis.visit_ident(ty);
246 }
247 TyKind::Tuple(tys) => tys.iter().for_each(|t| vis.visit_ty(t)),
248 }
249}
250
251pub fn walk_block<'a>(vis: &mut impl Visitor<'a>, block: &'a Block) {
252 block.stmts.iter().for_each(|s| vis.visit_stmt(s));
253}
254
255pub fn walk_stmt<'a>(vis: &mut impl Visitor<'a>, stmt: &'a Stmt) {
256 match &*stmt.kind {
257 StmtKind::Empty | StmtKind::Err => {}
258 StmtKind::Expr(expr) | StmtKind::Semi(expr) => vis.visit_expr(expr),
259 StmtKind::Item(item) => vis.visit_item(item),
260 StmtKind::Local(_, pat, value) => {
261 vis.visit_pat(pat);
262 vis.visit_expr(value);
263 }
264 StmtKind::Qubit(_, pat, init, block) => {
265 vis.visit_pat(pat);
266 vis.visit_qubit_init(init);
267 if let Some(b) = block.as_ref() {
268 vis.visit_block(b);
269 }
270 }
271 }
272}
273
274#[allow(clippy::too_many_lines)]
275pub fn walk_expr<'a>(vis: &mut impl Visitor<'a>, expr: &'a Expr) {
276 match &*expr.kind {
277 ExprKind::Array(exprs) => exprs.iter().for_each(|e| vis.visit_expr(e)),
278 ExprKind::ArrayRepeat(item, size) => {
279 vis.visit_expr(item);
280 vis.visit_expr(size);
281 }
282 ExprKind::Assign(lhs, rhs)
283 | ExprKind::AssignOp(_, lhs, rhs)
284 | ExprKind::BinOp(_, lhs, rhs) => {
285 vis.visit_expr(lhs);
286 vis.visit_expr(rhs);
287 }
288 ExprKind::AssignUpdate(record, index, value) => {
289 vis.visit_expr(record);
290 vis.visit_expr(index);
291 vis.visit_expr(value);
292 }
293 ExprKind::Block(block) => vis.visit_block(block),
294 ExprKind::Call(callee, arg) => {
295 vis.visit_expr(callee);
296 vis.visit_expr(arg);
297 }
298 ExprKind::Conjugate(within, apply) => {
299 vis.visit_block(within);
300 vis.visit_block(apply);
301 }
302 ExprKind::Fail(msg) => vis.visit_expr(msg),
303 ExprKind::Field(record, name) => {
304 vis.visit_expr(record);
305 if let FieldAccess::Ok(name) = name {
306 vis.visit_ident(name);
307 }
308 }
309 ExprKind::For(pat, iter, block) => {
310 vis.visit_pat(pat);
311 vis.visit_expr(iter);
312 vis.visit_block(block);
313 }
314 ExprKind::If(cond, body, otherwise) => {
315 vis.visit_expr(cond);
316 vis.visit_block(body);
317 if let Some(e) = otherwise.as_ref() {
318 vis.visit_expr(e);
319 }
320 }
321 ExprKind::Index(array, index) => {
322 vis.visit_expr(array);
323 vis.visit_expr(index);
324 }
325 ExprKind::Interpolate(components) => {
326 for component in components.as_ref() {
327 match component {
328 StringComponent::Expr(expr) => vis.visit_expr(expr.as_ref()),
329 StringComponent::Lit(_) => {}
330 }
331 }
332 }
333 ExprKind::Lambda(_, pat, expr) => {
334 vis.visit_pat(pat);
335 vis.visit_expr(expr);
336 }
337 ExprKind::Paren(expr) | ExprKind::Return(expr) | ExprKind::UnOp(_, expr) => {
338 vis.visit_expr(expr);
339 }
340 ExprKind::Path(path) => vis.visit_path_kind(path),
341 ExprKind::Range(start, step, end) => {
342 if let Some(s) = start.as_ref() {
343 vis.visit_expr(s);
344 }
345 if let Some(s) = step.as_ref() {
346 vis.visit_expr(s);
347 }
348 if let Some(e) = end.as_ref() {
349 vis.visit_expr(e);
350 }
351 }
352 ExprKind::Repeat(body, until, fixup) => {
353 vis.visit_block(body);
354 vis.visit_expr(until);
355 if let Some(f) = fixup.as_ref() {
356 vis.visit_block(f);
357 }
358 }
359 ExprKind::Struct(name, copy, fields) => {
360 vis.visit_path_kind(name);
361 if let Some(c) = copy.as_ref() {
362 vis.visit_expr(c);
363 }
364 fields.iter().for_each(|f| vis.visit_field_assign(f));
365 }
366 ExprKind::TernOp(_, e1, e2, e3) => {
367 vis.visit_expr(e1);
368 vis.visit_expr(e2);
369 vis.visit_expr(e3);
370 }
371 ExprKind::Tuple(exprs) => exprs.iter().for_each(|e| vis.visit_expr(e)),
372 ExprKind::While(cond, block) => {
373 vis.visit_expr(cond);
374 vis.visit_block(block);
375 }
376 ExprKind::Err | ExprKind::Hole | ExprKind::Lit(_) => {}
377 }
378}
379
380pub fn walk_field_assign<'a>(vis: &mut impl Visitor<'a>, assign: &'a FieldAssign) {
381 vis.visit_ident(&assign.field);
382 vis.visit_expr(&assign.value);
383}
384
385pub fn walk_pat<'a>(vis: &mut impl Visitor<'a>, pat: &'a Pat) {
386 match &*pat.kind {
387 PatKind::Bind(name, ty) => {
388 vis.visit_ident(name);
389 if let Some(t) = ty.as_ref() {
390 vis.visit_ty(t);
391 }
392 }
393 PatKind::Discard(ty) => ty.iter().for_each(|t| vis.visit_ty(t)),
394 PatKind::Elided | PatKind::Err => {}
395 PatKind::Paren(pat) => vis.visit_pat(pat),
396 PatKind::Tuple(pats) => pats.iter().for_each(|p| vis.visit_pat(p)),
397 }
398}
399
400pub fn walk_qubit_init<'a>(vis: &mut impl Visitor<'a>, init: &'a QubitInit) {
401 match &*init.kind {
402 QubitInitKind::Array(len) => vis.visit_expr(len),
403 QubitInitKind::Paren(init) => vis.visit_qubit_init(init),
404 QubitInitKind::Single | QubitInitKind::Err => {}
405 QubitInitKind::Tuple(inits) => inits.iter().for_each(|i| vis.visit_qubit_init(i)),
406 }
407}
408
409pub fn walk_path<'a>(vis: &mut impl Visitor<'a>, path: &'a Path) {
410 if let Some(ref parts) = path.segments {
411 vis.visit_idents(parts);
412 }
413 vis.visit_ident(&path.name);
414}
415
416pub fn walk_path_kind<'a>(vis: &mut impl Visitor<'a>, path: &'a PathKind) {
417 match path {
418 PathKind::Ok(path) => vis.visit_path(path),
419 PathKind::Err(Some(incomplete_path)) => {
420 vis.visit_idents(&incomplete_path.segments);
421 }
422 PathKind::Err(None) => {}
423 }
424}
425
426pub fn walk_idents<'a>(vis: &mut impl Visitor<'a>, idents: &'a [Ident]) {
427 for i in idents {
428 vis.visit_ident(i);
429 }
430}
431