#include "cool-tree.h" #include "cool-tree.handcode.h" #include "emit.h" #include "symtab.h" #include #include #include #include #include #include #include enum Basicness { Basic, NotBasic, Trivial }; enum VariableLocation { Attribute, Stack }; #define TRUE 1 #define FALSE 0 class CgenClassTable; typedef CgenClassTable *CgenClassTableP; class CgenNode; typedef CgenNode *CgenNodeP; class BoolConst; typedef std::vector> MethodListT; typedef std::vector> AttrListT; struct LocationTableItem { LocationTableItem(Symbol id, VariableLocation loc, int off) : id(id), location(loc), offset(off) {} Symbol id; VariableLocation location; int offset; }; class LocationTable { private: std::vector table; std::vector scope; public: // lookup the inner-most item with the same id as name LocationTableItem *lookup(Symbol name) { for (auto itr = table.rbegin(); itr != table.rend(); ++itr) { if (itr->id == name) { return &*itr; } } assert(0); return nullptr; } void add(LocationTableItem item) { table.push_back(item); }; void enterscope() { scope.push_back(table.size()); } void exitscope() { auto end = scope.back(); scope.pop_back(); table.erase(table.begin() + end, table.end()); } void dump() { scope.push_back(table.size()); for (size_t i = 0; i < scope.size() - 1; ++i) { std::cerr << "scope" << i << "\n"; for (size_t j = scope[i]; j < scope[i + 1]; j++) { std::cerr << table[j].id << ", " << table[j].location << ", " << table[j].offset << "\n"; } } scope.pop_back(); } }; class CgenClassTable : public SymbolTable { private: ostream &str; int stringclasstag; int intclasstag; int boolclasstag; IntEntry *_int_default = nullptr; StringEntry *_str_default = nullptr; BoolConst *_bool_default = nullptr; int label_count = 0; // an incremental counter to avoid label conflicts // The following methods emit code for // constants and global declarations. void code_global_data(); void code_global_text(); void code_bools(int); void code_select_gc(); void code_constants(); // The following creates an inheritance graph from // a list of classes. The graph is implemented as // a tree of `CgenNode', and class names are placed // in the base class symbol table. void install_basic_classes(); void install_class(CgenNodeP nd); void install_classes(Classes cs); void build_inheritance_tree(); void set_relations(CgenNodeP nd); //* New Methods void dump_inheritance_tree(); void code_class_nameTable(); void code_dispatchTable(); void code_prototypeObject(); CgenNode *get_node(Symbol); void code_objectTab(); void gen_init_code(); void gen_method_code(); public: LocationTable loctab; Symbol expr_type_decl; std::vector nodes; CgenNode *cur_class; CgenClassTable(Classes, ostream &str); void code(); CgenNode *root() { return nodes[0]; } /* aquire an unused label index */ int alloc_label_index() { return label_count++; } IntEntry *int_default() const { return _int_default; }; StringEntry *str_default() const { return _str_default; }; BoolConst *bool_default() const { return _bool_default; }; int get_method_index(Symbol class_name, Symbol method_name); }; class CgenNode : public class__class { private: CgenNodeP parentnd; // Parent of class std::vector children; // Children of class Basicness basic_status; // `Basic' if class is basic // `NotBasic' otherwise /* class_tag is allocated in pre-order */ uint32_t _class_tag = 0; /* record children's class tag range for type case code gen */ uint32_t _children_tag_range; AttrListT attributes; // attr list including inherited MethodListT methods; // method list including inherited and overidden methods public: CgenNode(Class_ c, Basicness bstatus); void add_child(CgenNodeP child); std::vector *get_children() { return &children; } void set_parentnd(CgenNodeP p); CgenNodeP get_parentnd() { return parentnd; } int basic() { return (basic_status == Basic); } uint32_t get_class_tag() { return _class_tag; } uint32_t get_children_tag() { return _children_tag_range; } void traverse_dump(int pad); uint32_t get_object_size() { return (3 + attributes.size()); } void traverse_generate_object(); void traverse_allocate_tag(); AttrListT *get_attributes() { return &attributes; }; MethodListT *get_methods() { return &methods; }; }; class BoolConst { private: int val; public: BoolConst(int); void code_def(ostream &, int boolclasstag); void code_ref(ostream &) const; }; inline bool is_no_expr(Expression expr) { return typeid(*expr) == typeid(no_expr_class); }