#ifndef SEMANT_H_ #define SEMANT_H_ #include #include #include #include #include #include "cool-tree.h" #include "cool-tree.handcode.h" #include "stringtab.h" #include "symtab.h" #include "list.h" #define TRUE 1 #define FALSE 0 class ClassTable; typedef ClassTable *ClassTableP; // This is a structure that may be used to contain the semantic // information such as the inheritance graph. You may use it or not as // you like: it is only here to provide a container for the supplied // methods. class ClassGraphNode { private: ClassGraphNode* parent; std::vector children; Class_ self; int mark = 0; public: // Note that, Class_ = Class__class*, itself is a ptr type, so just use it ClassGraphNode(Class_ self_class, ClassGraphNode* parent_class = nullptr) : parent(parent_class), self(self_class) { } ClassGraphNode(const ClassGraphNode&) = delete; ClassGraphNode& operator=(const ClassGraphNode) = delete; ~ ClassGraphNode() { // Long time no C++, god knows if the destructor works or not... while (!children.empty()) { auto child = children[children.size() - 1]; children.pop_back(); assert(child != nullptr); delete child; } } /* * Create a child node and set child points to child_class */ ClassGraphNode* new_child(Class_ child_class) { for (auto i = children.begin(); i != children.end(); ++ i) { if ((*i)->self == child_class) { // it is okay to judge class by compare node address // because a class cannot be redefined, the AST node is identical return *i; } } ClassGraphNode * newnode = new ClassGraphNode(child_class, this); children.push_back(newnode); return newnode; } /* * Set child_node as this's child, without any memory allocation */ void append_child(ClassGraphNode * child_node) { for (auto i = children.begin(); i != children.end(); ++ i) { if ((*i) == child_node) { return; } } child_node->parent = this; children.push_back(child_node); } /* * traverse and print class name */ void traverse(std::ostream& stream, int n) const { dump_Symbol(stream, n, dynamic_cast(self)->get_name()); for (auto child: children) { child->traverse(stream, n + 2); } } /* * traverse and mark all reachable children */ void traverse() { mark = 1; for (auto child : children) { child->traverse(); } } bool reachable() { return !(mark == 0); } Class_ get_class() { return self; } }; // First we need a tree-like struct to store inheritence relationship // Since class doesn't need to be defined before used, I guess first class ClassTable { private: int semant_errors; void install_basic_classes(); ostream& error_stream; ClassGraphNode* class_root; std::map name_to_node; // again, the correctness of using ptr can be inferred from `Single Copy` of the symbol string public: ClassTable(Classes); int errors() { return semant_errors; } ostream& semant_error(); ostream& semant_error(Class_ c); ostream& semant_error(Symbol filename, tree_node *t); }; #endif