1use crate::*;
22
23pub trait TypeVisitor: ExpressionVisitor {
47 fn visit_type(&mut self, input: &Type) {
48 match input {
49 Type::Array(array_type) => self.visit_array_type(array_type),
50 Type::Future(future_type) => self.visit_future_type(future_type),
51 Type::Mapping(mapping_type) => self.visit_mapping_type(mapping_type),
52 Type::Tuple(tuple_type) => self.visit_tuple_type(tuple_type),
53 Type::Address
54 | Type::Boolean
55 | Type::Composite(_)
56 | Type::Field
57 | Type::Group
58 | Type::Identifier(_)
59 | Type::Integer(_)
60 | Type::Scalar
61 | Type::Signature
62 | Type::String
63 | Type::Numeric
64 | Type::Unit
65 | Type::Err => {}
66 }
67 }
68
69 fn visit_array_type(&mut self, input: &ArrayType) {
70 self.visit_type(&input.element_type);
71 self.visit_expression(&input.length, &Default::default());
72 }
73
74 fn visit_future_type(&mut self, input: &FutureType) {
75 input.inputs.iter().for_each(|input| self.visit_type(input));
76 }
77
78 fn visit_mapping_type(&mut self, input: &MappingType) {
79 self.visit_type(&input.key);
80 self.visit_type(&input.value);
81 }
82
83 fn visit_tuple_type(&mut self, input: &TupleType) {
84 input.elements().iter().for_each(|input| self.visit_type(input));
85 }
86}
87
88pub trait ExpressionVisitor {
90 type AdditionalInput: Default;
91 type Output: Default;
92
93 fn visit_expression(&mut self, input: &Expression, additional: &Self::AdditionalInput) -> Self::Output {
94 match input {
95 Expression::Array(array) => self.visit_array(array, additional),
96 Expression::ArrayAccess(access) => self.visit_array_access(access, additional),
97 Expression::AssociatedConstant(constant) => self.visit_associated_constant(constant, additional),
98 Expression::AssociatedFunction(function) => self.visit_associated_function(function, additional),
99 Expression::Binary(binary) => self.visit_binary(binary, additional),
100 Expression::Call(call) => self.visit_call(call, additional),
101 Expression::Cast(cast) => self.visit_cast(cast, additional),
102 Expression::Struct(struct_) => self.visit_struct_init(struct_, additional),
103 Expression::Err(err) => self.visit_err(err, additional),
104 Expression::Identifier(identifier) => self.visit_identifier(identifier, additional),
105 Expression::Literal(literal) => self.visit_literal(literal, additional),
106 Expression::Locator(locator) => self.visit_locator(locator, additional),
107 Expression::MemberAccess(access) => self.visit_member_access(access, additional),
108 Expression::Repeat(repeat) => self.visit_repeat(repeat, additional),
109 Expression::Ternary(ternary) => self.visit_ternary(ternary, additional),
110 Expression::Tuple(tuple) => self.visit_tuple(tuple, additional),
111 Expression::TupleAccess(access) => self.visit_tuple_access(access, additional),
112 Expression::Unary(unary) => self.visit_unary(unary, additional),
113 Expression::Unit(unit) => self.visit_unit(unit, additional),
114 }
115 }
116
117 fn visit_array_access(&mut self, input: &ArrayAccess, additional: &Self::AdditionalInput) -> Self::Output {
118 self.visit_expression(&input.array, additional);
119 self.visit_expression(&input.index, additional);
120 Default::default()
121 }
122
123 fn visit_member_access(&mut self, input: &MemberAccess, additional: &Self::AdditionalInput) -> Self::Output {
124 self.visit_expression(&input.inner, additional);
125 Default::default()
126 }
127
128 fn visit_tuple_access(&mut self, input: &TupleAccess, additional: &Self::AdditionalInput) -> Self::Output {
129 self.visit_expression(&input.tuple, additional);
130 Default::default()
131 }
132
133 fn visit_array(&mut self, input: &ArrayExpression, additional: &Self::AdditionalInput) -> Self::Output {
134 input.elements.iter().for_each(|expr| {
135 self.visit_expression(expr, additional);
136 });
137 Default::default()
138 }
139
140 fn visit_associated_constant(
141 &mut self,
142 _input: &AssociatedConstantExpression,
143 _additional: &Self::AdditionalInput,
144 ) -> Self::Output {
145 Default::default()
146 }
147
148 fn visit_associated_function(
149 &mut self,
150 input: &AssociatedFunctionExpression,
151 _additional: &Self::AdditionalInput,
152 ) -> Self::Output {
153 input.arguments.iter().for_each(|arg| {
154 self.visit_expression(arg, &Default::default());
155 });
156 Default::default()
157 }
158
159 fn visit_binary(&mut self, input: &BinaryExpression, additional: &Self::AdditionalInput) -> Self::Output {
160 self.visit_expression(&input.left, additional);
161 self.visit_expression(&input.right, additional);
162 Default::default()
163 }
164
165 fn visit_call(&mut self, input: &CallExpression, additional: &Self::AdditionalInput) -> Self::Output {
166 input.arguments.iter().for_each(|expr| {
167 self.visit_expression(expr, additional);
168 });
169 Default::default()
170 }
171
172 fn visit_cast(&mut self, input: &CastExpression, additional: &Self::AdditionalInput) -> Self::Output {
173 self.visit_expression(&input.expression, additional);
174 Default::default()
175 }
176
177 fn visit_struct_init(&mut self, input: &StructExpression, additional: &Self::AdditionalInput) -> Self::Output {
178 for StructVariableInitializer { expression, .. } in input.members.iter() {
179 if let Some(expression) = expression {
180 self.visit_expression(expression, additional);
181 }
182 }
183 Default::default()
184 }
185
186 fn visit_err(&mut self, _input: &ErrExpression, _additional: &Self::AdditionalInput) -> Self::Output {
187 panic!("`ErrExpression`s should not be in the AST at this phase of compilation.")
188 }
189
190 fn visit_identifier(&mut self, _input: &Identifier, _additional: &Self::AdditionalInput) -> Self::Output {
191 Default::default()
192 }
193
194 fn visit_literal(&mut self, _input: &Literal, _additional: &Self::AdditionalInput) -> Self::Output {
195 Default::default()
196 }
197
198 fn visit_locator(&mut self, _input: &LocatorExpression, _additional: &Self::AdditionalInput) -> Self::Output {
199 Default::default()
200 }
201
202 fn visit_repeat(&mut self, input: &RepeatExpression, additional: &Self::AdditionalInput) -> Self::Output {
203 self.visit_expression(&input.expr, additional);
204 self.visit_expression(&input.count, additional);
205 Default::default()
206 }
207
208 fn visit_ternary(&mut self, input: &TernaryExpression, additional: &Self::AdditionalInput) -> Self::Output {
209 self.visit_expression(&input.condition, additional);
210 self.visit_expression(&input.if_true, additional);
211 self.visit_expression(&input.if_false, additional);
212 Default::default()
213 }
214
215 fn visit_tuple(&mut self, input: &TupleExpression, additional: &Self::AdditionalInput) -> Self::Output {
216 input.elements.iter().for_each(|expr| {
217 self.visit_expression(expr, additional);
218 });
219 Default::default()
220 }
221
222 fn visit_unary(&mut self, input: &UnaryExpression, additional: &Self::AdditionalInput) -> Self::Output {
223 self.visit_expression(&input.receiver, additional);
224 Default::default()
225 }
226
227 fn visit_unit(&mut self, _input: &UnitExpression, _additional: &Self::AdditionalInput) -> Self::Output {
228 Default::default()
229 }
230}
231
232pub trait StatementVisitor: TypeVisitor {
234 fn visit_statement(&mut self, input: &Statement) {
235 match input {
236 Statement::Assert(stmt) => self.visit_assert(stmt),
237 Statement::Assign(stmt) => self.visit_assign(stmt),
238 Statement::Block(stmt) => self.visit_block(stmt),
239 Statement::Conditional(stmt) => self.visit_conditional(stmt),
240 Statement::Const(stmt) => self.visit_const(stmt),
241 Statement::Definition(stmt) => self.visit_definition(stmt),
242 Statement::Expression(stmt) => self.visit_expression_statement(stmt),
243 Statement::Iteration(stmt) => self.visit_iteration(stmt),
244 Statement::Return(stmt) => self.visit_return(stmt),
245 }
246 }
247
248 fn visit_assert(&mut self, input: &AssertStatement) {
249 match &input.variant {
250 AssertVariant::Assert(expr) => self.visit_expression(expr, &Default::default()),
251 AssertVariant::AssertEq(left, right) | AssertVariant::AssertNeq(left, right) => {
252 self.visit_expression(left, &Default::default());
253 self.visit_expression(right, &Default::default())
254 }
255 };
256 }
257
258 fn visit_assign(&mut self, input: &AssignStatement) {
259 self.visit_expression(&input.value, &Default::default());
260 }
261
262 fn visit_block(&mut self, input: &Block) {
263 input.statements.iter().for_each(|stmt| self.visit_statement(stmt));
264 }
265
266 fn visit_conditional(&mut self, input: &ConditionalStatement) {
267 self.visit_expression(&input.condition, &Default::default());
268 self.visit_block(&input.then);
269 if let Some(stmt) = input.otherwise.as_ref() {
270 self.visit_statement(stmt);
271 }
272 }
273
274 fn visit_const(&mut self, input: &ConstDeclaration) {
275 self.visit_type(&input.type_);
276 self.visit_expression(&input.value, &Default::default());
277 }
278
279 fn visit_definition(&mut self, input: &DefinitionStatement) {
280 if let Some(ty) = input.type_.as_ref() {
281 self.visit_type(ty)
282 }
283 self.visit_expression(&input.value, &Default::default());
284 }
285
286 fn visit_expression_statement(&mut self, input: &ExpressionStatement) {
287 self.visit_expression(&input.expression, &Default::default());
288 }
289
290 fn visit_iteration(&mut self, input: &IterationStatement) {
291 if let Some(ty) = input.type_.as_ref() {
292 self.visit_type(ty)
293 }
294 self.visit_expression(&input.start, &Default::default());
295 self.visit_expression(&input.stop, &Default::default());
296 self.visit_block(&input.block);
297 }
298
299 fn visit_return(&mut self, input: &ReturnStatement) {
300 self.visit_expression(&input.expression, &Default::default());
301 }
302}
303
304pub trait ProgramVisitor: StatementVisitor {
306 fn visit_program(&mut self, input: &Program) {
307 input.imports.values().for_each(|import| self.visit_import(&import.0));
308 input.stubs.values().for_each(|stub| self.visit_stub(stub));
309 input.program_scopes.values().for_each(|scope| self.visit_program_scope(scope));
310 }
311
312 fn visit_program_scope(&mut self, input: &ProgramScope) {
313 input.structs.iter().for_each(|(_, c)| (self.visit_struct(c)));
314
315 input.mappings.iter().for_each(|(_, c)| (self.visit_mapping(c)));
316
317 input.functions.iter().for_each(|(_, c)| (self.visit_function(c)));
318
319 input.consts.iter().for_each(|(_, c)| (self.visit_const(c)));
320 }
321
322 fn visit_stub(&mut self, _input: &Stub) {}
323
324 fn visit_import(&mut self, input: &Program) {
325 self.visit_program(input)
326 }
327
328 fn visit_struct(&mut self, input: &Composite) {
329 input.members.iter().for_each(|member| self.visit_type(&member.type_));
330 }
331
332 fn visit_mapping(&mut self, input: &Mapping) {
333 self.visit_type(&input.key_type);
334 self.visit_type(&input.value_type);
335 }
336
337 fn visit_function(&mut self, input: &Function) {
338 input.const_parameters.iter().for_each(|input| self.visit_type(&input.type_));
339 input.input.iter().for_each(|input| self.visit_type(&input.type_));
340 input.output.iter().for_each(|output| self.visit_type(&output.type_));
341 self.visit_type(&input.output_type);
342 self.visit_block(&input.block);
343 }
344
345 fn visit_function_stub(&mut self, _input: &FunctionStub) {}
346
347 fn visit_struct_stub(&mut self, _input: &Composite) {}
348}