summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/ast/visitor.hh
blob: 420db00396e765a566283283e936ec153183ff76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
 ** \file ast/visitor.hh
 ** \brief Definition of ast::Visitor.
 */

#pragma once

#include <functional>
#include <ast/fwd.hh>
#include <misc/select-const.hh>

namespace ast
{
  /** \brief Root class of all Ast visitors.
   **
   ** GenVisitor<CONSTIFY> is the root class of all Ast visitors. */
  template <template <typename> class Const> class GenVisitor
  {
    /** \name Ctor & dtor.
     ** \{ */
  public:
    /// Convenient abbreviation.
    template <typename Type> using const_t = typename Const<Type>::type;

    /// Destroy a GenVisitor.
    virtual ~GenVisitor();
    /** \} */

    /// The entry point: visit \a e.
    virtual void operator()(const_t<Ast>& e);
    virtual void operator()(const_t<ArrayExp>&) = 0;
    virtual void operator()(const_t<ArrayTy>&) = 0;
    virtual void operator()(const_t<AssignExp>&) = 0;
    virtual void operator()(const_t<BreakExp>&) = 0;
    virtual void operator()(const_t<CallExp>&) = 0;
    virtual void operator()(const_t<CastExp>&) = 0;
    virtual void operator()(const_t<ChunkList>&) = 0;
    virtual void operator()(const_t<ClassTy>&) = 0;
    virtual void operator()(const_t<Field>&) = 0;
    virtual void operator()(const_t<FieldInit>&) = 0;
    virtual void operator()(const_t<FieldVar>&) = 0;
    virtual void operator()(const_t<ForExp>&) = 0;
    virtual void operator()(const_t<FunctionDec>&) = 0;
    virtual void operator()(const_t<IfExp>&) = 0;
    virtual void operator()(const_t<IntExp>&) = 0;
    virtual void operator()(const_t<LetExp>&) = 0;
    virtual void operator()(const_t<MethodCallExp>&) = 0;
    virtual void operator()(const_t<MethodDec>&) = 0;
    virtual void operator()(const_t<NameTy>&) = 0;
    virtual void operator()(const_t<NilExp>&) = 0;
    virtual void operator()(const_t<ObjectExp>&) = 0;
    virtual void operator()(const_t<OpExp>&) = 0;
    virtual void operator()(const_t<RecordExp>&) = 0;
    virtual void operator()(const_t<RecordTy>&) = 0;
    virtual void operator()(const_t<SeqExp>&) = 0;
    virtual void operator()(const_t<SimpleVar>&) = 0;
    virtual void operator()(const_t<StringExp>&) = 0;
    virtual void operator()(const_t<SubscriptVar>&) = 0;
    virtual void operator()(const_t<TypeDec>&) = 0;
    virtual void operator()(const_t<VarDec>&) = 0;
    virtual void operator()(const_t<WhileExp>&) = 0;

    virtual void operator()(const_t<FunctionChunk>&) = 0;
    virtual void operator()(const_t<MethodChunk>&) = 0;
    virtual void operator()(const_t<TypeChunk>&) = 0;
    virtual void operator()(const_t<VarChunk>&) = 0;

    virtual void operator()(const_t<AssertExp>&) = 0;

    /// Helper to visit nodes manipulated via a pointer.
    template <class E> void operator()(E* e);

  protected:
    /** A convenient shortcut for recurring code like this:

        \code
        if (e)
          e->accept(*this);
        \endcode

        However, the drawback of this approach is that it doesn't take
        care of the constness, and any \a const violation will be
        reported \em within the body of this method, not at its
        corresponding call site.

        We cannot use the misc/select_const.hh approach here, since
        the compiler cannot resolve a function overloaded or
        specialized on an associated type of a template.  E.g., writing
        \a accept like this:

        \code
        template <typename E>
        void accept(const_t<E>* e);
        \endcode

        won't work directly.  Of course, one can help the compiler,
        providing it with \a E

        \code
        accept<ast::NameTy>(e.result_get());
        \endcode

        but this is painful.  */
    template <typename E> void accept(E* e);
  };

  /// Shorthand for a const visitor.
  using ConstVisitor = GenVisitor<misc::constify_traits>;
  /// Shorthand for a non const visitor.
  using Visitor = GenVisitor<misc::id_traits>;

} // namespace ast

#include <ast/visitor.hxx>