/** ** \file object/renamer.cc ** \brief Implementation of object::Renamer. */ #include #include 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(&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(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