Skip to main content

plc_ast/
visitor.rs

1//! This module defines the `AstVisitor` trait and its associated macros.
2//! The `AstVisitor` trait provides a set of methods for traversing and visiting ASTs
3
4use crate::ast::{
5    flatten_expression_list, Allocation, Assignment, AstNode, AstStatement, BinaryExpression, CallStatement,
6    CompilationUnit, ConfigVariable, DataType, DataTypeDeclaration, DefaultValue, DirectAccess,
7    EmptyStatement, HardwareAccess, Implementation, Interface, JumpStatement, LabelStatement,
8    MultipliedStatement, Pou, PropertyBlock, RangeStatement, ReferenceAccess, ReferenceExpr, UnaryExpression,
9    UserTypeDeclaration, Variable, VariableBlock,
10};
11use crate::control_statements::{
12    AstControlStatement, ConditionalBlock, ForLoopStatement, LoopStatement, ReturnStatement,
13};
14use crate::literals::AstLiteral;
15
16/// Macro that calls the visitor's `visit` method for every AstNode in the passed iterator `iter`.
17macro_rules! visit_all_nodes {
18    ($visitor:expr, $iter:expr) => {
19        // Note: The `allow` is needed to suppress warnings about `while let Some(...)` warnings
20        // because `visit_all_nodes!` is used for both Option and Non-Option types
21        #[allow(warnings)]
22        {
23            for node in $iter {
24                $visitor.visit(node);
25            }
26        }
27    };
28}
29
30/// Macro that calls the visitor's `visit` method for every AstNode in the passed sequence of nodes.
31macro_rules! visit_nodes {
32    ($visitor:expr, $($node:expr),*) => {
33        $(
34            $visitor.visit($node);
35        )*
36    };
37}
38
39/// The `Walker` implements the traversal of the AST nodes and Ast-related objects (e.g. CompilationUnit).
40/// The `walk` method is called on the object to visit its children.
41/// If the object passed to a `AstVisitor`'s `visit` method implements the `Walker` trait,
42/// a call to the it's walk function continues the visiting process on its children.
43///
44/// Spliting the traversal logic into a separate trait allows to call the default traversal logic
45/// from the visitor while overriding the visitor's `visit` method for specific nodes.
46///
47/// # Example
48/// ```
49/// use plc_ast::ast::AstNode;
50/// use plc_ast::visitor::Walker;
51/// use plc_ast::visitor::AstVisitor;
52///
53/// struct MyAssignment {
54///   left: AstNode,
55///  right: AstNode,
56/// }
57///
58/// impl Walker for MyAssignment {
59///     fn walk<V>(&self, visitor: &mut V)
60///     where
61///         V: AstVisitor,
62///     {
63///         visitor.visit(&self.right);
64///         visitor.visit(&self.left);
65///     }
66/// }
67/// ```
68///
69pub trait Walker {
70    fn walk<V>(&self, visitor: &mut V)
71    where
72        V: AstVisitor;
73}
74
75/// The `AstVisitor` trait provides a set of methods for visiting different types of AST nodes.
76/// Implementors can individually override the methods they are interested in. When overriding a method,
77/// make sure to call `walk` on the visited statement to visit its children. DO NOT call walk on
78/// the node itself to avoid a recursion (last parameter). Implementors may also decide to not call
79/// the statement's `walk` method to avoid visiting the children of the statement.
80///
81/// The visitor offers strongly typed `visit_X` functions for every node type. The function's signature
82/// is `fn visit_X(&mut self, stmt: &X, node: &AstNode)`. The `stmt` parameter is the unwrapped, typed
83/// node and the `node` parameter is the `AstNode` wrapping the stmt. The `AstNode` node offers access to location
84/// information and the AstId. Note that some nodes are not wrapped in an `AstNode` node (e.g. `CompilationUnit`)
85/// and therefore only the strongly typed node is passed to the `visit_X` function.
86///
87/// # Example
88/// ```
89/// use plc_ast::{
90///    ast::{Assignment, AstNode},
91///    visitor::{AstVisitor, Walker},
92/// };
93///
94/// struct AssignmentCounter {
95///    count: usize,
96/// }
97///
98/// impl AstVisitor for AssignmentCounter {
99///    fn visit_assignment(&mut self, stmt: &Assignment, _node: &AstNode) {
100///        self.count += 1;
101///        // visit child nodes
102///        stmt.walk(self);
103///    }
104///
105///    fn visit_output_assignment(&mut self, stmt: &Assignment, _node: &AstNode) {
106///        self.count += 1;
107///        // visit child nodes
108///        stmt.walk(self);
109///    }
110/// }
111/// ```
112pub trait AstVisitor: Sized {
113    /// Visits this `AstNode`. The default implementation calls the `walk` method on the node
114    /// and will eventually call the strongly typed `visit` method for the node (e.g. visit_assignment
115    /// if the node is an `AstStatement::Assignment`).
116    /// # Arguments
117    /// * `node` - The `AstNode` node to visit.
118    fn visit(&mut self, node: &AstNode) {
119        node.walk(self)
120    }
121
122    /// Called when visiting a list of statements (e.g. implementation bodies, control flow branches).
123    /// Override this to intercept statement-list processing.
124    fn visit_statement_list(&mut self, stmts: &[AstNode]) {
125        for node in stmts {
126            self.visit(node);
127        }
128    }
129
130    /// Visits a `CompilationUnit` node.
131    /// Make sure to call `walk` on the `CompilationUnit` node to visit its children.
132    /// # Arguments
133    /// * `unit` - The unwraped, typed `CompilationUnit` node to visit.
134    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
135    fn visit_compilation_unit(&mut self, unit: &CompilationUnit) {
136        unit.walk(self)
137    }
138
139    /// Visits an `Implementation` node.
140    /// Make sure to call `walk` on the `Implementation` node to visit its children.
141    /// # Arguments
142    /// * `implementation` - The unwraped, typed `Implementation` node to visit.
143    fn visit_implementation(&mut self, implementation: &Implementation) {
144        implementation.walk(self);
145    }
146
147    /// Visits a `DataTypeDeclaration` node.
148    /// Make sure to call `walk` on the `VariableBlock` node to visit its children.
149    /// # Arguments
150    /// * `block` - The unwraped, typed `VariableBlock` node to visit.
151    fn visit_variable_block(&mut self, block: &VariableBlock) {
152        block.walk(self)
153    }
154
155    /// Visits a `Variable` node.
156    /// Make sure to call `walk` on the `Variable` node to visit its children.
157    /// # Arguments
158    /// * `variable` - The unwraped, typed `Variable` node to visit.
159    fn visit_variable(&mut self, variable: &Variable) {
160        variable.walk(self);
161    }
162
163    /// Visits a `ConfigVariable` node.
164    /// Make sure to call `walk` on the `ConfigVariable` node to visit its children.
165    /// # Arguments
166    /// * `variable` - The unwraped, typed `Variable` node to visit.
167    fn visit_config_variable(&mut self, config_variable: &ConfigVariable) {
168        config_variable.walk(self);
169    }
170
171    /// Visits a `Interface`.
172    /// Make sure to call `walk` on the `Interface` to visit its children.
173    /// # Arguments
174    /// * `interface` - The unwraped, typed `Interface` node to visit.
175    fn visit_interface(&mut self, interface: &Interface) {
176        interface.walk(self);
177    }
178
179    /// Visits a `Property`.
180    /// Make sure to call `walk` on the `PropertyBlock` to visit its children.
181    fn visit_property(&mut self, property: &PropertyBlock) {
182        property.walk(self);
183    }
184
185    /// Visits an enum element `AstNode` node.
186    /// Make sure to call `walk` on the `AstNode` node to visit its children.
187    /// # Arguments
188    /// * `element` - The unwraped, typed `AstNode` node to visit.
189    fn visit_enum_element(&mut self, element: &AstNode) {
190        element.walk(self);
191    }
192
193    /// Visits a `DataTypeDeclaration` node.
194    /// Make sure to call `walk` on the `DataTypeDeclaration` node to visit its children.
195    /// # Arguments
196    /// * `data_type_declaration` - The unwraped, typed `DataTypeDeclaration` node to visit.
197    fn visit_data_type_declaration(&mut self, data_type_declaration: &DataTypeDeclaration) {
198        data_type_declaration.walk(self);
199    }
200
201    /// Visits a `UserTypeDeclaration` node.
202    /// Make sure to call `walk` on the `UserTypeDeclaration` node to visit its children.
203    /// # Arguments
204    /// * `user_type` - The unwraped, typed `UserTypeDeclaration` node to visit.
205    fn visit_user_type_declaration(&mut self, user_type: &UserTypeDeclaration) {
206        user_type.walk(self);
207    }
208
209    /// Visits a `UserTypeDeclaration` node.
210    /// Make sure to call `walk` on the `DataType` node to visit its children.
211    /// # Arguments
212    /// * `data_type` - The unwraped, typed `DataType` node to visit.
213    fn visit_data_type(&mut self, data_type: &DataType) {
214        data_type.walk(self);
215    }
216
217    /// Visits a `Pou` node.
218    /// Make sure to call `walk` on the `Pou` node to visit its children.
219    /// # Arguments
220    /// * `pou` - The unwraped, typed `Pou` node to visit.
221    fn visit_pou(&mut self, pou: &Pou) {
222        pou.walk(self);
223    }
224
225    /// Visits an `EmptyStatement` node.
226    /// # Arguments
227    /// * `stmt` - The unwraped, typed `EmptyStatement` node to visit.
228    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
229    fn visit_empty_statement(&mut self, _stmt: &EmptyStatement, _node: &AstNode) {}
230
231    /// Visits a `DefaultValue` node.
232    /// # Arguments
233    /// * `stmt` - The unwraped, typed `DefaultValue` node to visit.
234    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
235    fn visit_default_value(&mut self, _stmt: &DefaultValue, _node: &AstNode) {}
236
237    /// Visits an `AstLiteral` node.
238    /// Make sure to call `walk` on the `AstLiteral` node to visit its children.
239    /// # Arguments
240    /// * `stmt` - The unwraped, typed `AstLiteral` node to visit.
241    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
242    fn visit_literal(&mut self, stmt: &AstLiteral, _node: &AstNode) {
243        stmt.walk(self)
244    }
245
246    /// Visits a `MultipliedStatement` node.
247    /// Make sure to call `walk` on the `MultipliedStatement` node to visit its children.
248    /// # Arguments
249    /// * `stmt` - The unwraped, typed `MultipliedStatement` node to visit.
250    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
251    fn visit_multiplied_statement(&mut self, stmt: &MultipliedStatement, _node: &AstNode) {
252        stmt.walk(self)
253    }
254
255    /// Visits a `ReferenceExpr` node.
256    /// Make sure to call `walk` on the `ReferenceExpr` node to visit its children.
257    /// # Arguments
258    /// * `stmt` - The unwraped, typed `ReferenceExpr` node to visit.
259    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
260    fn visit_reference_expr(&mut self, stmt: &ReferenceExpr, _node: &AstNode) {
261        stmt.walk(self)
262    }
263
264    /// Visits an `Identifier` node.
265    /// Make sure to call `walk` on the `Identifier` node to visit its children.
266    /// # Arguments
267    /// * `stmt` - The unwraped, typed `Identifier` node to visit.
268    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
269    fn visit_identifier(&mut self, _stmt: &str, _node: &AstNode) {}
270
271    /// Visits a `DirectAccess` node.
272    /// Make sure to call `walk` on the `DirectAccess` node to visit its children.
273    /// # Arguments
274    /// * `stmt` - The unwraped, typed `DirectAccess` node to visit.
275    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
276    fn visit_direct_access(&mut self, stmt: &DirectAccess, _node: &AstNode) {
277        stmt.walk(self)
278    }
279
280    /// Visits a `HardwareAccess` node.
281    /// Make sure to call `walk` on the `HardwareAccess` node to visit its children.
282    /// # Arguments
283    /// * `stmt` - The unwraped, typed `HardwareAccess` node to visit.
284    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
285    fn visit_hardware_access(&mut self, stmt: &HardwareAccess, _node: &AstNode) {
286        stmt.walk(self)
287    }
288
289    /// Visits a `BinaryExpression` node.
290    /// Make sure to call `walk` on the `BinaryExpression` node to visit its children.
291    /// # Arguments
292    /// * `stmt` - The unwraped, typed `BinaryExpression` node to visit.
293    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
294    fn visit_binary_expression(&mut self, stmt: &BinaryExpression, _node: &AstNode) {
295        stmt.walk(self)
296    }
297
298    /// Visits a `UnaryExpression` node.
299    /// Make sure to call `walk` on the `UnaryExpression` node to visit its children.
300    /// # Arguments
301    /// * `stmt` - The unwraped, typed `UnaryExpression` node to visit.
302    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
303    fn visit_unary_expression(&mut self, stmt: &UnaryExpression, _node: &AstNode) {
304        stmt.walk(self)
305    }
306
307    /// Visits an `ExpressionList` node.
308    /// Make sure to call `walk` on the `Vec<AstNode>` node to visit its children.
309    /// # Arguments
310    /// * `stmt` - The unwraped, typed `ExpressionList` node to visit.
311    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
312    fn visit_expression_list(&mut self, stmt: &Vec<AstNode>, _node: &AstNode) {
313        visit_all_nodes!(self, stmt);
314    }
315
316    /// Visits a `ParenExpression` node.
317    /// Make sure to call `walk` on the inner `AstNode` node to visit its children.
318    /// # Arguments
319    /// * `inner` - The unwraped, typed inner `AstNode` node to visit.
320    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
321    fn visit_paren_expression(&mut self, inner: &AstNode, _node: &AstNode) {
322        inner.walk(self)
323    }
324
325    /// Visits a `RangeStatement` node.
326    /// Make sure to call `walk` on the `RangeStatement` node to visit its children.
327    /// # Arguments
328    /// * `stmt` - The unwraped, typed `RangeStatement` node to visit.
329    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
330    fn visit_range_statement(&mut self, stmt: &RangeStatement, _node: &AstNode) {
331        stmt.walk(self)
332    }
333
334    /// Visits a `VlaRangeStatement` node.
335    /// # Arguments
336    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
337    fn visit_vla_range_statement(&mut self, _node: &AstNode) {}
338
339    /// Visits an `Assignment` node.
340    /// Make sure to call `walk` on the `Assignment` node to visit its children.
341    /// # Arguments
342    /// * `stmt` - The unwraped, typed `Assignment` node to visit.
343    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
344    fn visit_assignment(&mut self, stmt: &Assignment, _node: &AstNode) {
345        stmt.walk(self)
346    }
347
348    /// Visits an `OutputAssignment` node.
349    /// Make sure to call `walk` on the `Assignment` node to visit its children.
350    /// # Arguments
351    /// * `stmt` - The unwraped, typed `Assignment` node to visit.
352    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
353    fn visit_output_assignment(&mut self, stmt: &Assignment, _node: &AstNode) {
354        stmt.walk(self)
355    }
356
357    /// Visits an `RefAssignment` node.
358    /// Make sure to call `walk` on the `Assignment` node to visit its children.
359    /// # Arguments
360    /// * `stmt` - The unwraped, typed `Assignment` node to visit.
361    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
362    fn visit_ref_assignment(&mut self, stmt: &Assignment, _node: &AstNode) {
363        stmt.walk(self)
364    }
365
366    /// Visits a `CallStatement` node.
367    /// Make sure to call `walk` on the `CallStatement` node to visit its children.
368    /// # Arguments
369    /// * `stmt` - The unwraped, typed `CallStatement` node to visit.
370    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
371    fn visit_call_statement(&mut self, stmt: &CallStatement, _node: &AstNode) {
372        stmt.walk(self)
373    }
374
375    /// Visits an `AstControlStatement` node.
376    /// Make sure to call `walk` on the `AstControlStatement` node to visit its children.
377    /// # Arguments
378    /// * `stmt` - The unwraped, typed `AstControlStatement` node to visit.
379    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
380    fn visit_control_statement(&mut self, stmt: &AstControlStatement, node: &AstNode) {
381        match stmt {
382            AstControlStatement::WhileLoop(loop_stmt) => self.visit_while_loop_statement(loop_stmt, node),
383            AstControlStatement::RepeatLoop(loop_stmt) => self.visit_repeat_loop_statement(loop_stmt, node),
384            AstControlStatement::ForLoop(for_stmt) => self.visit_for_loop_statement(for_stmt, node),
385            _ => stmt.walk(self),
386        }
387    }
388
389    /// Visits a `ForLoop` control statement.
390    /// # Arguments
391    /// * `stmt` - The unwraped, typed `ForLoopStatement` node to visit.
392    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
393    fn visit_for_loop_statement(&mut self, stmt: &ForLoopStatement, _node: &AstNode) {
394        visit_nodes!(self, &stmt.counter, &stmt.start, &stmt.end);
395        visit_all_nodes!(self, &stmt.by_step);
396        self.visit_statement_list(&stmt.body);
397    }
398
399    /// Visits a `WhileLoop` control statement.
400    /// Make sure to call `walk` on the `LoopStatement` node to visit its children.
401    /// # Arguments
402    /// * `stmt` - The unwraped, typed `LoopStatement` node to visit.
403    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
404    fn visit_while_loop_statement(&mut self, stmt: &LoopStatement, _node: &AstNode) {
405        visit_nodes!(self, &stmt.condition);
406        self.visit_statement_list(&stmt.body);
407    }
408
409    /// Visits a `RepeatLoop` control statement.
410    /// Make sure to call `walk` on the `LoopStatement` node to visit its children.
411    /// # Arguments
412    /// * `stmt` - The unwraped, typed `LoopStatement` node to visit.
413    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
414    fn visit_repeat_loop_statement(&mut self, stmt: &LoopStatement, _node: &AstNode) {
415        visit_nodes!(self, &stmt.condition);
416        self.visit_statement_list(&stmt.body);
417    }
418
419    /// Visits a `CaseCondition` node.
420    /// Make sure to call `walk` on the child-`AstNode` node to visit its children.
421    /// # Arguments
422    /// * `stmt` - The unwraped, typed `CaseCondition` node to visit.
423    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
424    fn visit_case_condition(&mut self, child: &AstNode, _node: &AstNode) {
425        child.walk(self)
426    }
427
428    /// Visits an `ExitStatement` node.
429    /// # Arguments
430    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
431    fn visit_exit_statement(&mut self, _node: &AstNode) {}
432
433    /// Visits a `ContinueStatement` node.
434    /// # Arguments
435    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
436    fn visit_continue_statement(&mut self, _node: &AstNode) {}
437
438    /// Visits a `ReturnStatement` node.
439    /// Make sure to call `walk` on the `ReturnStatement` node to visit its children.
440    /// # Arguments
441    /// * `stmt` - The unwraped, typed `ReturnStatement` node to visit.
442    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
443    fn visit_return_statement(&mut self, stmt: &ReturnStatement, _node: &AstNode) {
444        stmt.walk(self)
445    }
446
447    /// Visits a `JumpStatement` node.
448    /// Make sure to call `walk` on the `JumpStatement` node to visit its children.
449    /// # Arguments
450    /// * `stmt` - The unwraped, typed `JumpStatement` node to visit.
451    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
452    fn visit_jump_statement(&mut self, stmt: &JumpStatement, _node: &AstNode) {
453        stmt.walk(self)
454    }
455
456    /// Visits a `LabelStatement` node.
457    /// # Arguments
458    /// * `stmt` - The unwraped, typed `LabelStatement` node to visit.
459    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
460    fn visit_label_statement(&mut self, _stmt: &LabelStatement, _node: &AstNode) {}
461
462    /// Visits an `Allocation` node
463    /// # Arguments
464    /// * `stmt` - The unwraped, typed `Allocation` node to visit.
465    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
466    fn visit_allocation(&mut self, _stmt: &Allocation, _node: &AstNode) {}
467
468    /// Visits a `Super` node.
469    /// # Arguments
470    /// * `stmt` - The unwraped, typed `Super` node to visit.
471    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
472    fn visit_super(&mut self, _stmt: &AstStatement, _node: &AstNode) {}
473
474    /// Visits a `This` node.
475    /// # Arguments
476    /// * `stmt` - The unwraped, typed `This` node to visit.
477    /// * `node` - The wrapped `AstNode` node to visit. Offers access to location information and AstId
478    fn visit_this(&mut self, _stmt: &AstStatement, _node: &AstNode) {}
479}
480
481/// Helper method that walks through a slice of `ConditionalBlock` and applies the visitor's `walk` method to each node.
482fn walk_conditional_blocks<V>(visitor: &mut V, blocks: &[ConditionalBlock])
483where
484    V: AstVisitor,
485{
486    for b in blocks {
487        visit_nodes!(visitor, &b.condition);
488        visitor.visit_statement_list(&b.body);
489    }
490}
491
492impl Walker for AstLiteral {
493    fn walk<V>(&self, _visitor: &mut V)
494    where
495        V: AstVisitor,
496    {
497        // do nothing
498    }
499}
500
501impl Walker for MultipliedStatement {
502    fn walk<V>(&self, visitor: &mut V)
503    where
504        V: AstVisitor,
505    {
506        visitor.visit(&self.element)
507    }
508}
509
510impl Walker for ReferenceExpr {
511    fn walk<V>(&self, visitor: &mut V)
512    where
513        V: AstVisitor,
514    {
515        if let Some(base) = &self.base {
516            visitor.visit(base);
517        }
518
519        match &self.access {
520            ReferenceAccess::Member(t) | ReferenceAccess::Index(t) | ReferenceAccess::Cast(t) => {
521                visitor.visit(t)
522            }
523            _ => {}
524        }
525    }
526}
527
528impl Walker for DirectAccess {
529    fn walk<V>(&self, visitor: &mut V)
530    where
531        V: AstVisitor,
532    {
533        visit_nodes!(visitor, &self.index);
534    }
535}
536
537impl Walker for HardwareAccess {
538    fn walk<V>(&self, visitor: &mut V)
539    where
540        V: AstVisitor,
541    {
542        visit_all_nodes!(visitor, &self.address);
543    }
544}
545
546impl Walker for BinaryExpression {
547    fn walk<V>(&self, visitor: &mut V)
548    where
549        V: AstVisitor,
550    {
551        visit_nodes!(visitor, &self.left, &self.right);
552    }
553}
554
555impl Walker for UnaryExpression {
556    fn walk<V>(&self, visitor: &mut V)
557    where
558        V: AstVisitor,
559    {
560        visit_nodes!(visitor, &self.value);
561    }
562}
563
564impl Walker for Assignment {
565    fn walk<V>(&self, visitor: &mut V)
566    where
567        V: AstVisitor,
568    {
569        visit_nodes!(visitor, &self.left, &self.right);
570    }
571}
572
573impl Walker for RangeStatement {
574    fn walk<V>(&self, visitor: &mut V)
575    where
576        V: AstVisitor,
577    {
578        visit_nodes!(visitor, &self.start, &self.end);
579    }
580}
581
582impl Walker for CallStatement {
583    fn walk<V>(&self, visitor: &mut V)
584    where
585        V: AstVisitor,
586    {
587        visit_nodes!(visitor, &self.operator);
588        if let Some(params) = &self.parameters {
589            visit_nodes!(visitor, params);
590        }
591    }
592}
593
594impl Walker for AstControlStatement {
595    fn walk<V>(&self, visitor: &mut V)
596    where
597        V: AstVisitor,
598    {
599        match self {
600            AstControlStatement::If(stmt) => {
601                walk_conditional_blocks(visitor, &stmt.blocks);
602                visitor.visit_statement_list(&stmt.else_block);
603            }
604            AstControlStatement::WhileLoop(stmt) | AstControlStatement::RepeatLoop(stmt) => {
605                visit_nodes!(visitor, &stmt.condition);
606                visitor.visit_statement_list(&stmt.body);
607            }
608            AstControlStatement::ForLoop(stmt) => {
609                visit_nodes!(visitor, &stmt.counter, &stmt.start, &stmt.end);
610                visit_all_nodes!(visitor, &stmt.by_step);
611                visitor.visit_statement_list(&stmt.body);
612            }
613            AstControlStatement::Case(stmt) => {
614                visit_nodes!(visitor, &stmt.selector);
615                walk_conditional_blocks(visitor, &stmt.case_blocks);
616                visitor.visit_statement_list(&stmt.else_block);
617            }
618        }
619    }
620}
621
622impl Walker for ReturnStatement {
623    fn walk<V>(&self, visitor: &mut V)
624    where
625        V: AstVisitor,
626    {
627        visit_all_nodes!(visitor, &self.condition);
628    }
629}
630
631impl Walker for JumpStatement {
632    fn walk<V>(&self, visitor: &mut V)
633    where
634        V: AstVisitor,
635    {
636        visit_nodes!(visitor, &self.condition, &self.target);
637    }
638}
639
640impl Walker for AstNode {
641    fn walk<V>(&self, visitor: &mut V)
642    where
643        V: AstVisitor,
644    {
645        let node = self;
646        match &self.stmt {
647            AstStatement::EmptyStatement(stmt) => visitor.visit_empty_statement(stmt, node),
648            AstStatement::DefaultValue(stmt) => visitor.visit_default_value(stmt, node),
649            AstStatement::Literal(stmt) => visitor.visit_literal(stmt, node),
650            AstStatement::MultipliedStatement(stmt) => visitor.visit_multiplied_statement(stmt, node),
651            AstStatement::ReferenceExpr(stmt) => visitor.visit_reference_expr(stmt, node),
652            AstStatement::Identifier(stmt) => visitor.visit_identifier(stmt, node),
653            AstStatement::DirectAccess(stmt) => visitor.visit_direct_access(stmt, node),
654            AstStatement::HardwareAccess(stmt) => visitor.visit_hardware_access(stmt, node),
655            AstStatement::BinaryExpression(stmt) => visitor.visit_binary_expression(stmt, node),
656            AstStatement::UnaryExpression(stmt) => visitor.visit_unary_expression(stmt, node),
657            AstStatement::ExpressionList(stmt) => visitor.visit_expression_list(stmt, node),
658            AstStatement::ParenExpression(stmt) => visitor.visit_paren_expression(stmt, node),
659            AstStatement::RangeStatement(stmt) => visitor.visit_range_statement(stmt, node),
660            AstStatement::VlaRangeStatement => visitor.visit_vla_range_statement(node),
661            AstStatement::Assignment(stmt) => visitor.visit_assignment(stmt, node),
662            AstStatement::OutputAssignment(stmt) => visitor.visit_output_assignment(stmt, node),
663            AstStatement::RefAssignment(stmt) => visitor.visit_ref_assignment(stmt, node),
664            AstStatement::CallStatement(stmt) => visitor.visit_call_statement(stmt, node),
665            AstStatement::ControlStatement(stmt) => visitor.visit_control_statement(stmt, node),
666            AstStatement::CaseCondition(stmt) => visitor.visit_case_condition(stmt, node),
667            AstStatement::ExitStatement(_stmt) => visitor.visit_exit_statement(node),
668            AstStatement::ContinueStatement(_stmt) => visitor.visit_continue_statement(node),
669            AstStatement::ReturnStatement(stmt) => visitor.visit_return_statement(stmt, node),
670            AstStatement::JumpStatement(stmt) => visitor.visit_jump_statement(stmt, node),
671            AstStatement::LabelStatement(stmt) => visitor.visit_label_statement(stmt, node),
672            AstStatement::AllocationStatement(stmt) => visitor.visit_allocation(stmt, node),
673            AstStatement::Super(_) => visitor.visit_super(&self.stmt, node),
674            AstStatement::This => visitor.visit_this(&self.stmt, node),
675        }
676    }
677}
678
679impl Walker for CompilationUnit {
680    fn walk<V>(&self, visitor: &mut V)
681    where
682        V: AstVisitor,
683    {
684        for user_type in &self.user_types {
685            visitor.visit_user_type_declaration(user_type);
686        }
687
688        for block in &self.global_vars {
689            visitor.visit_variable_block(block);
690        }
691        for config_variable in &self.var_config {
692            visitor.visit_config_variable(config_variable);
693        }
694
695        for interface in &self.interfaces {
696            visitor.visit_interface(interface);
697        }
698
699        for pou in &self.pous {
700            visitor.visit_pou(pou);
701        }
702
703        for i in &self.implementations {
704            visitor.visit_implementation(i);
705        }
706    }
707}
708
709impl Walker for UserTypeDeclaration {
710    fn walk<V>(&self, visitor: &mut V)
711    where
712        V: AstVisitor,
713    {
714        visitor.visit_data_type(&self.data_type);
715        visit_all_nodes!(visitor, &self.initializer);
716    }
717}
718
719impl Walker for VariableBlock {
720    fn walk<V>(&self, visitor: &mut V)
721    where
722        V: AstVisitor,
723    {
724        for v in self.variables.iter() {
725            visitor.visit_variable(v);
726        }
727    }
728}
729
730impl Walker for Variable {
731    fn walk<V>(&self, visitor: &mut V)
732    where
733        V: AstVisitor,
734    {
735        visit_all_nodes!(visitor, &self.address);
736        visitor.visit_data_type_declaration(&self.data_type_declaration);
737        visit_all_nodes!(visitor, &self.initializer);
738    }
739}
740
741impl Walker for ConfigVariable {
742    fn walk<V>(&self, _visitor: &mut V)
743    where
744        V: AstVisitor,
745    {
746        // do nothing
747    }
748}
749
750impl Walker for Interface {
751    fn walk<V>(&self, visitor: &mut V)
752    where
753        V: AstVisitor,
754    {
755        for method in &self.methods {
756            visitor.visit_pou(method);
757        }
758
759        for property in &self.properties {
760            visitor.visit_property(property);
761        }
762    }
763}
764
765impl Walker for PropertyBlock {
766    fn walk<V>(&self, visitor: &mut V)
767    where
768        V: AstVisitor,
769    {
770        for implementation in &self.implementations {
771            visitor.visit_data_type_declaration(&implementation.datatype);
772            for block in &implementation.variable_blocks {
773                visitor.visit_variable_block(block);
774            }
775            visitor.visit_statement_list(&implementation.body);
776        }
777    }
778}
779
780impl Walker for DataType {
781    fn walk<V>(&self, visitor: &mut V)
782    where
783        V: AstVisitor,
784    {
785        match self {
786            DataType::StructType { variables, .. } => {
787                for v in variables.iter() {
788                    visitor.visit_variable(v);
789                }
790            }
791            DataType::EnumType { elements, .. } => {
792                for ele in flatten_expression_list(elements) {
793                    visitor.visit_enum_element(ele);
794                }
795            }
796            DataType::SubRangeType { bounds, .. } => {
797                visit_all_nodes!(visitor, bounds);
798            }
799            DataType::ArrayType { bounds, referenced_type, .. } => {
800                visitor.visit(bounds);
801                visitor.visit_data_type_declaration(referenced_type);
802            }
803            DataType::PointerType { referenced_type, .. } => {
804                visitor.visit_data_type_declaration(referenced_type);
805            }
806            DataType::StringType { size, .. } => {
807                visit_all_nodes!(visitor, size);
808            }
809            DataType::VarArgs { referenced_type, .. } => {
810                if let Some(data_type_declaration) = referenced_type {
811                    visitor.visit_data_type_declaration(data_type_declaration);
812                }
813            }
814            DataType::GenericType { .. } => {
815                //no further visits
816            }
817        }
818    }
819}
820
821impl Walker for DataTypeDeclaration {
822    fn walk<V>(&self, visitor: &mut V)
823    where
824        V: AstVisitor,
825    {
826        if let DataTypeDeclaration::Definition { data_type, .. } = self {
827            visitor.visit_data_type(data_type);
828        }
829    }
830}
831
832impl<T> Walker for Option<T>
833where
834    T: Walker,
835{
836    fn walk<V>(&self, visitor: &mut V)
837    where
838        V: AstVisitor,
839    {
840        if let Some(node) = self {
841            node.walk(visitor);
842        }
843    }
844}
845
846impl Walker for Pou {
847    fn walk<V>(&self, visitor: &mut V)
848    where
849        V: AstVisitor,
850    {
851        for block in &self.variable_blocks {
852            visitor.visit_variable_block(block);
853        }
854
855        for property in &self.properties {
856            visitor.visit_property(property);
857        }
858
859        self.return_type.as_ref().inspect(|rt| visitor.visit_data_type_declaration(rt));
860    }
861}
862
863impl Walker for Implementation {
864    fn walk<V>(&self, visitor: &mut V)
865    where
866        V: AstVisitor,
867    {
868        visitor.visit_statement_list(&self.statements);
869    }
870}