add attr & method collect
This commit is contained in:
parent
e3673e17d3
commit
1da8dbb8c5
@ -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();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@ -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
|
||||||
|
|||||||
@ -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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -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; }
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user