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 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 {

View File

@ -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

View File

@ -5,9 +5,9 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <utility>
#include <vector>
#include <queue>
#include <memory.h>
#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<ClassGraphNode*> _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<Symbol, method_class>;
symtab_obj[cur_name] = new SymbolTable<Symbol, Entry>;
symtab_met[cur_name]->enterscope();
symtab_obj[cur_name]->enterscope();
_symtab_met[cur_name] = new SymbolTable<Symbol, method_class>;
_symtab_obj[cur_name] = new SymbolTable<Symbol, Entry>;
_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<attr_class*>(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<method_class*>(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)
{
}

View File

@ -145,19 +145,26 @@ private:
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;
std::map<Symbol, SymbolTable<Symbol, Entry>* > _symtab_obj;
std::map<Symbol, SymbolTable<Symbol, method_class>*> _symtab_met;
// Actually, it makes things easier to keep a list-shape copy of classes
std::vector<class__class*> _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__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; }
ostream& semant_error();
ostream& semant_error(Class_ c);