1 //! AST visitors (i.e. on-the-fly mutation at different places in the AST).
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.
8 //! Visitors must implement the [`Visitor`] trait in order to be usable.
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.
13 //! For instance, we can imagine visiting an AST to count how many variables are declared:
16 //! use glsl::syntax::{CompoundStatement, Expr, SingleDeclaration, Statement, TypeSpecifierNonArray};
17 //! use glsl::visitor::{Host, Visit, Visitor};
18 //! use std::iter::FromIterator;
20 //! let decl0 = Statement::declare_var(
21 //! TypeSpecifierNonArray::Float,
24 //! Some(Expr::from(3.14).into())
27 //! let decl1 = Statement::declare_var(
28 //! TypeSpecifierNonArray::Int,
34 //! let decl2 = Statement::declare_var(
35 //! TypeSpecifierNonArray::Vec4,
41 //! let compound = CompoundStatement::from_iter(vec![decl0, decl1, decl2]);
43 //! // our visitor that will count the number of variables it saw
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() {
55 //! // do not go deeper
60 //! let mut counter = Counter { var_nb: 0 };
61 //! compound.visit(&mut counter);
62 //! assert_eq!(counter.var_nb, 3);
65 //! [`Host`]: crate::visitor::Host
66 //! [`Host::visit`]: crate::visitor::Host::visit
67 //! [`Visitor`]: crate::visitor::Visitor
71 /// Visit strategy after having visited an AST node.
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)]
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.
81 /// The visitor won’t visit children nor siblings and will go up.
85 macro_rules! make_visitor_trait {
86 ($t:ident, $($ref:tt)*) => {
87 /// Visitor object, visiting AST nodes.
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.
92 fn visit_translation_unit(&mut self, _: $($ref)* syntax::TranslationUnit) -> Visit {
96 fn visit_external_declaration(&mut self, _: $($ref)* syntax::ExternalDeclaration) -> Visit {
100 fn visit_identifier(&mut self, _: $($ref)* syntax::Identifier) -> Visit {
104 fn visit_arrayed_identifier(&mut self, _: $($ref)* syntax::ArrayedIdentifier) -> Visit {
108 fn visit_type_name(&mut self, _: $($ref)* syntax::TypeName) -> Visit {
112 fn visit_block(&mut self, _: $($ref)* syntax::Block) -> Visit {
116 fn visit_for_init_statement(&mut self, _: $($ref)* syntax::ForInitStatement) -> Visit {
120 fn visit_for_rest_statement(&mut self, _: $($ref)* syntax::ForRestStatement) -> Visit {
124 fn visit_function_definition(&mut self, _: $($ref)* syntax::FunctionDefinition) -> Visit {
128 fn visit_function_parameter_declarator(
130 _: $($ref)* syntax::FunctionParameterDeclarator,
135 fn visit_function_prototype(&mut self, _: $($ref)* syntax::FunctionPrototype) -> Visit {
139 fn visit_init_declarator_list(&mut self, _: $($ref)* syntax::InitDeclaratorList) -> Visit {
143 fn visit_layout_qualifier(&mut self, _: $($ref)* syntax::LayoutQualifier) -> Visit {
147 fn visit_preprocessor(&mut self, _: $($ref)* syntax::Preprocessor) -> Visit {
151 fn visit_preprocessor_define(&mut self, _: $($ref)* syntax::PreprocessorDefine) -> Visit {
155 fn visit_preprocessor_elseif(&mut self, _: $($ref)* syntax::PreprocessorElseIf) -> Visit {
159 fn visit_preprocessor_error(&mut self, _: $($ref)* syntax::PreprocessorError) -> Visit {
163 fn visit_preprocessor_extension(&mut self, _: $($ref)* syntax::PreprocessorExtension) -> Visit {
167 fn visit_preprocessor_extension_behavior(
169 _: $($ref)* syntax::PreprocessorExtensionBehavior,
174 fn visit_preprocessor_extension_name(
176 _: $($ref)* syntax::PreprocessorExtensionName,
181 fn visit_preprocessor_if(&mut self, _: $($ref)* syntax::PreprocessorIf) -> Visit {
185 fn visit_preprocessor_ifdef(&mut self, _: $($ref)* syntax::PreprocessorIfDef) -> Visit {
189 fn visit_preprocessor_ifndef(&mut self, _: $($ref)* syntax::PreprocessorIfNDef) -> Visit {
193 fn visit_preprocessor_include(&mut self, _: $($ref)* syntax::PreprocessorInclude) -> Visit {
197 fn visit_preprocessor_line(&mut self, _: $($ref)* syntax::PreprocessorLine) -> Visit {
201 fn visit_preprocessor_pragma(&mut self, _: $($ref)* syntax::PreprocessorPragma) -> Visit {
205 fn visit_preprocessor_undef(&mut self, _: $($ref)* syntax::PreprocessorUndef) -> Visit {
209 fn visit_preprocessor_version(&mut self, _: $($ref)* syntax::PreprocessorVersion) -> Visit {
213 fn visit_preprocessor_version_profile(
215 _: $($ref)* syntax::PreprocessorVersionProfile,
220 fn visit_selection_statement(&mut self, _: $($ref)* syntax::SelectionStatement) -> Visit {
224 fn visit_selection_rest_statement(&mut self, _: $($ref)* syntax::SelectionRestStatement) -> Visit {
228 fn visit_single_declaration(&mut self, _: $($ref)* syntax::SingleDeclaration) -> Visit {
232 fn visit_single_declaration_no_type(&mut self, _: $($ref)* syntax::SingleDeclarationNoType) -> Visit {
236 fn visit_struct_field_specifier(&mut self, _: $($ref)* syntax::StructFieldSpecifier) -> Visit {
240 fn visit_struct_specifier(&mut self, _: $($ref)* syntax::StructSpecifier) -> Visit {
244 fn visit_switch_statement(&mut self, _: $($ref)* syntax::SwitchStatement) -> Visit {
248 fn visit_type_qualifier(&mut self, _: $($ref)* syntax::TypeQualifier) -> Visit {
252 fn visit_type_specifier(&mut self, _: $($ref)* syntax::TypeSpecifier) -> Visit {
256 fn visit_full_specified_type(&mut self, _: $($ref)* syntax::FullySpecifiedType) -> Visit {
260 fn visit_array_specifier(&mut self, _: $($ref)* syntax::ArraySpecifier) -> Visit {
264 fn visit_array_specifier_dimension(&mut self, _: $($ref)* syntax::ArraySpecifierDimension) -> Visit {
268 fn visit_assignment_op(&mut self, _: $($ref)* syntax::AssignmentOp) -> Visit {
272 fn visit_binary_op(&mut self, _: $($ref)* syntax::BinaryOp) -> Visit {
276 fn visit_case_label(&mut self, _: $($ref)* syntax::CaseLabel) -> Visit {
280 fn visit_condition(&mut self, _: $($ref)* syntax::Condition) -> Visit {
284 fn visit_declaration(&mut self, _: $($ref)* syntax::Declaration) -> Visit {
288 fn visit_expr(&mut self, _: $($ref)* syntax::Expr) -> Visit {
292 fn visit_fun_identifier(&mut self, _: $($ref)* syntax::FunIdentifier) -> Visit {
296 fn visit_function_parameter_declaration(
298 _: $($ref)* syntax::FunctionParameterDeclaration,
303 fn visit_initializer(&mut self, _: $($ref)* syntax::Initializer) -> Visit {
307 fn visit_interpolation_qualifier(&mut self, _: $($ref)* syntax::InterpolationQualifier) -> Visit {
311 fn visit_iteration_statement(&mut self, _: $($ref)* syntax::IterationStatement) -> Visit {
315 fn visit_jump_statement(&mut self, _: $($ref)* syntax::JumpStatement) -> Visit {
319 fn visit_layout_qualifier_spec(&mut self, _: $($ref)* syntax::LayoutQualifierSpec) -> Visit {
323 fn visit_precision_qualifier(&mut self, _: $($ref)* syntax::PrecisionQualifier) -> Visit {
327 fn visit_statement(&mut self, _: $($ref)* syntax::Statement) -> Visit {
331 fn visit_compound_statement(&mut self, _: $($ref)* syntax::CompoundStatement) -> Visit {
335 fn visit_simple_statement(&mut self, _: $($ref)* syntax::SimpleStatement) -> Visit {
339 fn visit_storage_qualifier(&mut self, _: $($ref)* syntax::StorageQualifier) -> Visit {
343 fn visit_type_qualifier_spec(&mut self, _: $($ref)* syntax::TypeQualifierSpec) -> Visit {
347 fn visit_type_specifier_non_array(&mut self, _: $($ref)* syntax::TypeSpecifierNonArray) -> Visit {
351 fn visit_unary_op(&mut self, _: $($ref)* syntax::UnaryOp) -> Visit {
355 fn visit_expr_statement(&mut self, _: $($ref)* syntax::ExprStatement) -> Visit {
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.
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.
370 /// The idea is that visiting an AST node is a two-step process:
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
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.
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.
386 /// Visit an AST node.
387 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
392 impl<T> $host_ty for Option<T>
396 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
400 if let Some(x) = self {
401 x.$mthd_name(visitor);
406 impl<T> $host_ty for Box<T>
410 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
414 (**self).$mthd_name(visitor);
418 impl $host_ty for syntax::TranslationUnit {
419 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
433 impl $host_ty for syntax::ExternalDeclaration {
434 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
438 let visit = visitor.visit_external_declaration(self);
440 if visit == Visit::Children {
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),
450 impl $host_ty for syntax::Preprocessor {
451 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
455 let visit = visitor.visit_preprocessor(self);
457 if visit == Visit::Children {
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),
478 impl $host_ty for syntax::PreprocessorDefine {
479 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
483 let visit = visitor.visit_preprocessor_define(self);
485 if visit == Visit::Children {
487 syntax::PreprocessorDefine::ObjectLike { ident, .. } => {
488 ident.$mthd_name(visitor);
491 syntax::PreprocessorDefine::FunctionLike {
496 ident.$mthd_name(visitor);
499 arg.$mthd_name(visitor);
507 impl $host_ty for syntax::PreprocessorElseIf {
508 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
512 let _ = visitor.visit_preprocessor_elseif(self);
516 impl $host_ty for syntax::PreprocessorError {
517 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
521 let _ = visitor.visit_preprocessor_error(self);
525 impl $host_ty for syntax::PreprocessorIf {
526 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
530 let _ = visitor.visit_preprocessor_if(self);
534 impl $host_ty for syntax::PreprocessorIfDef {
535 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
539 let visit = visitor.visit_preprocessor_ifdef(self);
541 if visit == Visit::Children {
542 self.ident.$mthd_name(visitor);
547 impl $host_ty for syntax::PreprocessorIfNDef {
548 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
552 let visit = visitor.visit_preprocessor_ifndef(self);
554 if visit == Visit::Children {
555 self.ident.$mthd_name(visitor);
560 impl $host_ty for syntax::PreprocessorInclude {
561 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
565 let _ = visitor.visit_preprocessor_include(self);
569 impl $host_ty for syntax::PreprocessorLine {
570 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
574 let _ = visitor.visit_preprocessor_line(self);
578 impl $host_ty for syntax::PreprocessorPragma {
579 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
583 let _ = visitor.visit_preprocessor_pragma(self);
587 impl $host_ty for syntax::PreprocessorUndef {
588 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
592 let visit = visitor.visit_preprocessor_undef(self);
594 if visit == Visit::Children {
595 self.name.$mthd_name(visitor);
600 impl $host_ty for syntax::PreprocessorVersion {
601 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
605 let visit = visitor.visit_preprocessor_version(self);
607 if visit == Visit::Children {
608 self.profile.$mthd_name(visitor);
613 impl $host_ty for syntax::PreprocessorVersionProfile {
614 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
618 let _ = visitor.visit_preprocessor_version_profile(self);
622 impl $host_ty for syntax::PreprocessorExtension {
623 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
636 impl $host_ty for syntax::PreprocessorExtensionBehavior {
637 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
641 let _ = visitor.visit_preprocessor_extension_behavior(self);
645 impl $host_ty for syntax::PreprocessorExtensionName {
646 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
650 let _ = visitor.visit_preprocessor_extension_name(self);
654 impl $host_ty for syntax::FunctionPrototype {
655 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
672 impl $host_ty for syntax::FunctionParameterDeclaration {
673 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
677 let visit = visitor.visit_function_parameter_declaration(self);
679 if visit == Visit::Children {
681 syntax::FunctionParameterDeclaration::Named(tq, fpd) => {
682 tq.$mthd_name(visitor);
683 fpd.$mthd_name(visitor);
686 syntax::FunctionParameterDeclaration::Unnamed(tq, ty) => {
687 tq.$mthd_name(visitor);
688 ty.$mthd_name(visitor);
695 impl $host_ty for syntax::FunctionParameterDeclarator {
696 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
709 impl $host_ty for syntax::FunctionDefinition {
710 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
723 impl $host_ty for syntax::Declaration {
724 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
728 let visit = visitor.visit_declaration(self);
730 if visit == Visit::Children {
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);
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);
755 impl $host_ty for syntax::Block {
756 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
770 self.identifier.$mthd_name(visitor);
775 impl $host_ty for syntax::InitDeclaratorList {
776 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
792 impl $host_ty for syntax::SingleDeclaration {
793 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
808 impl $host_ty for syntax::SingleDeclarationNoType {
809 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
822 impl $host_ty for syntax::FullySpecifiedType {
823 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
836 impl $host_ty for syntax::TypeSpecifier {
837 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
850 impl $host_ty for syntax::TypeSpecifierNonArray {
851 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
855 let visit = visitor.visit_type_specifier_non_array(self);
857 if visit == Visit::Children {
859 syntax::TypeSpecifierNonArray::Struct(ss) => ss.$mthd_name(visitor),
860 syntax::TypeSpecifierNonArray::TypeName(tn) => tn.$mthd_name(visitor),
867 impl $host_ty for syntax::TypeQualifier {
868 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
882 impl $host_ty for syntax::TypeQualifierSpec {
883 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
887 let visit = visitor.visit_type_qualifier_spec(self);
889 if visit == Visit::Children {
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),
901 impl $host_ty for syntax::StorageQualifier {
902 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
906 let visit = visitor.visit_storage_qualifier(self);
908 if visit == Visit::Children {
909 if let syntax::StorageQualifier::Subroutine(names) = self {
911 name.$mthd_name(visitor);
918 impl $host_ty for syntax::LayoutQualifier {
919 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
933 impl $host_ty for syntax::LayoutQualifierSpec {
934 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
952 impl $host_ty for syntax::PrecisionQualifier {
953 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
957 let _ = visitor.visit_precision_qualifier(self);
961 impl $host_ty for syntax::InterpolationQualifier {
962 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
966 let _ = visitor.visit_interpolation_qualifier(self);
970 impl $host_ty for syntax::TypeName {
971 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
975 let _ = visitor.visit_type_name(self);
979 impl $host_ty for syntax::Identifier {
980 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
984 let _ = visitor.visit_identifier(self);
988 impl $host_ty for syntax::ArrayedIdentifier {
989 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1002 impl $host_ty for syntax::Expr {
1003 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1007 let visit = visitor.visit_expr(self);
1009 if visit == Visit::Children {
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);
1018 syntax::Expr::Binary(op, a, b) => {
1019 op.$mthd_name(visitor);
1020 a.$mthd_name(visitor);
1021 b.$mthd_name(visitor);
1024 syntax::Expr::Ternary(a, b, c) => {
1025 a.$mthd_name(visitor);
1026 b.$mthd_name(visitor);
1027 c.$mthd_name(visitor);
1030 syntax::Expr::Assignment(lhs, op, rhs) => {
1031 lhs.$mthd_name(visitor);
1032 op.$mthd_name(visitor);
1033 rhs.$mthd_name(visitor);
1036 syntax::Expr::Bracket(e, arr_spec) => {
1037 e.$mthd_name(visitor);
1038 arr_spec.$mthd_name(visitor);
1041 syntax::Expr::FunCall(fi, params) => {
1042 fi.$mthd_name(visitor);
1044 for param in params {
1045 param.$mthd_name(visitor);
1049 syntax::Expr::Dot(e, i) => {
1050 e.$mthd_name(visitor);
1051 i.$mthd_name(visitor);
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);
1069 impl $host_ty for syntax::UnaryOp {
1070 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1074 let _ = visitor.visit_unary_op(self);
1078 impl $host_ty for syntax::BinaryOp {
1079 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1083 let _ = visitor.visit_binary_op(self);
1087 impl $host_ty for syntax::AssignmentOp {
1088 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1092 let _ = visitor.visit_assignment_op(self);
1096 impl $host_ty for syntax::ArraySpecifier {
1097 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1111 impl $host_ty for syntax::ArraySpecifierDimension {
1112 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1126 impl $host_ty for syntax::FunIdentifier {
1127 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1131 let visit = visitor.visit_fun_identifier(self);
1133 if visit == Visit::Children {
1135 syntax::FunIdentifier::Identifier(i) => i.$mthd_name(visitor),
1136 syntax::FunIdentifier::Expr(e) => e.$mthd_name(visitor),
1142 impl $host_ty for syntax::StructSpecifier {
1143 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1159 impl $host_ty for syntax::StructFieldSpecifier {
1160 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1177 impl $host_ty for syntax::Statement {
1178 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1182 let visit = visitor.visit_statement(self);
1184 if visit == Visit::Children {
1186 syntax::Statement::Compound(cs) => cs.$mthd_name(visitor),
1187 syntax::Statement::Simple(ss) => ss.$mthd_name(visitor),
1193 impl $host_ty for syntax::SimpleStatement {
1194 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1198 let visit = visitor.visit_simple_statement(self);
1200 if visit == Visit::Children {
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),
1214 impl $host_ty for syntax::CompoundStatement {
1215 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1229 impl $host_ty for syntax::SelectionStatement {
1230 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1243 impl $host_ty for syntax::SelectionRestStatement {
1244 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1248 let visit = visitor.visit_selection_rest_statement(self);
1250 if visit == Visit::Children {
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);
1263 impl $host_ty for syntax::SwitchStatement {
1264 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1280 impl $host_ty for syntax::CaseLabel {
1281 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1295 impl $host_ty for syntax::IterationStatement {
1296 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1300 let visit = visitor.visit_iteration_statement(self);
1302 if visit == Visit::Children {
1304 syntax::IterationStatement::While(c, s) => {
1305 c.$mthd_name(visitor);
1306 s.$mthd_name(visitor);
1309 syntax::IterationStatement::DoWhile(s, e) => {
1310 s.$mthd_name(visitor);
1311 e.$mthd_name(visitor);
1314 syntax::IterationStatement::For(fis, frs, s) => {
1315 fis.$mthd_name(visitor);
1316 frs.$mthd_name(visitor);
1317 s.$mthd_name(visitor);
1324 impl $host_ty for syntax::ForInitStatement {
1325 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1329 let visit = visitor.visit_for_init_statement(self);
1331 if visit == Visit::Children {
1333 syntax::ForInitStatement::Expression(e) => e.$mthd_name(visitor),
1334 syntax::ForInitStatement::Declaration(d) => d.$mthd_name(visitor),
1340 impl $host_ty for syntax::ForRestStatement {
1341 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1354 impl $host_ty for syntax::JumpStatement {
1355 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
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);
1369 impl $host_ty for syntax::Condition {
1370 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1374 let visit = visitor.visit_condition(self);
1376 if visit == Visit::Children {
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);
1390 impl $host_ty for syntax::Initializer {
1391 fn $mthd_name<V>($($ref)* self, visitor: &mut V)
1395 let visit = visitor.visit_initializer(self);
1397 if visit == Visit::Children {
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);
1414 make_visitor_trait!(Visitor, &);
1415 make_host_trait!(Host, Visitor, visit, &);
1418 make_visitor_trait!(VisitorMut, &mut);
1419 make_host_trait!(HostMut, VisitorMut, visit_mut, &mut);
1423 use std::iter::FromIterator;
1429 fn count_variables() {
1430 let decl0 = syntax::Statement::declare_var(
1431 syntax::TypeSpecifierNonArray::Float,
1434 Some(syntax::Expr::from(3.14).into()),
1437 let decl1 = syntax::Statement::declare_var(syntax::TypeSpecifierNonArray::Int, "y", None, None);
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
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() {
1461 let mut counter = Counter { var_nb: 0 };
1462 compound.visit(&mut counter);
1463 assert_eq!(counter.var_nb, 3);