microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
alex/second-api-refactor

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_ast/src/visit.rs

318lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::ast::{
5 Attr, Block, CallableBody, CallableDecl, Expr, ExprKind, FunctorExpr, FunctorExprKind, Ident,
6 Item, ItemKind, Namespace, Package, Pat, PatKind, Path, QubitInit, QubitInitKind, SpecBody,
7 SpecDecl, Stmt, StmtKind, StringComponent, TopLevelNode, Ty, TyDef, TyDefKind, TyKind,
8 Visibility,
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_visibility(&mut self, _: &'a Visibility) {}
29
30 fn visit_ty_def(&mut self, def: &'a TyDef) {
31 walk_ty_def(self, def);
32 }
33
34 fn visit_callable_decl(&mut self, decl: &'a CallableDecl) {
35 walk_callable_decl(self, decl);
36 }
37
38 fn visit_spec_decl(&mut self, decl: &'a SpecDecl) {
39 walk_spec_decl(self, decl);
40 }
41
42 fn visit_functor_expr(&mut self, expr: &'a FunctorExpr) {
43 walk_functor_expr(self, expr);
44 }
45
46 fn visit_ty(&mut self, ty: &'a Ty) {
47 walk_ty(self, ty);
48 }
49
50 fn visit_block(&mut self, block: &'a Block) {
51 walk_block(self, block);
52 }
53
54 fn visit_stmt(&mut self, stmt: &'a Stmt) {
55 walk_stmt(self, stmt);
56 }
57
58 fn visit_expr(&mut self, expr: &'a Expr) {
59 walk_expr(self, expr);
60 }
61
62 fn visit_pat(&mut self, pat: &'a Pat) {
63 walk_pat(self, pat);
64 }
65
66 fn visit_qubit_init(&mut self, init: &'a QubitInit) {
67 walk_qubit_init(self, init);
68 }
69
70 fn visit_path(&mut self, path: &'a Path) {
71 walk_path(self, path);
72 }
73
74 fn visit_ident(&mut self, _: &'a Ident) {}
75}
76
77pub fn walk_package<'a>(vis: &mut impl Visitor<'a>, package: &'a Package) {
78 package.nodes.iter().for_each(|n| match n {
79 TopLevelNode::Namespace(ns) => vis.visit_namespace(ns),
80 TopLevelNode::Stmt(stmt) => vis.visit_stmt(stmt),
81 });
82 package.entry.iter().for_each(|e| vis.visit_expr(e));
83}
84
85pub fn walk_namespace<'a>(vis: &mut impl Visitor<'a>, namespace: &'a Namespace) {
86 vis.visit_path(&namespace.name);
87 namespace.items.iter().for_each(|i| vis.visit_item(i));
88}
89
90pub fn walk_item<'a>(vis: &mut impl Visitor<'a>, item: &'a Item) {
91 item.attrs.iter().for_each(|a| vis.visit_attr(a));
92 item.visibility.iter().for_each(|v| vis.visit_visibility(v));
93 match &*item.kind {
94 ItemKind::Err => {}
95 ItemKind::Callable(decl) => vis.visit_callable_decl(decl),
96 ItemKind::Open(ns, alias) => {
97 vis.visit_path(ns);
98 alias.iter().for_each(|a| vis.visit_ident(a));
99 }
100 ItemKind::Ty(ident, def) => {
101 vis.visit_ident(ident);
102 vis.visit_ty_def(def);
103 }
104 ItemKind::Export(export) => {
105 for item in export.items.iter() {
106 vis.visit_path(&item.path);
107 if let Some(ref alias) = item.alias {
108 vis.visit_ident(alias);
109 }
110 }
111 }
112 ItemKind::Import(import) => import.items.iter().for_each(|i| {
113 vis.visit_path(&i.path);
114 if let Some(ref alias) = i.alias {
115 vis.visit_ident(alias);
116 }
117 }),
118 }
119}
120
121pub fn walk_attr<'a>(vis: &mut impl Visitor<'a>, attr: &'a Attr) {
122 vis.visit_ident(&attr.name);
123 vis.visit_expr(&attr.arg);
124}
125
126pub fn walk_ty_def<'a>(vis: &mut impl Visitor<'a>, def: &'a TyDef) {
127 match &*def.kind {
128 TyDefKind::Field(name, ty) => {
129 name.iter().for_each(|n| vis.visit_ident(n));
130 vis.visit_ty(ty);
131 }
132 TyDefKind::Paren(def) => vis.visit_ty_def(def),
133 TyDefKind::Tuple(defs) => defs.iter().for_each(|d| vis.visit_ty_def(d)),
134 TyDefKind::Err => {}
135 }
136}
137
138pub fn walk_callable_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a CallableDecl) {
139 vis.visit_ident(&decl.name);
140 decl.generics.iter().for_each(|p| vis.visit_ident(p));
141 vis.visit_pat(&decl.input);
142 vis.visit_ty(&decl.output);
143 decl.functors.iter().for_each(|f| vis.visit_functor_expr(f));
144 match &*decl.body {
145 CallableBody::Block(block) => vis.visit_block(block),
146 CallableBody::Specs(specs) => specs.iter().for_each(|s| vis.visit_spec_decl(s)),
147 }
148}
149
150pub fn walk_spec_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a SpecDecl) {
151 match &decl.body {
152 SpecBody::Gen(_) => {}
153 SpecBody::Impl(pat, block) => {
154 vis.visit_pat(pat);
155 vis.visit_block(block);
156 }
157 }
158}
159
160pub fn walk_functor_expr<'a>(vis: &mut impl Visitor<'a>, expr: &'a FunctorExpr) {
161 match &*expr.kind {
162 FunctorExprKind::BinOp(_, lhs, rhs) => {
163 vis.visit_functor_expr(lhs);
164 vis.visit_functor_expr(rhs);
165 }
166 FunctorExprKind::Lit(_) => {}
167 FunctorExprKind::Paren(expr) => vis.visit_functor_expr(expr),
168 }
169}
170
171pub fn walk_ty<'a>(vis: &mut impl Visitor<'a>, ty: &'a Ty) {
172 match &*ty.kind {
173 TyKind::Array(item) => vis.visit_ty(item),
174 TyKind::Arrow(_, lhs, rhs, functors) => {
175 vis.visit_ty(lhs);
176 vis.visit_ty(rhs);
177 functors.iter().for_each(|f| vis.visit_functor_expr(f));
178 }
179 TyKind::Hole | TyKind::Err => {}
180 TyKind::Paren(ty) => vis.visit_ty(ty),
181 TyKind::Path(path) => vis.visit_path(path),
182 TyKind::Param(name) => vis.visit_ident(name),
183 TyKind::Tuple(tys) => tys.iter().for_each(|t| vis.visit_ty(t)),
184 }
185}
186
187pub fn walk_block<'a>(vis: &mut impl Visitor<'a>, block: &'a Block) {
188 block.stmts.iter().for_each(|s| vis.visit_stmt(s));
189}
190
191pub fn walk_stmt<'a>(vis: &mut impl Visitor<'a>, stmt: &'a Stmt) {
192 match &*stmt.kind {
193 StmtKind::Empty | StmtKind::Err => {}
194 StmtKind::Expr(expr) | StmtKind::Semi(expr) => vis.visit_expr(expr),
195 StmtKind::Item(item) => vis.visit_item(item),
196 StmtKind::Local(_, pat, value) => {
197 vis.visit_pat(pat);
198 vis.visit_expr(value);
199 }
200 StmtKind::Qubit(_, pat, init, block) => {
201 vis.visit_pat(pat);
202 vis.visit_qubit_init(init);
203 block.iter().for_each(|b| vis.visit_block(b));
204 }
205 }
206}
207
208pub fn walk_expr<'a>(vis: &mut impl Visitor<'a>, expr: &'a Expr) {
209 match &*expr.kind {
210 ExprKind::Array(exprs) => exprs.iter().for_each(|e| vis.visit_expr(e)),
211 ExprKind::ArrayRepeat(item, size) => {
212 vis.visit_expr(item);
213 vis.visit_expr(size);
214 }
215 ExprKind::Assign(lhs, rhs)
216 | ExprKind::AssignOp(_, lhs, rhs)
217 | ExprKind::BinOp(_, lhs, rhs) => {
218 vis.visit_expr(lhs);
219 vis.visit_expr(rhs);
220 }
221 ExprKind::AssignUpdate(record, index, value) => {
222 vis.visit_expr(record);
223 vis.visit_expr(index);
224 vis.visit_expr(value);
225 }
226 ExprKind::Block(block) => vis.visit_block(block),
227 ExprKind::Call(callee, arg) => {
228 vis.visit_expr(callee);
229 vis.visit_expr(arg);
230 }
231 ExprKind::Conjugate(within, apply) => {
232 vis.visit_block(within);
233 vis.visit_block(apply);
234 }
235 ExprKind::Fail(msg) => vis.visit_expr(msg),
236 ExprKind::Field(record, name) => {
237 vis.visit_expr(record);
238 vis.visit_ident(name);
239 }
240 ExprKind::For(pat, iter, block) => {
241 vis.visit_pat(pat);
242 vis.visit_expr(iter);
243 vis.visit_block(block);
244 }
245 ExprKind::If(cond, body, otherwise) => {
246 vis.visit_expr(cond);
247 vis.visit_block(body);
248 otherwise.iter().for_each(|e| vis.visit_expr(e));
249 }
250 ExprKind::Index(array, index) => {
251 vis.visit_expr(array);
252 vis.visit_expr(index);
253 }
254 ExprKind::Interpolate(components) => {
255 for component in components.as_ref() {
256 match component {
257 StringComponent::Expr(expr) => vis.visit_expr(expr.as_ref()),
258 StringComponent::Lit(_) => {}
259 }
260 }
261 }
262 ExprKind::Lambda(_, pat, expr) => {
263 vis.visit_pat(pat);
264 vis.visit_expr(expr);
265 }
266 ExprKind::Paren(expr) | ExprKind::Return(expr) | ExprKind::UnOp(_, expr) => {
267 vis.visit_expr(expr);
268 }
269 ExprKind::Path(path) => vis.visit_path(path),
270 ExprKind::Range(start, step, end) => {
271 start.iter().for_each(|s| vis.visit_expr(s));
272 step.iter().for_each(|s| vis.visit_expr(s));
273 end.iter().for_each(|e| vis.visit_expr(e));
274 }
275 ExprKind::Repeat(body, until, fixup) => {
276 vis.visit_block(body);
277 vis.visit_expr(until);
278 fixup.iter().for_each(|f| vis.visit_block(f));
279 }
280 ExprKind::TernOp(_, e1, e2, e3) => {
281 vis.visit_expr(e1);
282 vis.visit_expr(e2);
283 vis.visit_expr(e3);
284 }
285 ExprKind::Tuple(exprs) => exprs.iter().for_each(|e| vis.visit_expr(e)),
286 ExprKind::While(cond, block) => {
287 vis.visit_expr(cond);
288 vis.visit_block(block);
289 }
290 ExprKind::Err | ExprKind::Hole | ExprKind::Lit(_) => {}
291 }
292}
293
294pub fn walk_pat<'a>(vis: &mut impl Visitor<'a>, pat: &'a Pat) {
295 match &*pat.kind {
296 PatKind::Bind(name, ty) => {
297 vis.visit_ident(name);
298 ty.iter().for_each(|t| vis.visit_ty(t));
299 }
300 PatKind::Discard(ty) => ty.iter().for_each(|t| vis.visit_ty(t)),
301 PatKind::Elided | PatKind::Err => {}
302 PatKind::Paren(pat) => vis.visit_pat(pat),
303 PatKind::Tuple(pats) => pats.iter().for_each(|p| vis.visit_pat(p)),
304 }
305}
306
307pub fn walk_qubit_init<'a>(vis: &mut impl Visitor<'a>, init: &'a QubitInit) {
308 match &*init.kind {
309 QubitInitKind::Array(len) => vis.visit_expr(len),
310 QubitInitKind::Paren(init) => vis.visit_qubit_init(init),
311 QubitInitKind::Single | QubitInitKind::Err => {}
312 QubitInitKind::Tuple(inits) => inits.iter().for_each(|i| vis.visit_qubit_init(i)),
313 }
314}
315
316pub fn walk_path<'a>(vis: &mut impl Visitor<'a>, idents: &'a Path) {
317 idents.iter().for_each(|i| vis.visit_ident(i));
318}
319