microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.2.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_fir/src/visit.rs

212lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::fir::{
5 Block, BlockId, CallableDecl, CallableImpl, Expr, ExprId, ExprKind, Ident, Item, ItemKind,
6 Package, Pat, PatId, PatKind, QubitInit, QubitInitKind, SpecDecl, SpecImpl, Stmt, StmtId,
7 StmtKind, StringComponent,
8};
9
10pub trait Visitor<'a>: Sized {
11 fn visit_package(&mut self, package: &'a Package) {
12 walk_package(self, package);
13 }
14
15 fn visit_item(&mut self, item: &'a Item) {
16 walk_item(self, item);
17 }
18
19 fn visit_callable_decl(&mut self, decl: &'a CallableDecl) {
20 walk_callable_decl(self, decl);
21 }
22
23 fn visit_callable_impl(&mut self, callable_impl: &'a CallableImpl) {
24 walk_callable_impl(self, callable_impl);
25 }
26
27 fn visit_spec_impl(&mut self, spec_impl: &'a SpecImpl) {
28 walk_spec_impl(self, spec_impl);
29 }
30
31 fn visit_spec_decl(&mut self, decl: &'a SpecDecl) {
32 walk_spec_decl(self, decl);
33 }
34
35 fn visit_block(&mut self, block: BlockId) {
36 walk_block(self, block);
37 }
38
39 fn visit_stmt(&mut self, stmt: StmtId) {
40 walk_stmt(self, stmt);
41 }
42
43 fn visit_expr(&mut self, expr: ExprId) {
44 walk_expr(self, expr);
45 }
46
47 fn visit_pat(&mut self, pat: PatId) {
48 walk_pat(self, pat);
49 }
50
51 fn visit_qubit_init(&mut self, init: &'a QubitInit) {
52 walk_qubit_init(self, init);
53 }
54
55 fn visit_ident(&mut self, _: &'a Ident) {}
56
57 fn get_block(&self, id: BlockId) -> &'a Block;
58 fn get_expr(&self, id: ExprId) -> &'a Expr;
59 fn get_pat(&self, id: PatId) -> &'a Pat;
60 fn get_stmt(&self, id: StmtId) -> &'a Stmt;
61}
62
63pub fn walk_package<'a>(vis: &mut impl Visitor<'a>, package: &'a Package) {
64 package.items.values().for_each(|i| vis.visit_item(i));
65 package.entry.iter().for_each(|e| vis.visit_expr(*e));
66}
67
68pub fn walk_item<'a>(vis: &mut impl Visitor<'a>, item: &'a Item) {
69 match &item.kind {
70 ItemKind::Callable(decl) => vis.visit_callable_decl(decl),
71 ItemKind::Namespace(name, _) | ItemKind::Ty(name, _) => vis.visit_ident(name),
72 };
73}
74
75pub fn walk_callable_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a CallableDecl) {
76 vis.visit_ident(&decl.name);
77 vis.visit_pat(decl.input);
78 vis.visit_callable_impl(&decl.implementation);
79}
80
81pub fn walk_callable_impl<'a>(vis: &mut impl Visitor<'a>, callable_impl: &'a CallableImpl) {
82 match callable_impl {
83 CallableImpl::Intrinsic => {}
84 CallableImpl::Spec(spec_impl) => {
85 vis.visit_spec_impl(spec_impl);
86 }
87 };
88}
89
90pub fn walk_spec_impl<'a>(vis: &mut impl Visitor<'a>, spec_impl: &'a SpecImpl) {
91 vis.visit_spec_decl(&spec_impl.body);
92 spec_impl
93 .adj
94 .iter()
95 .for_each(|spec| vis.visit_spec_decl(spec));
96 spec_impl
97 .ctl
98 .iter()
99 .for_each(|spec| vis.visit_spec_decl(spec));
100 spec_impl
101 .ctl_adj
102 .iter()
103 .for_each(|spec| vis.visit_spec_decl(spec));
104}
105
106pub fn walk_spec_decl<'a>(vis: &mut impl Visitor<'a>, decl: &'a SpecDecl) {
107 decl.input.iter().for_each(|pat| vis.visit_pat(*pat));
108 vis.visit_block(decl.block);
109}
110
111pub fn walk_block<'a>(vis: &mut impl Visitor<'a>, block: BlockId) {
112 let block = vis.get_block(block);
113 block.stmts.iter().for_each(|s| vis.visit_stmt(*s));
114}
115
116pub fn walk_stmt<'a>(vis: &mut impl Visitor<'a>, id: StmtId) {
117 let stmt = vis.get_stmt(id);
118 match &stmt.kind {
119 StmtKind::Item(_) => {}
120 StmtKind::Expr(expr) | StmtKind::Semi(expr) => vis.visit_expr(*expr),
121 StmtKind::Local(_, pat, value) => {
122 vis.visit_pat(*pat);
123 vis.visit_expr(*value);
124 }
125 }
126}
127
128pub fn walk_expr<'a>(vis: &mut impl Visitor<'a>, expr: ExprId) {
129 let expr = vis.get_expr(expr);
130 match &expr.kind {
131 ExprKind::Array(exprs) => exprs.iter().for_each(|e| vis.visit_expr(*e)),
132 ExprKind::ArrayRepeat(item, size) => {
133 vis.visit_expr(*item);
134 vis.visit_expr(*size);
135 }
136 ExprKind::Assign(lhs, rhs)
137 | ExprKind::AssignOp(_, lhs, rhs)
138 | ExprKind::BinOp(_, lhs, rhs) => {
139 vis.visit_expr(*lhs);
140 vis.visit_expr(*rhs);
141 }
142 ExprKind::AssignField(record, _, replace) | ExprKind::UpdateField(record, _, replace) => {
143 vis.visit_expr(*record);
144 vis.visit_expr(*replace);
145 }
146 ExprKind::AssignIndex(array, index, replace) => {
147 vis.visit_expr(*array);
148 vis.visit_expr(*index);
149 vis.visit_expr(*replace);
150 }
151 ExprKind::Block(block) => vis.visit_block(*block),
152 ExprKind::Call(callee, arg) => {
153 vis.visit_expr(*callee);
154 vis.visit_expr(*arg);
155 }
156 ExprKind::Fail(msg) => vis.visit_expr(*msg),
157 ExprKind::Field(record, _) => vis.visit_expr(*record),
158 ExprKind::If(cond, body, otherwise) => {
159 vis.visit_expr(*cond);
160 vis.visit_expr(*body);
161 otherwise.iter().for_each(|e| vis.visit_expr(*e));
162 }
163 ExprKind::Index(array, index) => {
164 vis.visit_expr(*array);
165 vis.visit_expr(*index);
166 }
167 ExprKind::Return(expr) | ExprKind::UnOp(_, expr) => {
168 vis.visit_expr(*expr);
169 }
170 ExprKind::Range(start, step, end) => {
171 start.iter().for_each(|s| vis.visit_expr(*s));
172 step.iter().for_each(|s| vis.visit_expr(*s));
173 end.iter().for_each(|e| vis.visit_expr(*e));
174 }
175 ExprKind::String(components) => {
176 for component in components {
177 match component {
178 StringComponent::Expr(expr) => vis.visit_expr(*expr),
179 StringComponent::Lit(_) => {}
180 }
181 }
182 }
183 ExprKind::UpdateIndex(e1, e2, e3) => {
184 vis.visit_expr(*e1);
185 vis.visit_expr(*e2);
186 vis.visit_expr(*e3);
187 }
188 ExprKind::Tuple(exprs) => exprs.iter().for_each(|e| vis.visit_expr(*e)),
189 ExprKind::While(cond, block) => {
190 vis.visit_expr(*cond);
191 vis.visit_block(*block);
192 }
193 ExprKind::Closure(_, _) | ExprKind::Hole | ExprKind::Lit(_) | ExprKind::Var(_, _) => {}
194 }
195}
196
197pub fn walk_pat<'a>(vis: &mut impl Visitor<'a>, pat: PatId) {
198 let pat = vis.get_pat(pat);
199 match &pat.kind {
200 PatKind::Bind(name) => vis.visit_ident(name),
201 PatKind::Discard => {}
202 PatKind::Tuple(pats) => pats.iter().for_each(|p| vis.visit_pat(*p)),
203 }
204}
205
206pub fn walk_qubit_init<'a>(vis: &mut impl Visitor<'a>, init: &'a QubitInit) {
207 match &init.kind {
208 QubitInitKind::Array(len) => vis.visit_expr(*len),
209 QubitInitKind::Single => {}
210 QubitInitKind::Tuple(inits) => inits.iter().for_each(|i| vis.visit_qubit_init(i)),
211 }
212}
213