microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.3.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc_fir/src/visit.rs

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