Bug 1880927 - Use YouTube channel news to ensure DRM-free content r=mboldan
[gecko.git] / third_party / rust / glsl / src / visitor.rs
blob5867c72dedfa01e28456be1358d8f48000ada246
1 //! AST visitors (i.e. on-the-fly mutation at different places in the AST).
2 //!
3 //! Visitors are mutable objects that can mutate parts of an AST while traversing it. You can see
4 //! them as flexible mutations taking place on *patterns* representing your AST – they get called
5 //! everytime an interesting node gets visited. Because of their mutable nature, you can accumulate
6 //! a state as you traverse the AST and implement exotic filtering.
7 //!
8 //! Visitors must implement the [`Visitor`] trait in order to be usable.
9 //!
10 //! In order to visit any part of an AST (from its very top root or from any part of it), you must
11 //! use the [`Host`] interface, that provides the [`Host::visit`] function.
12 //!
13 //! For instance, we can imagine visiting an AST to count how many variables are declared:
14 //!
15 //! ```
16 //! use glsl::syntax::{CompoundStatement, Expr, SingleDeclaration, Statement, TypeSpecifierNonArray};
17 //! use glsl::visitor::{Host, Visit, Visitor};
18 //! use std::iter::FromIterator;
19 //!
20 //! let decl0 = Statement::declare_var(
21 //!   TypeSpecifierNonArray::Float,
22 //!   "x",
23 //!   None,
24 //!   Some(Expr::from(3.14).into())
25 //! );
26 //!
27 //! let decl1 = Statement::declare_var(
28 //!   TypeSpecifierNonArray::Int,
29 //!   "y",
30 //!   None,
31 //!   None
32 //! );
33 //!
34 //! let decl2 = Statement::declare_var(
35 //!   TypeSpecifierNonArray::Vec4,
36 //!   "z",
37 //!   None,
38 //!   None
39 //! );
40 //!
41 //! let compound = CompoundStatement::from_iter(vec![decl0, decl1, decl2]);
42 //!
43 //! // our visitor that will count the number of variables it saw
44 //! struct Counter {
45 //!   var_nb: usize
46 //! }
47 //!
48 //! impl Visitor for Counter {
49 //!   // we are only interested in single declaration with a name
50 //!   fn visit_single_declaration(&mut self, declaration: &SingleDeclaration) -> Visit {
51 //!     if declaration.name.is_some() {
52 //!       self.var_nb += 1;
53 //!     }
54 //!
55 //!     // do not go deeper
56 //!     Visit::Parent
57 //!   }
58 //! }
59 //!
60 //! let mut counter = Counter { var_nb: 0 };
61 //! compound.visit(&mut counter);
62 //! assert_eq!(counter.var_nb, 3);
63 //! ```
64 //!
65 //! [`Host`]: crate::visitor::Host
66 //! [`Host::visit`]: crate::visitor::Host::visit
67 //! [`Visitor`]: crate::visitor::Visitor
69 use crate::syntax;
71 /// Visit strategy after having visited an AST node.
72 ///
73 /// Some AST nodes have *children* – in enum’s variants, in some fields as nested in [`Vec`], etc.
74 /// Those nodes can be visited depending on the strategy you chose.
75 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
76 pub enum Visit {
77   /// The visitor will go deeper in the AST by visiting all the children, if any. If no children are
78   /// present or if having children doesn’t make sense for a specific part of the AST, this
79   /// strategy will be ignored.
80   Children,
81   /// The visitor won’t visit children nor siblings and will go up.
82   Parent,
85 macro_rules! make_visitor_trait {
86   ($t:ident, $($ref:tt)*) => {
87     /// Visitor object, visiting AST nodes.
88     ///
89     /// This trait exists in two flavors, depending on whether you want to mutate the AST or not: [`Visitor`] doesn’t
90     /// allow for mutation while [`VisitorMut`] does.
91     pub trait $t {
92       fn visit_translation_unit(&mut self, _: $($ref)* syntax::TranslationUnit) -> Visit {
93         Visit::Children
94       }
96       fn visit_external_declaration(&mut self, _: $($ref)* syntax::ExternalDeclaration) -> Visit {
97         Visit::Children
98       }
100       fn visit_identifier(&mut self, _: $($ref)* syntax::Identifier) -> Visit {
101         Visit::Children
102       }
104       fn visit_arrayed_identifier(&mut self, _: $($ref)* syntax::ArrayedIdentifier) -> Visit {
105         Visit::Children
106       }
108       fn visit_type_name(&mut self, _: $($ref)* syntax::TypeName) -> Visit {
109         Visit::Children
110       }
112       fn visit_block(&mut self, _: $($ref)* syntax::Block) -> Visit {
113         Visit::Children
114       }
116       fn visit_for_init_statement(&mut self, _: $($ref)* syntax::ForInitStatement) -> Visit {
117         Visit::Children
118       }
120       fn visit_for_rest_statement(&mut self, _: $($ref)* syntax::ForRestStatement) -> Visit {
121         Visit::Children
122       }
124       fn visit_function_definition(&mut self, _: $($ref)* syntax::FunctionDefinition) -> Visit {
125         Visit::Children
126       }
128       fn visit_function_parameter_declarator(
129         &mut self,
130         _: $($ref)* syntax::FunctionParameterDeclarator,
131       ) -> Visit {
132         Visit::Children
133       }
135       fn visit_function_prototype(&mut self, _: $($ref)* syntax::FunctionPrototype) -> Visit {
136         Visit::Children
137       }
139       fn visit_init_declarator_list(&mut self, _: $($ref)* syntax::InitDeclaratorList) -> Visit {
140         Visit::Children
141       }
143       fn visit_layout_qualifier(&mut self, _: $($ref)* syntax::LayoutQualifier) -> Visit {
144         Visit::Children
145       }
147       fn visit_preprocessor(&mut self, _: $($ref)* syntax::Preprocessor) -> Visit {
148         Visit::Children
149       }
151       fn visit_preprocessor_define(&mut self, _: $($ref)* syntax::PreprocessorDefine) -> Visit {
152         Visit::Children
153       }
155       fn visit_preprocessor_elseif(&mut self, _: $($ref)* syntax::PreprocessorElseIf) -> Visit {
156         Visit::Children
157       }
159       fn visit_preprocessor_error(&mut self, _: $($ref)* syntax::PreprocessorError) -> Visit {
160         Visit::Children
161       }
163       fn visit_preprocessor_extension(&mut self, _: $($ref)* syntax::PreprocessorExtension) -> Visit {
164         Visit::Children
165       }
167       fn visit_preprocessor_extension_behavior(
168         &mut self,
169         _: $($ref)* syntax::PreprocessorExtensionBehavior,
170       ) -> Visit {
171         Visit::Children
172       }
174       fn visit_preprocessor_extension_name(
175         &mut self,
176         _: $($ref)* syntax::PreprocessorExtensionName,
177       ) -> Visit {
178         Visit::Children
179       }
181       fn visit_preprocessor_if(&mut self, _: $($ref)* syntax::PreprocessorIf) -> Visit {
182         Visit::Children
183       }
185       fn visit_preprocessor_ifdef(&mut self, _: $($ref)* syntax::PreprocessorIfDef) -> Visit {
186         Visit::Children
187       }
189       fn visit_preprocessor_ifndef(&mut self, _: $($ref)* syntax::PreprocessorIfNDef) -> Visit {
190         Visit::Children
191       }
193       fn visit_preprocessor_include(&mut self, _: $($ref)* syntax::PreprocessorInclude) -> Visit {
194         Visit::Children
195       }
197       fn visit_preprocessor_line(&mut self, _: $($ref)* syntax::PreprocessorLine) -> Visit {
198         Visit::Children
199       }
201       fn visit_preprocessor_pragma(&mut self, _: $($ref)* syntax::PreprocessorPragma) -> Visit {
202         Visit::Children
203       }
205       fn visit_preprocessor_undef(&mut self, _: $($ref)* syntax::PreprocessorUndef) -> Visit {
206         Visit::Children
207       }
209       fn visit_preprocessor_version(&mut self, _: $($ref)* syntax::PreprocessorVersion) -> Visit {
210         Visit::Children
211       }
213       fn visit_preprocessor_version_profile(
214         &mut self,
215         _: $($ref)* syntax::PreprocessorVersionProfile,
216       ) -> Visit {
217         Visit::Children
218       }
220       fn visit_selection_statement(&mut self, _: $($ref)* syntax::SelectionStatement) -> Visit {
221         Visit::Children
222       }
224       fn visit_selection_rest_statement(&mut self, _: $($ref)* syntax::SelectionRestStatement) -> Visit {
225         Visit::Children
226       }
228       fn visit_single_declaration(&mut self, _: $($ref)* syntax::SingleDeclaration) -> Visit {
229         Visit::Children
230       }
232       fn visit_single_declaration_no_type(&mut self, _: $($ref)* syntax::SingleDeclarationNoType) -> Visit {
233         Visit::Children
234       }
236       fn visit_struct_field_specifier(&mut self, _: $($ref)* syntax::StructFieldSpecifier) -> Visit {
237         Visit::Children
238       }
240       fn visit_struct_specifier(&mut self, _: $($ref)* syntax::StructSpecifier) -> Visit {
241         Visit::Children
242       }
244       fn visit_switch_statement(&mut self, _: $($ref)* syntax::SwitchStatement) -> Visit {
245         Visit::Children
246       }
248       fn visit_type_qualifier(&mut self, _: $($ref)* syntax::TypeQualifier) -> Visit {
249         Visit::Children
250       }
252       fn visit_type_specifier(&mut self, _: $($ref)* syntax::TypeSpecifier) -> Visit {
253         Visit::Children
254       }
256       fn visit_full_specified_type(&mut self, _: $($ref)* syntax::FullySpecifiedType) -> Visit {
257         Visit::Children
258       }
260       fn visit_array_specifier(&mut self, _: $($ref)* syntax::ArraySpecifier) -> Visit {
261         Visit::Children
262       }
264       fn visit_array_specifier_dimension(&mut self, _: $($ref)* syntax::ArraySpecifierDimension) -> Visit {
265         Visit::Children
266       }
268       fn visit_assignment_op(&mut self, _: $($ref)* syntax::AssignmentOp) -> Visit {
269         Visit::Children
270       }
272       fn visit_binary_op(&mut self, _: $($ref)* syntax::BinaryOp) -> Visit {
273         Visit::Children
274       }
276       fn visit_case_label(&mut self, _: $($ref)* syntax::CaseLabel) -> Visit {
277         Visit::Children
278       }
280       fn visit_condition(&mut self, _: $($ref)* syntax::Condition) -> Visit {
281         Visit::Children
282       }
284       fn visit_declaration(&mut self, _: $($ref)* syntax::Declaration) -> Visit {
285         Visit::Children
286       }
288       fn visit_expr(&mut self, _: $($ref)* syntax::Expr) -> Visit {
289         Visit::Children
290       }
292       fn visit_fun_identifier(&mut self, _: $($ref)* syntax::FunIdentifier) -> Visit {
293         Visit::Children
294       }
296       fn visit_function_parameter_declaration(
297         &mut self,
298         _: $($ref)* syntax::FunctionParameterDeclaration,
299       ) -> Visit {
300         Visit::Children
301       }
303       fn visit_initializer(&mut self, _: $($ref)* syntax::Initializer) -> Visit {
304         Visit::Children
305       }
307       fn visit_interpolation_qualifier(&mut self, _: $($ref)* syntax::InterpolationQualifier) -> Visit {
308         Visit::Children
309       }
311       fn visit_iteration_statement(&mut self, _: $($ref)* syntax::IterationStatement) -> Visit {
312         Visit::Children
313       }
315       fn visit_jump_statement(&mut self, _: $($ref)* syntax::JumpStatement) -> Visit {
316         Visit::Children
317       }
319       fn visit_layout_qualifier_spec(&mut self, _: $($ref)* syntax::LayoutQualifierSpec) -> Visit {
320         Visit::Children
321       }
323       fn visit_precision_qualifier(&mut self, _: $($ref)* syntax::PrecisionQualifier) -> Visit {
324         Visit::Children
325       }
327       fn visit_statement(&mut self, _: $($ref)* syntax::Statement) -> Visit {
328         Visit::Children
329       }
331       fn visit_compound_statement(&mut self, _: $($ref)* syntax::CompoundStatement) -> Visit {
332         Visit::Children
333       }
335       fn visit_simple_statement(&mut self, _: $($ref)* syntax::SimpleStatement) -> Visit {
336         Visit::Children
337       }
339       fn visit_storage_qualifier(&mut self, _: $($ref)* syntax::StorageQualifier) -> Visit {
340         Visit::Children
341       }
343       fn visit_type_qualifier_spec(&mut self, _: $($ref)* syntax::TypeQualifierSpec) -> Visit {
344         Visit::Children
345       }
347       fn visit_type_specifier_non_array(&mut self, _: $($ref)* syntax::TypeSpecifierNonArray) -> Visit {
348         Visit::Children
349       }
351       fn visit_unary_op(&mut self, _: $($ref)* syntax::UnaryOp) -> Visit {
352         Visit::Children
353       }
355       fn visit_expr_statement(&mut self, _: $($ref)* syntax::ExprStatement) -> Visit {
356         Visit::Children
357       }
358     }
359   }
362 macro_rules! make_host_trait {
363   ($host_ty:ident, $visitor_ty:ident, $mthd_name:ident, $($ref:tt)*) => {
364     /// Part of the AST that can be visited.
365     ///
366     /// You shouldn’t have to worry about this type nor how to implement it – it’s completely
367     /// implemented for you. However, it works in a pretty simple way: any implementor of the host trait can
368     /// be used with a visitor.
369     ///
370     /// The idea is that visiting an AST node is a two-step process:
371     ///
372     ///   - First, you *can* get your visitor called once as soon as an interesting node gets visited.
373     ///     For instance, if your visitor has an implementation for visiting expressions, everytime an
374     ///     expression gets visited, your visitor will run.
375     ///   - If your implementation of visiting an AST node returns [`Visit::Children`] and if the given
376     ///     node has children, the visitor will go deeper, invoking other calls if you have defined any.
377     ///     A typical pattern you might want to do is to implement your visitor to gets run on all
378     ///     typenames. Since expressions contains variables, you will get your visitor called once again
379     ///     there.
380     ///   - Notice that since visitors are mutable, you can accumulate a state as you go deeper in the
381     ///     AST to implement various checks and validations.
382     ///
383     /// Note that this trait exists in two versions: an immutable one, [`Host`], which doesn’t allow you to mutate the
384     /// AST (but takes a `&`), and a mutable one, [`HostMut`], which allows for AST mutation.
385     pub trait $host_ty {
386       /// Visit an AST node.
387       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
388       where
389           V: $visitor_ty;
390     }
392     impl<T> $host_ty for Option<T>
393       where
394           T: $host_ty,
395       {
396         fn $mthd_name<V>($($ref)* self, visitor: &mut V)
397         where
398             V: $visitor_ty,
399         {
400           if let Some(x) = self {
401             x.$mthd_name(visitor);
402           }
403         }
404       }
406     impl<T> $host_ty for Box<T>
407       where
408           T: $host_ty,
409       {
410         fn $mthd_name<V>($($ref)* self, visitor: &mut V)
411         where
412             V: $visitor_ty,
413         {
414           (**self).$mthd_name(visitor);
415         }
416       }
418     impl $host_ty for syntax::TranslationUnit {
419       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
420       where
421           V: $visitor_ty,
422       {
423         let visit = visitor.visit_translation_unit(self);
425         if visit == Visit::Children {
426           for ed in $($ref)* (self.0).0 {
427             ed.$mthd_name(visitor);
428           }
429         }
430       }
431     }
433     impl $host_ty for syntax::ExternalDeclaration {
434       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
435       where
436           V: $visitor_ty,
437       {
438         let visit = visitor.visit_external_declaration(self);
440         if visit == Visit::Children {
441           match self {
442             syntax::ExternalDeclaration::Preprocessor(p) => p.$mthd_name(visitor),
443             syntax::ExternalDeclaration::FunctionDefinition(fd) => fd.$mthd_name(visitor),
444             syntax::ExternalDeclaration::Declaration(d) => d.$mthd_name(visitor),
445           }
446         }
447       }
448     }
450     impl $host_ty for syntax::Preprocessor {
451       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
452       where
453           V: $visitor_ty,
454       {
455         let visit = visitor.visit_preprocessor(self);
457         if visit == Visit::Children {
458           match self {
459             syntax::Preprocessor::Define(pd) => pd.$mthd_name(visitor),
460             syntax::Preprocessor::Else => (),
461             syntax::Preprocessor::ElseIf(pei) => pei.$mthd_name(visitor),
462             syntax::Preprocessor::EndIf => (),
463             syntax::Preprocessor::Error(pe) => pe.$mthd_name(visitor),
464             syntax::Preprocessor::If(pi) => pi.$mthd_name(visitor),
465             syntax::Preprocessor::IfDef(pid) => pid.$mthd_name(visitor),
466             syntax::Preprocessor::IfNDef(pind) => pind.$mthd_name(visitor),
467             syntax::Preprocessor::Include(pi) => pi.$mthd_name(visitor),
468             syntax::Preprocessor::Line(pl) => pl.$mthd_name(visitor),
469             syntax::Preprocessor::Pragma(pp) => pp.$mthd_name(visitor),
470             syntax::Preprocessor::Undef(pu) => pu.$mthd_name(visitor),
471             syntax::Preprocessor::Version(pv) => pv.$mthd_name(visitor),
472             syntax::Preprocessor::Extension(ext) => ext.$mthd_name(visitor),
473           }
474         }
475       }
476     }
478     impl $host_ty for syntax::PreprocessorDefine {
479       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
480       where
481           V: $visitor_ty,
482       {
483         let visit = visitor.visit_preprocessor_define(self);
485         if visit == Visit::Children {
486           match self {
487             syntax::PreprocessorDefine::ObjectLike { ident, .. } => {
488               ident.$mthd_name(visitor);
489             }
491             syntax::PreprocessorDefine::FunctionLike {
492               ident,
493               args,
494               ..
495             } => {
496               ident.$mthd_name(visitor);
498               for arg in args {
499                 arg.$mthd_name(visitor);
500               }
501             }
502           }
503         }
504       }
505     }
507     impl $host_ty for syntax::PreprocessorElseIf {
508       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
509       where
510           V: $visitor_ty,
511       {
512         let _ = visitor.visit_preprocessor_elseif(self);
513       }
514     }
516     impl $host_ty for syntax::PreprocessorError {
517       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
518       where
519           V: $visitor_ty,
520       {
521         let _ = visitor.visit_preprocessor_error(self);
522       }
523     }
525     impl $host_ty for syntax::PreprocessorIf {
526       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
527       where
528           V: $visitor_ty,
529       {
530         let _ = visitor.visit_preprocessor_if(self);
531       }
532     }
534     impl $host_ty for syntax::PreprocessorIfDef {
535       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
536       where
537           V: $visitor_ty,
538       {
539         let visit = visitor.visit_preprocessor_ifdef(self);
541         if visit == Visit::Children {
542           self.ident.$mthd_name(visitor);
543         }
544       }
545     }
547     impl $host_ty for syntax::PreprocessorIfNDef {
548       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
549       where
550           V: $visitor_ty,
551       {
552         let visit = visitor.visit_preprocessor_ifndef(self);
554         if visit == Visit::Children {
555           self.ident.$mthd_name(visitor);
556         }
557       }
558     }
560     impl $host_ty for syntax::PreprocessorInclude {
561       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
562       where
563           V: $visitor_ty,
564       {
565         let _ = visitor.visit_preprocessor_include(self);
566       }
567     }
569     impl $host_ty for syntax::PreprocessorLine {
570       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
571       where
572           V: $visitor_ty,
573       {
574         let _ = visitor.visit_preprocessor_line(self);
575       }
576     }
578     impl $host_ty for syntax::PreprocessorPragma {
579       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
580       where
581           V: $visitor_ty,
582       {
583         let _ = visitor.visit_preprocessor_pragma(self);
584       }
585     }
587     impl $host_ty for syntax::PreprocessorUndef {
588       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
589       where
590           V: $visitor_ty,
591       {
592         let visit = visitor.visit_preprocessor_undef(self);
594         if visit == Visit::Children {
595           self.name.$mthd_name(visitor);
596         }
597       }
598     }
600     impl $host_ty for syntax::PreprocessorVersion {
601       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
602       where
603           V: $visitor_ty,
604       {
605         let visit = visitor.visit_preprocessor_version(self);
607         if visit == Visit::Children {
608           self.profile.$mthd_name(visitor);
609         }
610       }
611     }
613     impl $host_ty for syntax::PreprocessorVersionProfile {
614       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
615       where
616           V: $visitor_ty,
617       {
618         let _ = visitor.visit_preprocessor_version_profile(self);
619       }
620     }
622     impl $host_ty for syntax::PreprocessorExtension {
623       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
624       where
625           V: $visitor_ty,
626       {
627         let visit = visitor.visit_preprocessor_extension(self);
629         if visit == Visit::Children {
630           self.name.$mthd_name(visitor);
631           self.behavior.$mthd_name(visitor);
632         }
633       }
634     }
636     impl $host_ty for syntax::PreprocessorExtensionBehavior {
637       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
638       where
639           V: $visitor_ty,
640       {
641         let _ = visitor.visit_preprocessor_extension_behavior(self);
642       }
643     }
645     impl $host_ty for syntax::PreprocessorExtensionName {
646       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
647       where
648           V: $visitor_ty,
649       {
650         let _ = visitor.visit_preprocessor_extension_name(self);
651       }
652     }
654     impl $host_ty for syntax::FunctionPrototype {
655       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
656       where
657           V: $visitor_ty,
658       {
659         let visit = visitor.visit_function_prototype(self);
661         if visit == Visit::Children {
662           self.ty.$mthd_name(visitor);
663           self.name.$mthd_name(visitor);
665           for param in $($ref)* self.parameters {
666             param.$mthd_name(visitor);
667           }
668         }
669       }
670     }
672     impl $host_ty for syntax::FunctionParameterDeclaration {
673       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
674       where
675           V: $visitor_ty,
676       {
677         let visit = visitor.visit_function_parameter_declaration(self);
679         if visit == Visit::Children {
680           match self {
681             syntax::FunctionParameterDeclaration::Named(tq, fpd) => {
682               tq.$mthd_name(visitor);
683               fpd.$mthd_name(visitor);
684             }
686             syntax::FunctionParameterDeclaration::Unnamed(tq, ty) => {
687               tq.$mthd_name(visitor);
688               ty.$mthd_name(visitor);
689             }
690           }
691         }
692       }
693     }
695     impl $host_ty for syntax::FunctionParameterDeclarator {
696       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
697       where
698           V: $visitor_ty,
699       {
700         let visit = visitor.visit_function_parameter_declarator(self);
702         if visit == Visit::Children {
703           self.ty.$mthd_name(visitor);
704           self.ident.$mthd_name(visitor);
705         }
706       }
707     }
709     impl $host_ty for syntax::FunctionDefinition {
710       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
711       where
712           V: $visitor_ty,
713       {
714         let visit = visitor.visit_function_definition(self);
716         if visit == Visit::Children {
717           self.prototype.$mthd_name(visitor);
718           self.statement.$mthd_name(visitor);
719         }
720       }
721     }
723     impl $host_ty for syntax::Declaration {
724       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
725       where
726           V: $visitor_ty,
727       {
728         let visit = visitor.visit_declaration(self);
730         if visit == Visit::Children {
731           match self {
732             syntax::Declaration::FunctionPrototype(fp) => fp.$mthd_name(visitor),
734             syntax::Declaration::InitDeclaratorList(idl) => idl.$mthd_name(visitor),
736             syntax::Declaration::Precision(pq, ty) => {
737               pq.$mthd_name(visitor);
738               ty.$mthd_name(visitor);
739             }
741             syntax::Declaration::Block(block) => block.$mthd_name(visitor),
743             syntax::Declaration::Global(tq, idents) => {
744               tq.$mthd_name(visitor);
746               for ident in idents {
747                 ident.$mthd_name(visitor);
748               }
749             }
750           }
751         }
752       }
753     }
755     impl $host_ty for syntax::Block {
756       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
757       where
758           V: $visitor_ty,
759       {
760         let visit = visitor.visit_block(self);
762         if visit == Visit::Children {
763           self.qualifier.$mthd_name(visitor);
764           self.name.$mthd_name(visitor);
766           for field in $($ref)* self.fields {
767             field.$mthd_name(visitor);
768           }
770           self.identifier.$mthd_name(visitor);
771         }
772       }
773     }
775     impl $host_ty for syntax::InitDeclaratorList {
776       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
777       where
778           V: $visitor_ty,
779       {
780         let visit = visitor.visit_init_declarator_list(self);
782         if visit == Visit::Children {
783           self.head.$mthd_name(visitor);
785           for d in $($ref)* self.tail {
786             d.$mthd_name(visitor);
787           }
788         }
789       }
790     }
792     impl $host_ty for syntax::SingleDeclaration {
793       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
794       where
795           V: $visitor_ty,
796       {
797         let visit = visitor.visit_single_declaration(self);
799         if visit == Visit::Children {
800           self.ty.$mthd_name(visitor);
801           self.name.$mthd_name(visitor);
802           self.array_specifier.$mthd_name(visitor);
803           self.initializer.$mthd_name(visitor);
804         }
805       }
806     }
808     impl $host_ty for syntax::SingleDeclarationNoType {
809       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
810       where
811           V: $visitor_ty,
812       {
813         let visit = visitor.visit_single_declaration_no_type(self);
815         if visit == Visit::Children {
816           self.ident.$mthd_name(visitor);
817           self.initializer.$mthd_name(visitor);
818         }
819       }
820     }
822     impl $host_ty for syntax::FullySpecifiedType {
823       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
824       where
825           V: $visitor_ty,
826       {
827         let visit = visitor.visit_full_specified_type(self);
829         if visit == Visit::Children {
830           self.qualifier.$mthd_name(visitor);
831           self.ty.$mthd_name(visitor);
832         }
833       }
834     }
836     impl $host_ty for syntax::TypeSpecifier {
837       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
838       where
839           V: $visitor_ty,
840       {
841         let visit = visitor.visit_type_specifier(self);
843         if visit == Visit::Children {
844           self.ty.$mthd_name(visitor);
845           self.array_specifier.$mthd_name(visitor);
846         }
847       }
848     }
850     impl $host_ty for syntax::TypeSpecifierNonArray {
851       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
852       where
853           V: $visitor_ty,
854       {
855         let visit = visitor.visit_type_specifier_non_array(self);
857         if visit == Visit::Children {
858           match self {
859             syntax::TypeSpecifierNonArray::Struct(ss) => ss.$mthd_name(visitor),
860             syntax::TypeSpecifierNonArray::TypeName(tn) => tn.$mthd_name(visitor),
861             _ => (),
862           }
863         }
864       }
865     }
867     impl $host_ty for syntax::TypeQualifier {
868       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
869       where
870           V: $visitor_ty,
871       {
872         let visit = visitor.visit_type_qualifier(self);
874         if visit == Visit::Children {
875           for tqs in $($ref)* self.qualifiers.0 {
876             tqs.$mthd_name(visitor);
877           }
878         }
879       }
880     }
882     impl $host_ty for syntax::TypeQualifierSpec {
883       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
884       where
885           V: $visitor_ty,
886       {
887         let visit = visitor.visit_type_qualifier_spec(self);
889         if visit == Visit::Children {
890           match self {
891             syntax::TypeQualifierSpec::Storage(sq) => sq.$mthd_name(visitor),
892             syntax::TypeQualifierSpec::Layout(lq) => lq.$mthd_name(visitor),
893             syntax::TypeQualifierSpec::Precision(pq) => pq.$mthd_name(visitor),
894             syntax::TypeQualifierSpec::Interpolation(iq) => iq.$mthd_name(visitor),
895             _ => (),
896           }
897         }
898       }
899     }
901     impl $host_ty for syntax::StorageQualifier {
902       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
903       where
904           V: $visitor_ty,
905       {
906         let visit = visitor.visit_storage_qualifier(self);
908         if visit == Visit::Children {
909           if let syntax::StorageQualifier::Subroutine(names) = self {
910             for name in names {
911               name.$mthd_name(visitor);
912             }
913           }
914         }
915       }
916     }
918     impl $host_ty for syntax::LayoutQualifier {
919       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
920       where
921           V: $visitor_ty,
922       {
923         let visit = visitor.visit_layout_qualifier(self);
925         if visit == Visit::Children {
926           for lqs in $($ref)* self.ids.0 {
927             lqs.$mthd_name(visitor);
928           }
929         }
930       }
931     }
933     impl $host_ty for syntax::LayoutQualifierSpec {
934       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
935       where
936           V: $visitor_ty,
937       {
938         let visit = visitor.visit_layout_qualifier_spec(self);
940         if visit == Visit::Children {
941           if let syntax::LayoutQualifierSpec::Identifier(ident, expr) = self {
942             ident.$mthd_name(visitor);
944             if let Some(e) = expr {
945               e.$mthd_name(visitor);
946             }
947           }
948         }
949       }
950     }
952     impl $host_ty for syntax::PrecisionQualifier {
953       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
954       where
955           V: $visitor_ty,
956       {
957         let _ = visitor.visit_precision_qualifier(self);
958       }
959     }
961     impl $host_ty for syntax::InterpolationQualifier {
962       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
963       where
964           V: $visitor_ty,
965       {
966         let _ = visitor.visit_interpolation_qualifier(self);
967       }
968     }
970     impl $host_ty for syntax::TypeName {
971       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
972       where
973           V: $visitor_ty,
974       {
975         let _ = visitor.visit_type_name(self);
976       }
977     }
979     impl $host_ty for syntax::Identifier {
980       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
981       where
982           V: $visitor_ty,
983       {
984         let _ = visitor.visit_identifier(self);
985       }
986     }
988     impl $host_ty for syntax::ArrayedIdentifier {
989       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
990       where
991           V: $visitor_ty,
992       {
993         let visit = visitor.visit_arrayed_identifier(self);
995         if visit == Visit::Children {
996           self.ident.$mthd_name(visitor);
997           self.array_spec.$mthd_name(visitor);
998         }
999       }
1000     }
1002     impl $host_ty for syntax::Expr {
1003       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1004       where
1005           V: $visitor_ty,
1006       {
1007         let visit = visitor.visit_expr(self);
1009         if visit == Visit::Children {
1010           match self {
1011             syntax::Expr::Variable(ident) => ident.$mthd_name(visitor),
1013             syntax::Expr::Unary(op, e) => {
1014               op.$mthd_name(visitor);
1015               e.$mthd_name(visitor);
1016             }
1018             syntax::Expr::Binary(op, a, b) => {
1019               op.$mthd_name(visitor);
1020               a.$mthd_name(visitor);
1021               b.$mthd_name(visitor);
1022             }
1024             syntax::Expr::Ternary(a, b, c) => {
1025               a.$mthd_name(visitor);
1026               b.$mthd_name(visitor);
1027               c.$mthd_name(visitor);
1028             }
1030             syntax::Expr::Assignment(lhs, op, rhs) => {
1031               lhs.$mthd_name(visitor);
1032               op.$mthd_name(visitor);
1033               rhs.$mthd_name(visitor);
1034             }
1036             syntax::Expr::Bracket(e, arr_spec) => {
1037               e.$mthd_name(visitor);
1038               arr_spec.$mthd_name(visitor);
1039             }
1041             syntax::Expr::FunCall(fi, params) => {
1042               fi.$mthd_name(visitor);
1044               for param in params {
1045                 param.$mthd_name(visitor);
1046               }
1047             }
1049             syntax::Expr::Dot(e, i) => {
1050               e.$mthd_name(visitor);
1051               i.$mthd_name(visitor);
1052             }
1054             syntax::Expr::PostInc(e) => e.$mthd_name(visitor),
1056             syntax::Expr::PostDec(e) => e.$mthd_name(visitor),
1058             syntax::Expr::Comma(a, b) => {
1059               a.$mthd_name(visitor);
1060               b.$mthd_name(visitor);
1061             }
1063             _ => (),
1064           }
1065         }
1066       }
1067     }
1069     impl $host_ty for syntax::UnaryOp {
1070       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1071       where
1072           V: $visitor_ty,
1073       {
1074         let _ = visitor.visit_unary_op(self);
1075       }
1076     }
1078     impl $host_ty for syntax::BinaryOp {
1079       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1080       where
1081           V: $visitor_ty,
1082       {
1083         let _ = visitor.visit_binary_op(self);
1084       }
1085     }
1087     impl $host_ty for syntax::AssignmentOp {
1088       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1089       where
1090           V: $visitor_ty,
1091       {
1092         let _ = visitor.visit_assignment_op(self);
1093       }
1094     }
1096     impl $host_ty for syntax::ArraySpecifier {
1097       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1098       where
1099           V: $visitor_ty,
1100       {
1101         let visit = visitor.visit_array_specifier(self);
1103         if visit == Visit::Children {
1104           for dimension in $($ref)* self.dimensions {
1105             dimension.$mthd_name(visitor);
1106           }
1107         }
1108       }
1109     }
1111     impl $host_ty for syntax::ArraySpecifierDimension {
1112       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1113       where
1114           V: $visitor_ty,
1115       {
1116         let visit = visitor.visit_array_specifier_dimension(self);
1118         if visit == Visit::Children {
1119           if let syntax::ArraySpecifierDimension::ExplicitlySized(e) = self {
1120             e.$mthd_name(visitor);
1121           }
1122         }
1123       }
1124     }
1126     impl $host_ty for syntax::FunIdentifier {
1127       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1128       where
1129           V: $visitor_ty,
1130       {
1131         let visit = visitor.visit_fun_identifier(self);
1133         if visit == Visit::Children {
1134           match self {
1135             syntax::FunIdentifier::Identifier(i) => i.$mthd_name(visitor),
1136             syntax::FunIdentifier::Expr(e) => e.$mthd_name(visitor),
1137           }
1138         }
1139       }
1140     }
1142     impl $host_ty for syntax::StructSpecifier {
1143       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1144       where
1145           V: $visitor_ty,
1146       {
1147         let visit = visitor.visit_struct_specifier(self);
1149         if visit == Visit::Children {
1150           self.name.$mthd_name(visitor);
1152           for field in $($ref)* self.fields.0 {
1153             field.$mthd_name(visitor);
1154           }
1155         }
1156       }
1157     }
1159     impl $host_ty for syntax::StructFieldSpecifier {
1160       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1161       where
1162           V: $visitor_ty,
1163       {
1164         let visit = visitor.visit_struct_field_specifier(self);
1166         if visit == Visit::Children {
1167           self.qualifier.$mthd_name(visitor);
1168           self.ty.$mthd_name(visitor);
1170           for identifier in $($ref)* self.identifiers.0 {
1171             identifier.$mthd_name(visitor);
1172           }
1173         }
1174       }
1175     }
1177     impl $host_ty for syntax::Statement {
1178       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1179       where
1180           V: $visitor_ty,
1181       {
1182         let visit = visitor.visit_statement(self);
1184         if visit == Visit::Children {
1185           match self {
1186             syntax::Statement::Compound(cs) => cs.$mthd_name(visitor),
1187             syntax::Statement::Simple(ss) => ss.$mthd_name(visitor),
1188           }
1189         }
1190       }
1191     }
1193     impl $host_ty for syntax::SimpleStatement {
1194       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1195       where
1196           V: $visitor_ty,
1197       {
1198         let visit = visitor.visit_simple_statement(self);
1200         if visit == Visit::Children {
1201           match self {
1202             syntax::SimpleStatement::Declaration(d) => d.$mthd_name(visitor),
1203             syntax::SimpleStatement::Expression(e) => e.$mthd_name(visitor),
1204             syntax::SimpleStatement::Selection(s) => s.$mthd_name(visitor),
1205             syntax::SimpleStatement::Switch(s) => s.$mthd_name(visitor),
1206             syntax::SimpleStatement::CaseLabel(cl) => cl.$mthd_name(visitor),
1207             syntax::SimpleStatement::Iteration(i) => i.$mthd_name(visitor),
1208             syntax::SimpleStatement::Jump(j) => j.$mthd_name(visitor),
1209           }
1210         }
1211       }
1212     }
1214     impl $host_ty for syntax::CompoundStatement {
1215       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1216       where
1217           V: $visitor_ty,
1218       {
1219         let visit = visitor.visit_compound_statement(self);
1221         if visit == Visit::Children {
1222           for stmt in $($ref)* self.statement_list {
1223             stmt.$mthd_name(visitor);
1224           }
1225         }
1226       }
1227     }
1229     impl $host_ty for syntax::SelectionStatement {
1230       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1231       where
1232           V: $visitor_ty,
1233       {
1234         let visit = visitor.visit_selection_statement(self);
1236         if visit == Visit::Children {
1237           self.cond.$mthd_name(visitor);
1238           self.rest.$mthd_name(visitor);
1239         }
1240       }
1241     }
1243     impl $host_ty for syntax::SelectionRestStatement {
1244       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1245       where
1246           V: $visitor_ty,
1247       {
1248         let visit = visitor.visit_selection_rest_statement(self);
1250         if visit == Visit::Children {
1251           match self {
1252             syntax::SelectionRestStatement::Statement(s) => s.$mthd_name(visitor),
1254             syntax::SelectionRestStatement::Else(a, b) => {
1255               a.$mthd_name(visitor);
1256               b.$mthd_name(visitor);
1257             }
1258           }
1259         }
1260       }
1261     }
1263     impl $host_ty for syntax::SwitchStatement {
1264       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1265       where
1266           V: $visitor_ty,
1267       {
1268         let visit = visitor.visit_switch_statement(self);
1270         if visit == Visit::Children {
1271           self.head.$mthd_name(visitor);
1273           for s in $($ref)* self.body {
1274             s.$mthd_name(visitor);
1275           }
1276         }
1277       }
1278     }
1280     impl $host_ty for syntax::CaseLabel {
1281       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1282       where
1283           V: $visitor_ty,
1284       {
1285         let visit = visitor.visit_case_label(self);
1287         if visit == Visit::Children {
1288           if let syntax::CaseLabel::Case(e) = self {
1289             e.$mthd_name(visitor);
1290           }
1291         }
1292       }
1293     }
1295     impl $host_ty for syntax::IterationStatement {
1296       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1297       where
1298           V: $visitor_ty,
1299       {
1300         let visit = visitor.visit_iteration_statement(self);
1302         if visit == Visit::Children {
1303           match self {
1304             syntax::IterationStatement::While(c, s) => {
1305               c.$mthd_name(visitor);
1306               s.$mthd_name(visitor);
1307             }
1309             syntax::IterationStatement::DoWhile(s, e) => {
1310               s.$mthd_name(visitor);
1311               e.$mthd_name(visitor);
1312             }
1314             syntax::IterationStatement::For(fis, frs, s) => {
1315               fis.$mthd_name(visitor);
1316               frs.$mthd_name(visitor);
1317               s.$mthd_name(visitor);
1318             }
1319           }
1320         }
1321       }
1322     }
1324     impl $host_ty for syntax::ForInitStatement {
1325       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1326       where
1327           V: $visitor_ty,
1328       {
1329         let visit = visitor.visit_for_init_statement(self);
1331         if visit == Visit::Children {
1332           match self {
1333             syntax::ForInitStatement::Expression(e) => e.$mthd_name(visitor),
1334             syntax::ForInitStatement::Declaration(d) => d.$mthd_name(visitor),
1335           }
1336         }
1337       }
1338     }
1340     impl $host_ty for syntax::ForRestStatement {
1341       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1342       where
1343           V: $visitor_ty,
1344       {
1345         let visit = visitor.visit_for_rest_statement(self);
1347         if visit == Visit::Children {
1348           self.condition.$mthd_name(visitor);
1349           self.post_expr.$mthd_name(visitor);
1350         }
1351       }
1352     }
1354     impl $host_ty for syntax::JumpStatement {
1355       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1356       where
1357           V: $visitor_ty,
1358       {
1359         let visit = visitor.visit_jump_statement(self);
1361         if visit == Visit::Children {
1362           if let syntax::JumpStatement::Return(r) = self {
1363             r.$mthd_name(visitor);
1364           }
1365         }
1366       }
1367     }
1369     impl $host_ty for syntax::Condition {
1370       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1371       where
1372           V: $visitor_ty,
1373       {
1374         let visit = visitor.visit_condition(self);
1376         if visit == Visit::Children {
1377           match self {
1378             syntax::Condition::Expr(e) => e.$mthd_name(visitor),
1380             syntax::Condition::Assignment(fst, ident, init) => {
1381               fst.$mthd_name(visitor);
1382               ident.$mthd_name(visitor);
1383               init.$mthd_name(visitor);
1384             }
1385           }
1386         }
1387       }
1388     }
1390     impl $host_ty for syntax::Initializer {
1391       fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1392       where
1393           V: $visitor_ty,
1394       {
1395         let visit = visitor.visit_initializer(self);
1397         if visit == Visit::Children {
1398           match self {
1399             syntax::Initializer::Simple(e) => e.$mthd_name(visitor),
1401             syntax::Initializer::List(i) => {
1402               for i in $($ref)* i.0 {
1403                 i.$mthd_name(visitor);
1404               }
1405             }
1406           }
1407         }
1408       }
1409     }
1410   }
1413 // immutable
1414 make_visitor_trait!(Visitor, &);
1415 make_host_trait!(Host, Visitor, visit, &);
1417 // mutable
1418 make_visitor_trait!(VisitorMut, &mut);
1419 make_host_trait!(HostMut, VisitorMut, visit_mut, &mut);
1421 #[cfg(test)]
1422 mod tests {
1423   use std::iter::FromIterator;
1425   use super::*;
1426   use syntax;
1428   #[test]
1429   fn count_variables() {
1430     let decl0 = syntax::Statement::declare_var(
1431       syntax::TypeSpecifierNonArray::Float,
1432       "x",
1433       None,
1434       Some(syntax::Expr::from(3.14).into()),
1435     );
1437     let decl1 = syntax::Statement::declare_var(syntax::TypeSpecifierNonArray::Int, "y", None, None);
1439     let decl2 =
1440       syntax::Statement::declare_var(syntax::TypeSpecifierNonArray::Vec4, "z", None, None);
1442     let compound = syntax::CompoundStatement::from_iter(vec![decl0, decl1, decl2]);
1444     // our visitor that will count the number of variables it saw
1445     struct Counter {
1446       var_nb: usize,
1447     }
1449     impl Visitor for Counter {
1450       // we are only interested in single declaration with a name
1451       fn visit_single_declaration(&mut self, declaration: &syntax::SingleDeclaration) -> Visit {
1452         if declaration.name.is_some() {
1453           self.var_nb += 1;
1454         }
1456         // do not go deeper
1457         Visit::Parent
1458       }
1459     }
1461     let mut counter = Counter { var_nb: 0 };
1462     compound.visit(&mut counter);
1463     assert_eq!(counter.var_nb, 3);
1464   }