done without gc
This commit is contained in:
parent
c29b455305
commit
fec2e03a75
@ -356,6 +356,63 @@ static void emit_gc_check(char *source, ostream &s) {
|
|||||||
s << JAL << "_gc_check" << endl;
|
s << JAL << "_gc_check" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
| ........ |
|
||||||
|
|------------|
|
||||||
|
| param 2 |
|
||||||
|
|------------|
|
||||||
|
| param 1 |
|
||||||
|
|------------|
|
||||||
|
| old $fp |<----------- $sp before entry
|
||||||
|
|------------|
|
||||||
|
| old $s0 |
|
||||||
|
|------------|
|
||||||
|
| ret addr |<----------- current $fp
|
||||||
|
|------------|
|
||||||
|
| local 1 |<----------- $sp at entry
|
||||||
|
|------------|
|
||||||
|
| local 2 |
|
||||||
|
|------------|
|
||||||
|
| ........ |
|
||||||
|
Throughout the code generated for expressions, I used 4 registers:
|
||||||
|
$a0, $s0, $a1, $t1. According to MIPS calling conventions, only $s0 needs
|
||||||
|
to be saved. Thus the callee pushes and pops $fp,$s0,$ra when entering and
|
||||||
|
leaving the context.
|
||||||
|
By default, self object is passed to called in $a0, so move it to $s0
|
||||||
|
*/
|
||||||
|
static void emit_procedure_header(ostream &s) {
|
||||||
|
/*
|
||||||
|
addiu $sp $sp -12
|
||||||
|
sw $fp 12($sp)
|
||||||
|
sw $s0 8($sp)
|
||||||
|
sw $ra 4($sp)
|
||||||
|
addiu $fp $sp 4
|
||||||
|
move $s0 $a0
|
||||||
|
*/
|
||||||
|
emit_addiu(SP, SP, -12, s);
|
||||||
|
emit_store(FP, 3, SP, s);
|
||||||
|
emit_store(SELF, 2, SP, s);
|
||||||
|
emit_store(RA, 1, SP, s);
|
||||||
|
emit_addiu(FP, SP, 4, s);
|
||||||
|
emit_move(SELF, ACC, s);
|
||||||
|
rel_stack_depth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void emit_procedure_footer(int nparams, ostream &s) {
|
||||||
|
/*
|
||||||
|
lw $fp 12($sp)
|
||||||
|
lw $s0 8($sp)
|
||||||
|
lw $ra 4($sp)
|
||||||
|
addiu $sp $sp (12 + 4 * nparams)
|
||||||
|
jr $ra
|
||||||
|
*/
|
||||||
|
emit_load(FP, 3, SP, s);
|
||||||
|
emit_load(SELF, 2, SP, s);
|
||||||
|
emit_load(RA, 1, SP, s);
|
||||||
|
emit_addiu(SP, SP, 4 * (3 + nparams), s);
|
||||||
|
emit_return(s);
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -635,16 +692,16 @@ void CgenClassTable::code_prototypeObject() {
|
|||||||
str << WORD << node->get_class_tag() << endl; // class tag
|
str << WORD << node->get_class_tag() << endl; // class tag
|
||||||
str << WORD << node->get_object_size() << endl; // object size
|
str << WORD << node->get_object_size() << endl; // object size
|
||||||
str << WORD << node->get_name() << DISPTAB_SUFFIX << endl; // dispatch ptr
|
str << WORD << node->get_name() << DISPTAB_SUFFIX << endl; // dispatch ptr
|
||||||
for (auto attr : *node->get_attributes()) {
|
for (auto attr_pair : *node->get_attributes()) {
|
||||||
if (attr->type_decl == Int) {
|
if (attr_pair.second->type_decl == Int) {
|
||||||
str << WORD;
|
str << WORD;
|
||||||
_int_default->code_ref(str);
|
_int_default->code_ref(str);
|
||||||
str << endl;
|
str << endl;
|
||||||
} else if (attr->type_decl == Bool) {
|
} else if (attr_pair.second->type_decl == Bool) {
|
||||||
str << WORD;
|
str << WORD;
|
||||||
_bool_default->code_ref(str);
|
_bool_default->code_ref(str);
|
||||||
str << endl;
|
str << endl;
|
||||||
} else if (attr->type_decl == Str) {
|
} else if (attr_pair.second->type_decl == Str) {
|
||||||
str << WORD;
|
str << WORD;
|
||||||
_str_default->code_ref(str);
|
_str_default->code_ref(str);
|
||||||
str << endl;
|
str << endl;
|
||||||
@ -666,6 +723,81 @@ void CgenClassTable::code_objectTab() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CgenClassTable::gen_init_code() {
|
||||||
|
for (auto node : nodes) {
|
||||||
|
this->cur_class = node;
|
||||||
|
str << node->get_name() << CLASSINIT_SUFFIX << LABEL;
|
||||||
|
emit_procedure_header(str);
|
||||||
|
if (node->get_parentnd() && node->get_parentnd()->name != No_class) {
|
||||||
|
str << JAL << node->parent->get_string() << CLASSINIT_SUFFIX << endl;
|
||||||
|
}
|
||||||
|
auto attrs = node->get_attributes();
|
||||||
|
// attributes are available when initializing
|
||||||
|
loctab.enterscope();
|
||||||
|
for (auto i = 0U; i < attrs->size(); ++i) {
|
||||||
|
auto attr_pair = (*attrs)[i];
|
||||||
|
loctab.add(LocationTableItem(attr_pair.second->name, Attribute,
|
||||||
|
i + DEFAULT_OBJFIELDS));
|
||||||
|
}
|
||||||
|
for (auto i = 0U; i < attrs->size(); ++i) {
|
||||||
|
auto attr_pair = (*attrs)[i];
|
||||||
|
if (attr_pair.first->name != node->name)
|
||||||
|
continue;
|
||||||
|
// base class initializer will handle inherited attributes
|
||||||
|
// here we only deal with our new attributes
|
||||||
|
if (is_no_expr(attr_pair.second->init))
|
||||||
|
continue;
|
||||||
|
// we can safely skip for those attributes without initialization expr
|
||||||
|
// because the default values are set in the prototype object, when
|
||||||
|
// the object is created by Object.copy(), they will be set to correct
|
||||||
|
// default values
|
||||||
|
this->expr_type_decl = attr_pair.second->type_decl;
|
||||||
|
attr_pair.second->init->code(str, this);
|
||||||
|
emit_store(ACC, i + DEFAULT_OBJFIELDS, SELF, str);
|
||||||
|
}
|
||||||
|
loctab.exitscope();
|
||||||
|
emit_move(ACC, SELF, str);
|
||||||
|
// remember to place the initialized object back to $a0, other code rely on
|
||||||
|
// this behavior
|
||||||
|
emit_procedure_footer(0, str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CgenClassTable::gen_method_code() {
|
||||||
|
for (auto node : nodes) {
|
||||||
|
if (node->basic())
|
||||||
|
continue;
|
||||||
|
this->cur_class = node;
|
||||||
|
for (auto method_pair : *node->get_methods()) {
|
||||||
|
if (method_pair.first->name != node->name)
|
||||||
|
continue; // skip inherited methods
|
||||||
|
auto method = method_pair.second;
|
||||||
|
auto attrs = node->get_attributes();
|
||||||
|
// add attributes and formals to location table
|
||||||
|
loctab.enterscope();
|
||||||
|
// add attributes
|
||||||
|
for (auto i = 0U; i < attrs->size(); ++i) {
|
||||||
|
auto attr_pair = (*attrs)[i];
|
||||||
|
loctab.add(LocationTableItem(attr_pair.second->name, Attribute,
|
||||||
|
i + DEFAULT_OBJFIELDS));
|
||||||
|
}
|
||||||
|
// add formals
|
||||||
|
for (auto i = method->formals->first(); method->formals->more(i);
|
||||||
|
i = method->formals->next(i)) {
|
||||||
|
auto formal = static_cast<formal_class *>(method->formals->nth(i));
|
||||||
|
loctab.add(LocationTableItem(formal->name, Stack,
|
||||||
|
method->formals->len() - i + 3 - 1));
|
||||||
|
// &formal[i] = (4 * i + 12)($fp)
|
||||||
|
}
|
||||||
|
str << node->name << "." << method->name << LABEL;
|
||||||
|
emit_procedure_header(str);
|
||||||
|
method->expr->code(str, this);
|
||||||
|
emit_procedure_footer(method->formals->len(), str);
|
||||||
|
loctab.exitscope();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CgenClassTable::CgenClassTable(Classes classes, ostream &s) : str(s) {
|
CgenClassTable::CgenClassTable(Classes classes, ostream &s) : str(s) {
|
||||||
enterscope();
|
enterscope();
|
||||||
if (cgen_debug)
|
if (cgen_debug)
|
||||||
@ -974,10 +1106,13 @@ void CgenClassTable::code() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Add your code to emit
|
if (cgen_debug)
|
||||||
// - object initializer
|
cout << "generating object initializers" << endl;
|
||||||
// - the class methods
|
gen_init_code();
|
||||||
// - etc...
|
|
||||||
|
if (cgen_debug)
|
||||||
|
cout << "generating class methods" << endl;
|
||||||
|
gen_method_code();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
@ -1031,7 +1166,9 @@ void CgenNode::traverse_generate_object() {
|
|||||||
feature_i = features->next(feature_i)) {
|
feature_i = features->next(feature_i)) {
|
||||||
auto feature = features->nth(feature_i);
|
auto feature = features->nth(feature_i);
|
||||||
if (typeid(*feature) == typeid(attr_class)) {
|
if (typeid(*feature) == typeid(attr_class)) {
|
||||||
this->attributes.push_back(static_cast<attr_class *>(feature));
|
this->attributes.push_back(
|
||||||
|
std::make_pair(static_cast<class__class *>(this),
|
||||||
|
static_cast<attr_class *>(feature)));
|
||||||
// inherited attrs cannot be redefined, so simply add to list
|
// inherited attrs cannot be redefined, so simply add to list
|
||||||
} else {
|
} else {
|
||||||
auto method = static_cast<method_class *>(feature);
|
auto method = static_cast<method_class *>(feature);
|
||||||
@ -1055,7 +1192,8 @@ void CgenNode::traverse_generate_object() {
|
|||||||
std::cerr << "Object info -- " << this->name << "\n";
|
std::cerr << "Object info -- " << this->name << "\n";
|
||||||
std::cerr << "Attributes:\n";
|
std::cerr << "Attributes:\n";
|
||||||
for (auto attr : attributes) {
|
for (auto attr : attributes) {
|
||||||
std::cerr << " " << attr->name << ":" << attr->type_decl << "\n";
|
std::cerr << " " << attr.first->name << "." << attr.second->name << ":"
|
||||||
|
<< attr.second->type_decl << "\n";
|
||||||
}
|
}
|
||||||
std::cerr << "Methods:\n";
|
std::cerr << "Methods:\n";
|
||||||
for (auto method : methods) {
|
for (auto method : methods) {
|
||||||
@ -1118,11 +1256,13 @@ void assign_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
and jalr.
|
and jalr.
|
||||||
*/
|
*/
|
||||||
void static_dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
void static_dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
||||||
|
int nparams = 0;
|
||||||
for (auto actual_i = this->actual->first(); this->actual->more(actual_i);
|
for (auto actual_i = this->actual->first(); this->actual->more(actual_i);
|
||||||
actual_i = this->actual->next(actual_i)) {
|
actual_i = this->actual->next(actual_i)) {
|
||||||
auto actual_expr = this->actual->nth(actual_i);
|
auto actual_expr = this->actual->nth(actual_i);
|
||||||
actual_expr->code(s, classtab);
|
actual_expr->code(s, classtab);
|
||||||
emit_push(ACC, s); // push param to stack
|
emit_push(ACC, s); // push param to stack
|
||||||
|
++ nparams;
|
||||||
}
|
}
|
||||||
this->expr->code(s, classtab);
|
this->expr->code(s, classtab);
|
||||||
auto label_dispatch = classtab->alloc_label_index();
|
auto label_dispatch = classtab->alloc_label_index();
|
||||||
@ -1130,11 +1270,11 @@ void static_dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
emit_bne(ACC, ZERO, label_dispatch, s);
|
emit_bne(ACC, ZERO, label_dispatch, s);
|
||||||
// Prints the line number, from $t1, and filename, from $a0, at which the
|
// Prints the line number, from $t1, and filename, from $a0, at which the
|
||||||
// dispatch occurred, and aborts.
|
// dispatch occurred, and aborts.
|
||||||
emit_load_imm(T1, this->line_number, s);
|
|
||||||
emit_partial_load_address(ACC, s);
|
emit_partial_load_address(ACC, s);
|
||||||
stringtable.lookup_string(classtab->cur_class->get_filename()->get_string())
|
stringtable.lookup_string(classtab->cur_class->get_filename()->get_string())
|
||||||
->code_ref(s);
|
->code_ref(s);
|
||||||
s << endl;
|
s << endl;
|
||||||
|
emit_load_imm(T1, this->line_number, s);
|
||||||
emit_jal("_dispatch_abort", s);
|
emit_jal("_dispatch_abort", s);
|
||||||
// ready to call the method
|
// ready to call the method
|
||||||
emit_label_def(label_dispatch, s);
|
emit_label_def(label_dispatch, s);
|
||||||
@ -1146,6 +1286,7 @@ void static_dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
emit_load(T1, classtab->get_method_index(this->type_name, this->name), T1, s);
|
emit_load(T1, classtab->get_method_index(this->type_name, this->name), T1, s);
|
||||||
// call the method whose address is in $t1, with self object in $a0
|
// call the method whose address is in $t1, with self object in $a0
|
||||||
emit_jalr(T1, s);
|
emit_jalr(T1, s);
|
||||||
|
rel_stack_depth -= nparams;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1154,11 +1295,13 @@ void static_dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
dispTab feild(offset 8) instead of querying method address at compile time.
|
dispTab feild(offset 8) instead of querying method address at compile time.
|
||||||
*/
|
*/
|
||||||
void dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
void dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
||||||
|
int nparams = 0;
|
||||||
for (auto actual_i = this->actual->first(); this->actual->more(actual_i);
|
for (auto actual_i = this->actual->first(); this->actual->more(actual_i);
|
||||||
actual_i = this->actual->next(actual_i)) {
|
actual_i = this->actual->next(actual_i)) {
|
||||||
auto actual_expr = this->actual->nth(actual_i);
|
auto actual_expr = this->actual->nth(actual_i);
|
||||||
actual_expr->code(s, classtab);
|
actual_expr->code(s, classtab);
|
||||||
emit_push(ACC, s); // push param to stack
|
emit_push(ACC, s); // push param to stack
|
||||||
|
++ nparams;
|
||||||
}
|
}
|
||||||
this->expr->code(s, classtab);
|
this->expr->code(s, classtab);
|
||||||
auto label_dispatch = classtab->alloc_label_index();
|
auto label_dispatch = classtab->alloc_label_index();
|
||||||
@ -1166,11 +1309,11 @@ void dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
emit_bne(ACC, ZERO, label_dispatch, s);
|
emit_bne(ACC, ZERO, label_dispatch, s);
|
||||||
// Prints the line number, from $t1, and filename, from $a0, at which the
|
// Prints the line number, from $t1, and filename, from $a0, at which the
|
||||||
// dispatch occurred, and aborts.
|
// dispatch occurred, and aborts.
|
||||||
emit_load_imm(T1, this->line_number, s);
|
|
||||||
emit_partial_load_address(ACC, s);
|
emit_partial_load_address(ACC, s);
|
||||||
stringtable.lookup_string(classtab->cur_class->get_filename()->get_string())
|
stringtable.lookup_string(classtab->cur_class->get_filename()->get_string())
|
||||||
->code_ref(s);
|
->code_ref(s);
|
||||||
s << endl;
|
s << endl;
|
||||||
|
emit_load_imm(T1, this->line_number, s);
|
||||||
emit_jal("_dispatch_abort", s);
|
emit_jal("_dispatch_abort", s);
|
||||||
// ready to call the method
|
// ready to call the method
|
||||||
emit_label_def(label_dispatch, s);
|
emit_label_def(label_dispatch, s);
|
||||||
@ -1188,6 +1331,7 @@ void dispatch_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
emit_load(T1, method_index, T1, s);
|
emit_load(T1, method_index, T1, s);
|
||||||
// call the method whose address is in $t1, with self object in $a0
|
// call the method whose address is in $t1, with self object in $a0
|
||||||
emit_jalr(T1, s);
|
emit_jalr(T1, s);
|
||||||
|
rel_stack_depth -= nparams;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1233,14 +1377,14 @@ void loop_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
available at runtime.
|
available at runtime.
|
||||||
Again, through reverse engineering (^_^) the reference compiler, I managed to
|
Again, through reverse engineering (^_^) the reference compiler, I managed to
|
||||||
find out a relatively simple way to embed hierarchy into the program.
|
find out a relatively simple way to embed hierarchy into the program.
|
||||||
We may use the class tag to do this. In advance, allocate the class tags in
|
We may use the class tag to do this. In advance, allocate the class tags in
|
||||||
pre-order traversal of the inheritance tree, and record for each node when
|
pre-order traversal of the inheritance tree, and record for each node when
|
||||||
all its children is allocated. In this way, every node has a range of tags
|
all its children is allocated. In this way, every node has a range of tags
|
||||||
covering itself and its children. When generating `case`, start from the
|
covering itself and its children. When generating `case`, start from the
|
||||||
leaves, because we need to match the closest ancestor. If the tag is in some
|
leaves, because we need to match the closest ancestor. If the tag is in some
|
||||||
range, then we can say it matches the branch.
|
range, then we can say it matches the branch.
|
||||||
Besides the hierarchy problem, there are two runtime error here: a case
|
Besides the hierarchy problem, there are two runtime error here: a case
|
||||||
statement has no match -> `_case_abort`; a case on a void object ->
|
statement has no match -> `_case_abort`; a case on a void object ->
|
||||||
`_case_abort2`. Remember to set these two guys.
|
`_case_abort2`. Remember to set these two guys.
|
||||||
*/
|
*/
|
||||||
void typcase_class::code(ostream &s, CgenClassTable *classtab) {
|
void typcase_class::code(ostream &s, CgenClassTable *classtab) {
|
||||||
@ -1282,10 +1426,11 @@ void typcase_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
emit_bgti(T1, node->get_children_tag(), label_branch, s);
|
emit_bgti(T1, node->get_children_tag(), label_branch, s);
|
||||||
// though maybe quite trivial(just bind another name), still push to stack
|
// though maybe quite trivial(just bind another name), still push to stack
|
||||||
// because we dont know whether $a0 is going to be overwritten
|
// because we dont know whether $a0 is going to be overwritten
|
||||||
emit_push(ACC, s);
|
emit_push(ACC, s);
|
||||||
// allocate a new location
|
// allocate a new location
|
||||||
classtab->enterscope();
|
classtab->loctab.enterscope();
|
||||||
classtab->loctab.add(LocationTableItem(branch->name, Stack, -rel_stack_depth));
|
classtab->loctab.add(
|
||||||
|
LocationTableItem(branch->name, Stack, -rel_stack_depth));
|
||||||
// if expr's tag is in range, evaluate this branch
|
// if expr's tag is in range, evaluate this branch
|
||||||
branch->expr->code(s, classtab);
|
branch->expr->code(s, classtab);
|
||||||
classtab->loctab.exitscope();
|
classtab->loctab.exitscope();
|
||||||
@ -1295,7 +1440,7 @@ void typcase_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
// the label for the next branch
|
// the label for the next branch
|
||||||
emit_label_def(label_branch, s);
|
emit_label_def(label_branch, s);
|
||||||
}
|
}
|
||||||
// no match, the procedure's is in $a0, which remains unmodified if no branch
|
// no match, the procedure's is in $a0, which remains unmodified if no branch
|
||||||
// is taken, thus unnecessary to set it
|
// is taken, thus unnecessary to set it
|
||||||
emit_jal("_case_abort", s);
|
emit_jal("_case_abort", s);
|
||||||
emit_label_def(label_exit, s);
|
emit_label_def(label_exit, s);
|
||||||
@ -1423,7 +1568,7 @@ void neg_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
this->e1->code(s, classtab);
|
this->e1->code(s, classtab);
|
||||||
emit_jal("Object.copy", s);
|
emit_jal("Object.copy", s);
|
||||||
emit_fetch_int(T1, ACC, s);
|
emit_fetch_int(T1, ACC, s);
|
||||||
emit_neg(T1, ACC, s);
|
emit_neg(T1, T1, s);
|
||||||
emit_store_int(T1, ACC, s);
|
emit_store_int(T1, ACC, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1633,6 +1778,8 @@ void no_expr_class::code(ostream &s, CgenClassTable *classtab) {
|
|||||||
emit_load_bool(ACC, *classtab->bool_default(), s);
|
emit_load_bool(ACC, *classtab->bool_default(), s);
|
||||||
} else if (classtab->expr_type_decl == Str) {
|
} else if (classtab->expr_type_decl == Str) {
|
||||||
emit_load_string(ACC, classtab->str_default(), s);
|
emit_load_string(ACC, classtab->str_default(), s);
|
||||||
|
} else if (classtab->expr_type_decl == prim_slot) {
|
||||||
|
assert(0); // basic type should not get attrs init
|
||||||
} else {
|
} else {
|
||||||
assert(classtab->expr_type_decl);
|
assert(classtab->expr_type_decl);
|
||||||
emit_move(ACC, ZERO, s);
|
emit_move(ACC, ZERO, s);
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
#include "cool-tree.h"
|
#include "cool-tree.h"
|
||||||
|
#include "cool-tree.handcode.h"
|
||||||
#include "emit.h"
|
#include "emit.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -24,7 +25,7 @@ typedef CgenNode *CgenNodeP;
|
|||||||
class BoolConst;
|
class BoolConst;
|
||||||
|
|
||||||
typedef std::vector<std::pair<class__class *, method_class *>> MethodListT;
|
typedef std::vector<std::pair<class__class *, method_class *>> MethodListT;
|
||||||
typedef std::vector<attr_class *> AttrListT;
|
typedef std::vector<std::pair<class__class *, attr_class *>> AttrListT;
|
||||||
|
|
||||||
struct LocationTableItem {
|
struct LocationTableItem {
|
||||||
LocationTableItem(Symbol id, VariableLocation loc, int off)
|
LocationTableItem(Symbol id, VariableLocation loc, int off)
|
||||||
@ -108,6 +109,7 @@ private:
|
|||||||
CgenNode *get_node(Symbol);
|
CgenNode *get_node(Symbol);
|
||||||
void code_objectTab();
|
void code_objectTab();
|
||||||
void gen_init_code();
|
void gen_init_code();
|
||||||
|
void gen_method_code();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LocationTable loctab;
|
LocationTable loctab;
|
||||||
@ -168,3 +170,7 @@ public:
|
|||||||
void code_def(ostream &, int boolclasstag);
|
void code_def(ostream &, int boolclasstag);
|
||||||
void code_ref(ostream &) const;
|
void code_ref(ostream &) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline bool is_no_expr(Expression expr) {
|
||||||
|
return typeid(*expr) == typeid(no_expr_class);
|
||||||
|
}
|
||||||
@ -20,8 +20,11 @@ class B inherits A {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class C inherits A {
|
class C inherits A {
|
||||||
attr_C_1 : String <- "This is C\n".concat(new A.method_common2());
|
|
||||||
attr_C_2 : SELF_TYPE;
|
attr_C_2 : SELF_TYPE;
|
||||||
|
attr_C_0 : Int <- 10;
|
||||||
|
attr_C_1 : String <- "This is C\n".concat(new A.method_common2());
|
||||||
|
attr_C_3 : Int <- "12345".length();
|
||||||
|
attr_C_4 : Bool <- "12345".length() = 5;
|
||||||
method_common(x1: Int) : SELF_TYPE {
|
method_common(x1: Int) : SELF_TYPE {
|
||||||
self
|
self
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,2 +1,4 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
./lexer $* | ./parser $* | ./semant $* > debug.in
|
||||||
./lexer $* | ./parser $* | ./semant $* | ./cgen $*
|
./lexer $* | ./parser $* | ./semant $* | ./cgen $*
|
||||||
|
rm debug.in
|
||||||
@ -1,2 +1,5 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
filename=$(basename -- "$*")
|
||||||
|
filename="${filename%.*}"
|
||||||
../../bin/lexer $* | ../../bin/parser $* | ../../bin/semant $* | ../../bin/cgen $*
|
../../bin/lexer $* | ../../bin/parser $* | ../../bin/semant $* | ../../bin/cgen $*
|
||||||
|
mv $filename.s $filename.std.s
|
||||||
Loading…
Reference in New Issue
Block a user