microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.19.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/compiler/qsc_ast/src/visit.rs

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