summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/object/renamer.cc
diff options
context:
space:
mode:
Diffstat (limited to 'tiger-compiler/src/object/renamer.cc')
-rw-r--r--tiger-compiler/src/object/renamer.cc142
1 files changed, 142 insertions, 0 deletions
diff --git a/tiger-compiler/src/object/renamer.cc b/tiger-compiler/src/object/renamer.cc
new file mode 100644
index 0000000..0abae10
--- /dev/null
+++ b/tiger-compiler/src/object/renamer.cc
@@ -0,0 +1,142 @@
+/**
+ ** \file object/renamer.cc
+ ** \brief Implementation of object::Renamer.
+ */
+
+#include <memory>
+
+#include <object/renamer.hh>
+
+namespace object
+{
+ using namespace ast;
+
+ Renamer::Renamer()
+ : super_type()
+ , class_names_(new class_names_type)
+ , within_class_ty_(false)
+ {
+ // Give a name to the built-in class Object.
+ misc::put(*class_names_, &type::Class::object_instance(), "Object");
+ }
+
+ /**
+ * Get the node's type as a class, if it references one
+ * @param ast Any typable node
+ * @return The node's referenced class type if there is one, nullptr if not
+ */
+ static inline const type::Class* get_referenced_class_type(const Typable& ast)
+ {
+ return dynamic_cast<const type::Class*>(&ast.type_get()->actual());
+ }
+
+ /*----------------------------.
+ | Visiting definition sites. |
+ `----------------------------*/
+
+ void Renamer::operator()(ast::VarDec& e)
+ {
+ if (within_class_ty_)
+ // Don't rename class attributes.
+ super_type::super_type::operator()(e);
+ else
+ // But still rename other variable declarations.
+ super_type::operator()(e);
+ }
+
+ void Renamer::operator()(ast::MethodChunk& e)
+ {
+ // FIXME DONE: Some code was deleted here (Just recurse on children nodes).
+ chunk_visit<MethodChunk>(e);
+ }
+
+ void Renamer::operator()(ast::MethodDec& e)
+ {
+ bool saved_within_class_ty = within_class_ty_;
+ within_class_ty_ = false;
+ /* We can't call bind::Binder::visit directly, because this method
+ delegates the recursion task to DefaultVisitor, which doesn't
+ have a proper operator() for MethodDec. This visitor however
+ knows how to handle a FunctionDec; therefore we upcast the
+ MethodDec to a FunctionDec before visiting it. */
+ ast::FunctionDec& fundec = e;
+ visit(fundec, &fundec);
+ within_class_ty_ = saved_within_class_ty;
+ }
+
+ void Renamer::operator()(ast::TypeDec& e)
+ {
+ // Rename.
+ // FIXME DONE: Some code was deleted here.
+ if (class_names_->find(get_referenced_class_type(e)) == class_names_->end())
+ super_type::operator()(e);
+
+ // Collect the name of the classes.
+ // FIXME DONE: Some code was deleted here.
+ if (auto classtype = get_referenced_class_type(e))
+ {
+ class_names_->insert(std::make_pair(classtype, e.name_get()));
+ }
+ }
+
+ /*-----------------------.
+ | Visiting usage sites. |
+ `-----------------------*/
+
+ void Renamer::operator()(ast::MethodCallExp& e)
+ {
+ // FIXME DONE: Some code was deleted here.
+ super_type::operator()(e.object_get());
+ e.name_set(e.def_get()->name_get());
+ CallExp& upcast = e;
+ precondition(upcast.def_get() == nullptr);
+ super_type::operator()(upcast);
+ }
+
+ /*--------------------------------------.
+ | Visiting other object-related nodes. |
+ `--------------------------------------*/
+
+ void Renamer::operator()(ast::ClassTy& e)
+ {
+ // FIXME DONE: Some code was deleted here.
+ bool saved_within_class_ty = within_class_ty_;
+ within_class_ty_ = true;
+ if (e.super_get().name_get() != "Object")
+ e.super_get().name_set(e.super_get().def_get()->name_get());
+ super_type::operator()(e.chunks_get());
+ within_class_ty_ = saved_within_class_ty;
+ }
+
+ void Renamer::operator()(ast::ObjectExp& e)
+ {
+ // FIXME DONE: Some code was deleted here.
+ if (auto name = class_names_->find(get_referenced_class_type(e));
+ name != class_names_->end())
+ e.type_name_get().name_set(name->second);
+ else
+ {
+ this->accept(e.type_name_get().def_get());
+ e.type_name_get().name_set(e.type_name_get().def_get()->name_get());
+ class_names_->insert(
+ std::make_pair(get_referenced_class_type(e),
+ e.type_name_get().name_get()));
+ }
+ }
+
+ void Renamer::operator()(ast::LetExp& e)
+ {
+ // FIXME DONE: Some code was deleted here.
+ bool saved_within_class_ty = within_class_ty_;
+ within_class_ty_ = false;
+ super_type::operator()(e);
+ within_class_ty_ = saved_within_class_ty;
+ }
+
+ /*--------------.
+ | Class names. |
+ `--------------*/
+
+ class_names_type* Renamer::class_names_get() const { return class_names_; }
+
+} // namespace object