refine code, comment; small bug fix
This commit is contained in:
parent
67cdb55125
commit
891e07e968
@ -22,6 +22,8 @@ class ErrTest {
|
||||
SELF_TYPE => self;
|
||||
x5:
|
||||
SELF_TYPE => self;
|
||||
self:
|
||||
SELF_TYPE => self;
|
||||
esac;
|
||||
1 + case (new Ok2_2) of
|
||||
x1 : Ok2_1 => new Ok2_1;
|
||||
|
||||
@ -36,7 +36,6 @@ 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
|
||||
@ -51,7 +50,6 @@ 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
|
||||
@ -80,7 +78,6 @@ class Expression_class : public tree_node {
|
||||
public:
|
||||
tree_node *copy() { return copy_Expression(); }
|
||||
virtual Expression copy_Expression() = 0;
|
||||
virtual Symbol semant(Class_, ClassTable*) = 0;
|
||||
#ifdef Expression_EXTRAS
|
||||
Expression_EXTRAS
|
||||
#endif
|
||||
@ -167,7 +164,6 @@ public:
|
||||
Symbol get_name() const { return name; }
|
||||
Symbol get_parent() const { return parent; }
|
||||
Features get_features() const { return features; }
|
||||
void semant(ClassTable*);
|
||||
|
||||
#ifdef Class__SHARED_EXTRAS
|
||||
Class__SHARED_EXTRAS
|
||||
@ -199,7 +195,6 @@ 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
|
||||
@ -228,7 +223,6 @@ 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
|
||||
|
||||
@ -56,20 +56,23 @@ void dump_with_types(ostream&, int);
|
||||
|
||||
#define Class__EXTRAS \
|
||||
virtual Symbol get_filename() = 0; \
|
||||
virtual void dump_with_types(ostream&,int) = 0;
|
||||
virtual void dump_with_types(ostream&,int) = 0; \
|
||||
virtual void semant(ClassTable*) = 0;
|
||||
|
||||
|
||||
#define class__EXTRAS \
|
||||
Symbol get_filename() { return filename; } \
|
||||
void dump_with_types(ostream&,int);
|
||||
|
||||
void dump_with_types(ostream&,int); \
|
||||
void semant(ClassTable*);
|
||||
|
||||
#define Feature_EXTRAS \
|
||||
virtual void dump_with_types(ostream&,int) = 0;
|
||||
virtual void dump_with_types(ostream&,int) = 0; \
|
||||
virtual void semant(Class_, ClassTable*) = 0;
|
||||
|
||||
|
||||
#define Feature_SHARED_EXTRAS \
|
||||
void dump_with_types(ostream&,int);
|
||||
void dump_with_types(ostream&,int); \
|
||||
void semant(Class_, ClassTable*);
|
||||
|
||||
|
||||
|
||||
@ -97,7 +100,9 @@ Symbol get_type() { return type; } \
|
||||
Expression set_type(Symbol s) { type = s; return this; } \
|
||||
virtual void dump_with_types(ostream&,int) = 0; \
|
||||
void dump_type(ostream&, int); \
|
||||
Expression_class() { type = (Symbol) NULL; }
|
||||
Expression_class() { type = (Symbol) NULL; } \
|
||||
virtual Symbol semant(Class_, ClassTable*) = 0;
|
||||
|
||||
|
||||
#define Expression_SHARED_EXTRAS \
|
||||
void dump_with_types(ostream&,int); \
|
||||
|
||||
@ -222,7 +222,7 @@ void ClassTable::install_all_features() {
|
||||
_symtab_obj[cur_name] = new SymbolTable<Symbol, Entry>;
|
||||
_symtab_met[cur_name]->enterscope();
|
||||
_symtab_obj[cur_name]->enterscope();
|
||||
|
||||
_symtab_obj[cur_name]->addid(self, SELF_TYPE);
|
||||
auto cur_features = cur_class->get_features();
|
||||
for (auto j = cur_features->first(); cur_features->more(j); j = cur_features->next(j)) {
|
||||
auto cur_feature = cur_features->nth(j);
|
||||
@ -492,7 +492,7 @@ ostream& ClassTable::semant_error()
|
||||
*/
|
||||
bool ClassTable::conform(Symbol T1, Symbol T0) const {
|
||||
if (T1 == T0) return true;
|
||||
if (!class_exist(T0) || !class_exist(T1))
|
||||
if (!class_defined(T0) || !class_defined(T1))
|
||||
return true;
|
||||
auto cur_node_itr = name_to_node.find(T1);
|
||||
if (cur_node_itr == name_to_node.end()){
|
||||
@ -509,6 +509,9 @@ bool ClassTable::conform(Symbol T1, Symbol T0) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* conformance check with SELF_TYPE support
|
||||
*/
|
||||
bool ClassTable::conform_self(Symbol T1, Symbol T0, Symbol env_class) const {
|
||||
if (T1 == T0) return true;
|
||||
/*
|
||||
@ -525,11 +528,17 @@ bool ClassTable::conform_self(Symbol T1, Symbol T0, Symbol env_class) const {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* conformance check with SELF_TYPE support
|
||||
*/
|
||||
bool ClassTable::conform_self(Symbol T1, Symbol T0, Class_ env_class) const {
|
||||
return conform_self(T1, T0, class_to_name(env_class));
|
||||
}
|
||||
|
||||
bool ClassTable::class_exist(Symbol class_id) const {
|
||||
/*
|
||||
* Check whether a class is defined (not including SELF_TYPE)
|
||||
*/
|
||||
bool ClassTable::class_defined(Symbol class_id) const {
|
||||
return name_to_node.find(class_id) != name_to_node.end();
|
||||
}
|
||||
|
||||
@ -541,17 +550,23 @@ bool ClassTable::class_exist(Symbol class_id) const {
|
||||
* - declared type of a let variable
|
||||
* - declared type of an attribute
|
||||
*/
|
||||
bool ClassTable::class_exist_self(Symbol class_id) const {
|
||||
bool ClassTable::class_defined_self(Symbol class_id) const {
|
||||
if (class_id == SELF_TYPE) return true;
|
||||
else return class_exist(class_id);
|
||||
else return class_defined(class_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the `join` of two types, aka Lowest Upper Bound
|
||||
* Actually it is the LCA of the two nodes on inheritence tree
|
||||
*
|
||||
* Warning:
|
||||
* If either of the inputs is undefined, the operation returns Object
|
||||
*/
|
||||
Symbol ClassTable::lub(Symbol T1, Symbol T2) const {
|
||||
if (T1 == T2) return T1;
|
||||
auto node1_iter = name_to_node.find(T1);
|
||||
auto node2_iter = name_to_node.find(T2);
|
||||
// assert(node1_iter != name_to_node.end());
|
||||
// assert(node2_iter != name_to_node.end());
|
||||
/* Return Object if one of the argument is undefined for recovery */
|
||||
if (node1_iter == name_to_node.end() || node2_iter == name_to_node.end()) {
|
||||
return Object;
|
||||
}
|
||||
@ -585,11 +600,25 @@ Symbol ClassTable::lub(Symbol T1, Symbol T2) const {
|
||||
return node_lower->get_class()->get_name();
|
||||
}
|
||||
|
||||
/*
|
||||
* lub operation with SELF_TYPE support
|
||||
*/
|
||||
Symbol ClassTable::lub(Symbol T1, Symbol T2, Symbol env_class) const {
|
||||
if (T1 == SELF_TYPE) T1 = env_class;
|
||||
if (T2 == SELF_TYPE) T2 = env_class;
|
||||
return lub(T1, T2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Wrapper for the Object Symbol Table
|
||||
*/
|
||||
SymbolTable<Symbol, Entry>* ClassTable::symtab_obj(Class_ class_i) const {
|
||||
auto class_id = static_cast<class__class*>(class_i)->get_name();
|
||||
auto _iter = _symtab_obj.find(class_id);
|
||||
if (_iter == _symtab_obj.end()) return nullptr;
|
||||
return _iter->second;
|
||||
};
|
||||
|
||||
/* This is the entry point to the semantic checker.
|
||||
|
||||
Your checker should do the following two things:
|
||||
@ -619,13 +648,7 @@ void program_class::semant()
|
||||
classtable->install_all_features();
|
||||
/* Top down type checking */
|
||||
for (auto class_i : classtable->class_vec()) {
|
||||
// before we enter a class, add self:SELF_TYPE to its scope
|
||||
// TODO: Maybe integrate this into last scan
|
||||
classtable->symtab_obj(class_i)->enterscope();
|
||||
classtable->symtab_obj(class_i)->addid(self, SELF_TYPE);
|
||||
class_i->semant(classtable);
|
||||
// leave scope
|
||||
classtable->symtab_obj(class_i)->exitscope();
|
||||
}
|
||||
|
||||
if (classtable->errors()) {
|
||||
@ -649,7 +672,7 @@ void attr_class::semant(Class_ cur_class, ClassTable * classtable)
|
||||
* 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_self(type_decl)) {
|
||||
if (!classtable->class_defined_self(type_decl)) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Class " << type_decl
|
||||
<< " of attribute " << name
|
||||
@ -674,6 +697,12 @@ void attr_class::semant(Class_ cur_class, ClassTable * classtable)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Method:
|
||||
* Check formal types and and them to scope
|
||||
* Checks the body of the method in an env in which formals and `self` bounded
|
||||
* Check body type conforms to the declared return type
|
||||
*/
|
||||
void method_class::semant(Class_ cur_class, ClassTable * classtable)
|
||||
{
|
||||
auto symtab_obj = classtable->symtab_obj(cur_class);
|
||||
@ -694,7 +723,7 @@ void method_class::semant(Class_ cur_class, ClassTable * classtable)
|
||||
<< "Formal parameter " << formal_i_name
|
||||
<< " is multiply defined.\n";
|
||||
}
|
||||
if (!classtable->class_exist(formal_i_type)) {
|
||||
if (!classtable->class_defined(formal_i_type)) {
|
||||
classtable->semant_error(cur_class->get_filename(), formal_i)
|
||||
<< "Class " << formal_i_type
|
||||
<< " of formal parameter " << formal_i_name
|
||||
@ -702,7 +731,7 @@ void method_class::semant(Class_ cur_class, ClassTable * classtable)
|
||||
}
|
||||
}
|
||||
auto expr_type = this->expr->semant(cur_class, classtable);
|
||||
if (!classtable->class_exist_self(this->return_type)) {
|
||||
if (!classtable->class_defined_self(this->return_type)) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Undefined return type " << this->return_type
|
||||
<< " in method " << this->name
|
||||
@ -725,15 +754,14 @@ void method_class::semant(Class_ cur_class, ClassTable * classtable)
|
||||
*/
|
||||
Symbol assign_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
// auto lhs_type = classtable->symtab_obj(cur_class)->lookup(name);
|
||||
if (this->name == self) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Cannot assign to 'self'.\n";
|
||||
}
|
||||
auto lhs_type = classtable->symtab_object_lookup_parent(cur_class, name);
|
||||
auto lhs_type = classtable->symtab_object_lookup_parent(cur_class, this->name);
|
||||
if (lhs_type == nullptr) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Assignment to undeclared variable " << name << ".\n";
|
||||
<< "Assignment to undeclared variable " << this->name << ".\n";
|
||||
lhs_type = Object;
|
||||
}
|
||||
auto rhs_type = this->expr->semant(cur_class, classtable);
|
||||
@ -741,7 +769,7 @@ Symbol assign_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Type " << rhs_type
|
||||
<< " of assigned expression does not conform to declared type " << lhs_type
|
||||
<< " of identifier " << name
|
||||
<< " of identifier " << this->name
|
||||
<< ".\n";
|
||||
}
|
||||
this->type = rhs_type;
|
||||
@ -750,14 +778,14 @@ Symbol assign_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
|
||||
Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
auto expr_type = expr->semant(cur_class, classtable);
|
||||
auto expr_type = this->expr->semant(cur_class, classtable);
|
||||
std::vector<Symbol> _param_type;
|
||||
for (auto i = actual->first(); actual->more(i); i = actual->next(i)) {
|
||||
auto param_i = actual->nth(i);
|
||||
for (auto i = this->actual->first(); this->actual->more(i); i = this->actual->next(i)) {
|
||||
auto param_i = this->actual->nth(i);
|
||||
auto param_i_type = param_i->semant(cur_class, classtable);
|
||||
_param_type.push_back(param_i_type);
|
||||
}
|
||||
if (!classtable->class_exist(this->type_name)) {
|
||||
if (!classtable->class_defined(this->type_name)) {
|
||||
if (this->type_name == SELF_TYPE){
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Static dispatch to SELF_TYPE.\n";
|
||||
@ -767,33 +795,27 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< "Static dispatch on undefined class " << this->type_name
|
||||
<< ".\n";
|
||||
}
|
||||
this->type = Object;
|
||||
return this->type;
|
||||
return (this->type = Object);
|
||||
}
|
||||
if (!classtable->conform_self(expr_type, this->type_name, cur_class)) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Expression type " << expr_type
|
||||
<< " does not conform to declared static dispatch type " << this->type_name
|
||||
<< ".\n";
|
||||
this->type = Object;
|
||||
return this->type;
|
||||
return (this->type = Object);
|
||||
}
|
||||
// auto symtab_method = classtable->symtab_met(this->type_name);
|
||||
// auto cur_method = symtab_method->lookup(name);
|
||||
auto cur_method = classtable->symtab_method_lookup_parent(this->type_name, this->name);
|
||||
if (cur_method == nullptr) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Static dispatch to undefined method " << name
|
||||
<< "Static dispatch to undefined method " << this->name
|
||||
<< ".\n";
|
||||
this->type = Object;
|
||||
return Object;
|
||||
return (this->type = Object);
|
||||
}
|
||||
if (actual->len() != cur_method->get_formals()->len()) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Method " << name
|
||||
<< "Method " << this->name
|
||||
<< " called with wrong number of arguments.\n";
|
||||
this->type = Object;
|
||||
return Object;
|
||||
return (this->type = Object);
|
||||
}
|
||||
auto formals = cur_method->get_formals();
|
||||
auto _param_type_iter = _param_type.begin();
|
||||
@ -814,8 +836,7 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
return_type = expr_type;
|
||||
// if expr_type (T_0) is SELF_TYPE, then dispath type just keep it
|
||||
}
|
||||
this->type = return_type;
|
||||
return this->type;
|
||||
return (this->type = return_type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -826,10 +847,10 @@ Symbol static_dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
*/
|
||||
Symbol dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
auto expr_type = expr->semant(cur_class, classtable); // T_0
|
||||
auto expr_type = this->expr->semant(cur_class, classtable); // T_0
|
||||
std::vector<Symbol> _param_type; // T_i
|
||||
for (auto i = actual->first(); actual->more(i); i = actual->next(i)) {
|
||||
auto param_i = actual->nth(i);
|
||||
for (auto i = this->actual->first(); this->actual->more(i); i = this->actual->next(i)) {
|
||||
auto param_i = this->actual->nth(i);
|
||||
auto param_i_type = param_i->semant(cur_class, classtable);
|
||||
_param_type.push_back(param_i_type);
|
||||
}
|
||||
@ -837,29 +858,27 @@ Symbol dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
if (expr_type == SELF_TYPE) {
|
||||
method_env_class = classtable->class_to_name(cur_class);
|
||||
}
|
||||
if (!classtable->class_exist(method_env_class)) {
|
||||
if (!classtable->class_defined(method_env_class)) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Dispatch on undefined class " << method_env_class
|
||||
<< ".\n";
|
||||
this->type = Object;
|
||||
return this->type;
|
||||
}
|
||||
// auto symtab_method = classtable->symtab_met(method_env_class);
|
||||
// auto cur_method = symtab_method->lookup(name);
|
||||
auto cur_method = classtable->symtab_method_lookup_parent(method_env_class, this->name);
|
||||
if (cur_method == nullptr) {
|
||||
if (semant_debug) {
|
||||
std::cerr << "lookup method " << this->name << " in class " << method_env_class << "\n";
|
||||
}
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Dispatch to undefined method " << name
|
||||
<< "Dispatch to undefined method " << this->name
|
||||
<< ".\n";
|
||||
this->type = Object;
|
||||
return Object;
|
||||
}
|
||||
if (actual->len() != cur_method->get_formals()->len()) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Method " << name
|
||||
<< "Method " << this->name
|
||||
<< " called with wrong number of arguments.\n";
|
||||
this->type = Object;
|
||||
return Object;
|
||||
@ -886,8 +905,7 @@ Symbol dispatch_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
if (return_type == SELF_TYPE) {
|
||||
return_type = expr_type;
|
||||
}
|
||||
this->type = return_type;
|
||||
return this->type;
|
||||
return (this->type = return_type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -924,8 +942,7 @@ Symbol loop_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< "Loop condition does not have type Bool.\n";
|
||||
}
|
||||
auto _ = this->body->semant(cur_class, classtable);
|
||||
this->type = Object;
|
||||
return Object;
|
||||
return (this->type = Object);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -939,8 +956,8 @@ Symbol typcase_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
auto _ = this->expr->semant(cur_class, classtable);
|
||||
std::set<Symbol> _existed_type;
|
||||
Symbol entire_type = nullptr;
|
||||
for (auto i = cases->first(); cases->more(i); i = cases->next(i)) {
|
||||
auto branch_i = static_cast<branch_class*>(cases->nth(i));
|
||||
for (auto i = this->cases->first(); this->cases->more(i); i = this->cases->next(i)) {
|
||||
auto branch_i = static_cast<branch_class*>(this->cases->nth(i));
|
||||
auto type_decl_i = branch_i->get_type_decl();
|
||||
auto name_i = branch_i->get_name();
|
||||
// first check duplicated type
|
||||
@ -957,12 +974,16 @@ Symbol typcase_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
if the type does not exist, it continue to use the undefined type
|
||||
for later expr typing
|
||||
*/
|
||||
if (name_i == self) {
|
||||
classtable->semant_error(cur_class->get_filename(), branch_i)
|
||||
<< "\'self\' bound in 'case'.\n";
|
||||
}
|
||||
if (type_decl_i == SELF_TYPE) {
|
||||
classtable->semant_error(cur_class->get_filename(), branch_i)
|
||||
<< "Identifier " << name_i
|
||||
<< " declared with type SELF_TYPE in case branch.\n";
|
||||
}
|
||||
else if (!classtable->class_exist(type_decl_i)) {
|
||||
else if (!classtable->class_defined(type_decl_i)) {
|
||||
classtable->semant_error(cur_class->get_filename(), branch_i)
|
||||
<< "Class " << type_decl_i
|
||||
<< " of case branch is undefined.\n";
|
||||
@ -980,8 +1001,7 @@ Symbol typcase_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
entire_type = classtable->lub(entire_type, branch_expr_type);
|
||||
}
|
||||
}
|
||||
this->type = entire_type;
|
||||
return this->type;
|
||||
return (this->type = entire_type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -991,11 +1011,10 @@ Symbol typcase_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
Symbol block_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
Symbol type_i;
|
||||
for (auto i = body->first(); body->more(i); i = body->next(i)) {
|
||||
type_i = body->nth(i)->semant(cur_class, classtable);
|
||||
for (auto i = this->body->first(); this->body->more(i); i = this->body->next(i)) {
|
||||
type_i = this->body->nth(i)->semant(cur_class, classtable);
|
||||
}
|
||||
this->type = type_i;
|
||||
return type_i;
|
||||
return (this->type = type_i);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1012,28 +1031,27 @@ Symbol let_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "\'self\' cannot be bound in a \'let\' expression.\n";
|
||||
}
|
||||
if (!classtable->class_exist_self(type_decl)) {
|
||||
if (!classtable->class_defined_self(this->type_decl)) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Class " << type_decl
|
||||
<< " of let-bound identifier " << identifier
|
||||
<< "Class " << this->type_decl
|
||||
<< " of let-bound identifier " << this->identifier
|
||||
<< " is undefined.\n";
|
||||
}
|
||||
if (typeid(*init) != typeid(no_expr_class)) {
|
||||
auto init_type = init->semant(cur_class, classtable);
|
||||
if (!classtable->conform_self(init_type, type_decl, cur_class)) {
|
||||
if (typeid(*this->init) != typeid(no_expr_class)) {
|
||||
auto init_type = this->init->semant(cur_class, classtable);
|
||||
if (!classtable->conform_self(init_type, this->type_decl, cur_class)) {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Inferred type " << init_type
|
||||
<< " of initialization of " << identifier
|
||||
<< " does not conform to identifier's declared type " << type_decl
|
||||
<< " of initialization of " << this->identifier
|
||||
<< " does not conform to identifier's declared type " << this->type_decl
|
||||
<< ".\n";
|
||||
}
|
||||
}
|
||||
classtable->symtab_obj(cur_class)->enterscope();
|
||||
classtable->symtab_obj(cur_class)->addid(identifier, type_decl);
|
||||
classtable->symtab_obj(cur_class)->addid(this->identifier, this->type_decl);
|
||||
auto expr_type = this->body->semant(cur_class, classtable);
|
||||
classtable->symtab_obj(cur_class)->exitscope();
|
||||
this->type = expr_type;
|
||||
return this->type;
|
||||
return (this->type = expr_type);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1050,8 +1068,7 @@ Symbol plus_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< " + " << e2_type
|
||||
<< "\n";
|
||||
}
|
||||
this->type = Int;
|
||||
return Int;
|
||||
return (this->type = Int);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1068,8 +1085,7 @@ Symbol sub_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< " - " << e2_type
|
||||
<< "\n";
|
||||
}
|
||||
this->type = Int;
|
||||
return Int;
|
||||
return (this->type = Int);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1086,8 +1102,7 @@ Symbol mul_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< " * " << e2_type
|
||||
<< "\n";
|
||||
}
|
||||
this->type = Int;
|
||||
return Int;
|
||||
return (this->type = Int);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1104,8 +1119,7 @@ Symbol divide_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< " / " << e2_type
|
||||
<< "\n";
|
||||
}
|
||||
this->type = Int;
|
||||
return Int;
|
||||
return (this->type = Int);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1120,8 +1134,7 @@ Symbol neg_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< "Argument of '~' has type " << type_subexpr
|
||||
<< " instead of Int.\n";
|
||||
}
|
||||
this->type = Int;
|
||||
return Int;
|
||||
return (this->type = Int);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1138,8 +1151,7 @@ Symbol lt_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< " < " << e2_type
|
||||
<< "\n";
|
||||
}
|
||||
this->type = Bool;
|
||||
return Bool;
|
||||
return (this->type = Bool);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1159,8 +1171,7 @@ Symbol eq_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Illegal comparison with a basic type.\n";
|
||||
}
|
||||
this->type = Bool;
|
||||
return Bool;
|
||||
return (this->type = Bool);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1177,8 +1188,7 @@ Symbol leq_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< " <= " << e2_type
|
||||
<< "\n";
|
||||
}
|
||||
this->type = Bool;
|
||||
return Bool;
|
||||
return (this->type = Bool);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1201,8 +1211,7 @@ Symbol comp_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
<< "Argument of 'not' has type " << type_subexpr
|
||||
<< " instead of Bool.\n";
|
||||
}
|
||||
this->type = Bool;
|
||||
return Bool;
|
||||
return (this->type = Bool);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1211,8 +1220,7 @@ Symbol comp_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
*/
|
||||
Symbol int_const_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
this->type = Int;
|
||||
return this->type;
|
||||
return (this->type = Int);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1221,8 +1229,7 @@ Symbol int_const_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
*/
|
||||
Symbol bool_const_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
this->type = Bool;
|
||||
return this->type;
|
||||
return (this->type = Bool);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1231,8 +1238,7 @@ Symbol bool_const_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
*/
|
||||
Symbol string_const_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
this->type = Str;
|
||||
return this->type;
|
||||
return (this->type = Str);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1248,13 +1254,13 @@ Symbol string_const_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
*/
|
||||
Symbol new__class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
if (classtable->class_exist_self(this->type_name)) {
|
||||
if (classtable->class_defined_self(this->type_name)) {
|
||||
this->type = this->type_name;
|
||||
}
|
||||
else {
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "\'new\' used with undefined class " << this->type_name
|
||||
<< ".\n";
|
||||
<< "\'new\' used with undefined class " << this->type_name
|
||||
<< ".\n";
|
||||
this->type = Object;
|
||||
}
|
||||
return this->type;
|
||||
@ -1267,8 +1273,7 @@ Symbol new__class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
Symbol isvoid_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
auto _ = this->e1->semant(cur_class, classtable);
|
||||
this->type = Bool;
|
||||
return Bool;
|
||||
return (this->type = Bool);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1289,20 +1294,13 @@ Symbol no_expr_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
*/
|
||||
Symbol object_class::semant(Class_ cur_class, ClassTable* classtable)
|
||||
{
|
||||
auto object_type = classtable->symtab_object_lookup_parent(cur_class, name);
|
||||
auto object_type = classtable->symtab_object_lookup_parent(cur_class, this->name);
|
||||
if (object_type != nullptr) {
|
||||
this->type = object_type;
|
||||
return object_type;
|
||||
return (this->type = object_type);
|
||||
}
|
||||
else {
|
||||
if (semant_debug) {
|
||||
std::cerr << "Cannot find " << name << " in Class " << classtable->class_to_name(cur_class) << "\n";
|
||||
classtable->symtab_obj(cur_class)->dump();
|
||||
std::cerr << "-------------------\n";
|
||||
}
|
||||
classtable->semant_error(cur_class->get_filename(), this)
|
||||
<< "Undeclared identifier " << name<< ".\n";
|
||||
this->type = Object;
|
||||
return Object;
|
||||
<< "Undeclared identifier " << this->name<< ".\n";
|
||||
return (this->type = Object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,32 +103,9 @@ public:
|
||||
class__class* get_class() {
|
||||
return static_cast<class__class*>(self);
|
||||
}
|
||||
|
||||
// static void traverse_iter(ClassGraphNode* root) {
|
||||
// auto cur_node = root;
|
||||
// std::vector<size_t> stk;
|
||||
// stk.push_back(0);
|
||||
// std::cout << pad((stk.size()-1) * 4) << cur_node->get_class()->get_name() << "\n";
|
||||
// while (!stk.empty()) {
|
||||
// if (cur_node->children.size() == stk.back()) {
|
||||
// // we have finished all the children
|
||||
// stk.pop_back();
|
||||
// cur_node = cur_node->parent;
|
||||
// continue;
|
||||
// }
|
||||
// auto next_idx = stk.back();
|
||||
// stk.pop_back();
|
||||
// stk.push_back(next_idx + 1);
|
||||
// cur_node = cur_node->children[next_idx];
|
||||
// std::cout << pad((stk.size()) * 2) << cur_node->get_class()->get_name() << "\n";
|
||||
// stk.push_back(0);
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
// First we need a tree-like struct to store inheritence relationship
|
||||
// Since class doesn't need to be defined before used, I guess first
|
||||
class ClassTable {
|
||||
private:
|
||||
int semant_errors;
|
||||
@ -153,6 +130,7 @@ private:
|
||||
|
||||
public:
|
||||
ClassTable(Classes);
|
||||
|
||||
/* helpers */
|
||||
void install_all_features();
|
||||
void symtab_dump(Symbol);
|
||||
@ -163,30 +141,15 @@ public:
|
||||
bool conform(Symbol, Symbol) const;
|
||||
bool conform_self(Symbol, Symbol, Symbol) const;
|
||||
bool conform_self(Symbol, Symbol, Class_) const;
|
||||
bool class_exist(Symbol) const;
|
||||
bool class_exist_self(Symbol) const;
|
||||
bool class_defined(Symbol) const;
|
||||
bool class_defined_self(Symbol) const;
|
||||
Symbol lub(Symbol, Symbol) const;
|
||||
Symbol lub(Symbol, Symbol, Symbol) const;
|
||||
static Symbol class_to_name(Class_ class_item) { return static_cast<class__class*>(class_item)->get_name(); }
|
||||
|
||||
/* wrappers */
|
||||
std::vector<class__class*>& class_vec() { return _class_vec; }
|
||||
SymbolTable<Symbol, Entry>* symtab_obj(Class_ class_i) const {
|
||||
auto class_id = static_cast<class__class*>(class_i)->get_name();
|
||||
auto _iter = _symtab_obj.find(class_id);
|
||||
if (_iter == _symtab_obj.end()) return nullptr;
|
||||
return _iter->second;
|
||||
};
|
||||
SymbolTable<Symbol, method_class>* symtab_met(Class_ class_i) const {
|
||||
auto class_id = static_cast<class__class*>(class_i)->get_name();
|
||||
auto _iter = _symtab_met.find(class_id);
|
||||
if (_iter == _symtab_met.end()) return nullptr;
|
||||
return _iter->second;
|
||||
};
|
||||
SymbolTable<Symbol, method_class>* symtab_met(Symbol class_id) const {
|
||||
auto _iter = _symtab_met.find(class_id);
|
||||
if (_iter == _symtab_met.end()) return nullptr;
|
||||
return _iter->second;
|
||||
};
|
||||
SymbolTable<Symbol, Entry>* symtab_obj(Class_ class_i) const;
|
||||
|
||||
int errors() { return semant_errors; }
|
||||
ostream& semant_error();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user