summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/type/class.cc
blob: a1876d358024f2726db3243345248f59273a006d (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
115
116
117
118
119
120
121
122
123
/**
 ** \file type/class.cc
 ** \brief Implementation for type/class.hh.
 */

#include <ostream>

#include <misc/algorithm.hh>
#include <type/class.hh>
#include <type/visitor.hh>

namespace type
{
  Class::Class(const Class* super)
    : Type()
    , id_(fresh_id())
    , super_(super)
    , subclasses_()
  {}

  void Class::accept(ConstVisitor& v) const { v(*this); }

  void Class::accept(Visitor& v) { v(*this); }

  const Type* Class::attr_type(misc::symbol key) const
  {
    // FIXME DONE: Some code was deleted here.
    const auto& attribute = std::ranges::find_if(
      attrs_,
      [&key] (const misc::symbol& name) { return name == key; },
      [] (const Attribute& attr) { return attr.name_get(); }
    );

    return attribute != attrs_.end() ? &attribute->type_get() : nullptr;
  }

  const Type* Class::meth_type(misc::symbol key) const
  {
    // FIXME DONE: Some code was deleted here.
    const auto& method = std::ranges::find_if(
      meths_,
      [&key] (const misc::symbol& name) { return name == key; },
      [] (const Method* const meth) { return meth->name_get(); }
    );

    return method != meths_.end() ? &(*method)->type_get() : nullptr;
  }

  // FIXME DONE: Some code was deleted here (Find common super class).
  const Class* Class::common_root(const Class& other) const
  {
    // temporary note: i'm tired so maybe the algo sucks ass :c
    if (*this == other)
    {
      return this;
    }

    std::vector<const Class*> super_classes;

    for (auto this_sc = this; this_sc != nullptr; this_sc = this_sc->super_)
    {
      super_classes.push_back(this_sc);
    }

    for (auto other_sc = &other; other_sc != nullptr; other_sc = other_sc->super_)
    {
      if (auto matching = std::ranges::find(super_classes, other_sc);
          matching != super_classes.end())
      {
        return *matching;
      }
    }

    return nullptr;
  }

  // FIXME DONE: Some code was deleted here (Super class soundness test).
  bool Class::sound() const
  {
    auto reference = this;
    std::vector<const Class*> previous;

    while (reference != nullptr)
      {
        if (std::ranges::find(previous, reference) != previous.end())
          {
            return false;
          }

        previous.push_back(reference);
        reference = reference->super_;
      }

    return true;
  }

  // FIXME DONE: Some code was deleted here (Special implementation of "compatible_with" for Class).
  bool Class::compatible_with(const Type& other) const
  {
    if (Type::compatible_with(other) || dynamic_cast<const Nil*>(&other))
    {
      return true;
    }

    const auto ptr = dynamic_cast<const Class*>(&other);

    return ptr && common_root(*ptr);
  }

  const Class& Class::object_instance()
  {
    // FIXME DONE: Some code was deleted here.
    static const Class object { nullptr };
    return object;
  }

  unsigned Class::fresh_id()
  {
    static unsigned counter_ = 0;
    return counter_++;
  }

} // namespace type