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 *)
|
||||
|
||||
class Err1 inherits Int {};
|
||||
(*class Err1 inherits Int {};
|
||||
class Err3 inherits String {};
|
||||
class Err3 inherits Bool {};
|
||||
class Err4 inherits Err3 {};
|
||||
class Err4 inherits NOEXIST {};
|
||||
class Err4 inherits Err3 {};*)
|
||||
class Err4 inherits Ok1 {
|
||||
bye: SS <- 10;
|
||||
hello(a: TT) : NOEXIST { new Object };
|
||||
};
|
||||
|
||||
|
||||
class Main inherits IO {
|
||||
main(): Object {
|
||||
{
|
||||
a();
|
||||
(new Err4).hell();
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -164,6 +164,7 @@ public:
|
||||
Symbol get_name() const { return name; }
|
||||
Symbol get_parent() const { return parent; }
|
||||
Features get_features() const { return features; }
|
||||
void semant();
|
||||
|
||||
#ifdef Class__SHARED_EXTRAS
|
||||
Class__SHARED_EXTRAS
|
||||
@ -191,6 +192,11 @@ public:
|
||||
Feature copy_Feature();
|
||||
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
|
||||
Feature_SHARED_EXTRAS
|
||||
#endif
|
||||
@ -215,6 +221,10 @@ public:
|
||||
Feature copy_Feature();
|
||||
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
|
||||
Feature_SHARED_EXTRAS
|
||||
#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) {
|
||||
install_basic_classes();
|
||||
/* first scan: de-duplicate class definitions*/
|
||||
std::vector<class__class* > class_vec;
|
||||
for (auto i = classes->first(); classes->more(i); i = classes->next(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";
|
||||
}
|
||||
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
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* second scan: check base class inheritable */
|
||||
auto sym_Bool = idtable.lookup_string("Bool");
|
||||
auto sym_Int = idtable.lookup_string("Int");
|
||||
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
|
||||
// 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
|
||||
|
||||
/* third scan: check cyclic inheritance */
|
||||
class_root->traverse();
|
||||
for (auto i : name_to_node) {
|
||||
if (!i.second->reachable()) {
|
||||
@ -139,9 +148,41 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr)
|
||||
}
|
||||
if (semant_errors) return;
|
||||
if (semant_debug) {
|
||||
std::cout << "Class Inheritance Analysis done.\n";
|
||||
std::cerr<< "Class Inheritance Analysis done.\n";
|
||||
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() {
|
||||
@ -316,6 +357,15 @@ void program_class::semant()
|
||||
/* ClassTable constructor may do some semantic analysis */
|
||||
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 */
|
||||
|
||||
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
|
||||
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:
|
||||
ClassTable(Classes);
|
||||
int errors() { return semant_errors; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user