add helpers for typing; fix self attr; fix SELF_TYPE is_exist

This commit is contained in:
ridethepig 2023-03-25 15:23:44 +00:00
parent 1e072b28fc
commit cde6479576
4 changed files with 97 additions and 30 deletions

View File

@ -34,7 +34,7 @@ class Err3 inherits String {};
class Err3 inherits Bool {}; class Err3 inherits Bool {};
class Err4 inherits Err3 {};*) class Err4 inherits Err3 {};*)
class Err4 inherits Ok1 { class Err4 inherits Ok1 {
bye: Bool <- 10; bye: NOEXIST <- 10;
hello(a: TT) : NOEXIST { new Object }; hello(a: TT) : NOEXIST { new Object };
}; };
@ -69,6 +69,7 @@ class DummyMain {
class Main inherits DummyMain { class Main inherits DummyMain {
attr1: Bool <- (new Err5).hello(); attr1: Bool <- (new Err5).hello();
attr2: Int <- (new Err5).bye(); attr2: Int <- (new Err5).bye();
self(): SELF_TYPE { new SELF_TYPE };
main(): Object { main(): Object {
{ {
let x:Int in { let x:Int in {
@ -79,7 +80,7 @@ class Main inherits DummyMain {
} }
}; };
main: Bool <- true; main: Bool <- true + false;
}; };
class Err5 { class Err5 {

View File

@ -28,6 +28,7 @@ public:
}; };
class ClassTable;
// define simple phylum - Class_ // define simple phylum - Class_
typedef class Class__class *Class_; typedef class Class__class *Class_;
@ -35,6 +36,7 @@ class Class__class : public tree_node {
public: public:
tree_node *copy() { return copy_Class_(); } tree_node *copy() { return copy_Class_(); }
virtual Class_ copy_Class_() = 0; virtual Class_ copy_Class_() = 0;
virtual void semant(ClassTable*) = 0;
#ifdef Class__EXTRAS #ifdef Class__EXTRAS
Class__EXTRAS Class__EXTRAS
@ -49,6 +51,7 @@ class Feature_class : public tree_node {
public: public:
tree_node *copy() { return copy_Feature(); } tree_node *copy() { return copy_Feature(); }
virtual Feature copy_Feature() = 0; virtual Feature copy_Feature() = 0;
virtual void semant(Class_, ClassTable*) = 0;
#ifdef Feature_EXTRAS #ifdef Feature_EXTRAS
Feature_EXTRAS Feature_EXTRAS
@ -164,7 +167,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(); void semant(ClassTable*);
#ifdef Class__SHARED_EXTRAS #ifdef Class__SHARED_EXTRAS
Class__SHARED_EXTRAS Class__SHARED_EXTRAS
@ -196,6 +199,7 @@ public:
Formals get_formals() const { return formals; }; Formals get_formals() const { return formals; };
Symbol get_return_type() const { return return_type; }; Symbol get_return_type() const { return return_type; };
Expression get_expr() const { return expr; }; Expression get_expr() const { return expr; };
void semant(Class_, ClassTable*);
#ifdef Feature_SHARED_EXTRAS #ifdef Feature_SHARED_EXTRAS
Feature_SHARED_EXTRAS Feature_SHARED_EXTRAS
@ -224,6 +228,7 @@ public:
Symbol get_name() const { return name; }; Symbol get_name() const { return name; };
Symbol get_type_decl() const { return type_decl; }; Symbol get_type_decl() const { return type_decl; };
Expression get_init() const { return init; }; Expression get_init() const { return init; };
void semant(Class_, ClassTable*);
#ifdef Feature_SHARED_EXTRAS #ifdef Feature_SHARED_EXTRAS
Feature_SHARED_EXTRAS Feature_SHARED_EXTRAS

View File

@ -5,9 +5,9 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <utility>
#include <vector> #include <vector>
#include <queue> #include <queue>
#include <memory.h>
#include "cool-tree.h" #include "cool-tree.h"
#include "semant.h" #include "semant.h"
#include "utilities.h" #include "utilities.h"
@ -110,14 +110,10 @@ ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr)
} }
/* second scan: check base class inheritable */ /* 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) { for (auto class_i : _class_vec) {
auto sym_parent = class_i->get_parent(); auto sym_parent = class_i->get_parent();
// Cool has restrictions on inheriting from the basic classes // 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() semant_error(class_i) << "Class " << class_i->get_name()
<< " cannot inherit class " << sym_parent << ".\n"; << " 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) { void ClassTable::symtab_dump(Symbol class_name) {
std::cerr << "SymTab of " << class_name << "\n"; std::cerr << "SymTab of " << class_name << "\n";
std::cerr << "M(" << class_name << ") ="; std::cerr << "M(" << class_name << ") =";
symtab_met[class_name]->dump(); _symtab_met[class_name]->dump();
std::cerr << "O(" << class_name << ") ="; std::cerr << "O(" << class_name << ") =";
symtab_obj[class_name]->dump(); _symtab_obj[class_name]->dump();
std::cerr << "--------\n\n"; 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 class_node = name_to_node[class_name];
auto parent_node= class_node->parent; auto parent_node= class_node->parent;
while (parent_node) { 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 // only need to lookup in the top scope, because attributes all reside in top scope
if (result) return result; if (result) return result;
parent_node = parent_node->parent; 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 class_node = name_to_node[class_name];
auto parent_node= class_node->parent; auto parent_node= class_node->parent;
while (parent_node) { 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 // only need to lookup in the top scope, because attributes all reside in top scope
if (result) return result; if (result) return result;
parent_node = parent_node->parent; 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() { void ClassTable::install_all_features() {
/* fourth scan: gather attr and method definition */ /* 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; class__class* class_Main = nullptr;
method_class* method_main = nullptr; // main in class Main method_class* method_main = nullptr; // main in class Main
std::queue<ClassGraphNode*> _iter_queue; std::queue<ClassGraphNode*> _iter_queue;
@ -208,13 +202,13 @@ void ClassTable::install_all_features() {
} }
auto cur_class = cur_node->get_class(); auto cur_class = cur_node->get_class();
auto cur_name = cur_class->get_name(); auto cur_name = cur_class->get_name();
if (cur_name == sym_Main) { if (cur_name == Main) {
class_Main = cur_class; class_Main = cur_class;
} }
symtab_met[cur_name] = new SymbolTable<Symbol, method_class>; _symtab_met[cur_name] = new SymbolTable<Symbol, method_class>;
symtab_obj[cur_name] = new SymbolTable<Symbol, Entry>; _symtab_obj[cur_name] = new SymbolTable<Symbol, Entry>;
symtab_met[cur_name]->enterscope(); _symtab_met[cur_name]->enterscope();
symtab_obj[cur_name]->enterscope(); _symtab_obj[cur_name]->enterscope();
auto cur_features = cur_class->get_features(); auto cur_features = cur_class->get_features();
for (auto j = cur_features->first(); cur_features->more(j); j = cur_features->next(j)) { 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)) { if (typeid(*cur_feature) == typeid(attr_class)) {
auto cur_attr = static_cast<attr_class*>(cur_feature); auto cur_attr = static_cast<attr_class*>(cur_feature);
// std::cerr << "attr " << cur_attr->get_name() << "\n"; // 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() semant_error(cur_class->get_filename(), cur_attr) << "Attribute " << cur_attr->get_name()
<< " is multiply defined.\n"; << " is multiply defined.\n";
} }
@ -233,13 +231,13 @@ void ClassTable::install_all_features() {
<< " is an attribute of an inherited class.\n"; << " is an attribute of an inherited class.\n";
} }
else { 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)) { else if (typeid(*cur_feature) == typeid(method_class)) {
auto cur_method = static_cast<method_class*>(cur_feature); auto cur_method = static_cast<method_class*>(cur_feature);
// std::cerr << "method " << cur_method->get_name() << "\n"; // 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() semant_error(cur_class->get_filename(), cur_method) << "Method " << cur_method->get_name()
<< " is multiply defined.\n"; << " is multiply defined.\n";
} }
@ -292,8 +290,8 @@ void ClassTable::install_all_features() {
} }
if (!_error_flag) { if (!_error_flag) {
// std::cerr << "method done " << cur_method->get_name() << "\n"; // std::cerr << "method done " << cur_method->get_name() << "\n";
symtab_met[cur_name]->addid(cur_method->get_name(), cur_method); _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) { if (class_Main != nullptr && cur_name == Main && cur_method->get_name() == main_meth) {
// main in class Main // main in class Main
method_main = cur_method; method_main = cur_method;
} }
@ -471,7 +469,28 @@ ostream& ClassTable::semant_error()
return error_stream; 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. /* This is the entry point to the semantic checker.
@ -502,7 +521,13 @@ void program_class::semant()
classtable->install_all_features(); classtable->install_all_features();
/* Top down type checking */ /* Top down type checking */
for (auto class_i : classtable->class_vec()) { 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()) { 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)
{
}

View File

@ -145,19 +145,26 @@ private:
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 // 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, Entry>* > _symtab_obj;
std::map<Symbol, SymbolTable<Symbol, method_class>*> symtab_met; std::map<Symbol, SymbolTable<Symbol, method_class>*> _symtab_met;
// Actually, it makes things easier to keep a list-shape copy of classes // Actually, it makes things easier to keep a list-shape copy of classes
std::vector<class__class*> _class_vec; std::vector<class__class*> _class_vec;
public: public:
ClassTable(Classes); ClassTable(Classes);
/* helpers */
void install_all_features(); void install_all_features();
void symtab_dump(Symbol); void symtab_dump(Symbol);
Symbol symtab_object_lookup_parent(Symbol, Symbol); Symbol symtab_object_lookup_parent(Symbol, Symbol);
method_class* symtab_method_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__class*>& class_vec() { return _class_vec; } std::vector<class__class*>& class_vec() { return _class_vec; }
SymbolTable<Symbol, Entry>* symtab_obj(Symbol class_id) { return _symtab_obj[class_id]; };
SymbolTable<Symbol, method_class>* symtab_met(Symbol class_id) { return _symtab_met[class_id]; };
int errors() { return semant_errors; } int errors() { return semant_errors; }
ostream& semant_error(); ostream& semant_error();
ostream& semant_error(Class_ c); ostream& semant_error(Class_ c);