summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/object/type-checker.hh
blob: c965d2578d710db9cf9eed03f95e67086848c972 (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
/**
 ** \file object/type-checker.hh
 ** \brief Checking an ObjectTiger program in a Tiger program.
 */

#pragma once

#include <type/class.hh>
#include <type/type-checker.hh>
#include <type/types.hh>

namespace object
{
  /** \brief Perform type checking, allowing objects, and compute
   ** the bindings of the object's methods and fields.
   **
   ** Inheritence is declared virtual to enable diamond inheritance with
   ** the TypeChecker (src/combine/type-checker.hh), inheriting
   ** from overload::TypeChecker and object::TypeChecker, both inheriting from
   ** type::TypeChecker.
   **/
  class TypeChecker : virtual public type::TypeChecker
  {
  public:
    /// Superclass.
    using super_type = type::TypeChecker;
    using super_type::operator();

    /// Construction.
    TypeChecker();

  protected:
    // ------------------------- //
    // The core of the visitor.  //
    // ------------------------- //

    // ---------------- //
    // Visiting /Var/.  //
    // ---------------- //

    void operator()(ast::FieldVar& e) override;
    void operator()(ast::SimpleVar& e) override;

    // --------------- //
    // Visiting /Ty/.  //
    // --------------- //

    void operator()(ast::NameTy& e) override;

    // ---------------- //
    // Visiting /Exp/.  //
    // ---------------- //

    // Method exp.
    void operator()(ast::IfExp& e) override;
    void operator()(ast::OpExp& e) override;
    void operator()(ast::ObjectExp& e) override;
    void operator()(ast::MethodCallExp& e) override;

    // ---------------- //
    // Visiting /Dec/.  //
    // ---------------- //

    /** Visit a chunk of type declarations.

        This method is like type::TypeChecker's one, except that it
        processes class declarations in three steps, instead of two
        (visit the headers, then the bodies):

        <ol>
        <li>visit headers, as in type::TypeChecker;</li>
        <li>visit bodies, which ignore all members of the class;</li>
        <li>visit members, i.e., attributes and methods.</li>
        </ol>

        This way, a method of a class can use the type of this class
        (e.g., return \a self), as that type has been created in the
        second step, and the method is processed in the third.  */
    void operator()(ast::TypeChunk& e) override;

    // Check a Method's declaration header.
    void visit_dec_header(ast::MethodDec& e);
    // Check a Method's declaration body.
    void visit_dec_body(ast::MethodDec& e);

    /// Visit a chunk of method declarations.
    void operator()(ast::MethodChunk& e) override;

    /// Visit a single Variable Declaration.
    void operator()(ast::VarDec& e) override;

    // --------------- //
    // Visiting /Ty/.  //
    // --------------- //

    // Visit a class definition \em without its members.
    void operator()(ast::ClassTy& e) override;
    // Visit the members of a class.
    virtual void visit_dec_members(ast::ClassTy& e);

  private:
    /// Current visited class.
    type::Class* current_ = nullptr;
    /// Are we directly within an ast::ClassTy's body?
    bool within_class_body_p_ = false;
  };

} // namespace object