classnameTab
This commit is contained in:
parent
b2142969f8
commit
d4aeee16cc
@ -262,3 +262,7 @@ PA 2-5 正式写编译器。PA2 写词法分析器,首先读一遍 README 和
|
||||
- 栈和寄存器约定:方法调用参数放在栈上、从左到右依次压栈,`a0` 寄存器里面放 `self` 对象指针。指定了一组 Scratch registers 供 runtime routine 存放临时数据,因此需要调用者保存;还有堆指针和堆界限两个寄存器,完全由 runtime 控制。其他的都可以用。
|
||||
- Label:生成的代码需要和 runtime 一起变成最后执行的机器码,因此有一些 label 是指定的,就类似于接口一样的东西。有些 label 是 runtime 提供给我们使用的,也有一些需要我们生成供 runtime 使用。有一句话 `There is no need for code that initializes an object of class Bool if the generated code contains definitions of both Bool objects in the static data area.` 没看懂
|
||||
- 执行初始化:需要生成一些代码来调用 main 方法。首先通过 Main prototype 生成一个 Main 类的对象并用 `Main_init` 初始化,该初始化方法依次执行 Main 的基类的初始化最后初始化 Main;然后调用 `Main.main`,在 `a0` 里面放上 `Main` 的指针并设置 `ra`;执行结束后,`Main.main` 返回,这里打印出提示信息并终止执行。
|
||||
|
||||
#### 读框架
|
||||
|
||||
这次的框架代码非常的多,而且写的很抽象,因此讲一讲。其实最好的方法是自己写个测试代码,然后用参考编译器生成出来看一看具体是啥样子的,光看他的 skeleton 是真的要绕半天。
|
||||
@ -26,7 +26,7 @@ FFLAGS = -d8 -ocool-lex.cc
|
||||
BFLAGS = -d -v -y -b cool --debug -p cool_yy
|
||||
|
||||
CC=g++
|
||||
CFLAGS=-g -Wall -Wno-unused -Wno-write-strings -Wno-deprecated ${CPPINCLUDE} -DDEBUG -std=c++11
|
||||
CFLAGS=-g -Wall -Wno-unused -Wno-write-strings -Wno-deprecated ${CPPINCLUDE} -DDEBUG -std=c++11 -Wno-unknown-pragmas
|
||||
FLEX=flex ${FFLAGS}
|
||||
BISON= bison ${BFLAGS}
|
||||
DEPEND = ${CC} -MM ${CPPINCLUDE}
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
|
||||
#include "cgen.h"
|
||||
#include "cgen_gc.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
extern void emit_string_constant(ostream &str, char *s);
|
||||
@ -127,6 +128,8 @@ void program_class::cgen(ostream &os) {
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma region StaticEmitProcedures
|
||||
|
||||
static void emit_load(char *dest_reg, int offset, char *source_reg,
|
||||
ostream &s) {
|
||||
s << LW << dest_reg << " " << offset * WORD_SIZE << "(" << source_reg << ")"
|
||||
@ -326,6 +329,8 @@ static void emit_gc_check(char *source, ostream &s) {
|
||||
s << JAL << "_gc_check" << endl;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// coding strings, ints, and booleans
|
||||
@ -347,6 +352,8 @@ static void emit_gc_check(char *source, ostream &s) {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma region ConstantCoding
|
||||
|
||||
//
|
||||
// Strings
|
||||
//
|
||||
@ -454,6 +461,8 @@ void BoolConst::code_def(ostream &s, int boolclasstag) {
|
||||
s << WORD << val << endl; // value (0 or 1)
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// CgenClassTable methods
|
||||
@ -575,12 +584,22 @@ void CgenClassTable::code_constants() {
|
||||
code_bools(boolclasstag);
|
||||
}
|
||||
|
||||
CgenClassTable::CgenClassTable(Classes classes, ostream &s)
|
||||
: nds(NULL), str(s) {
|
||||
stringclasstag = 1 /* Change to your String class tag here */;
|
||||
intclasstag = 2 /* Change to your Int class tag here */;
|
||||
boolclasstag = 3 /* Change to your Bool class tag here */;
|
||||
void CgenClassTable::code_class_nameTable() {
|
||||
str << CLASSNAMETAB << LABEL;
|
||||
|
||||
for (auto node : nodes) {
|
||||
auto name_entry = stringtable.lookup_string(node->name->get_string());
|
||||
str << WORD;
|
||||
name_entry->code_ref(str);
|
||||
str << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CgenClassTable::code_dispatchTable() {}
|
||||
|
||||
void CgenClassTable::code_prototypeObject() {}
|
||||
|
||||
CgenClassTable::CgenClassTable(Classes classes, ostream &s) : str(s) {
|
||||
enterscope();
|
||||
if (cgen_debug)
|
||||
cout << "Building CgenClassTable" << endl;
|
||||
@ -606,6 +625,7 @@ void CgenClassTable::install_basic_classes() {
|
||||
// No_class serves as the parent of Object and the other special classes.
|
||||
// SELF_TYPE is the self class; it cannot be redefined or inherited.
|
||||
// prim_slot is a class known to the code generator.
|
||||
// it serves as the value type of Int, Boolean, String
|
||||
//
|
||||
addid(No_class,
|
||||
new CgenNode(class_(No_class, No_class, nil_Features(), filename),
|
||||
@ -710,6 +730,10 @@ void CgenClassTable::install_basic_classes() {
|
||||
Str, no_expr()))),
|
||||
filename),
|
||||
Basic, this));
|
||||
|
||||
stringclasstag = get_node(Str)->get_class_tag();
|
||||
intclasstag = get_node(Int)->get_class_tag();
|
||||
boolclasstag = get_node(Bool)->get_class_tag();
|
||||
}
|
||||
|
||||
// CgenClassTable::install_class
|
||||
@ -726,7 +750,8 @@ void CgenClassTable::install_class(CgenNodeP nd) {
|
||||
|
||||
// The class name is legal, so add it to the list of classes
|
||||
// and the symbol table.
|
||||
nds = new List<CgenNode>(nd, nds);
|
||||
nodes.push_back(nd);
|
||||
nd->set_class_tag(nodes.size());
|
||||
addid(name, nd);
|
||||
}
|
||||
|
||||
@ -739,8 +764,8 @@ void CgenClassTable::install_classes(Classes cs) {
|
||||
// CgenClassTable::build_inheritance_tree
|
||||
//
|
||||
void CgenClassTable::build_inheritance_tree() {
|
||||
for (List<CgenNode> *l = nds; l; l = l->tl())
|
||||
set_relations(l->hd());
|
||||
for (auto node : nodes)
|
||||
set_relations(node);
|
||||
}
|
||||
|
||||
//
|
||||
@ -755,9 +780,7 @@ void CgenClassTable::set_relations(CgenNodeP nd) {
|
||||
parent_node->add_child(nd);
|
||||
}
|
||||
|
||||
void CgenNode::add_child(CgenNodeP n) {
|
||||
children = new List<CgenNode>(n, children);
|
||||
}
|
||||
void CgenNode::add_child(CgenNodeP n) { children.push_back(n); }
|
||||
|
||||
void CgenNode::set_parentnd(CgenNodeP p) {
|
||||
assert(parentnd == NULL);
|
||||
@ -765,11 +788,19 @@ void CgenNode::set_parentnd(CgenNodeP p) {
|
||||
parentnd = p;
|
||||
}
|
||||
|
||||
void CgenNode::traverse_dump(int pad) {
|
||||
for (int i = 0; i < pad; ++i)
|
||||
std::cerr << " ";
|
||||
std::cerr << this->name << ":" << this->_class_tag << "\n";
|
||||
for (auto child : children) {
|
||||
child->traverse_dump(pad + 2);
|
||||
}
|
||||
}
|
||||
|
||||
void CgenClassTable::dump_inheritance_tree() {
|
||||
CgenNode *object_node = nullptr;
|
||||
|
||||
for (auto l = nds; l; l = l->tl()) {
|
||||
auto cur_node = l->hd();
|
||||
for (auto cur_node : nodes) {
|
||||
if (cur_node->name == Object) {
|
||||
object_node = cur_node;
|
||||
break;
|
||||
@ -778,6 +809,18 @@ void CgenClassTable::dump_inheritance_tree() {
|
||||
object_node->traverse_dump(0);
|
||||
}
|
||||
|
||||
CgenNode *CgenClassTable::get_node(Symbol class_name) {
|
||||
for (auto node : nodes) {
|
||||
if (node->name == class_name) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
if (cgen_debug)
|
||||
std::cerr << "get_node " << class_name << " not found\n";
|
||||
assert(0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CgenClassTable::code() {
|
||||
if (cgen_debug)
|
||||
cout << "coding global data" << endl;
|
||||
@ -791,6 +834,10 @@ void CgenClassTable::code() {
|
||||
cout << "coding constants" << endl;
|
||||
code_constants();
|
||||
|
||||
if (cgen_debug)
|
||||
cout << "coding class_nameTab" << endl;
|
||||
code_class_nameTable();
|
||||
|
||||
// Add your code to emit
|
||||
// - prototype objects
|
||||
// - class_nameTab
|
||||
@ -816,7 +863,7 @@ CgenNodeP CgenClassTable::root() { return probe(Object); }
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
CgenNode::CgenNode(Class_ nd, Basicness bstatus, CgenClassTableP ct)
|
||||
: class__class((const class__class &)*nd), parentnd(NULL), children(NULL),
|
||||
: class__class((const class__class &)*nd), parentnd(NULL),
|
||||
basic_status(bstatus) {
|
||||
stringtable.add_string(name->get_string()); // Add class name to string table
|
||||
}
|
||||
@ -831,6 +878,8 @@ CgenNode::CgenNode(Class_ nd, Basicness bstatus, CgenClassTableP ct)
|
||||
//
|
||||
//*****************************************************************
|
||||
|
||||
#pragma region ExpressionCoding
|
||||
|
||||
void assign_class::code(ostream &s) {}
|
||||
|
||||
void static_dispatch_class::code(ostream &s) {}
|
||||
@ -887,3 +936,5 @@ void isvoid_class::code(ostream &s) {}
|
||||
void no_expr_class::code(ostream &s) {}
|
||||
|
||||
void object_class::code(ostream &s) {}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
#include "emit.h"
|
||||
#include "symtab.h"
|
||||
#include <assert.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
@ -17,7 +19,7 @@ typedef CgenNode *CgenNodeP;
|
||||
|
||||
class CgenClassTable : public SymbolTable<Symbol, CgenNode> {
|
||||
private:
|
||||
List<CgenNode> *nds;
|
||||
std::vector<CgenNode*> nodes;
|
||||
ostream &str;
|
||||
int stringclasstag;
|
||||
int intclasstag;
|
||||
@ -44,6 +46,10 @@ private:
|
||||
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);
|
||||
|
||||
public:
|
||||
CgenClassTable(Classes, ostream &str);
|
||||
@ -54,26 +60,25 @@ public:
|
||||
class CgenNode : public class__class {
|
||||
private:
|
||||
CgenNodeP parentnd; // Parent of class
|
||||
List<CgenNode> *children; // Children 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
|
||||
*/
|
||||
|
||||
public:
|
||||
CgenNode(Class_ c, Basicness bstatus, CgenClassTableP class_table);
|
||||
|
||||
void add_child(CgenNodeP child);
|
||||
List<CgenNode> *get_children() { return children; }
|
||||
std::vector<CgenNode*>& get_children() { return children; }
|
||||
void set_parentnd(CgenNodeP p);
|
||||
CgenNodeP get_parentnd() { return parentnd; }
|
||||
int basic() { return (basic_status == Basic); }
|
||||
void traverse_dump(int pad) {
|
||||
for (int i = 0; i < pad; ++i)
|
||||
std::cerr << " ";
|
||||
std::cerr << this->name << "\n";
|
||||
for (auto l = children; l; l = l->tl()) {
|
||||
l->hd()->traverse_dump(pad + 2);
|
||||
}
|
||||
}
|
||||
uint32_t get_class_tag() { return _class_tag; }
|
||||
void set_class_tag(uint32_t val) { _class_tag = val; }
|
||||
void traverse_dump(int pad);
|
||||
};
|
||||
|
||||
class BoolConst {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user