read the doc and format skeleton code

This commit is contained in:
ridethepig 2023-03-29 02:03:47 +00:00
parent 040115e812
commit b2142969f8
8 changed files with 909 additions and 985 deletions

View File

@ -234,3 +234,31 @@ PA 2-5 正式写编译器。PA2 写词法分析器,首先读一遍 README 和
- 返回 Object 的情况objectid 未定义、new 未定义类、函数调用中无法确定被调用函数的情况类未定义、函数未定义、函数参数个数不对、loop 返回值。 - 返回 Object 的情况objectid 未定义、new 未定义类、函数调用中无法确定被调用函数的情况类未定义、函数未定义、函数参数个数不对、loop 返回值。
剩下的基本上能从手册的12章中比较清晰的看出来。 剩下的基本上能从手册的12章中比较清晰的看出来。
### PA5
#### 读文档
最后一个 PA那必然是要把剩下来的文档全部读完。需要预先看一遍带是 `cool-tour.pdf` 的第7章 Runtime System 和 PA5 handout至于 `cool-manual.pdf` 的第13章语义部分倒是可以一边实现一边看。
先看 handout
- 代码量巨大无比,竟然是 PA4 的2倍
- 文件简述:`cgen.{cc|hh}` 大部分需要写的代码,和 PA4 类似的结构,从 AST 的根节点开始进行 `cgen``cool-tree.h` 和 PA4 类似;`cgen_supp.cc` 定义辅助函数;`emit.h` 里面有一些 MIPS 汇编和符号宏定义;剩下的都是老熟人了。
- 主要任务:
- 生成全局常量prototype objects
- 生成全局表,`class_nameTab` `class_objTab` 还有方法调用表
- 生成每个类的初始化代码
- 生成方法定义
推荐的实现方法还是分两部分,先生成对象布局,然后第二遍在生成每个表达式的代码。
- 提醒注意:这次没有必要去“逆向”参考编译器了,因为它实现了一些高级功能比如寄存器分配优化,这个 PA5 并不要求这个。
- 运行时错误处理manual 规定了6种运行时错误生成的代码需要检测三种(static) dispatch on void, case on void, missing branch除零可以交给模拟器剩下两种由 Runtime 处理。
- GC有一个3个命令行开关控制垃圾回收系统相关的功能。默认情况下不打开 `-g` 开关,此时不启用 GC也就是说这是一个选做功能`-t` 迫使 GC 系统在每次分配对象的时候进行回收;`-T` 的功能交给实现,可能会用来实现一些其他的运行时检查。实现 GC 功能的时候,需要认真阅读 Runtime 手册相关内容。这里可以去看看 CS143 课程网站上的那个单独的 `cool-runtime.pdf`,似乎写的更加详细一些。
- 测试工具:和 PA4 类似,提供了一个 `-c` 选项来设置全局变量 `cgen_debug`。同时提供了一个第三方实现的 `Coolaid` 工具对生成的 MIPS 汇编进行一些检查,说不定会有帮助。最后关于 `Spim` 的 warning 可能会有用。
然后看看 Runtime System
- 首先是对象布局GC Tag 设为-1Object Size 也得填上dispatch pointer 因为不会被 runtime 用到,所以需要自己设计 dispatch 表;对于属性,`Int` 只有一个32位整数、`Bool` 也是如此、`String` 有一个32位的长度+后面全部是 ASCII 字节(最后需要 word 对齐),然后还有空指针 void。
- 然后是一个叫原型对象Prototype Object的东西COOL 里面新建对象的方法是使用 `Object.copy()`,因此我们需要生成这些供其复制的东西,也就是 prototype object。生成的时候需要正确设置前面的头部对于属性三个基本类型有自己的规定其余类型的属性随意设置。
- 栈和寄存器约定:方法调用参数放在栈上、从左到右依次压栈,`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` 返回,这里打印出提示信息并终止执行。

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,11 @@
#include <assert.h>
#include <stdio.h>
#include "emit.h"
#include "cool-tree.h" #include "cool-tree.h"
#include "emit.h"
#include "symtab.h" #include "symtab.h"
#include <assert.h>
#include <iostream>
#include <stdio.h>
enum Basicness {Basic, NotBasic}; enum Basicness { Basic, NotBasic };
#define TRUE 1 #define TRUE 1
#define FALSE 0 #define FALSE 0
@ -14,67 +15,73 @@ typedef CgenClassTable *CgenClassTableP;
class CgenNode; class CgenNode;
typedef CgenNode *CgenNodeP; typedef CgenNode *CgenNodeP;
class CgenClassTable : public SymbolTable<Symbol,CgenNode> { class CgenClassTable : public SymbolTable<Symbol, CgenNode> {
private: private:
List<CgenNode> *nds; List<CgenNode> *nds;
ostream& str; ostream &str;
int stringclasstag; int stringclasstag;
int intclasstag; int intclasstag;
int boolclasstag; int boolclasstag;
// The following methods emit code for
// constants and global declarations.
// The following methods emit code for void code_global_data();
// constants and global declarations. void code_global_text();
void code_bools(int);
void code_select_gc();
void code_constants();
void code_global_data(); // The following creates an inheritance graph from
void code_global_text(); // a list of classes. The graph is implemented as
void code_bools(int); // a tree of `CgenNode', and class names are placed
void code_select_gc(); // in the base class symbol table.
void code_constants();
// The following creates an inheritance graph from void install_basic_classes();
// a list of classes. The graph is implemented as void install_class(CgenNodeP nd);
// a tree of `CgenNode', and class names are placed void install_classes(Classes cs);
// in the base class symbol table. void build_inheritance_tree();
void set_relations(CgenNodeP nd);
//* New Methods
void dump_inheritance_tree();
void install_basic_classes();
void install_class(CgenNodeP nd);
void install_classes(Classes cs);
void build_inheritance_tree();
void set_relations(CgenNodeP nd);
public: public:
CgenClassTable(Classes, ostream& str); CgenClassTable(Classes, ostream &str);
void code(); void code();
CgenNodeP root(); CgenNodeP root();
}; };
class CgenNode : public class__class { class CgenNode : public class__class {
private: private:
CgenNodeP parentnd; // Parent of class CgenNodeP parentnd; // Parent of class
List<CgenNode> *children; // Children of class List<CgenNode> *children; // Children of class
Basicness basic_status; // `Basic' if class is basic Basicness basic_status; // `Basic' if class is basic
// `NotBasic' otherwise // `NotBasic' otherwise
public: public:
CgenNode(Class_ c, CgenNode(Class_ c, Basicness bstatus, CgenClassTableP class_table);
Basicness bstatus,
CgenClassTableP class_table);
void add_child(CgenNodeP child); void add_child(CgenNodeP child);
List<CgenNode> *get_children() { return children; } List<CgenNode> *get_children() { return children; }
void set_parentnd(CgenNodeP p); void set_parentnd(CgenNodeP p);
CgenNodeP get_parentnd() { return parentnd; } CgenNodeP get_parentnd() { return parentnd; }
int basic() { return (basic_status == Basic); } 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);
}
}
}; };
class BoolConst class BoolConst {
{ private:
private:
int val; int val;
public:
BoolConst(int);
void code_def(ostream&, int boolclasstag);
void code_ref(ostream&) const;
};
public:
BoolConst(int);
void code_def(ostream &, int boolclasstag);
void code_ref(ostream &) const;
};

View File

@ -1,30 +1,25 @@
#include "stringtab.h"
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "stringtab.h"
static int ascii = 0; static int ascii = 0;
void ascii_mode(ostream& str) void ascii_mode(ostream &str) {
{ if (!ascii) {
if (!ascii) str << "\t.ascii\t\"";
{ ascii = 1;
str << "\t.ascii\t\""; }
ascii = 1;
}
} }
void byte_mode(ostream& str) void byte_mode(ostream &str) {
{ if (ascii) {
if (ascii) str << "\"\n";
{ ascii = 0;
str << "\"\n"; }
ascii = 0;
}
} }
void emit_string_constant(ostream& str, char* s) void emit_string_constant(ostream &str, char *s) {
{
ascii = 0; ascii = 0;
while (*s) { while (*s) {
@ -39,23 +34,20 @@ void emit_string_constant(ostream& str, char* s)
break; break;
case '\\': case '\\':
byte_mode(str); byte_mode(str);
str << "\t.byte\t" << (int) ((unsigned char) '\\') << endl; str << "\t.byte\t" << (int)((unsigned char)'\\') << endl;
break; break;
case '"' : case '"':
ascii_mode(str); ascii_mode(str);
str << "\\\""; str << "\\\"";
break; break;
default: default:
if (*s >= ' ' && ((unsigned char) *s) < 128) if (*s >= ' ' && ((unsigned char)*s) < 128) {
{ ascii_mode(str);
ascii_mode(str); str << *s;
str << *s; } else {
} byte_mode(str);
else str << "\t.byte\t" << (int)((unsigned char)*s) << endl;
{ }
byte_mode(str);
str << "\t.byte\t" << (int) ((unsigned char) *s) << endl;
}
break; break;
} }
s++; s++;
@ -63,5 +55,3 @@ void emit_string_constant(ostream& str, char* s)
byte_mode(str); byte_mode(str);
str << "\t.byte\t0\t" << endl; str << "\t.byte\t0\t" << endl;
} }

File diff suppressed because it is too large Load Diff

View File

@ -4,19 +4,20 @@
#ifndef COOL_TREE_HANDCODE_H #ifndef COOL_TREE_HANDCODE_H
#define COOL_TREE_HANDCODE_H #define COOL_TREE_HANDCODE_H
#include <iostream>
#include "tree.h"
#include "cool.h" #include "cool.h"
#include "stringtab.h" #include "stringtab.h"
#include "tree.h"
#include <iostream>
#define yylineno curr_lineno; #define yylineno curr_lineno;
extern int yylineno; extern int yylineno;
inline Boolean copy_Boolean(Boolean b) {return b; } inline Boolean copy_Boolean(Boolean b) { return b; }
inline void assert_Boolean(Boolean) {} inline void assert_Boolean(Boolean) {}
inline void dump_Boolean(ostream& stream, int padding, Boolean b) inline void dump_Boolean(ostream &stream, int padding, Boolean b) {
{ stream << pad(padding) << (int) b << "\n"; } stream << pad(padding) << (int)b << "\n";
}
void dump_Symbol(ostream& stream, int padding, Symbol b); void dump_Symbol(ostream &stream, int padding, Symbol b);
void assert_Symbol(Symbol b); void assert_Symbol(Symbol b);
Symbol copy_Symbol(Symbol b); Symbol copy_Symbol(Symbol b);
@ -44,66 +45,52 @@ typedef Expressions_class *Expressions;
typedef list_node<Case> Cases_class; typedef list_node<Case> Cases_class;
typedef Cases_class *Cases; typedef Cases_class *Cases;
#define Program_EXTRAS \ #define Program_EXTRAS \
virtual void cgen(ostream&) = 0; \ virtual void cgen(ostream &) = 0; \
virtual void dump_with_types(ostream&, int) = 0; virtual void dump_with_types(ostream &, int) = 0;
#define program_EXTRAS \
void cgen(ostream &); \
void dump_with_types(ostream &, int);
#define Class__EXTRAS \
virtual Symbol get_name() = 0; \
virtual Symbol get_parent() = 0; \
virtual Symbol get_filename() = 0; \
virtual void dump_with_types(ostream &, int) = 0;
#define program_EXTRAS \ #define class__EXTRAS \
void cgen(ostream&); \ Symbol get_name() { return name; } \
void dump_with_types(ostream&, int); Symbol get_parent() { return parent; } \
Symbol get_filename() { return filename; } \
void dump_with_types(ostream &, int);
#define Class__EXTRAS \ #define Feature_EXTRAS virtual void dump_with_types(ostream &, int) = 0;
virtual Symbol get_name() = 0; \
virtual Symbol get_parent() = 0; \
virtual Symbol get_filename() = 0; \
virtual void dump_with_types(ostream&,int) = 0;
#define Feature_SHARED_EXTRAS void dump_with_types(ostream &, int);
#define class__EXTRAS \ #define Formal_EXTRAS virtual void dump_with_types(ostream &, int) = 0;
Symbol get_name() { return name; } \
Symbol get_parent() { return parent; } \
Symbol get_filename() { return filename; } \
void dump_with_types(ostream&,int);
#define formal_EXTRAS void dump_with_types(ostream &, int);
#define Feature_EXTRAS \ #define Case_EXTRAS virtual void dump_with_types(ostream &, int) = 0;
virtual void dump_with_types(ostream&,int) = 0;
#define branch_EXTRAS void dump_with_types(ostream &, int);
#define Feature_SHARED_EXTRAS \ #define Expression_EXTRAS \
void dump_with_types(ostream&,int); Symbol type; \
Symbol get_type() { return type; } \
Expression set_type(Symbol s) { \
#define Formal_EXTRAS \ type = s; \
virtual void dump_with_types(ostream&,int) = 0; return this; \
} \
virtual void code(ostream &) = 0; \
#define formal_EXTRAS \ virtual void dump_with_types(ostream &, int) = 0; \
void dump_with_types(ostream&,int); void dump_type(ostream &, int); \
Expression_class() { type = (Symbol)NULL; }
#define Case_EXTRAS \
virtual void dump_with_types(ostream& ,int) = 0;
#define branch_EXTRAS \
void dump_with_types(ostream& ,int);
#define Expression_EXTRAS \
Symbol type; \
Symbol get_type() { return type; } \
Expression set_type(Symbol s) { type = s; return this; } \
virtual void code(ostream&) = 0; \
virtual void dump_with_types(ostream&,int) = 0; \
void dump_type(ostream&, int); \
Expression_class() { type = (Symbol) NULL; }
#define Expression_SHARED_EXTRAS \
void code(ostream&); \
void dump_with_types(ostream&,int);
#define Expression_SHARED_EXTRAS \
void code(ostream &); \
void dump_with_types(ostream &, int);
#endif #endif

View File

@ -3,7 +3,27 @@
as possible. as possible.
*) *)
class Main { class A inherits IO {
attr_A_1 : Int <- 10;
attr_A_2 : Bool <- false;
attr_A_3 : A <- self;
method_common(x1: Int) : SELF_TYPE {
self
};
};
class B inherits A {
};
class C inherits A {
attr_C_1 : String <- "This is C\n";
method_common(x1: Int) : SELF_TYPE {
self
};
};
class Main inherits IO {
main():Int { 0 }; main():Int { 0 };
}; };

BIN
handouts/cool-runtime.pdf Normal file

Binary file not shown.