use crate::syntax;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Visit {
  
  
  
  Children,
  
  Parent,
}
pub trait Visitor {
  fn visit_translation_unit(&mut self, _: &mut syntax::TranslationUnit) -> Visit {
    Visit::Children
  }
  fn visit_external_declaration(&mut self, _: &mut syntax::ExternalDeclaration) -> Visit {
    Visit::Children
  }
  fn visit_identifier(&mut self, _: &mut syntax::Identifier) -> Visit {
    Visit::Children
  }
  fn visit_arrayed_identifier(&mut self, _: &mut syntax::ArrayedIdentifier) -> Visit {
    Visit::Children
  }
  fn visit_type_name(&mut self, _: &mut syntax::TypeName) -> Visit {
    Visit::Children
  }
  fn visit_block(&mut self, _: &mut syntax::Block) -> Visit {
    Visit::Children
  }
  fn visit_for_init_statement(&mut self, _: &mut syntax::ForInitStatement) -> Visit {
    Visit::Children
  }
  fn visit_for_rest_statement(&mut self, _: &mut syntax::ForRestStatement) -> Visit {
    Visit::Children
  }
  fn visit_function_definition(&mut self, _: &mut syntax::FunctionDefinition) -> Visit {
    Visit::Children
  }
  fn visit_function_parameter_declarator(
    &mut self,
    _: &mut syntax::FunctionParameterDeclarator,
  ) -> Visit {
    Visit::Children
  }
  fn visit_function_prototype(&mut self, _: &mut syntax::FunctionPrototype) -> Visit {
    Visit::Children
  }
  fn visit_init_declarator_list(&mut self, _: &mut syntax::InitDeclaratorList) -> Visit {
    Visit::Children
  }
  fn visit_layout_qualifier(&mut self, _: &mut syntax::LayoutQualifier) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor(&mut self, _: &mut syntax::Preprocessor) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_define(&mut self, _: &mut syntax::PreprocessorDefine) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_elseif(&mut self, _: &mut syntax::PreprocessorElseIf) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_error(&mut self, _: &mut syntax::PreprocessorError) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_extension(&mut self, _: &mut syntax::PreprocessorExtension) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_extension_behavior(
    &mut self,
    _: &mut syntax::PreprocessorExtensionBehavior,
  ) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_extension_name(
    &mut self,
    _: &mut syntax::PreprocessorExtensionName,
  ) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_if(&mut self, _: &mut syntax::PreprocessorIf) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_ifdef(&mut self, _: &mut syntax::PreprocessorIfDef) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_ifndef(&mut self, _: &mut syntax::PreprocessorIfNDef) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_include(&mut self, _: &mut syntax::PreprocessorInclude) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_line(&mut self, _: &mut syntax::PreprocessorLine) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_pragma(&mut self, _: &mut syntax::PreprocessorPragma) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_undef(&mut self, _: &mut syntax::PreprocessorUndef) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_version(&mut self, _: &mut syntax::PreprocessorVersion) -> Visit {
    Visit::Children
  }
  fn visit_preprocessor_version_profile(
    &mut self,
    _: &mut syntax::PreprocessorVersionProfile,
  ) -> Visit {
    Visit::Children
  }
  fn visit_selection_statement(&mut self, _: &mut syntax::SelectionStatement) -> Visit {
    Visit::Children
  }
  fn visit_selection_rest_statement(&mut self, _: &mut syntax::SelectionRestStatement) -> Visit {
    Visit::Children
  }
  fn visit_single_declaration(&mut self, _: &mut syntax::SingleDeclaration) -> Visit {
    Visit::Children
  }
  fn visit_single_declaration_no_type(&mut self, _: &mut syntax::SingleDeclarationNoType) -> Visit {
    Visit::Children
  }
  fn visit_struct_field_specifier(&mut self, _: &mut syntax::StructFieldSpecifier) -> Visit {
    Visit::Children
  }
  fn visit_struct_specifier(&mut self, _: &mut syntax::StructSpecifier) -> Visit {
    Visit::Children
  }
  fn visit_switch_statement(&mut self, _: &mut syntax::SwitchStatement) -> Visit {
    Visit::Children
  }
  fn visit_type_qualifier(&mut self, _: &mut syntax::TypeQualifier) -> Visit {
    Visit::Children
  }
  fn visit_type_specifier(&mut self, _: &mut syntax::TypeSpecifier) -> Visit {
    Visit::Children
  }
  fn visit_full_specified_type(&mut self, _: &mut syntax::FullySpecifiedType) -> Visit {
    Visit::Children
  }
  fn visit_array_specifier(&mut self, _: &mut syntax::ArraySpecifier) -> Visit {
    Visit::Children
  }
  fn visit_assignment_op(&mut self, _: &mut syntax::AssignmentOp) -> Visit {
    Visit::Children
  }
  fn visit_binary_op(&mut self, _: &mut syntax::BinaryOp) -> Visit {
    Visit::Children
  }
  fn visit_case_label(&mut self, _: &mut syntax::CaseLabel) -> Visit {
    Visit::Children
  }
  fn visit_condition(&mut self, _: &mut syntax::Condition) -> Visit {
    Visit::Children
  }
  fn visit_declaration(&mut self, _: &mut syntax::Declaration) -> Visit {
    Visit::Children
  }
  fn visit_expr(&mut self, _: &mut syntax::Expr) -> Visit {
    Visit::Children
  }
  fn visit_fun_identifier(&mut self, _: &mut syntax::FunIdentifier) -> Visit {
    Visit::Children
  }
  fn visit_function_parameter_declaration(
    &mut self,
    _: &mut syntax::FunctionParameterDeclaration,
  ) -> Visit {
    Visit::Children
  }
  fn visit_initializer(&mut self, _: &mut syntax::Initializer) -> Visit {
    Visit::Children
  }
  fn visit_interpolation_qualifier(&mut self, _: &mut syntax::InterpolationQualifier) -> Visit {
    Visit::Children
  }
  fn visit_iteration_statement(&mut self, _: &mut syntax::IterationStatement) -> Visit {
    Visit::Children
  }
  fn visit_jump_statement(&mut self, _: &mut syntax::JumpStatement) -> Visit {
    Visit::Children
  }
  fn visit_layout_qualifier_spec(&mut self, _: &mut syntax::LayoutQualifierSpec) -> Visit {
    Visit::Children
  }
  fn visit_precision_qualifier(&mut self, _: &mut syntax::PrecisionQualifier) -> Visit {
    Visit::Children
  }
  fn visit_statement(&mut self, _: &mut syntax::Statement) -> Visit {
    Visit::Children
  }
  fn visit_compound_statement(&mut self, _: &mut syntax::CompoundStatement) -> Visit {
    Visit::Children
  }
  fn visit_simple_statement(&mut self, _: &mut syntax::SimpleStatement) -> Visit {
    Visit::Children
  }
  fn visit_storage_qualifier(&mut self, _: &mut syntax::StorageQualifier) -> Visit {
    Visit::Children
  }
  fn visit_type_qualifier_spec(&mut self, _: &mut syntax::TypeQualifierSpec) -> Visit {
    Visit::Children
  }
  fn visit_type_specifier_non_array(&mut self, _: &mut syntax::TypeSpecifierNonArray) -> Visit {
    Visit::Children
  }
  fn visit_unary_op(&mut self, _: &mut syntax::UnaryOp) -> Visit {
    Visit::Children
  }
  fn visit_expr_statement(&mut self, _: &mut syntax::ExprStatement) -> Visit {
    Visit::Children
  }
}
pub trait Host {
  
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor;
}
impl<T> Host for Option<T>
where
  T: Host,
{
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    if let Some(ref mut x) = *self {
      x.visit(visitor);
    }
  }
}
impl<T> Host for Box<T>
where
  T: Host,
{
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    (**self).visit(visitor);
  }
}
impl Host for syntax::TranslationUnit {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_translation_unit(self);
    if visit == Visit::Children {
      for ed in &mut (self.0).0 {
        ed.visit(visitor);
      }
    }
  }
}
impl Host for syntax::ExternalDeclaration {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_external_declaration(self);
    if visit == Visit::Children {
      match *self {
        syntax::ExternalDeclaration::Preprocessor(ref mut p) => p.visit(visitor),
        syntax::ExternalDeclaration::FunctionDefinition(ref mut fd) => fd.visit(visitor),
        syntax::ExternalDeclaration::Declaration(ref mut d) => d.visit(visitor),
      }
    }
  }
}
impl Host for syntax::Preprocessor {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_preprocessor(self);
    if visit == Visit::Children {
      match *self {
        syntax::Preprocessor::Define(ref mut pd) => pd.visit(visitor),
        syntax::Preprocessor::Else => (),
        syntax::Preprocessor::ElseIf(ref mut pei) => pei.visit(visitor),
        syntax::Preprocessor::EndIf => (),
        syntax::Preprocessor::Error(ref mut pe) => pe.visit(visitor),
        syntax::Preprocessor::If(ref mut pi) => pi.visit(visitor),
        syntax::Preprocessor::IfDef(ref mut pid) => pid.visit(visitor),
        syntax::Preprocessor::IfNDef(ref mut pind) => pind.visit(visitor),
        syntax::Preprocessor::Include(ref mut pi) => pi.visit(visitor),
        syntax::Preprocessor::Line(ref mut pl) => pl.visit(visitor),
        syntax::Preprocessor::Pragma(ref mut pp) => pp.visit(visitor),
        syntax::Preprocessor::Undef(ref mut pu) => pu.visit(visitor),
        syntax::Preprocessor::Version(ref mut pv) => pv.visit(visitor),
        syntax::Preprocessor::Extension(ref mut ext) => ext.visit(visitor),
      }
    }
  }
}
impl Host for syntax::PreprocessorDefine {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_preprocessor_define(self);
    if visit == Visit::Children {
      match *self {
        syntax::PreprocessorDefine::ObjectLike { ref mut ident, .. } => {
          ident.visit(visitor);
        }
        syntax::PreprocessorDefine::FunctionLike {
          ref mut ident,
          ref mut args,
          ..
        } => {
          ident.visit(visitor);
          for arg in args {
            arg.visit(visitor);
          }
        }
      }
    }
  }
}
impl Host for syntax::PreprocessorElseIf {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_elseif(self);
  }
}
impl Host for syntax::PreprocessorError {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_error(self);
  }
}
impl Host for syntax::PreprocessorIf {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_if(self);
  }
}
impl Host for syntax::PreprocessorIfDef {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_preprocessor_ifdef(self);
    if visit == Visit::Children {
      self.ident.visit(visitor);
    }
  }
}
impl Host for syntax::PreprocessorIfNDef {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_preprocessor_ifndef(self);
    if visit == Visit::Children {
      self.ident.visit(visitor);
    }
  }
}
impl Host for syntax::PreprocessorInclude {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_include(self);
  }
}
impl Host for syntax::PreprocessorLine {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_line(self);
  }
}
impl Host for syntax::PreprocessorPragma {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_pragma(self);
  }
}
impl Host for syntax::PreprocessorUndef {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_preprocessor_undef(self);
    if visit == Visit::Children {
      self.name.visit(visitor);
    }
  }
}
impl Host for syntax::PreprocessorVersion {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_preprocessor_version(self);
    if visit == Visit::Children {
      self.profile.visit(visitor);
    }
  }
}
impl Host for syntax::PreprocessorVersionProfile {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_version_profile(self);
  }
}
impl Host for syntax::PreprocessorExtension {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_preprocessor_extension(self);
    if visit == Visit::Children {
      self.name.visit(visitor);
      self.behavior.visit(visitor);
    }
  }
}
impl Host for syntax::PreprocessorExtensionBehavior {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_extension_behavior(self);
  }
}
impl Host for syntax::PreprocessorExtensionName {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_preprocessor_extension_name(self);
  }
}
impl Host for syntax::FunctionPrototype {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_function_prototype(self);
    if visit == Visit::Children {
      self.ty.visit(visitor);
      self.name.visit(visitor);
      for param in &mut self.parameters {
        param.visit(visitor);
      }
    }
  }
}
impl Host for syntax::FunctionParameterDeclaration {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_function_parameter_declaration(self);
    if visit == Visit::Children {
      match *self {
        syntax::FunctionParameterDeclaration::Named(ref mut tq, ref mut fpd) => {
          tq.visit(visitor);
          fpd.visit(visitor);
        }
        syntax::FunctionParameterDeclaration::Unnamed(ref mut tq, ref mut ty) => {
          tq.visit(visitor);
          ty.visit(visitor);
        }
      }
    }
  }
}
impl Host for syntax::FunctionParameterDeclarator {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_function_parameter_declarator(self);
    if visit == Visit::Children {
      self.ty.visit(visitor);
      self.ident.visit(visitor);
    }
  }
}
impl Host for syntax::FunctionDefinition {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_function_definition(self);
    if visit == Visit::Children {
      self.prototype.visit(visitor);
      self.statement.visit(visitor);
    }
  }
}
impl Host for syntax::Declaration {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_declaration(self);
    if visit == Visit::Children {
      match *self {
        syntax::Declaration::FunctionPrototype(ref mut fp) => fp.visit(visitor),
        syntax::Declaration::InitDeclaratorList(ref mut idl) => idl.visit(visitor),
        syntax::Declaration::Precision(ref mut pq, ref mut ty) => {
          pq.visit(visitor);
          ty.visit(visitor);
        }
        syntax::Declaration::Block(ref mut block) => block.visit(visitor),
        syntax::Declaration::Global(ref mut tq, ref mut idents) => {
          tq.visit(visitor);
          for ident in idents {
            ident.visit(visitor);
          }
        }
      }
    }
  }
}
impl Host for syntax::Block {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_block(self);
    if visit == Visit::Children {
      self.qualifier.visit(visitor);
      self.name.visit(visitor);
      for field in &mut self.fields {
        field.visit(visitor);
      }
      self.identifier.visit(visitor);
    }
  }
}
impl Host for syntax::InitDeclaratorList {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_init_declarator_list(self);
    if visit == Visit::Children {
      self.head.visit(visitor);
      for d in &mut self.tail {
        d.visit(visitor);
      }
    }
  }
}
impl Host for syntax::SingleDeclaration {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_single_declaration(self);
    if visit == Visit::Children {
      self.ty.visit(visitor);
      self.name.visit(visitor);
      self.array_specifier.visit(visitor);
      self.initializer.visit(visitor);
    }
  }
}
impl Host for syntax::SingleDeclarationNoType {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_single_declaration_no_type(self);
    if visit == Visit::Children {
      self.ident.visit(visitor);
      self.initializer.visit(visitor);
    }
  }
}
impl Host for syntax::FullySpecifiedType {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_full_specified_type(self);
    if visit == Visit::Children {
      self.qualifier.visit(visitor);
      self.ty.visit(visitor);
    }
  }
}
impl Host for syntax::TypeSpecifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_type_specifier(self);
    if visit == Visit::Children {
      self.ty.visit(visitor);
      self.array_specifier.visit(visitor);
    }
  }
}
impl Host for syntax::TypeSpecifierNonArray {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_type_specifier_non_array(self);
    if visit == Visit::Children {
      match *self {
        syntax::TypeSpecifierNonArray::Struct(ref mut ss) => ss.visit(visitor),
        syntax::TypeSpecifierNonArray::TypeName(ref mut tn) => tn.visit(visitor),
        _ => (),
      }
    }
  }
}
impl Host for syntax::TypeQualifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_type_qualifier(self);
    if visit == Visit::Children {
      for tqs in &mut self.qualifiers.0 {
        tqs.visit(visitor);
      }
    }
  }
}
impl Host for syntax::TypeQualifierSpec {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_type_qualifier_spec(self);
    if visit == Visit::Children {
      match *self {
        syntax::TypeQualifierSpec::Storage(ref mut sq) => sq.visit(visitor),
        syntax::TypeQualifierSpec::Layout(ref mut lq) => lq.visit(visitor),
        syntax::TypeQualifierSpec::Precision(ref mut pq) => pq.visit(visitor),
        syntax::TypeQualifierSpec::Interpolation(ref mut iq) => iq.visit(visitor),
        _ => (),
      }
    }
  }
}
impl Host for syntax::StorageQualifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_storage_qualifier(self);
    if visit == Visit::Children {
      if let syntax::StorageQualifier::Subroutine(ref mut names) = *self {
        for name in names {
          name.visit(visitor);
        }
      }
    }
  }
}
impl Host for syntax::LayoutQualifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_layout_qualifier(self);
    if visit == Visit::Children {
      for lqs in &mut self.ids.0 {
        lqs.visit(visitor);
      }
    }
  }
}
impl Host for syntax::LayoutQualifierSpec {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_layout_qualifier_spec(self);
    if visit == Visit::Children {
      if let syntax::LayoutQualifierSpec::Identifier(ref mut ident, ref mut expr) = *self {
        ident.visit(visitor);
        if let Some(ref mut e) = *expr {
          e.visit(visitor);
        }
      }
    }
  }
}
impl Host for syntax::PrecisionQualifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_precision_qualifier(self);
  }
}
impl Host for syntax::InterpolationQualifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_interpolation_qualifier(self);
  }
}
impl Host for syntax::TypeName {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_type_name(self);
  }
}
impl Host for syntax::Identifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_identifier(self);
  }
}
impl Host for syntax::ArrayedIdentifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_arrayed_identifier(self);
    if visit == Visit::Children {
      self.ident.visit(visitor);
      self.array_spec.visit(visitor);
    }
  }
}
impl Host for syntax::Expr {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_expr(self);
    if visit == Visit::Children {
      match *self {
        syntax::Expr::Variable(ref mut ident) => ident.visit(visitor),
        syntax::Expr::Unary(ref mut op, ref mut e) => {
          op.visit(visitor);
          e.visit(visitor);
        }
        syntax::Expr::Binary(ref mut op, ref mut a, ref mut b) => {
          op.visit(visitor);
          a.visit(visitor);
          b.visit(visitor);
        }
        syntax::Expr::Ternary(ref mut a, ref mut b, ref mut c) => {
          a.visit(visitor);
          b.visit(visitor);
          c.visit(visitor);
        }
        syntax::Expr::Assignment(ref mut lhs, ref mut op, ref mut rhs) => {
          lhs.visit(visitor);
          op.visit(visitor);
          rhs.visit(visitor);
        }
        syntax::Expr::Bracket(ref mut e, ref mut arr_spec) => {
          e.visit(visitor);
          arr_spec.visit(visitor);
        }
        syntax::Expr::FunCall(ref mut fi, ref mut params) => {
          fi.visit(visitor);
          for param in params {
            param.visit(visitor);
          }
        }
        syntax::Expr::Dot(ref mut e, ref mut i) => {
          e.visit(visitor);
          i.visit(visitor);
        }
        syntax::Expr::PostInc(ref mut e) => e.visit(visitor),
        syntax::Expr::PostDec(ref mut e) => e.visit(visitor),
        syntax::Expr::Comma(ref mut a, ref mut b) => {
          a.visit(visitor);
          b.visit(visitor);
        }
        _ => (),
      }
    }
  }
}
impl Host for syntax::UnaryOp {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_unary_op(self);
  }
}
impl Host for syntax::BinaryOp {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_binary_op(self);
  }
}
impl Host for syntax::AssignmentOp {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let _ = visitor.visit_assignment_op(self);
  }
}
impl Host for syntax::ArraySpecifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_array_specifier(self);
    if visit == Visit::Children {
      if let syntax::ArraySpecifier::ExplicitlySized(ref mut e) = *self {
        e.visit(visitor);
      }
    }
  }
}
impl Host for syntax::FunIdentifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_fun_identifier(self);
    if visit == Visit::Children {
      match *self {
        syntax::FunIdentifier::Identifier(ref mut i) => i.visit(visitor),
        syntax::FunIdentifier::Expr(ref mut e) => e.visit(visitor),
      }
    }
  }
}
impl Host for syntax::StructSpecifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_struct_specifier(self);
    if visit == Visit::Children {
      self.name.visit(visitor);
      for field in &mut self.fields.0 {
        field.visit(visitor);
      }
    }
  }
}
impl Host for syntax::StructFieldSpecifier {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_struct_field_specifier(self);
    if visit == Visit::Children {
      self.qualifier.visit(visitor);
      self.ty.visit(visitor);
      for identifier in &mut self.identifiers.0 {
        identifier.visit(visitor);
      }
    }
  }
}
impl Host for syntax::Statement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_statement(self);
    if visit == Visit::Children {
      match *self {
        syntax::Statement::Compound(ref mut cs) => cs.visit(visitor),
        syntax::Statement::Simple(ref mut ss) => ss.visit(visitor),
      }
    }
  }
}
impl Host for syntax::SimpleStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_simple_statement(self);
    if visit == Visit::Children {
      match *self {
        syntax::SimpleStatement::Declaration(ref mut d) => d.visit(visitor),
        syntax::SimpleStatement::Expression(ref mut e) => e.visit(visitor),
        syntax::SimpleStatement::Selection(ref mut s) => s.visit(visitor),
        syntax::SimpleStatement::Switch(ref mut s) => s.visit(visitor),
        syntax::SimpleStatement::CaseLabel(ref mut cl) => cl.visit(visitor),
        syntax::SimpleStatement::Iteration(ref mut i) => i.visit(visitor),
        syntax::SimpleStatement::Jump(ref mut j) => j.visit(visitor),
      }
    }
  }
}
impl Host for syntax::CompoundStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_compound_statement(self);
    if visit == Visit::Children {
      for stmt in &mut self.statement_list {
        stmt.visit(visitor);
      }
    }
  }
}
impl Host for syntax::SelectionStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_selection_statement(self);
    if visit == Visit::Children {
      self.cond.visit(visitor);
      self.rest.visit(visitor);
    }
  }
}
impl Host for syntax::SelectionRestStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_selection_rest_statement(self);
    if visit == Visit::Children {
      match *self {
        syntax::SelectionRestStatement::Statement(ref mut s) => s.visit(visitor),
        syntax::SelectionRestStatement::Else(ref mut a, ref mut b) => {
          a.visit(visitor);
          b.visit(visitor);
        }
      }
    }
  }
}
impl Host for syntax::SwitchStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_switch_statement(self);
    if visit == Visit::Children {
      self.head.visit(visitor);
      for s in &mut self.body {
        s.visit(visitor);
      }
    }
  }
}
impl Host for syntax::CaseLabel {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_case_label(self);
    if visit == Visit::Children {
      if let syntax::CaseLabel::Case(ref mut e) = *self {
        e.visit(visitor);
      }
    }
  }
}
impl Host for syntax::IterationStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_iteration_statement(self);
    if visit == Visit::Children {
      match *self {
        syntax::IterationStatement::While(ref mut c, ref mut s) => {
          c.visit(visitor);
          s.visit(visitor);
        }
        syntax::IterationStatement::DoWhile(ref mut s, ref mut e) => {
          s.visit(visitor);
          e.visit(visitor);
        }
        syntax::IterationStatement::For(ref mut fis, ref mut frs, ref mut s) => {
          fis.visit(visitor);
          frs.visit(visitor);
          s.visit(visitor);
        }
      }
    }
  }
}
impl Host for syntax::ForInitStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_for_init_statement(self);
    if visit == Visit::Children {
      match *self {
        syntax::ForInitStatement::Expression(ref mut e) => e.visit(visitor),
        syntax::ForInitStatement::Declaration(ref mut d) => d.visit(visitor),
      }
    }
  }
}
impl Host for syntax::ForRestStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_for_rest_statement(self);
    if visit == Visit::Children {
      self.condition.visit(visitor);
      self.post_expr.visit(visitor);
    }
  }
}
impl Host for syntax::JumpStatement {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_jump_statement(self);
    if visit == Visit::Children {
      if let syntax::JumpStatement::Return(ref mut r) = *self {
        r.visit(visitor);
      }
    }
  }
}
impl Host for syntax::Condition {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_condition(self);
    if visit == Visit::Children {
      match *self {
        syntax::Condition::Expr(ref mut e) => e.visit(visitor),
        syntax::Condition::Assignment(ref mut fst, ref mut ident, ref mut init) => {
          fst.visit(visitor);
          ident.visit(visitor);
          init.visit(visitor);
        }
      }
    }
  }
}
impl Host for syntax::Initializer {
  fn visit<V>(&mut self, visitor: &mut V)
  where
    V: Visitor,
  {
    let visit = visitor.visit_initializer(self);
    if visit == Visit::Children {
      match *self {
        syntax::Initializer::Simple(ref mut e) => e.visit(visitor),
        syntax::Initializer::List(ref mut i) => {
          for i in &mut i.0 {
            i.visit(visitor);
          }
        }
      }
    }
  }
}
#[cfg(test)]
mod tests {
  use std::iter::FromIterator;
  use super::*;
  use syntax;
  #[test]
  fn count_variables() {
    let decl0 = syntax::Statement::declare_var(
      syntax::TypeSpecifierNonArray::Float,
      "x",
      None,
      Some(syntax::Expr::from(3.14).into()),
    );
    let decl1 = syntax::Statement::declare_var(syntax::TypeSpecifierNonArray::Int, "y", None, None);
    let decl2 =
      syntax::Statement::declare_var(syntax::TypeSpecifierNonArray::Vec4, "z", None, None);
    let mut compound = syntax::CompoundStatement::from_iter(vec![decl0, decl1, decl2]);
    
    struct Counter {
      var_nb: usize,
    }
    impl Visitor for Counter {
      
      fn visit_single_declaration(&mut self, declaration: &mut syntax::SingleDeclaration) -> Visit {
        if declaration.name.is_some() {
          self.var_nb += 1;
        }
        
        Visit::Parent
      }
    }
    let mut counter = Counter { var_nb: 0 };
    compound.visit(&mut counter);
    assert_eq!(counter.var_nb, 3);
  }
}