add helpers for typing; fix self attr; fix SELF_TYPE is_exist
This commit is contained in:
parent
1e072b28fc
commit
cde6479576
@ -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 {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -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);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user