From cde64795763d18087a69bad41c4cc790f03b15ae Mon Sep 17 00:00:00 2001 From: ridethepig Date: Sat, 25 Mar 2023 15:23:44 +0000 Subject: [PATCH] add helpers for typing; fix self attr; fix SELF_TYPE is_exist --- assignments/PA4/bad_inherit.cl | 5 +- assignments/PA4/cool-tree.h | 7 ++- assignments/PA4/semant.cc | 104 +++++++++++++++++++++++++-------- assignments/PA4/semant.h | 11 +++- 4 files changed, 97 insertions(+), 30 deletions(-) diff --git a/assignments/PA4/bad_inherit.cl b/assignments/PA4/bad_inherit.cl index c405155..a2ee04b 100644 --- a/assignments/PA4/bad_inherit.cl +++ b/assignments/PA4/bad_inherit.cl @@ -34,7 +34,7 @@ class Err3 inherits String {}; class Err3 inherits Bool {}; class Err4 inherits Err3 {};*) class Err4 inherits Ok1 { - bye: Bool <- 10; + bye: NOEXIST <- 10; hello(a: TT) : NOEXIST { new Object }; }; @@ -69,6 +69,7 @@ class DummyMain { class Main inherits DummyMain { attr1: Bool <- (new Err5).hello(); attr2: Int <- (new Err5).bye(); + self(): SELF_TYPE { new SELF_TYPE }; main(): Object { { let x:Int in { @@ -79,7 +80,7 @@ class Main inherits DummyMain { } }; - main: Bool <- true; + main: Bool <- true + false; }; class Err5 { diff --git a/assignments/PA4/cool-tree.h b/assignments/PA4/cool-tree.h index 66b485d..679d727 100644 --- a/assignments/PA4/cool-tree.h +++ b/assignments/PA4/cool-tree.h @@ -28,6 +28,7 @@ public: }; +class ClassTable; // define simple phylum - Class_ typedef class Class__class *Class_; @@ -35,6 +36,7 @@ class Class__class : public tree_node { public: tree_node *copy() { return copy_Class_(); } virtual Class_ copy_Class_() = 0; + virtual void semant(ClassTable*) = 0; #ifdef Class__EXTRAS Class__EXTRAS @@ -49,6 +51,7 @@ class Feature_class : public tree_node { public: tree_node *copy() { return copy_Feature(); } virtual Feature copy_Feature() = 0; + virtual void semant(Class_, ClassTable*) = 0; #ifdef Feature_EXTRAS Feature_EXTRAS @@ -164,7 +167,7 @@ public: Symbol get_name() const { return name; } Symbol get_parent() const { return parent; } Features get_features() const { return features; } - void semant(); + void semant(ClassTable*); #ifdef Class__SHARED_EXTRAS Class__SHARED_EXTRAS @@ -196,6 +199,7 @@ public: Formals get_formals() const { return formals; }; Symbol get_return_type() const { return return_type; }; Expression get_expr() const { return expr; }; + void semant(Class_, ClassTable*); #ifdef Feature_SHARED_EXTRAS Feature_SHARED_EXTRAS @@ -224,6 +228,7 @@ public: Symbol get_name() const { return name; }; Symbol get_type_decl() const { return type_decl; }; Expression get_init() const { return init; }; + void semant(Class_, ClassTable*); #ifdef Feature_SHARED_EXTRAS Feature_SHARED_EXTRAS diff --git a/assignments/PA4/semant.cc b/assignments/PA4/semant.cc index b30a252..53dd47a 100644 --- a/assignments/PA4/semant.cc +++ b/assignments/PA4/semant.cc @@ -5,9 +5,9 @@ #include #include #include -#include #include #include +#include #include "cool-tree.h" #include "semant.h" #include "utilities.h" @@ -110,14 +110,10 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr) } /* 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"); - for (auto class_i : _class_vec) { auto sym_parent = class_i->get_parent(); // Cool has restrictions on inheriting from the basic classes - if ( sym_parent == sym_Bool || sym_parent == sym_Int || sym_parent == sym_String) { + if ( sym_parent == Bool || sym_parent == Int || sym_parent == Str) { semant_error(class_i) << "Class " << class_i->get_name() << " cannot inherit class " << sym_parent << ".\n"; } @@ -157,9 +153,9 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr) void ClassTable::symtab_dump(Symbol class_name) { std::cerr << "SymTab of " << class_name << "\n"; std::cerr << "M(" << class_name << ") ="; - symtab_met[class_name]->dump(); + _symtab_met[class_name]->dump(); std::cerr << "O(" << class_name << ") ="; - symtab_obj[class_name]->dump(); + _symtab_obj[class_name]->dump(); std::cerr << "--------\n\n"; } @@ -168,7 +164,7 @@ Symbol ClassTable::symtab_object_lookup_parent(Symbol class_name, Symbol object_ auto class_node = name_to_node[class_name]; auto parent_node= class_node->parent; while (parent_node) { - auto result = symtab_obj[parent_node->get_class()->get_name()]->probe(object_name); + auto result = _symtab_obj[parent_node->get_class()->get_name()]->probe(object_name); // only need to lookup in the top scope, because attributes all reside in top scope if (result) return result; parent_node = parent_node->parent; @@ -181,7 +177,7 @@ method_class* ClassTable::symtab_method_lookup_parent(Symbol class_name, Symbol auto class_node = name_to_node[class_name]; auto parent_node= class_node->parent; while (parent_node) { - auto result = symtab_met[parent_node->get_class()->get_name()]->probe(method_name); + auto result = _symtab_met[parent_node->get_class()->get_name()]->probe(method_name); // only need to lookup in the top scope, because attributes all reside in top scope if (result) return result; parent_node = parent_node->parent; @@ -191,8 +187,6 @@ method_class* ClassTable::symtab_method_lookup_parent(Symbol class_name, Symbol void ClassTable::install_all_features() { /* fourth scan: gather attr and method definition */ - auto sym_Main = idtable.lookup_string("Main"); - auto sym_main = idtable.lookup_string("main"); class__class* class_Main = nullptr; method_class* method_main = nullptr; // main in class Main std::queue _iter_queue; @@ -208,13 +202,13 @@ void ClassTable::install_all_features() { } auto cur_class = cur_node->get_class(); auto cur_name = cur_class->get_name(); - if (cur_name == sym_Main) { + if (cur_name == Main) { class_Main = cur_class; } - symtab_met[cur_name] = new SymbolTable; - symtab_obj[cur_name] = new SymbolTable; - symtab_met[cur_name]->enterscope(); - symtab_obj[cur_name]->enterscope(); + _symtab_met[cur_name] = new SymbolTable; + _symtab_obj[cur_name] = new SymbolTable; + _symtab_met[cur_name]->enterscope(); + _symtab_obj[cur_name]->enterscope(); auto cur_features = cur_class->get_features(); for (auto j = cur_features->first(); cur_features->more(j); j = cur_features->next(j)) { @@ -223,7 +217,11 @@ void ClassTable::install_all_features() { if (typeid(*cur_feature) == typeid(attr_class)) { auto cur_attr = static_cast(cur_feature); // std::cerr << "attr " << cur_attr->get_name() << "\n"; - if (symtab_obj[cur_name]->lookup(cur_attr->get_name()) != nullptr) { + if (cur_attr->get_name() == self) { + semant_error(cur_class->get_filename(), cur_attr) + << "\'self\' cannot be the name of an attribute.\n"; + } + else if (_symtab_obj[cur_name]->lookup(cur_attr->get_name()) != nullptr) { semant_error(cur_class->get_filename(), cur_attr) << "Attribute " << cur_attr->get_name() << " is multiply defined.\n"; } @@ -233,13 +231,13 @@ void ClassTable::install_all_features() { << " is an attribute of an inherited class.\n"; } else { - symtab_obj[cur_name]->addid(cur_attr->get_name(), cur_attr->get_type_decl()); + _symtab_obj[cur_name]->addid(cur_attr->get_name(), cur_attr->get_type_decl()); } } else if (typeid(*cur_feature) == typeid(method_class)) { auto cur_method = static_cast(cur_feature); // std::cerr << "method " << cur_method->get_name() << "\n"; - if (symtab_met[cur_name]->lookup(cur_method->get_name()) != nullptr) { + if (_symtab_met[cur_name]->lookup(cur_method->get_name()) != nullptr) { semant_error(cur_class->get_filename(), cur_method) << "Method " << cur_method->get_name() << " is multiply defined.\n"; } @@ -292,8 +290,8 @@ void ClassTable::install_all_features() { } if (!_error_flag) { // std::cerr << "method done " << cur_method->get_name() << "\n"; - symtab_met[cur_name]->addid(cur_method->get_name(), cur_method); - if (class_Main != nullptr && cur_name == sym_Main && cur_method->get_name() == sym_main) { + _symtab_met[cur_name]->addid(cur_method->get_name(), cur_method); + if (class_Main != nullptr && cur_name == Main && cur_method->get_name() == main_meth) { // main in class Main method_main = cur_method; } @@ -471,7 +469,28 @@ ostream& ClassTable::semant_error() return error_stream; } +/* +* Query the Inheritance Graph if T1 <= T0 +* Note: if T1 inherits from(or is) T0, then T1 <= T0 +*/ +bool ClassTable::conform(Symbol T1, Symbol T0) const { + if (T1 == T0) return true; + auto cur_node_itr = name_to_node.find(T1); + assert(cur_node_itr != name_to_node.end()); + auto cur_node = cur_node_itr->second; + while (cur_node) { + if (cur_node->get_class()->get_name() == T0) { + return true; + } + cur_node = cur_node->parent; + } + return false; +} +bool ClassTable::class_exist(Symbol class_id) const { + if (class_id == SELF_TYPE) return true; + return name_to_node.find(class_id) != name_to_node.end(); +} /* This is the entry point to the semantic checker. @@ -502,7 +521,13 @@ void program_class::semant() classtable->install_all_features(); /* Top down type checking */ for (auto class_i : classtable->class_vec()) { - class_i->semant(); + // before we enter a class, add self:SELF_TYPE to its scope + // TODO: Maybe integrate this into last scan + classtable->symtab_obj(class_i->get_name())->enterscope(); + classtable->symtab_obj(class_i->get_name())->addid(self, SELF_TYPE); + class_i->semant(classtable); + // leave scope + classtable->symtab_obj(class_i->get_name())->exitscope(); } if (classtable->errors()) { @@ -511,7 +536,36 @@ void program_class::semant() } } -void class__class::semant() +void class__class::semant(ClassTable * classtable) { - + for (auto i = features->first(); features->more(i); i = features->next(i)) { + auto cur_feature = features->nth(i); + cur_feature->semant(this, classtable); + } } + +void attr_class::semant(Class_ cur_class, ClassTable * classtable) +{ + if (typeid(*init) == typeid(no_expr_class)) { + /* + * Attr-No-Init: + * Check if Declared Type is defined, if so, do nothing because already + * in AST; else, error report and set its type to Object + */ + if (!classtable->class_exist(type_decl)) { + classtable->semant_error(cur_class->get_filename(), this) + << "Class " << type_decl + << " of attribute " << name + << " is undefined.\n"; + this->type_decl = Object; + } + } + else { + // Attr-Init + } +} + +void method_class::semant(Class_ cur_class, ClassTable * classtable) +{ + +} \ No newline at end of file diff --git a/assignments/PA4/semant.h b/assignments/PA4/semant.h index df33b36..36b68e1 100644 --- a/assignments/PA4/semant.h +++ b/assignments/PA4/semant.h @@ -145,19 +145,26 @@ private: std::map name_to_node; // The symbol table only stores pointers, so DATA type defined here dont need a ptr - std::map* > symtab_obj; - std::map*> symtab_met; + std::map* > _symtab_obj; + std::map*> _symtab_met; // Actually, it makes things easier to keep a list-shape copy of classes std::vector _class_vec; public: ClassTable(Classes); + /* helpers */ void install_all_features(); void symtab_dump(Symbol); Symbol symtab_object_lookup_parent(Symbol, Symbol); method_class* symtab_method_lookup_parent(Symbol, Symbol); + bool conform(Symbol, Symbol) const; + bool class_exist(Symbol) const; + /* wrappers */ std::vector& class_vec() { return _class_vec; } + SymbolTable* symtab_obj(Symbol class_id) { return _symtab_obj[class_id]; }; + SymbolTable* symtab_met(Symbol class_id) { return _symtab_met[class_id]; }; + int errors() { return semant_errors; } ostream& semant_error(); ostream& semant_error(Class_ c);