add attr & method collect

This commit is contained in:
ridethepig 2023-03-24 15:46:11 +00:00
parent e3673e17d3
commit 1da8dbb8c5
4 changed files with 78 additions and 8 deletions

View File

@ -29,17 +29,20 @@ class Ok4 inherits Ok2_2 {};
(* Cool has restrictions on inheriting from basic classes *) (* Cool has restrictions on inheriting from basic classes *)
class Err1 inherits Int {}; (*class Err1 inherits Int {};
class Err3 inherits String {}; class Err3 inherits String {};
class Err3 inherits Bool {}; class Err3 inherits Bool {};
class Err4 inherits Err3 {}; class Err4 inherits Err3 {};*)
class Err4 inherits NOEXIST {}; class Err4 inherits Ok1 {
bye: SS <- 10;
hello(a: TT) : NOEXIST { new Object };
};
class Main inherits IO { class Main inherits IO {
main(): Object { main(): Object {
{ {
a(); (new Err4).hell();
} }
}; };
}; };

View File

@ -164,6 +164,7 @@ public:
Symbol get_name() const { return name; } Symbol get_name() const { return name; }
Symbol get_parent() const { return parent; } Symbol get_parent() const { return parent; }
Features get_features() const { return features; } Features get_features() const { return features; }
void semant();
#ifdef Class__SHARED_EXTRAS #ifdef Class__SHARED_EXTRAS
Class__SHARED_EXTRAS Class__SHARED_EXTRAS
@ -191,6 +192,11 @@ public:
Feature copy_Feature(); Feature copy_Feature();
void dump(ostream& stream, int n); void dump(ostream& stream, int n);
Symbol get_name() const { return name; };
Formals get_formals() const { return formals; };
Symbol get_return_type() const { return return_type; };
Expression get_expr() const { return expr; };
#ifdef Feature_SHARED_EXTRAS #ifdef Feature_SHARED_EXTRAS
Feature_SHARED_EXTRAS Feature_SHARED_EXTRAS
#endif #endif
@ -215,6 +221,10 @@ public:
Feature copy_Feature(); Feature copy_Feature();
void dump(ostream& stream, int n); void dump(ostream& stream, int n);
Symbol get_name() const { return name; };
Symbol get_type_decl() const { return type_decl; };
Expression get_init() const { return init; };
#ifdef Feature_SHARED_EXTRAS #ifdef Feature_SHARED_EXTRAS
Feature_SHARED_EXTRAS Feature_SHARED_EXTRAS
#endif #endif

View File

@ -86,9 +86,14 @@ static void initialize_constants(void)
} }
/*
* In ClassTable's constructor, the inheritance graph is built and checked,
* with all defined classes recorded for later check.
* In addition, scan attribute and method definition into global Symbol Table
*/
ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr) { ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr) {
install_basic_classes(); install_basic_classes();
/* first scan: de-duplicate class definitions*/
std::vector<class__class* > class_vec; std::vector<class__class* > class_vec;
for (auto i = classes->first(); classes->more(i); i = classes->next(i)) { for (auto i = classes->first(); classes->more(i); i = classes->next(i)) {
auto class_i = static_cast<class__class*>(classes->nth(i)); auto class_i = static_cast<class__class*>(classes->nth(i));
@ -96,12 +101,14 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr)
semant_error(class_i) << "Class " << class_i->get_name() << " was previously defined.\n"; semant_error(class_i) << "Class " << class_i->get_name() << " was previously defined.\n";
} }
else { else {
name_to_node[class_i->get_name()] = new ClassGraphNode(class_i, nullptr);
// null means we have this class, but not yet build inheritence graph for it // null means we have this class, but not yet build inheritence graph for it
name_to_node[class_i->get_name()] = new ClassGraphNode(class_i, nullptr);
// discard redefined classes by constructing a new vector of classes
class_vec.push_back(class_i); class_vec.push_back(class_i);
} }
} }
/* second scan: check base class inheritable */
auto sym_Bool = idtable.lookup_string("Bool"); auto sym_Bool = idtable.lookup_string("Bool");
auto sym_Int = idtable.lookup_string("Int"); auto sym_Int = idtable.lookup_string("Int");
auto sym_String = idtable.lookup_string("String"); auto sym_String = idtable.lookup_string("String");
@ -130,6 +137,8 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr)
// In COOL's case, every class could have only one base class // In COOL's case, every class could have only one base class
// One simple judgement is that, if it cannot go up to object, then the class or its ancestor involves in a cycle // One simple judgement is that, if it cannot go up to object, then the class or its ancestor involves in a cycle
// Thus, we can start from object and mark all reachable nodes, error report those unreachable nodes // Thus, we can start from object and mark all reachable nodes, error report those unreachable nodes
/* third scan: check cyclic inheritance */
class_root->traverse(); class_root->traverse();
for (auto i : name_to_node) { for (auto i : name_to_node) {
if (!i.second->reachable()) { if (!i.second->reachable()) {
@ -139,9 +148,41 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr)
} }
if (semant_errors) return; if (semant_errors) return;
if (semant_debug) { if (semant_debug) {
std::cout << "Class Inheritance Analysis done.\n"; std::cerr<< "Class Inheritance Analysis done.\n";
class_root->traverse(std::cout, 0); class_root->traverse(std::cout, 0);
} }
/* fourth scan: gather attr and method definition */
for (auto class_i : class_vec) {
auto features_i = class_i->get_features();
auto name_i = class_i->get_name();
symtab_met[name_i] = new SymbolTable<Symbol, method_class>;
symtab_obj[name_i] = new SymbolTable<Symbol, Entry>;
symtab_met[name_i]->enterscope();
symtab_obj[name_i]->enterscope();
for (auto j = features_i->first(); features_i->more(j); j = features_i->next(j)) {
auto feature_j = features_i->nth(j);
if (typeid(*feature_j) == typeid(attr_class)) {
auto attr_j = static_cast<attr_class*>(feature_j);
symtab_obj[name_i]->addid(attr_j->get_name(), attr_j->get_type_decl());
}
else if (typeid(*feature_j) == typeid(method_class)) {
auto method_j = static_cast<method_class*>(feature_j);
symtab_met[name_i]->addid(method_j->get_name(), method_j);
}
else assert(0);
}
}
if (semant_debug) {
std::cerr << "Attr & Methods Collection done.\n";
for (auto class_i : class_vec) {
auto name_i = class_i->get_name();
std::cerr << "M(" << name_i << ") =";
symtab_met[name_i]->dump();
std::cerr << "O(" << name_i << ") =";
symtab_obj[name_i]->dump();
std::cerr << "--------\n\n";
}
}
} }
void ClassTable::install_basic_classes() { void ClassTable::install_basic_classes() {
@ -316,6 +357,15 @@ void program_class::semant()
/* ClassTable constructor may do some semantic analysis */ /* ClassTable constructor may do some semantic analysis */
ClassTable *classtable = new ClassTable(classes); ClassTable *classtable = new ClassTable(classes);
/* Without confidence in inheritance consistency, abort before type checking*/
if (classtable->errors()) {
cerr << "Compilation halted due to static semantic errors." << endl;
exit(1);
}
for (auto i = classes->first(); classes->more(i); i = classes->next(i)) {
auto class_i = static_cast<class__class*>(classes->nth(i));
class_i->semant();
}
/* some semantic analysis code may go here */ /* some semantic analysis code may go here */
if (classtable->errors()) { if (classtable->errors()) {
@ -324,4 +374,7 @@ void program_class::semant()
} }
} }
void class__class::semant()
{
}

View File

@ -125,6 +125,10 @@ private:
// anyways we don't need name shadowing here, I just save my effort // anyways we don't need name shadowing here, I just save my effort
std::map<Symbol, ClassGraphNode*> name_to_node; std::map<Symbol, ClassGraphNode*> name_to_node;
// The symbol table only stores pointers, so DATA type defined here dont need a ptr
std::map<Symbol, SymbolTable<Symbol, Entry>* > symtab_obj;
std::map<Symbol, SymbolTable<Symbol, method_class>*> symtab_met;
public: public:
ClassTable(Classes); ClassTable(Classes);
int errors() { return semant_errors; } int errors() { return semant_errors; }