CS143-Lab/assignments/PA5/cgen.h
2023-03-31 18:04:51 +08:00

158 lines
4.2 KiB
C++

#include "cool-tree.h"
#include "emit.h"
#include "symtab.h"
#include <assert.h>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <stdio.h>
#include <utility>
#include <vector>
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;
typedef std::vector<std::pair<class__class *, method_class *>> MethodListT;
typedef std::vector<attr_class *> 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<LocationTableItem> table;
std::vector<size_t> 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;
}
}
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<Symbol, CgenNode> {
private:
std::vector<CgenNode *> nodes;
ostream &str;
int stringclasstag;
int intclasstag;
int boolclasstag;
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 gen_init_code();
public:
LocationTable loctab;
CgenClassTable(Classes, ostream &str);
void code();
CgenNode* root() { return nodes[0]; }
/* aquire an unused label index */
int alloc_label_index() { return label_count++; }
};
class CgenNode : public class__class {
private:
CgenNodeP parentnd; // Parent of class
std::vector<CgenNode *> children; // Children of class
Basicness basic_status; // `Basic' if class is basic
// `NotBasic' otherwise
uint32_t _class_tag = 0;
/* Allocate a class_tag on first scan increase in scanning order,
starting from 1, so 0 is actually invalid by design
*/
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<CgenNode *> *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; }
void set_class_tag(uint32_t val) { _class_tag = val; }
void traverse_dump(int pad);
uint32_t get_object_size() { return (3 + attributes.size()); }
void traverse_generate_object();
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;
};