microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.8.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_ast/src/visit.rs

353lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::ast::{
5 Attr, Block, CallableBody, CallableDecl, Expr, ExprKind, FieldAssign, FieldDef, FunctorExpr,
6 FunctorExprKind, Ident, Idents, Item, ItemKind, Namespace, Package, Pat, PatKind, Path,
7 QubitInit, QubitInitKind, SpecBody, SpecDecl, Stmt, StmtKind, StringComponent, StructDecl,
8 TopLevelNode, Ty, TyDef, TyDefKind, TyKind,
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_ident(&mut self, _: &'a Ident) {}
85
86 fn visit_idents(&mut self, idents: &'a Idents) {
87 walk_idents(self, idents);
88 }
89}
90
91pub fn walk_package<'a>(vis: &mut impl Visitor<'a>, package: &'a Package) {
92 package.nodes.iter().for_each(|n| match n {
93 TopLevelNode::Namespace(ns) => vis.visit_namespace(ns),
94 TopLevelNode::Stmt(stmt) => vis.visit_stmt(stmt),
95 });
96 package.entry.iter().for_each(|e| vis.visit_expr(e));
97}
98
99pub fn walk_namespace<'a>(vis: &mut impl Visitor<'a>, namespace: &'a Namespace) {
100 vis.visit_idents(&namespace.name);
101 namespace.items.iter().for_each(|i| vis.visit_item(i));
102}
103
104pub fn walk_item<'a>(vis: &mut impl Visitor<'a>, item: &'a Item) {
105 item.attrs.iter().for_each(|a| vis.visit_attr(a));
106 match &*item.kind {
107 ItemKind::Err => {}
108 ItemKind::Callable(decl) => vis.visit_callable_decl(decl),
109 ItemKind::Open(ns, alias) => {
110 vis.visit_idents(ns);
111 alias.iter().for_each(|a| vis.visit_ident(a));
112 }
113 ItemKind::Ty(ident, def) => {
114 vis.visit_ident(ident);
115 vis.visit_ty_def(def);
116 }
117 ItemKind::Struct(decl) => vis.visit_struct_decl(decl),
118 ItemKind::ImportOrExport(decl) => {
119 for item in &decl.items {
120 vis.visit_path(&item.path);
121 if let Some(ref alias) = item.alias {
122 vis.visit_ident(alias);
123 }
124 }
125 }
126 }
127}
128
129pub fn walk_attr<'a>(vis: &mut impl Visitor<'a>, attr: &'a Attr) {
130 vis.visit_ident(&attr.name);
131 vis.visit_expr(&attr.arg);
132}
133
134pub fn walk_ty_def<'a>(vis: &mut impl Visitor<'a>, def: &'a TyDef) {
135 match &*def.kind {
136 TyDefKind::Field(name, ty) => {
137 name.iter().for_each(|n| vis.visit_ident(n));
138 vis.visit_ty(ty);
139 }
140 TyDefKind::Paren(def) => vis.visit_ty_def(def),
141 TyDefKind::Tuple(defs) => defs.iter().for_each(|d| vis.visit_ty_def(d)),
142 TyDefKind::Err => {}
143 }
144}
145
146pub fn walk_callable_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a CallableDecl) {
147 vis.visit_ident(&decl.name);
148 decl.generics.iter().for_each(|p| vis.visit_ident(p));
149 vis.visit_pat(&decl.input);
150 vis.visit_ty(&decl.output);
151 decl.functors.iter().for_each(|f| vis.visit_functor_expr(f));
152 match &*decl.body {
153 CallableBody::Block(block) => vis.visit_block(block),
154 CallableBody::Specs(specs) => specs.iter().for_each(|s| vis.visit_spec_decl(s)),
155 }
156}
157
158pub fn walk_struct_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a StructDecl) {
159 vis.visit_ident(&decl.name);
160 decl.fields.iter().for_each(|f| vis.visit_field_def(f));
161}
162
163pub fn walk_field_def<'a>(vis: &mut impl Visitor<'a>, def: &'a FieldDef) {
164 vis.visit_ident(&def.name);
165 vis.visit_ty(&def.ty);
166}
167
168pub fn walk_spec_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a SpecDecl) {
169 match &decl.body {
170 SpecBody::Gen(_) => {}
171 SpecBody::Impl(pat, block) => {
172 vis.visit_pat(pat);
173 vis.visit_block(block);
174 }
175 }
176}
177
178pub fn walk_functor_expr<'a>(vis: &mut impl Visitor<'a>, expr: &'a FunctorExpr) {
179 match &*expr.kind {
180 FunctorExprKind::BinOp(_, lhs, rhs) => {
181 vis.visit_functor_expr(lhs);
182 vis.visit_functor_expr(rhs);
183 }
184 FunctorExprKind::Lit(_) => {}
185 FunctorExprKind::Paren(expr) => vis.visit_functor_expr(expr),
186 }
187}
188
189pub fn walk_ty<'a>(vis: &mut impl Visitor<'a>, ty: &'a Ty) {
190 match &*ty.kind {
191 TyKind::Array(item) => vis.visit_ty(item),
192 TyKind::Arrow(_, lhs, rhs, functors) => {
193 vis.visit_ty(lhs);
194 vis.visit_ty(rhs);
195 functors.iter().for_each(|f| vis.visit_functor_expr(f));
196 }
197 TyKind::Hole | TyKind::Err => {}
198 TyKind::Paren(ty) => vis.visit_ty(ty),
199 TyKind::Path(path) => vis.visit_path(path),
200 TyKind::Param(name) => vis.visit_ident(name),
201 TyKind::Tuple(tys) => tys.iter().for_each(|t| vis.visit_ty(t)),
202 }
203}
204
205pub fn walk_block<'a>(vis: &mut impl Visitor<'a>, block: &'a Block) {
206 block.stmts.iter().for_each(|s| vis.visit_stmt(s));
207}
208
209pub fn walk_stmt<'a>(vis: &mut impl Visitor<'a>, stmt: &'a Stmt) {
210 match &*stmt.kind {
211 StmtKind::Empty | StmtKind::Err => {}
212 StmtKind::Expr(expr) | StmtKind::Semi(expr) => vis.visit_expr(expr),
213 StmtKind::Item(item) => vis.visit_item(item),
214 StmtKind::Local(_, pat, value) => {
215 vis.visit_pat(pat);
216 vis.visit_expr(value);
217 }
218 StmtKind::Qubit(_, pat, init, block) => {
219 vis.visit_pat(pat);
220 vis.visit_qubit_init(init);
221 block.iter().for_each(|b| vis.visit_block(b));
222 }
223 }
224}
225
226pub fn walk_expr<'a>(vis: &mut impl Visitor<'a>, expr: &'a Expr) {
227 match &*expr.kind {
228 ExprKind::Array(exprs) => exprs.iter().for_each(|e| vis.visit_expr(e)),
229 ExprKind::ArrayRepeat(item, size) => {
230 vis.visit_expr(item);
231 vis.visit_expr(size);
232 }
233 ExprKind::Assign(lhs, rhs)
234 | ExprKind::AssignOp(_, lhs, rhs)
235 | ExprKind::BinOp(_, lhs, rhs) => {
236 vis.visit_expr(lhs);
237 vis.visit_expr(rhs);
238 }
239 ExprKind::AssignUpdate(record, index, value) => {
240 vis.visit_expr(record);
241 vis.visit_expr(index);
242 vis.visit_expr(value);
243 }
244 ExprKind::Block(block) => vis.visit_block(block),
245 ExprKind::Call(callee, arg) => {
246 vis.visit_expr(callee);
247 vis.visit_expr(arg);
248 }
249 ExprKind::Conjugate(within, apply) => {
250 vis.visit_block(within);
251 vis.visit_block(apply);
252 }
253 ExprKind::Fail(msg) => vis.visit_expr(msg),
254 ExprKind::Field(record, name) => {
255 vis.visit_expr(record);
256 vis.visit_ident(name);
257 }
258 ExprKind::For(pat, iter, block) => {
259 vis.visit_pat(pat);
260 vis.visit_expr(iter);
261 vis.visit_block(block);
262 }
263 ExprKind::If(cond, body, otherwise) => {
264 vis.visit_expr(cond);
265 vis.visit_block(body);
266 otherwise.iter().for_each(|e| vis.visit_expr(e));
267 }
268 ExprKind::Index(array, index) => {
269 vis.visit_expr(array);
270 vis.visit_expr(index);
271 }
272 ExprKind::Interpolate(components) => {
273 for component in components.as_ref() {
274 match component {
275 StringComponent::Expr(expr) => vis.visit_expr(expr.as_ref()),
276 StringComponent::Lit(_) => {}
277 }
278 }
279 }
280 ExprKind::Lambda(_, pat, expr) => {
281 vis.visit_pat(pat);
282 vis.visit_expr(expr);
283 }
284 ExprKind::Paren(expr) | ExprKind::Return(expr) | ExprKind::UnOp(_, expr) => {
285 vis.visit_expr(expr);
286 }
287 ExprKind::Path(path) => vis.visit_path(path),
288 ExprKind::Range(start, step, end) => {
289 start.iter().for_each(|s| vis.visit_expr(s));
290 step.iter().for_each(|s| vis.visit_expr(s));
291 end.iter().for_each(|e| vis.visit_expr(e));
292 }
293 ExprKind::Repeat(body, until, fixup) => {
294 vis.visit_block(body);
295 vis.visit_expr(until);
296 fixup.iter().for_each(|f| vis.visit_block(f));
297 }
298 ExprKind::Struct(name, copy, fields) => {
299 vis.visit_path(name);
300 copy.iter().for_each(|c| vis.visit_expr(c));
301 fields.iter().for_each(|f| vis.visit_field_assign(f));
302 }
303 ExprKind::TernOp(_, e1, e2, e3) => {
304 vis.visit_expr(e1);
305 vis.visit_expr(e2);
306 vis.visit_expr(e3);
307 }
308 ExprKind::Tuple(exprs) => exprs.iter().for_each(|e| vis.visit_expr(e)),
309 ExprKind::While(cond, block) => {
310 vis.visit_expr(cond);
311 vis.visit_block(block);
312 }
313 ExprKind::Err | ExprKind::Hole | ExprKind::Lit(_) => {}
314 }
315}
316
317pub fn walk_field_assign<'a>(vis: &mut impl Visitor<'a>, assign: &'a FieldAssign) {
318 vis.visit_ident(&assign.field);
319 vis.visit_expr(&assign.value);
320}
321
322pub fn walk_pat<'a>(vis: &mut impl Visitor<'a>, pat: &'a Pat) {
323 match &*pat.kind {
324 PatKind::Bind(name, ty) => {
325 vis.visit_ident(name);
326 ty.iter().for_each(|t| vis.visit_ty(t));
327 }
328 PatKind::Discard(ty) => ty.iter().for_each(|t| vis.visit_ty(t)),
329 PatKind::Elided | PatKind::Err => {}
330 PatKind::Paren(pat) => vis.visit_pat(pat),
331 PatKind::Tuple(pats) => pats.iter().for_each(|p| vis.visit_pat(p)),
332 }
333}
334
335pub fn walk_qubit_init<'a>(vis: &mut impl Visitor<'a>, init: &'a QubitInit) {
336 match &*init.kind {
337 QubitInitKind::Array(len) => vis.visit_expr(len),
338 QubitInitKind::Paren(init) => vis.visit_qubit_init(init),
339 QubitInitKind::Single | QubitInitKind::Err => {}
340 QubitInitKind::Tuple(inits) => inits.iter().for_each(|i| vis.visit_qubit_init(i)),
341 }
342}
343
344pub fn walk_path<'a>(vis: &mut impl Visitor<'a>, path: &'a Path) {
345 if let Some(ref parts) = path.segments {
346 vis.visit_idents(parts);
347 }
348 vis.visit_ident(&path.name);
349}
350
351pub fn walk_idents<'a>(vis: &mut impl Visitor<'a>, idents: &'a Idents) {
352 idents.iter().for_each(|i| vis.visit_ident(i));
353}