Skip to content

Instantly share code, notes, and snippets.

@ghaiklor
Created January 9, 2020 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghaiklor/97fdb62081932093ed9c4efb2d1a6686 to your computer and use it in GitHub Desktop.
Save ghaiklor/97fdb62081932093ed9c4efb2d1a6686 to your computer and use it in GitHub Desktop.
Semantic analysis phase for COOL language
#ifndef COOL_TREE_H
#define COOL_TREE_H
//////////////////////////////////////////////////////////
//
// file: cool-tree.h
//
// This file defines classes for each phylum and constructor
//
//////////////////////////////////////////////////////////
#include <typeinfo>
#include "tree.h"
#include "cool-tree.handcode.h"
#include "symtab.h"
#include <algorithm>
class Visitor;
class semanVisitor;
class ClassTable;
// define the class for phylum
// define simple phylum - Program
typedef class Program_class *Program;
class Program_class : public tree_node {
public:
tree_node *copy() {
return copy_Program();
}
virtual Program copy_Program() = 0;
void accept(Visitor *v);
#ifdef Program_EXTRAS
Program_EXTRAS
#endif
};
// define simple phylum - Class_
typedef class Class__class *Class_;
class Class__class : public tree_node {
public:
tree_node *copy() {
return copy_Class_();
}
virtual Class_ copy_Class_() = 0;
void accept(Visitor *v);
#ifdef Class__EXTRAS
Class__EXTRAS
#endif
};
// define simple phylum - Feature
typedef class Feature_class *Feature;
class Feature_class : public tree_node {
private:
bool is_method;
public:
tree_node *copy() {
return copy_Feature();
}
virtual Feature copy_Feature() = 0;
bool get_is_method () {
return is_method;
}
void set_is_method () {
is_method = true;
}
void set_is_attribute() {
is_method= false;
}
void accept(Visitor *v);
#ifdef Feature_EXTRAS
Feature_EXTRAS
#endif
};
// define simple phylum - Formal
typedef class Formal_class *Formal;
class Formal_class : public tree_node {
public:
tree_node *copy() {
return copy_Formal();
}
virtual Formal copy_Formal() = 0;
void accept(Visitor *v);
#ifdef Formal_EXTRAS
Formal_EXTRAS
#endif
};
// define simple phylum - Expression
typedef class Expression_class *Expression;
class Expression_class : public tree_node {
public:
tree_node *copy() {
return copy_Expression();
}
virtual Expression copy_Expression() = 0;
void accept(Visitor *v);
#ifdef Expression_EXTRAS
Expression_EXTRAS
#endif
};
// define simple phylum - Case
typedef class Case_class *Case;
class Case_class : public tree_node {
public:
tree_node *copy() {
return copy_Case();
}
virtual Case copy_Case() = 0;
void accept(Visitor *v);
#ifdef Case_EXTRAS
Case_EXTRAS
#endif
};
// define the class for phylum - LIST
// define list phlyum - Classes
typedef list_node<Class_> Classes_class;
typedef Classes_class *Classes;
// define list phlyum - Features
typedef list_node<Feature> Features_class;
typedef Features_class *Features;
// define list phlyum - Formals
typedef list_node<Formal> Formals_class;
typedef Formals_class *Formals;
// define list phlyum - Expressions
typedef list_node<Expression> Expressions_class;
typedef Expressions_class *Expressions;
// define list phlyum - Cases
typedef list_node<Case> Cases_class;
typedef Cases_class *Cases;
// define the class for constructors
// define constructor - program
class program_class : public Program_class {
protected:
Classes classes;
public:
program_class(Classes a1) {
classes = a1;
}
Program copy_Program();
void dump(ostream& stream, int n);
Classes getClasses() {
return classes;
}
void accept(Visitor *v);
private:
semanVisitor *sv;
bool OcurredExpection;
#ifdef Program_SHARED_EXTRAS
Program_SHARED_EXTRAS
#endif
#ifdef program_EXTRAS
program_EXTRAS
#endif
};
// define constructor - class_
class class__class : public Class__class {
protected:
Symbol name;
Symbol parent;
Features features;
Symbol filename;
public:
class__class(Symbol a1, Symbol a2, Features a3, Symbol a4) {
name = a1;
parent = a2;
features = a3;
filename = a4;
parent_feature_list = new nil_node<Feature>();
}
Features parent_feature_list ;
Class_ copy_Class_();
void dump(ostream& stream, int n);
Symbol get_name() {
return name;
}
Symbol get_parent() {
return parent;
}
Features get_features() {
return features;
}
void accept(Visitor *v);
void add_parentMembers(Visitor *v, Features &features);
#ifdef Class__SHARED_EXTRAS
Class__SHARED_EXTRAS
#endif
#ifdef class__EXTRAS
class__EXTRAS
#endif
};
// define constructor - method
class method_class : public Feature_class {
protected:
Symbol name;
Formals formals;
Symbol return_type;
Expression expr;
public:
method_class(Symbol a1, Formals a2, Symbol a3, Expression a4) {
name = a1;
formals = a2;
return_type = a3;
expr = a4;
set_is_method();
}
Feature copy_Feature();
void dump(ostream& stream, int n);
void accept(Visitor *v);
Symbol get_name() {
return name;
}
Formals get_formals() {
return formals;
}
Symbol get_return_type() {
return return_type;
}
Expression get_expr() {
return expr;
}
#ifdef Feature_SHARED_EXTRAS
Feature_SHARED_EXTRAS
#endif
#ifdef method_EXTRAS
method_EXTRAS
#endif
};
// define constructor - attr
class attr_class : public Feature_class {
protected:
Symbol name;
Symbol type_decl;
Expression init;
public:
attr_class(Symbol a1, Symbol a2, Expression a3) {
name = a1;
type_decl = a2;
init = a3;
set_is_attribute();
}
Feature copy_Feature();
void dump(ostream& stream, int n);
void accept(Visitor *v);
Symbol get_name() {
return name;
}
Symbol get_type_decl() {
return type_decl;
}
Expression get_init() {
return init;
}
#ifdef Feature_SHARED_EXTRAS
Feature_SHARED_EXTRAS
#endif
#ifdef attr_EXTRAS
attr_EXTRAS
#endif
};
// define constructor - formal
class formal_class : public Formal_class {
protected:
Symbol name;
Symbol type_decl;
public:
formal_class(Symbol a1, Symbol a2) {
name = a1;
type_decl = a2;
}
Formal copy_Formal();
void dump(ostream& stream, int n);
void accept(Visitor *v);
Symbol get_name() {
return name;
}
Symbol get_type_decl() {
return type_decl;
}
#ifdef Formal_SHARED_EXTRAS
Formal_SHARED_EXTRAS
#endif
#ifdef formal_EXTRAS
formal_EXTRAS
#endif
};
// define constructor - branch
class branch_class : public Case_class {
protected:
Symbol name;
Symbol type_decl;
Expression expr;
public:
branch_class(Symbol a1, Symbol a2, Expression a3) {
name = a1;
type_decl = a2;
expr = a3;
}
Case copy_Case();
void dump(ostream& stream, int n);
Symbol get_name() {
return name;
}
Symbol get_type_decl() {
return type_decl;
}
Expression get_expr() {
return expr;
}
void accept(Visitor *v);
#ifdef Case_SHARED_EXTRAS
Case_SHARED_EXTRAS
#endif
#ifdef branch_EXTRAS
branch_EXTRAS
#endif
};
// define constructor - assign
class assign_class : public Expression_class {
protected:
Symbol name;
Expression expr;
public:
assign_class(Symbol a1, Expression a2) {
name = a1;
expr = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Symbol get_name() {
return name;
}
Expression get_expr() {
return expr;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef assign_EXTRAS
assign_EXTRAS
#endif
};
// define constructor - static_dispatch
class static_dispatch_class : public Expression_class {
protected:
Expression expr;
Symbol type_name;
Symbol name;
Expressions actual;
public:
static_dispatch_class(Expression a1, Symbol a2, Symbol a3, Expressions a4) {
expr = a1;
type_name = a2;
name = a3;
actual = a4;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_expr() {
return expr;
}
Symbol get_type_name() {
return type_name;
}
Symbol get_name() {
return name;
}
Expressions get_actual() {
return actual;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef static_dispatch_EXTRAS
static_dispatch_EXTRAS
#endif
};
// define constructor - dispatch
class dispatch_class : public Expression_class {
protected:
Expression expr;
Symbol name;
Expressions actual;
public:
dispatch_class(Expression a1, Symbol a2, Expressions a3) {
expr = a1;
name = a2;
actual = a3;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_expr() {
return expr;
}
Symbol get_name() {
return name;
}
Expressions get_actual() {
return actual;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef dispatch_EXTRAS
dispatch_EXTRAS
#endif
};
// define constructor - cond
class cond_class : public Expression_class {
protected:
Expression pred;
Expression then_exp;
Expression else_exp;
public:
cond_class(Expression a1, Expression a2, Expression a3) {
pred = a1;
then_exp = a2;
else_exp = a3;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_pred() {
return pred;
}
Expression get_then_exp() {
return then_exp;
}
Expression get_else_exp() {
return else_exp;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef cond_EXTRAS
cond_EXTRAS
#endif
};
// define constructor - loop
class loop_class : public Expression_class {
protected:
Expression pred;
Expression body;
public:
loop_class(Expression a1, Expression a2) {
pred = a1;
body = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_pred() {
return pred;
}
Expression get_body() {
return body;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef loop_EXTRAS
loop_EXTRAS
#endif
};
// define constructor - typcase
class typcase_class : public Expression_class {
protected:
Expression expr;
Cases cases;
public:
typcase_class(Expression a1, Cases a2) {
expr = a1;
cases = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_expr() {
return expr;
}
Cases get_cases() {
return cases;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef typcase_EXTRAS
typcase_EXTRAS
#endif
};
// define constructor - block
class block_class : public Expression_class {
protected:
Expressions body;
public:
block_class(Expressions a1) {
body = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expressions get_body() {
return body;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef block_EXTRAS
block_EXTRAS
#endif
};
// define constructor - let
class let_class : public Expression_class {
protected:
Symbol identifier;
Symbol type_decl;
Expression init;
Expression body;
public:
let_class(Symbol a1, Symbol a2, Expression a3, Expression a4) {
identifier = a1;
type_decl = a2;
init = a3;
body = a4;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Symbol get_identifier() {
return identifier;
}
Symbol get_type_decl() {
return type_decl;
}
Expression get_init() {
return init;
}
Expression get_body() {
return body;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef let_EXTRAS
let_EXTRAS
#endif
};
// define constructor - plus
class plus_class : public Expression_class {
protected:
Expression e1;
Expression e2;
public:
plus_class(Expression a1, Expression a2) {
e1 = a1;
e2 = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
Expression get_e2() {
return e2;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef plus_EXTRAS
plus_EXTRAS
#endif
};
// define constructor - sub
class sub_class : public Expression_class {
protected:
Expression e1;
Expression e2;
public:
sub_class(Expression a1, Expression a2) {
e1 = a1;
e2 = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
Expression get_e2() {
return e2;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef sub_EXTRAS
sub_EXTRAS
#endif
};
// define constructor - mul
class mul_class : public Expression_class {
protected:
Expression e1;
Expression e2;
public:
mul_class(Expression a1, Expression a2) {
e1 = a1;
e2 = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
Expression get_e2() {
return e2;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef mul_EXTRAS
mul_EXTRAS
#endif
};
// define constructor - divide
class divide_class : public Expression_class {
protected:
Expression e1;
Expression e2;
public:
divide_class(Expression a1, Expression a2) {
e1 = a1;
e2 = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
Expression get_e2() {
return e2;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef divide_EXTRAS
divide_EXTRAS
#endif
};
// define constructor - neg
class neg_class : public Expression_class {
protected:
Expression e1;
public:
neg_class(Expression a1) {
e1 = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef neg_EXTRAS
neg_EXTRAS
#endif
};
// define constructor - lt
class lt_class : public Expression_class {
protected:
Expression e1;
Expression e2;
public:
lt_class(Expression a1, Expression a2) {
e1 = a1;
e2 = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
Expression get_e2() {
return e2;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef lt_EXTRAS
lt_EXTRAS
#endif
};
// define constructor - eq
class eq_class : public Expression_class {
protected:
Expression e1;
Expression e2;
public:
eq_class(Expression a1, Expression a2) {
e1 = a1;
e2 = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
Expression get_e2() {
return e2;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef eq_EXTRAS
eq_EXTRAS
#endif
};
// define constructor - leq
class leq_class : public Expression_class {
protected:
Expression e1;
Expression e2;
public:
leq_class(Expression a1, Expression a2) {
e1 = a1;
e2 = a2;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
Expression get_e2() {
return e2;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef leq_EXTRAS
leq_EXTRAS
#endif
};
// define constructor - comp
class comp_class : public Expression_class {
protected:
Expression e1;
public:
comp_class(Expression a1) {
e1 = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef comp_EXTRAS
comp_EXTRAS
#endif
};
// define constructor - int_const
class int_const_class : public Expression_class {
protected:
Symbol token;
public:
int_const_class(Symbol a1) {
token = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Symbol get_token() {
return token;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef int_const_EXTRAS
int_const_EXTRAS
#endif
};
// define constructor - bool_const
class bool_const_class : public Expression_class {
protected:
Boolean val;
public:
bool_const_class(Boolean a1) {
val = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Boolean get_val() {
return val;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef bool_const_EXTRAS
bool_const_EXTRAS
#endif
};
// define constructor - string_const
class string_const_class : public Expression_class {
protected:
Symbol token;
public:
string_const_class(Symbol a1) {
token = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Symbol get_token() {
return token;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef string_const_EXTRAS
string_const_EXTRAS
#endif
};
// define constructor - new_
class new__class : public Expression_class {
protected:
Symbol type_name;
public:
new__class(Symbol a1) {
type_name = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Symbol get_type_name() {
return type_name;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef new__EXTRAS
new__EXTRAS
#endif
};
// define constructor - isvoid
class isvoid_class : public Expression_class {
protected:
Expression e1;
public:
isvoid_class(Expression a1) {
e1 = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Expression get_e1() {
return e1;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef isvoid_EXTRAS
isvoid_EXTRAS
#endif
};
// define constructor - no_expr
class no_expr_class : public Expression_class {
protected:
public:
no_expr_class() {
}
Expression copy_Expression();
void dump(ostream& stream, int n);
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef no_expr_EXTRAS
no_expr_EXTRAS
#endif
};
// define constructor - object
class object_class : public Expression_class {
protected:
Symbol name;
public:
object_class(Symbol a1) {
name = a1;
}
Expression copy_Expression();
void dump(ostream& stream, int n);
Symbol get_name() {
return name;
}
void accept(Visitor *v);
#ifdef Expression_SHARED_EXTRAS
Expression_SHARED_EXTRAS
#endif
#ifdef object_EXTRAS
object_EXTRAS
#endif
};
class Visitor {
public:
virtual void visit(Program e)=0;
virtual void visit(Class_ e)=0;
virtual void visit(Feature e)=0;
virtual void visit(Formal)=0;
virtual void visit(Expression e)=0;
virtual void visit(Case e)=0;
virtual void visit(program_class *e)=0;
virtual void visit(class__class *e)=0;
virtual void visit(method_class *e)=0;
virtual void visit(attr_class *e)=0;
virtual void visit(formal_class *e)=0;
virtual void visit(branch_class *e)=0;
virtual void visit(assign_class *e)=0;
virtual void visit(static_dispatch_class *e)=0;
virtual void visit(dispatch_class *e)=0;
virtual void visit(cond_class *e)=0;
virtual void visit(loop_class *e)=0;
virtual void visit(typcase_class *e)=0;
virtual void visit(block_class *e)=0;
virtual void visit(let_class *e)=0;
virtual void visit(plus_class *e)=0;
virtual void visit(sub_class *e)=0;
virtual void visit(mul_class *e)=0;
virtual void visit(divide_class *e)=0;
virtual void visit(neg_class *e)=0;
virtual void visit(lt_class *e)=0;
virtual void visit(eq_class *e)=0;
virtual void visit(leq_class *e)=0;
virtual void visit(comp_class *e)=0;
virtual void visit(int_const_class *e)=0;
virtual void visit(bool_const_class *e)=0;
virtual void visit(string_const_class *e)=0;
virtual void visit(new__class *e)=0;
virtual void visit(isvoid_class *e)=0;
virtual void visit(no_expr_class *e)=0;
virtual void visit(object_class *e)=0;
virtual void enterscope()=0;
virtual void exitscope()=0;
};
class semanVisitor: public Visitor
{
public:
SymbolTable<Symbol, tree_node> *symtable_o;
SymbolTable<Symbol, tree_node> *symtable_m;
ClassTable *classTable;
semanVisitor(ClassTable *ct) {
symtable_o=new SymbolTable<Symbol, tree_node>();
symtable_m=new SymbolTable<Symbol, tree_node>();
classTable = ct;
}
void getSymbolTableO() {
symtable_o->dump();
}
void getSymbolTableM() {
symtable_m->dump();
}
void enterscope() {
symtable_o->enterscope();
symtable_m->enterscope();
}
void exitscope() {
symtable_o->exitscope();
symtable_m->exitscope();
}
void addId(Symbol s, tree_node *i, bool is_method)
{
if(is_method)
symtable_m->addid(s, i);
else
symtable_o->addid(s,i);
}
tree_node * probeMethod(Symbol s) {
return symtable_m->probe(s);
}
tree_node * probeObject(Symbol s) {
return symtable_o->probe(s);
}
tree_node * lookupMethod(Symbol s) {
return symtable_m->lookup(s);
}
tree_node * lookupObject(Symbol s) {
return symtable_o->lookup(s);
}
void visit(Program e);
void visit(Class_ e);
void visit(Feature e);
void visit(Formal);
void visit(Expression e);
void visit(Case e);
void visit(program_class *e);
void visit(class__class *e);
void visit(method_class *e);
void visit(attr_class *e);
void visit(formal_class *e);
void visit(branch_class *e);
void visit(assign_class *e);
void visit(static_dispatch_class *e);
void visit(dispatch_class *e);
void visit(cond_class *e);
void visit(loop_class *e);
void visit(typcase_class *e);
void visit(block_class *e);
void visit(let_class *e);
void visit(plus_class *e);
void visit(sub_class *e);
void visit(mul_class *e);
void visit(divide_class *e);
void visit(neg_class *e);
void visit(lt_class *e);
void visit(eq_class *e);
void visit(leq_class *e);
void visit(comp_class *e);
void visit(int_const_class *e);
void visit(bool_const_class *e);
void visit(string_const_class *e);
void visit(new__class *e);
void visit(isvoid_class *e);
void visit(no_expr_class *e);
void visit(object_class *e);
private:
class__class* currentClass;
};
// define the prototypes of the interface
Classes nil_Classes();
Classes single_Classes(Class_);
Classes append_Classes(Classes, Classes);
Features nil_Features();
Features single_Features(Feature);
Features append_Features(Features, Features);
Formals nil_Formals();
Formals single_Formals(Formal);
Formals append_Formals(Formals, Formals);
Expressions nil_Expressions();
Expressions single_Expressions(Expression);
Expressions append_Expressions(Expressions, Expressions);
Cases nil_Cases();
Cases single_Cases(Case);
Cases append_Cases(Cases, Cases);
Program program(Classes);
Class_ class_(Symbol, Symbol, Features, Symbol);
Feature method(Symbol, Formals, Symbol, Expression);
Feature attr(Symbol, Symbol, Expression);
Formal formal(Symbol, Symbol);
Case branch(Symbol, Symbol, Expression);
Expression assign(Symbol, Expression);
Expression static_dispatch(Expression, Symbol, Symbol, Expressions);
Expression dispatch(Expression, Symbol, Expressions);
Expression cond(Expression, Expression, Expression);
Expression loop(Expression, Expression);
Expression typcase(Expression, Cases);
Expression block(Expressions);
Expression let(Symbol, Symbol, Expression, Expression);
Expression plus(Expression, Expression);
Expression sub(Expression, Expression);
Expression mul(Expression, Expression);
Expression divide(Expression, Expression);
Expression neg(Expression);
Expression lt(Expression, Expression);
Expression eq(Expression, Expression);
Expression leq(Expression, Expression);
Expression comp(Expression);
Expression int_const(Symbol);
Expression bool_const(Boolean);
Expression string_const(Symbol);
Expression new_(Symbol);
Expression isvoid(Expression);
Expression no_expr();
Expression object(Symbol);
#endif
// Copyright songhan
// I've tried for few days implementig semantic analysis
// but it it too hard for me (at the current moment)
// So I took the implementation from here - https://github.com/songhan/CS143/tree/master/assignment3
// There is no my work here, but for consistence I save it here in gist anyway
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "semant.h"
#include "utilities.h"
#include "typeinfo"
#include <queue>
#include <vector>
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wsign-compare"
extern int semant_debug;
extern char *curr_filename;
//////////////////////////////////////////////////////////////////////
//
// Symbols
//
// For convenience, a large number of symbols are predefined here.
// These symbols include the primitive type and method names, as well
// as fixed names used by the runtime system.
//
//////////////////////////////////////////////////////////////////////
static Symbol
arg,
arg2,
Bool,
concat,
cool_abort,
copy,
Int,
in_int,
in_string,
IO,
length,
Main,
main_meth,
No_class,
No_type,
Object,
out_int,
out_string,
prim_slot,
self,
SELF_TYPE,
Str,
str_field,
substr,
type_name,
val;
//
// Initializing the predefined symbols.
//
static void initialize_constants(void)
{
arg = idtable.add_string("arg");
arg2 = idtable.add_string("arg2");
Bool = idtable.add_string("Bool");
concat = idtable.add_string("concat");
cool_abort = idtable.add_string("abort");
copy = idtable.add_string("copy");
Int = idtable.add_string("Int");
in_int = idtable.add_string("in_int");
in_string = idtable.add_string("in_string");
IO = idtable.add_string("IO");
length = idtable.add_string("length");
Main = idtable.add_string("Main");
main_meth = idtable.add_string("main");
// _no_class is a symbol that can't be the name of any
// user-defined class.
No_class = idtable.add_string("_no_class");
No_type = idtable.add_string("_no_type");
Object = idtable.add_string("Object");
out_int = idtable.add_string("out_int");
out_string = idtable.add_string("out_string");
prim_slot = idtable.add_string("_prim_slot");
self = idtable.add_string("self");
SELF_TYPE = idtable.add_string("SELF_TYPE");
Str = idtable.add_string("String");
str_field = idtable.add_string("_str_field");
substr = idtable.add_string("substr");
type_name = idtable.add_string("type_name");
val = idtable.add_string("_val");
}
ClassTable::ClassTable(Classes classes) : semant_errors(0) , error_stream(cerr) {
install_basic_classes();
install_user_classes(classes);
check_cycle();
if(cycle_found)
{
cerr<<"Cycle found in inheritance graph!"<<endl;
fatal();
}
install_method_map();
}
/* Methods for ClassTable */
bool ClassTable::class_exist(Symbol c)
{
return (class_map.count(c) > 0);
}
std::vector<Symbol> ClassTable::get_signature(Symbol class_name, Symbol method_name)
{
std::vector<Symbol> sig;
if (method_map.count(class_name)==0)
semant_error()<<" No class_name found"<<endl;
else if (method_map[class_name].count(method_name)==0)
semant_error()<<" No method_name found"<<endl;
else
{
method_class* m = method_map[class_name][method_name];
Formals formals = m->get_formals();
//add formals' types:
for(int i = formals->first(); formals->more(i); i = formals->next(i))
{
formal_class *fm = (formal_class *)formals->nth(i);
sig.push_back(fm->get_type_decl());
}
// add return type:
sig.push_back(m->get_return_type());
}
return sig;
}
void ClassTable::verify_signature( class__class* cls, method_class* m )
{
Formals formals = m->get_formals();
// iterater through the formal list to check each can't be self or SELF_TYPE
for (int i = formals->first(); formals->more(i); i = formals->next(i))
{
formal_class* fm = (formal_class *) formals->nth(i);
//formal list shouldn't have self
if(fm->get_name() == self)
semant_error((cls->get_filename()), m)<<"formal list shouldn't have self "<<endl;
//formal list shouldn't have SELF_TYPE
if(fm->get_name() == SELF_TYPE)
semant_error((cls->get_filename()), m)<<"formal list shouldn't have SELF_TYPE "<<endl;
}
//check the return type should be an already defined class
if (class_map[m->get_return_type()] == NULL && m->get_return_type() != SELF_TYPE)
semant_error((cls->get_filename()), m)<<" return type not defined in method "<< m->get_name()<<endl;
}
bool ClassTable::method_exist(Symbol class_name, Symbol method_name)
{
bool exist=true;
if (method_map.count(class_name)==0)
exist = false;
else if (method_map[class_name].count(method_name)==0)
exist = false;
return exist;
}
method_class* ClassTable::get_method(Symbol class_name, Symbol method_name)
{
return method_map[class_name][method_name];
}
void ClassTable::install_basic_classes() {
// The tree package uses these globals to annotate the classes built below.
// curr_lineno = 0;
Symbol filename = stringtable.add_string("<basic class>");
// The following demonstrates how to create dummy parse trees to
// refer to basic Cool classes. There's no need for method
// bodies -- these are already built into the runtime system.
// IMPORTANT: The results of the following expressions are
// stored in local variables. You will want to do something
// with those variables at the end of this method to make this
// code meaningful.
//
// The Object class has no parent class. Its methods are
// abort() : Object aborts the program
// type_name() : Str returns a string representation of class name
// copy() : SELF_TYPE returns a copy of the object
//
// There is no need for method bodies in the basic classes---these
// are already built in to the runtime system.
Class_ Object_class =
class_(Object,
No_class,
append_Features(
append_Features(
single_Features(method(cool_abort, nil_Formals(), Object, no_expr())),
single_Features(method(type_name, nil_Formals(), Str, no_expr()))),
single_Features(method(copy, nil_Formals(), SELF_TYPE, no_expr()))),
filename);
//
// The IO class inherits from Object. Its methods are
// out_string(Str) : SELF_TYPE writes a string to the output
// out_int(Int) : SELF_TYPE " an int " " "
// in_string() : Str reads a string from the input
// in_int() : Int " an int " " "
//
Class_ IO_class =
class_(IO,
Object,
append_Features(
append_Features(
append_Features(
single_Features(method(out_string, single_Formals(formal(arg, Str)),
SELF_TYPE, no_expr())),
single_Features(method(out_int, single_Formals(formal(arg, Int)),
SELF_TYPE, no_expr()))),
single_Features(method(in_string, nil_Formals(), Str, no_expr()))),
single_Features(method(in_int, nil_Formals(), Int, no_expr()))),
filename);
//
// The Int class has no methods and only a single attribute, the
// "val" for the integer.
//
Class_ Int_class =
class_(Int,
Object,
single_Features(attr(val, prim_slot, no_expr())),
filename);
//
// Bool also has only the "val" slot.
//
Class_ Bool_class =
class_(Bool, Object, single_Features(attr(val, prim_slot, no_expr())),filename);
//
// The class Str has a number of slots and operations:
// val the length of the string
// str_field the string itself
// length() : Int returns length of the string
// concat(arg: Str) : Str performs string concatenation
// substr(arg: Int, arg2: Int): Str substring selection
//
Class_ Str_class =
class_(Str,
Object,
append_Features(
append_Features(
append_Features(
append_Features(
single_Features(attr(val, Int, no_expr())),
single_Features(attr(str_field, prim_slot, no_expr()))),
single_Features(method(length, nil_Formals(), Int, no_expr()))),
single_Features(method(concat,
single_Formals(formal(arg, Str)),
Str,
no_expr()))),
single_Features(method(substr,
append_Formals(single_Formals(formal(arg, Int)),
single_Formals(formal(arg2, Int))),
Str,
no_expr()))),
filename);
//add these basic class names:
basic_class_set.insert(Object);
basic_class_set.insert(IO);
basic_class_set.insert(Int);
basic_class_set.insert(Bool);
basic_class_set.insert(Str);
basic_class_set.insert(SELF_TYPE); //TODO: is this needed?
//add these class mapping from name to class:
class_map.insert(std::make_pair(Object, (class__class *)Object_class));
class_map.insert(std::make_pair(IO, (class__class *)IO_class));
class_map.insert(std::make_pair(Int, (class__class *)Int_class));
class_map.insert(std::make_pair(Bool, (class__class *)Bool_class));
class_map.insert(std::make_pair(Str, (class__class *)Str_class));
//populate the inherit graph with the basic classes:
inherit_graph[No_class].insert(Object);
inherit_graph[Object].insert(IO);
inherit_graph[Object].insert(Int);
inherit_graph[Object].insert(Bool);
inherit_graph[Object].insert(Str);
}
void ClassTable::install_user_classes( Classes classes )
{
bool contains_main = false;
for (int i = classes->first(); classes->more(i); i = classes->next(i))
{
//iterate over all the classes: cls
class__class* cls = (class__class *) classes->nth(i);
//cout<<"adding class "<<cls->get_name()<<endl;
//check class redefinition:
if(class_map.count(cls->get_name())) {
semant_error(cls->get_filename(), cls)<<"Class "<<cls->get_name()<<" was previously defined"<<endl;
fatal();
}
//check basic class redefinition:
if(basic_class_set.count(cls->get_name())) {
semant_error(cls->get_filename(), cls)<<"Redefinition of basic class "<<cls->get_name()<<endl;
fatal();
}
//if Main class exist
if(cls->get_name() == Main)
contains_main = true;
//populate the class map with current class cls
class_map.insert(std::make_pair(cls->get_name(), cls));
}
if (!contains_main)
semant_error()<<"Class Main is not defined."<<endl;
//print_class_map();
// second iteration: begin insert the parent-child:
for (int i = classes->first(); classes->more(i); i = classes->next(i))
{
class__class * cls = (class__class *) classes->nth(i);
Symbol parent = cls->get_parent();
// inherit from basic class
if( parent == Int || parent == Str || parent == Bool ) {
semant_error(cls->get_filename(), cls)<<"class "<<cls->get_name()<<" can't inherit class "<<parent<<endl;
fatal();
}
// inherit from SELF_TYPE
if ( parent == SELF_TYPE ) {
semant_error(cls->get_filename(), cls)<<"class "<<cls->get_name()<<" can't inherit from SELF_TYPE"<<endl;
fatal();
}
// inherit from non-existing parent
if ( class_map.count(parent)==0 ) {
semant_error(cls->get_filename(), cls)<<"class "<<cls->get_name()<<" inheriting from non-existing parent"<<endl;
fatal();
}
// Finally add the child to the parent key in the inherit graph
inherit_graph[parent].insert(cls->get_name());
}
//To debug least upper bound:
//Symbol c1, c2, common;
//for (int i = classes->first(); classes->more(i); i = classes->next(i))
//{
// class__class * cls = (class__class *) classes->nth(i);
// // To debug is_child:
// // //cout<<cls->get_name()<<" is child of Oject: "<<is_child(cls->get_name(), Object)<<endl;
// if (!strcmp(cls->get_name()->get_string(),"D7"))
// c1=cls->get_name();
// if (!strcmp(cls->get_name()->get_string(),"D5"))
// c2=cls->get_name();
//}
//common = least_upper_bound(c1, c2);
////cout<<c1<<" and "<<c2<<" is commoned at "<<common<<endl;
}
void ClassTable::install_method_map()
{
bool main_found = false;
bool main_has_formal = false;
std::queue<Symbol> q;
q.push(Object);
Symbol c;
// BFS all the classes
while ( !q.empty() )
{
c = q.front();
//cout<<"install method for class "<<c<<endl;
q.pop();
// for each class, get the features
Features features = class_map[c]->get_features();
for(int i = features->first(); features->more(i); i = features->next(i))
{
Feature f = features->nth(i);
if (f->get_is_method())
{
method_class* m = (method_class*)f;
verify_signature(class_map[c], m);
method_map[c][m->get_name()]=m;
if (c==Main && m->get_name()==main_meth)
{
main_found = true;
if (m->get_formals()->len()>0)
main_has_formal = true;
}
}
}
//also add features from parent class:
std::map<Symbol, method_class*> parent_methods =
method_map[class_map[c]->get_parent()];
std::map<Symbol, method_class*>::iterator iter;
for (iter=parent_methods.begin(); iter!=parent_methods.end(); ++iter)
{
if (method_map[c].count(iter->first) == 0 )
method_map[c][iter->first]= iter->second;
}
std::set<Symbol> child_class = inherit_graph[c];
std::set<Symbol>::iterator iter2;
for(iter2= child_class.begin(); iter2!= child_class.end(); ++iter2)
q.push(*iter2) ;
}
if (!main_found)
// semant_error(class_map[c]->get_filename(), class_map[c])<<" No main method found"<<endl;
if (main_has_formal)
semant_error(class_map[c]->get_filename(), class_map[c])<<" main method shouldn't have formals"<<endl;
}
class__class* ClassTable::get_parent( Symbol class_name )
{
class__class *cls = (class__class *) class_map[class_name];
return class_map[cls->get_parent()];
}
bool ClassTable::is_child (Symbol c, Symbol p)
{
////cout<<"is child called"<<endl;
bool c_is_child = false;
std::map<Symbol, int> visited_map;
std::map<Symbol, std::set<Symbol> > ::iterator iter;
std::set<Symbol>::iterator iter2;
// set visited color to all zero
for (iter = inherit_graph.begin(); iter != inherit_graph.end(); ++iter)
{
visited_map[iter->first] = 0;
for (iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2)
visited_map[*iter2] = 0;
}
DFS_is_child(visited_map, c, p, c_is_child);
return c_is_child;
}
void ClassTable::DFS_is_child(std::map<Symbol, int> visited_map, Symbol c, Symbol p, bool &c_is_child)
{
//visit p
if (p == c)
c_is_child = true;
// mark p as visited
visited_map[p] = 1;
// recursively visit p's child
for (std::set<Symbol>::iterator iter = inherit_graph[p].begin(); iter != inherit_graph[p].end(); ++iter)
{
if (visited_map[*iter] == 0)
DFS_is_child(visited_map, c, *iter, c_is_child);
}
}
void ClassTable::check_cycle()
{
cycle_found = false;
std::map<Symbol, int> visited_map;
std::map<Symbol, std::set<Symbol> > ::iterator iter;
std::set<Symbol>::iterator iter2;
// set visited color to all zero
for (iter = inherit_graph.begin(); iter != inherit_graph.end(); ++iter)
{
visited_map[iter->first] = 0;
for (iter2 = iter->second.begin(); iter2 != iter->second.end(); ++iter2)
visited_map[*iter2] = 0;
}
for (iter = inherit_graph.begin(); iter != inherit_graph.end(); ++iter)
{
DFS_has_cycle(visited_map, iter->first);
if (cycle_found)
break;
}
}
void ClassTable::DFS_has_cycle(std::map<Symbol, int> visited_map, Symbol c)
{
visited_map[c] = -1;
for (std::set<Symbol>::iterator iter = inherit_graph[c].begin(); iter != inherit_graph[c].end(); ++iter)
{
if(visited_map[*iter] == -1)
cycle_found = true;
else if (visited_map[*iter] == 0)
DFS_has_cycle(visited_map, *iter);
}
visited_map[c] = 1;
}
Symbol ClassTable::least_upper_bound(Symbol c1, Symbol c2)
{
bool is_upper_bound = true;
Symbol head = Object;
std::set<Symbol>::iterator iter;
while (is_upper_bound == true)
{
is_upper_bound = false;
for (iter = inherit_graph[head].begin(); iter != inherit_graph[head].end(); ++iter)
{
if ( is_child(c1, *iter) && is_child(c2, *iter))
{
is_upper_bound = true;
head = *iter;
break;
}
}
}
return head;
}
void ClassTable::print_inherit_map()
{
std::map<Symbol, std::set<Symbol> > ::iterator iter1;
std::set<Symbol>::iterator iter2;
for (iter1=inherit_graph.begin(); iter1!=inherit_graph.end(); ++iter1)
{
//cout<<"Parent: "<<iter1->first<<" -> ";
for (iter2=iter1->second.begin(); iter2!=iter1->second.end(); ++iter2)
{
//cout<<(*iter2)<<", " ;
}
//cout<<endl;
}
}
void ClassTable::print_class_map()
{
//cout<<endl<<"printing the class_map"<<endl;
std::map<Symbol, class__class *>::iterator iter;
for( iter = class_map.begin(); iter != class_map.end(); ++iter ) ;
////cout<<iter->first<<endl;
//////cout<<endl;
}
////////////////////////////////////////////////////////////////////
//
// semant_error is an overloaded function for reporting errors
// during semantic analysis. There are three versions:
//
// ostream& ClassTable::semant_error()
//
// ostream& ClassTable::semant_error(Class_ c)
// print line number and filename for `c'
//
// ostream& ClassTable::semant_error(Symbol filename, tree_node *t)
// print a line number and filename
//
///////////////////////////////////////////////////////////////////
ostream& ClassTable::semant_error(Class_ c)
{
return semant_error(c->get_filename(),c);
}
ostream& ClassTable::semant_error(Symbol filename, tree_node *t)
{
error_stream << filename << ":" << t->get_line_number() << ": ";
return semant_error();
}
ostream& ClassTable::semant_error()
{
semant_errors++;
return error_stream;
}
void ClassTable::fatal()
{
cerr<<"Compilation halted due to static semantic errors."<<endl;
exit(1);
}
/* This is the entry point to the semantic checker.
Your checker should do the following two things:
1) Check that the program is semantically correct
2) Decorate the abstract syntax tree with type information
by setting the `type' field in each Expression node.
(see `tree.h')
You are free to first do 1), make sure you catch all semantic
errors. Part 2) can be done in a second stage, when you want
to build mycoolc.
*/
/* This is the entry point to the semantic checker.
Your checker should do the following two things:
1) Check that the program is semantically correct
2) Decorate the abstract syntax tree with type information
by setting the `type' field in each Expression node.
(see `tree.h')
You are free to first do 1), make sure you catch all semantic
errors. Part 2) can be done in a second stage, when you want
to build mycoolc.
*/
void program_class::semant()
{
initialize_constants();
/* ClassTable constructor may do some semantic analysis */
/* some semantic analysis code may go here */
ClassTable *classTable = new ClassTable(classes);
OcurredExpection = false;
sv = new semanVisitor(classTable);
this->accept(sv);
if(classTable->errors())
{
cerr << "compilation halted due to static semantic errors." << endl;
exit(1);
}
}
void semanVisitor::visit(Program e) {
cerr << "public void visit (program e) should never be called." << endl;
}
void semanVisitor::visit(Class_ e) {
cerr << "public void visit (Class_ e) should never be called." << endl;
}
void semanVisitor::visit(Feature e) {
cerr << "public void visit (Feature e) should never be called." << endl;
}
void semanVisitor::visit(Formal e) {
cerr << "public void visit (Formal e) should never be called." << endl;
}
void semanVisitor::visit(Case e) {
cerr << "public void visit (Case e) should never be called." << endl;
}
void semanVisitor::visit(Expression e) {
//cout << "come to visit Expression" << endl;
//cout << "visit Expression: "<< typeid(*e).name()<<endl;
if (typeid(*e)==typeid(assign_class)) {
assign_class* node=(assign_class *) (e); //cout<<"before visit assign"<<endl;
visit(node); //cout<<" after visit assign"<<endl;
}
else if(typeid(*e) == typeid(static_dispatch_class)) {
static_dispatch_class* node = (static_dispatch_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(dispatch_class)) {
dispatch_class* node = (dispatch_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(cond_class)) {
cond_class* node = (cond_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(loop_class)) {
loop_class* node = (loop_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(typcase_class) ) {
typcase_class* node = (typcase_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(block_class)) {
block_class* node = (block_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(let_class)) {
let_class* node = (let_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(plus_class) ) {
plus_class* node = (plus_class*) (e);
visit(node);
}
else if(typeid(*e) == typeid(sub_class)) {
sub_class* node = (sub_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(mul_class)) {
mul_class* node = (mul_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(divide_class)) {
divide_class* node = (divide_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(neg_class)) {
neg_class* node = (neg_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(lt_class)) {
lt_class* node = (lt_class*) e;
visit(node);
}
else if( typeid(*e) == typeid(eq_class)) {
eq_class* node = (eq_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(leq_class)) {
leq_class* node = (leq_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(comp_class)) {
comp_class* node = (comp_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(int_const_class)) {
int_const_class* node = (int_const_class*) e;
visit(node); //cout<<"after visit int const " << node->get_token()<<endl;
}
else if(typeid(*e)== typeid(bool_const_class)) {
bool_const_class* node = (bool_const_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(string_const_class)) {
string_const_class* node = (string_const_class*) e;
visit(node);
}
else if(typeid(*e)== typeid(new__class)) {
new__class* node = (new__class*) e;
visit(node);
}
else if(typeid(*e)== typeid(isvoid_class)) {
isvoid_class* node = (isvoid_class*) e;
visit(node);
}
else if(typeid(*e)== typeid(no_expr_class)) {
no_expr_class* node = (no_expr_class*) e;
visit(node);
}
else if(typeid(*e) == typeid(object_class)) {
object_class* node = (object_class*) e;
visit(node);
}
}
void semanVisitor::visit(program_class* prg) {
Classes classes = prg->getClasses();
for(int i =classes->first(); classes->more(i); i=classes->next(i) ) {
// class__class* cl = (class__class*) classes->nth(i);
}
}
void semanVisitor::visit(class__class* cl)
{
currentClass = cl;
Features features = cl->get_features();
Features parent_feature_list = cl->parent_feature_list;
//cout << "visit class__class: features length: " << features->len()<<endl;
for(int i=0; i < features->len(); i++)
{
Feature ft1 = (Feature) features->nth(i);
bool conflictWithParents = false;
for(int j=0; j < parent_feature_list->len(); j++)
{
Feature ft2 = (Feature) parent_feature_list->nth(j);
if((!(ft1->get_is_method()) && !(ft2->get_is_method()))
&& (((attr_class*)ft1)->get_name() == ((attr_class*)ft2)->get_name()))
{
conflictWithParents = true;
classTable->semant_error(currentClass->get_filename(), ft1)<<"atrribute "<<((attr_class*)ft1)->get_name()<<"is an attribute of inherited class"<<endl;
break;
}
else if((ft1->get_is_method() && ft2->get_is_method())
&& ((method_class*)ft1)->get_name()->get_string() == ((method_class*)ft2)->get_name()->get_string())
{
method_class* mt1 =((method_class*)ft1);
method_class* mt2 =((method_class*)ft2);
//check return_type
if(mt1->get_return_type()->get_string()!=mt2->get_return_type()->get_string())
{
classTable->semant_error(currentClass->get_filename(), ft1)<<"return type is different from inherited type"<<endl;
break;
}
bool sameFormalsLength = false;
Formals fms1 = mt1->get_formals();
Formals fms2 = mt2->get_formals();
if(fms1->len() == fms2->len()) {
sameFormalsLength = true;
}
else {
classTable->semant_error(currentClass->get_filename(), ft1)<<"different number of formals from parent"<<endl;
}
//check formal type
if(sameFormalsLength )
{
for(int q =0; q< fms1->len(); q++)
{
formal_class* fm1 = (formal_class*)fms1->nth(q);
formal_class* fm2 = (formal_class*)fms2->nth(q);
if(fm1->get_type_decl()->get_string() != fm2->get_type_decl()->get_string())
{
classTable->semant_error(currentClass->get_filename(), ft1)<<"method parameter type is different from parent"<<endl;
break;
}
}
}
}
}
if(conflictWithParents == false)
{
// check feature defined conflicts within the current class
for(int k=0; k< i; k++)
{
Feature ft3 = (Feature) features->nth(k);
if((!(ft1->get_is_method()) && !(ft3->get_is_method()))
&& ((attr_class*)ft1)->get_name()->get_string()== ((attr_class*)ft3)->get_name()->get_string())
{
classTable->semant_error(currentClass->get_filename(), ft1)<<"attribute is multiply defined"<<endl;
break;
}
else if ((ft1->get_is_method() && ft3->get_is_method())
&& ((method_class*)ft1)->get_name()->get_string()== ((method_class*)ft3)->get_name()->get_string())
{
classTable->semant_error(currentClass->get_filename(), ft1)<<"method is multiply defined"<<endl;
break;
}
}
}
}
}
void semanVisitor::visit(method_class *mt)
{
Formals formals = mt->get_formals();
//cout<< "visiting method " << mt->get_name()<< endl;
for(int i =formals->first(); formals->more(i); i=formals->next(i) )
{
formal_class* fm = (formal_class*) formals->nth(i);
//cout<< "formal name: " << fm->get_name()<<endl;
tree_node *node = probeObject(fm->get_name());
// Check if formal is multiply defined
if (node != NULL)
{
if((typeid(*node))==typeid(formal_class))
classTable->semant_error(currentClass->get_filename(), fm)<<"formal multiply defined"<<endl;
}
else
addId(fm->get_name(),fm, 0);
}
this->visit(mt->get_expr());
// get method signature
std::vector<Symbol> signature = classTable->get_signature(currentClass->get_name(), mt->get_name());
//check whether return type is compatible
Symbol return_from_method = mt->get_return_type();
Symbol return_from_expr = mt->get_expr()->get_type();
Symbol return_from_expr_infer = return_from_expr;
if(return_from_expr_infer == SELF_TYPE) {
return_from_expr_infer = this->currentClass->get_name();
}
bool case_1 = (return_from_method == SELF_TYPE) &&
(return_from_expr != SELF_TYPE);
bool case_2 = (return_from_method != SELF_TYPE) &&
(!classTable->is_child(return_from_expr_infer,return_from_method));
if(case_1 || case_2) {
classTable->semant_error(currentClass->get_filename(),mt)<<"return type does not match!"<<endl;
}
}
void semanVisitor::visit(attr_class *at) {
// check self is not the name
if(at->get_name() == self) {
classTable->semant_error(currentClass->get_filename(), at)
<< "cannot use \'self\' as the name of an attribute.\n" <<endl;
}
// check whether type decl is valid
if(at->get_type_decl() != SELF_TYPE &&
!classTable->class_exist(at->get_type_decl())) {
classTable->semant_error(currentClass->get_filename(), at)
<< "class " << at->get_type_decl()->get_string()
<< " of attribute " << at->get_name()->get_string()
<< " is undefined.\n" <<endl;
}
this->visit(at->get_init());
if(at->get_init()->get_type()==NULL)
return;
//verif whether type decl is compatible
Symbol type_decl = at->get_type_decl();
Symbol type_init = at->get_init()->get_type();
if(type_init == SELF_TYPE) {
type_init = this->currentClass->get_name();
}
if(!this->classTable->is_child(type_init,type_decl)) {
classTable->semant_error(currentClass->get_filename(),at)
<< "Initialized type " << type_init->get_string()
<< " of attribute " << at->get_name()->get_string()
<< " does not conform to the declared type "
<< type_decl->get_string() << ".\n" << endl;
}
}
void semanVisitor::visit(formal_class* fm) {
//check whether type_decl is valid
if (fm->get_type_decl() == SELF_TYPE)
{
classTable->semant_error(currentClass->get_filename(), fm)
<<"Formal parameter cannot have SELF_TYPE"<<endl;
}
else if( !classTable->class_exist(fm->get_type_decl()))
{
classTable->semant_error(currentClass->get_filename(), fm)
<< "class " << fm->get_type_decl()->get_string()
<< " of formal " << fm->get_name()->get_string()
<< " is undefined.\n" << endl;
}
}
void semanVisitor::visit(branch_class *br)
{
// no need to check object redefinition
addId(br->get_name(), br, 0);
if(!classTable->class_exist(br->get_type_decl())) {
classTable->semant_error(currentClass->get_filename(), br)
<< "Class " << br->get_type_decl()
<< " in case branch is undefined.\n" << endl;
}
//SELF_TYPE is not allowed in case branch
if((br->get_type_decl()) == SELF_TYPE)
{
classTable->semant_error(currentClass->get_filename(), br)
<< "Identifier " << br->get_name()->get_string()
<< " declared with SELF_TYPE in case. \n" << endl;
}
this->visit(br->get_expr());
}
void semanVisitor::visit(assign_class *as) {
if(symtable_o->lookup(as->get_name())==NULL)
{
classTable->semant_error(currentClass->get_filename(),as)
<< "Assigned variable "<< as->get_name()->get_string()
<<" is undeclared.\n" <<endl;
as->set_type(Object);
return;
}
if(as->get_name() == self) {
classTable->semant_error(currentClass->get_filename(), as)
<< "\'self\' cannot be assigned.\n" <<endl;
as->set_type(Object);
return;
}
Symbol type =NULL;
tree_node *node = symtable_o->lookup(as->get_name());
//cout<<"!!!assign class called. name: "<<as->get_name()<<" type: "<<typeid(*node).name()<<endl;
//check type of ID
if(typeid(*node) == typeid(attr_class))
{
type = ((attr_class*) node )->get_type_decl();
//cout<<"from 1 attr" << endl;
}
else if(typeid(*node) == typeid(formal_class))
{
type = ((formal_class*) node)->get_type_decl();
//cout<<"from 2 formal" << endl;
}
else if(typeid(*node) == typeid(let_class))
{
type = ((let_class*) node)->get_type_decl();
//cout<<"from 3 let" << endl;
}
else if(typeid(*node) == typeid(branch_class))
{
type = ((branch_class*)node)->get_type_decl();
//cout<< "from 4 branch" << endl;
}
//cout<<"type is "<<type->get_string()<<endl;
this->visit(as->get_expr()); //cout<< "finish visit expression" << endl;
Symbol type1 = as->get_expr()->get_type(); //cout<< "type1 is: "<< type1->get_string()<<endl;
//error is type1 >= type
Symbol type_cur = type;
Symbol type1_cur = type1;
if(type_cur == SELF_TYPE) {
type_cur = currentClass->get_name();
}
if(type1_cur == SELF_TYPE) {
type1_cur = currentClass->get_name();
}
if(!this->classTable->is_child(type1_cur,type_cur)) {
classTable->semant_error(currentClass->get_filename(),as)
<< "Type of assigned expression is " << type1_cur->get_string()
<< " which does not conform to the declared type "
<< type->get_string() << " of " << as->get_name()->get_string()<< endl;
as->set_type(Object);
return;
}
as->set_type(type1);
}
void semanVisitor::visit( static_dispatch_class *e )
{
this->visit(e->get_expr());
Expressions actual = e->get_actual();
for(int i =actual->first(); actual->more(i); i=actual->next(i) ) {
Expression_class* ex = (Expression_class*) actual->nth(i);
this->visit(ex);
}
Symbol static_type = e->get_type_name();
if(!classTable->method_exist(static_type, e->get_name())) {
classTable->semant_error(currentClass->get_filename(), e)
<< "Cannot dispatch to undefined method "
<<e->get_name()->get_string() << ". \n" << endl;
e->set_type(Object);
return;
}
Symbol type_caller = e->get_expr()->get_type();
Symbol type_caller_cur = type_caller;
if(type_caller_cur == SELF_TYPE) {
type_caller_cur = this->currentClass->get_name();
}
if(!classTable->is_child(type_caller_cur, static_type)) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Expression type is " << type_caller_cur->get_string()
<< " which does not conform to the declared static type "
<< static_type->get_string() << ".\n" << endl;
e->set_type(Object);
return;
}
std::vector<Symbol> sig = classTable->get_signature(static_type, e->get_name());
if(sig.size()-1 != actual->len()) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Number of arguments is imcompatible of the called method "
<< e->get_name() << ".\n" << endl;
e->set_type(Object);
return;
}
for(int i=0; i<sig.size()-1; i++) {
Symbol type_formal = sig[i];
Symbol type_act = actual->nth(i)->get_type();
Symbol type_act_cur = type_act;
if(type_act == SELF_TYPE) {
type_act_cur = currentClass->get_name();
}
if(!classTable->is_child(type_act_cur, type_formal)) {
method_class* m = classTable->get_method(type_caller_cur, e->get_name());
formal_class* f = (formal_class*) m->get_formals()->nth(i);
classTable->semant_error(currentClass->get_filename(),e)
<< "Type of parameter " << f->get_name()
<< " in called method " << e->get_name()
<< " is " << type_act_cur->get_string()
<< " which does not conform to declared type "
<< f->get_type_decl() << ".\n" << endl;
e->set_type(Object);
return;
}
}
Symbol return_type = sig[sig.size()-1];
if(return_type == SELF_TYPE) {
return_type = type_caller;
}
e->set_type(return_type);
}
void semanVisitor::visit( dispatch_class *e )
{
this->visit(e->get_expr());
Expressions actual = e->get_actual();
for(int i =actual->first(); actual->more(i); i=actual->next(i) ) {
Expression_class* ex = (Expression_class*) actual->nth(i);
this->visit(ex);
}
Symbol type_caller = e->get_expr()->get_type();
Symbol type_caller_cur = type_caller;
if(type_caller_cur == SELF_TYPE) {
type_caller_cur = this->currentClass->get_name();
}
if(!classTable->method_exist(type_caller_cur, e->get_name())) {
classTable->semant_error(currentClass->get_filename(), e)
<< "Cannot dispatch to undefined method "
<<e->get_name()->get_string() << ". \n" << endl;
e->set_type(Object);
return;
}
std::vector<Symbol> sig = classTable->get_signature(type_caller_cur, e->get_name());
if(sig.size()-1 != actual->len()) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Number of arguments is imcompatible of the called method "
<< e->get_name() << ".\n" << endl;
e->set_type(Object);
return;
}
for(int i=0; i<sig.size()-1; i++) {
Symbol type_formal = sig[i];
Symbol type_act = actual->nth(i)->get_type();
Symbol type_act_cur = type_act;
if(type_act == SELF_TYPE) {
type_act_cur = currentClass->get_name();
}
if(!classTable->is_child(type_act_cur, type_formal)) {
method_class* m = classTable->get_method(type_caller_cur, e->get_name());
formal_class* f = (formal_class*) m->get_formals()->nth(i);
classTable->semant_error(currentClass->get_filename(),e)
<< "Type of parameter " << f->get_name()
<< " in called method " << e->get_name()
<< " is " << type_act_cur->get_string()
<< " which does not conform to declared type "
<< f->get_type_decl() << ".\n" << endl;
e->set_type(Object);
return;
}
}
Symbol return_type = sig[sig.size()-1];
if(return_type == SELF_TYPE) {
return_type = type_caller;
}
e->set_type(return_type);
}
void semanVisitor::visit( cond_class *e )
{
this->visit(e->get_pred());
this->visit(e->get_then_exp());
this->visit(e->get_else_exp());
if(Bool != e->get_pred()->get_type()) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Type of \'if\' predication is not Bool.\n" << endl;
e->set_type(Object);
return;
}
else {
Symbol type_then = e-> get_then_exp()->get_type();
Symbol type_else = e-> get_else_exp()->get_type();
if((type_then == SELF_TYPE) && (type_else == SELF_TYPE)) {
e->set_type(SELF_TYPE);
return;
}
else if(type_then == SELF_TYPE) {
type_then = currentClass->get_name();
}
else if(type_else == SELF_TYPE) {
type_else = currentClass->get_name();
}
Symbol lub = classTable->least_upper_bound(type_else, type_then);
e->set_type(lub);
}
}
void semanVisitor::visit( loop_class *e )
{
this->visit(e->get_pred());
this->visit(e->get_body());
if(e->get_pred()->get_type() != Bool) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Type of loop conditon is not Bool.\n" << endl;
e->set_type(Object);
return;
}
e->set_type(Object);
}
void semanVisitor::visit( typcase_class *e )
{
this->visit(e->get_expr());
Cases cases = e->get_cases();
if(cases->len() == 0) {
e->set_type(Object);
return;
}
else
{
for(int i =cases->first(); cases->more(i); i=cases->next(i) )
{
branch_class* ty = (branch_class*) cases->nth(i);
if (ty->get_name()==self)
classTable->semant_error(currentClass->get_filename(),ty)
<< "self can not bound in case!"<<endl;
this->visit(ty);
}
for(int j=0; j< cases->len(); j++)
{
for(int k =j+1; k < cases->len(); k++)
{
branch_class* bj = (branch_class*) cases->nth(j);
branch_class* bk = (branch_class*) cases->nth(k);
if(bj->get_type_decl() == bk->get_type_decl())
{
classTable->semant_error(currentClass->get_filename(),bj)
<< "Branch " << bj->get_type_decl()->get_string()
<< " is duplicated in case statement.\n" << endl;
e->set_type(Object);
return;
}
}
}
Symbol type = ((branch_class*)cases->nth(0))->get_expr()->get_type();
if(type == SELF_TYPE) {
type = currentClass->get_name();
}
for(int i =cases->first(); cases->more(i); i=cases->next(i) ) {
branch_class* b = (branch_class*) cases->nth(i);
Symbol type_b = b->get_expr()->get_type();
if(type_b == SELF_TYPE) type_b = currentClass->get_name();
type = classTable->least_upper_bound(type, type_b);
}
bool all_self = true;
for(int i =cases->first(); cases->more(i); i=cases->next(i) ) {
branch_class* b = (branch_class*) cases->nth(i);
if(b->get_expr()->get_type() != SELF_TYPE) {
all_self = false;
break;
}
}
if(all_self) e->set_type(SELF_TYPE);
else e->set_type(type);
}
}
void semanVisitor::visit( block_class *e )
{
Expressions body = e->get_body();
Symbol type = NULL;
for(int i =body->first(); body->more(i); i=body->next(i) ) {
Expression_class* ex = (Expression_class*) body->nth(i);
//cout<<"block visit start"<<endl;
this->visit(ex);
//cout<<"block visit finish"<<endl;
type = ex->get_type();
}
e->set_type(type);
}
void semanVisitor::visit( let_class *e )
{
Symbol type_id = e->get_type_decl();
if(e->get_identifier() == self) {
classTable->semant_error(currentClass->get_filename(), e)
<< "Cannot bind \'self in a \'let\' expression.\n" << endl;
e->set_type(Object);
return;
}
this->visit(e->get_init());
if(type_id == SELF_TYPE) {
type_id = currentClass->get_name();
}
if(typeid((e->get_init()))!=typeid(no_expr_class))
{
type_id=e->get_init()->get_type();
if(type_id != NULL && !classTable->is_child(type_id,e->get_type_decl()))
{
classTable->semant_error(currentClass->get_filename(), e)
<< "Inferred type of initialization of " << e->get_identifier()->get_string()
<< " is " << type_id->get_string()
<< " which does not conform to the declared type "
<< e->get_type_decl()->get_string() << endl;
e->set_type(Object);
return;
}
}
// we need this enter and exit scope since not all "let" processing is
enterscope();
addId(e->get_identifier(), e, 0);
this->visit(e->get_body());
exitscope();
e->set_type(e->get_body()->get_type());
}
void semanVisitor::visit( plus_class *e )
{
this->visit(e->get_e1());
this->visit(e->get_e2());
Symbol type1 = e->get_e1()->get_type();
Symbol type2 = e->get_e2()->get_type();
if(type1 == Int && type2 == Int) {
e->set_type(Int);
//cout<<"plus finish"<<endl;
}
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Non-Int arguments for" << type1->get_string()
<< " + " << type2->get_string() << ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( sub_class *e )
{
this->visit(e->get_e1());
this->visit(e->get_e2());
Symbol type1 = e->get_e1()->get_type();
Symbol type2 = e->get_e2()->get_type();
if(type1 == Int && type2 == Int) e->set_type(Int);
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Non-Int arguments for" << type1->get_string()
<< " - " << type2->get_string() << ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( mul_class *e )
{
this->visit(e->get_e1());
this->visit(e->get_e2());
Symbol type1 = e->get_e1()->get_type();
Symbol type2 = e->get_e2()->get_type();
if(type1 == Int && type2 == Int) e->set_type(Int);
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Non-Int arguments for" << type1->get_string()
<< " * " << type2->get_string() << ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( divide_class *e )
{
this->visit(e->get_e1());
this->visit(e->get_e2());
Symbol type1 = e->get_e1()->get_type();
Symbol type2 = e->get_e2()->get_type();
if(type1 == Int && type2 == Int) e->set_type(Int);
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Non-Int arguments for" << type1->get_string()
<< " / " << type2->get_string() << ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( neg_class *e )
{
this->visit(e->get_e1());
if(e->get_e1()->get_type()==Int) e->set_type(Int);
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Argument has type " << e->get_e1()->get_type()->get_string()
<< ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( lt_class *e )
{
this->visit(e->get_e1());
this->visit(e->get_e2());
Symbol type1 = e->get_e1()->get_type();
Symbol type2 = e->get_e2()->get_type();
if(type1 == Int && type2 == Int) e->set_type(Bool);
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Non-Int arguments for" << type1->get_string()
<< " < " << type2->get_string() << ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( eq_class *e )
{
this->visit(e->get_e1());
this->visit(e->get_e2());
Symbol type1 = e->get_e1()->get_type();
Symbol type2 = e->get_e2()->get_type();
bool base_type1 = (type1 == Int)||(type1 == Bool)||(type1 == Str);
bool base_type2 = (type2 == Int)||(type2 == Bool)||(type2 == Str);
bool incompatible_base_type = (base_type1 && base_type2 && type1!=type2);
bool not_all_base_type = (base_type1 != base_type2);
if(incompatible_base_type || not_all_base_type) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Illegal comparison with basic types" << endl;
e->set_type(Object);
return;
}
else e->set_type(Bool);
}
void semanVisitor::visit( leq_class *e )
{
this->visit(e->get_e1());
this->visit(e->get_e2());
Symbol type1 = e->get_e1()->get_type();
Symbol type2 = e->get_e2()->get_type();
if(type1 == Int && type2 == Int) e->set_type(Bool);
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Non-Int arguments for" << type1->get_string()
<< " <= " << type2->get_string() << ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( comp_class *e )
{
this->visit(e->get_e1());
if(e->get_e1()->get_type()==Bool) e->set_type(Bool);
else {
classTable->semant_error(currentClass->get_filename(),e)
<< "Argument has type " << e->get_e1()->get_type()->get_string()
<< ".\n" << endl;
e->set_type(Object);
return;
}
}
void semanVisitor::visit( int_const_class *e )
{
inttable.add_int(atoi(e->get_token()->get_string()));
e->set_type(Int);
}
void semanVisitor::visit( bool_const_class *e )
{
e->set_type(Bool);
}
void semanVisitor::visit( string_const_class *e )
{
stringtable.add_string(e->get_token()->get_string());
e->set_type(Str);
}
void semanVisitor::visit( new__class *e )
{
Symbol type = e->get_type_name();
if(e->get_type_name() != SELF_TYPE &&
!classTable->class_exist(type)) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Cannot use \'new\' with undefined class "
<< type->get_string()
<<".\n" << endl;
e->set_type(Object);
return;
}
if(type == SELF_TYPE) e->set_type(SELF_TYPE);
else e->set_type(type);
}
void semanVisitor::visit( isvoid_class *e )
{
this->visit(e->get_e1());
e->set_type(Bool);
}
void semanVisitor::visit( no_expr_class *e )
{
// do nothing
}
void semanVisitor::visit( object_class *e )
{
Symbol type = NULL;
if(e->get_name() == self) {
e->set_type(SELF_TYPE);
return;
}
if(symtable_o->lookup(e->get_name())==NULL) {
classTable->semant_error(currentClass->get_filename(),e)
<< "Undeclared identifier" << e->get_name()->get_string()
<<".\n" << endl;
e->set_type(Object);
return;
}
tree_node* node = symtable_o->lookup(e->get_name());
//cout<<"!!!object class called. name: "<<e->get_name()<<" type: "<<typeid(*node).name()<<endl;
//check type of ID
if(typeid(*node) == typeid(attr_class))
{
type = ((attr_class*) node )->get_type_decl();
//cout<<"from 1 attr" << endl;
}
else if(typeid(*node) == typeid(formal_class))
{
type = ((formal_class*) node)->get_type_decl();
//cout<<"from 2 formal" << endl;
}
else if(typeid(*node) == typeid(let_class))
{
type = ((let_class*) node)->get_type_decl();
//cout<<"from 3 let" << endl;
}
else if(typeid(*node) == typeid(branch_class))
{
type = ((branch_class*)node)->get_type_decl();
//cout<< "from 4 branch" << endl;
}
//cout<<"type is "<<type->get_string()<<endl;
e->set_type(type);
}
/**************************************************************/
/* Accept function */
/**************************************************************/
void program_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
for(int i =classes->first(); classes->more(i); i=classes->next(i)) {
class__class* cl = (class__class*)classes->nth(i);
cl->accept(v);
}
v->exitscope();
}
void class__class::accept(Visitor *v)
{
v->enterscope();
//cout << endl<<"--Visiting class: " << this->get_name()<< " .feature length = "<<features->len() << endl;
semanVisitor* sv = (semanVisitor*) v;
if( parent != No_class) {
class__class* parentClass__class = sv->classTable->get_parent(this->get_name());
if(parentClass__class != NULL)
{
//cout<<"parent class is: "<<parentClass__class->get_name()<<endl;
parentClass__class->add_parentMembers(v, parent_feature_list);
//cout<< "1.parent feature list length: "<<parent_feature_list->len()<< endl;
}
}
v->visit(this);
for(int i = features->first(); features->more(i); i = features->next(i))
{
Feature ft = (Feature) features->nth(i);
if(ft->get_is_method())
{
method_class* mt = (method_class*) ft;
/* Feature f = (Feature)sv->probeMethod(mt->get_name()) ;
if( !f->get_is_method() )*/
{
sv->addId(mt->get_name(), mt, 1);
//cout<< "add method @@@@@@@@@@@@@@@@ " << mt->get_name()<<endl;
}
}
else if(!(ft->get_is_method()) )
{
attr_class* at = (attr_class*) ft;
/*Feature f = (Feature)sv->probeMethod(at->get_name()) ;
if( f->get_is_method() )*/
{
sv->addId(at->get_name(), at, 0);
//cout<< "add object@@@@@@@@@@@@@@@@@ " <<at->get_name()<< endl;
}
}
}
//cout<< "2.parent feature list length: "<<parent_feature_list->len()<< endl;
//cout << "features length: " << features->len()<<endl;
for(int i = parent_feature_list->first(); parent_feature_list->more(i); i = parent_feature_list->next(i))
{
Feature ft = (Feature) parent_feature_list->nth(i);
if(ft->get_is_method())
{
method_class* mt = (method_class*) ft;
tree_node *node = sv->probeObject(mt->get_name());
// Check if formal is multiply defined
if (node == NULL || (typeid(*node)) != typeid(method_class) )
{
sv->addId(mt->get_name(), mt, 1);
//cout<< "add method @@@@@@@@@@@@@@@@@@" << mt->get_name()<<endl;
}
}
else if (!(ft->get_is_method()))
{
attr_class* at = (attr_class*) ft;
tree_node *node = sv->probeObject(at->get_name());
// Check if formal is multiply defined
if (node == NULL || (typeid(*node)) != typeid(attr_class) )
{
sv->addId(at->get_name(), at, 0);
//cout<< "add object@@@@@@@@@@@@@@@@@ " <<at->get_name()<< endl;
}
}
}
for(int i = features->first(); features->more(i); i = features->next(i))
{
Feature ft = (Feature) features->nth(i);
if (ft->get_is_method()) {
method_class* mt = (method_class*) ft;
//cout<<"---visiting method "<<mt->get_name()<<endl;
mt->accept(v);
}
else if (!(ft->get_is_method())) {
attr_class *at = (attr_class*) ft;
//cout<<"---visiting attribute "<<at->get_name()<<endl;
at->accept(v);
}
}
v->exitscope();
//cout<< " exit class " <<this->get_name()<< endl;
}
void class__class::add_parentMembers(Visitor *v, Features &parent_feature_list)
{
semanVisitor* sv = (semanVisitor*) v;
//cout<<"adding parent members for "<<this->get_name()<<endl;
for(int i=0; i < features->len(); i++)
{
Feature ft = (Feature) features->nth(i);
if (ft->get_is_method())
{
method_class* mt = (method_class*) ft;
parent_feature_list = append_Features(single_Features(mt), parent_feature_list);
//cout<<": added parent method "<<mt->get_name()<<endl;
}
else if (!(ft->get_is_method()))
{
attr_class* at = (attr_class*) ft;
parent_feature_list = append_Features(single_Features(at), parent_feature_list);
//cout<<": added parent attr "<<at->get_name()<<endl;
}
}
//for(int i = parent_feature_list->first(); parent_feature_list->more(i); i = parent_feature_list->next(i))
// if (parent_feature_list->nth(i)->get_is_method())
// {
// method_class *m =(method_class *)parent_feature_list->nth(i);
// //cout<<"; added parent method "<<m->get_name()<<endl;
// }
if(parent != No_class) {
class__class* parentClass__class = sv->classTable->get_parent(this->get_name());
parentClass__class->add_parentMembers(v, parent_feature_list);
}
//cout<<" inside: parent feature list length = "<<parent_feature_list->len()<<endl;
}
void method_class::accept(Visitor *v) {
v->enterscope(); //cout << "before visit " << this->get_name() << endl;
v->visit(this);
//cout << "after visit " << this->get_name() << endl;
for(int i =formals->first(); formals->more(i); i=formals->next(i)) {
formal_class* fm = (formal_class*)formals->nth(i);
fm->accept(v);
}
v->exitscope();
}
void attr_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void formal_class::accept(Visitor *v) {
v->visit(this);
}
void Expression_class::accept( Visitor *v )
{
v->enterscope();
v->visit(this);
v->exitscope();
}
void branch_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
expr->accept(v);
v->exitscope();
}
void assign_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
//expr->accept(v);
v->exitscope();
}
void static_dispatch_class::accept(Visitor *v) {
v->enterscope();
expr->accept(v);
v->visit(this);
for(int i =actual->first(); actual->more(i); i=actual->next(i)) {
Expression_class* ac = (Expression_class*)actual->nth(i);
ac->accept(v);
}
v->exitscope();
}
void dispatch_class::accept(Visitor *v) {
v->enterscope();
expr->accept(v);
v->visit(this);
for(int i =actual->first(); actual->more(i); i=actual->next(i)) {
Expression_class* ac = (Expression_class*)actual->nth(i);
ac->accept(v);
}
v->exitscope();
}
void cond_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
pred->accept(v);
then_exp->accept(v);
else_exp->accept(v);
v->exitscope();
}
void loop_class ::accept(Visitor *v) {
v->visit(this);
}
void typcase_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
expr->accept(v);
for(int i =cases->first(); cases->more(i); i=cases->next(i)) {
branch_class* cs = (branch_class*)cases->nth(i);
cs->accept(v);
}
v->exitscope();
}
void block_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void let_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void plus_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
e2->accept(v);
v->exitscope();
}
void sub_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
e2->accept(v);
v->exitscope();
}
void mul_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
e2->accept(v);
v->exitscope();
}
void divide_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
e2->accept(v);
v->exitscope();
}
void neg_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
v->exitscope();
}
void lt_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
e2->accept(v);
v->exitscope();
}
void eq_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
e2->accept(v);
v->exitscope();
}
void leq_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
e2->accept(v);
v->exitscope();
}
void comp_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
v->exitscope();
}
void int_const_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void bool_const_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void string_const_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void new__class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void isvoid_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
e1->accept(v);
v->exitscope();
}
void no_expr_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
void object_class::accept(Visitor *v) {
v->enterscope();
v->visit(this);
v->exitscope();
}
#ifndef SEMANT_H_
#define SEMANT_H_
#include <assert.h>
#include <iostream>
#include "cool-tree.h"
#include "stringtab.h"
#include "symtab.h"
#include "list.h"
#include <map>
#include <set>
#include <vector>
#define TRUE 1
#define FALSE 0
class ClassTable;
typedef ClassTable *ClassTableP;
// This is a structure that may be used to contain the semantic
// information such as the inheritance graph. You may use it or not as
// you like: it is only here to provide a container for the supplied
// methods.
class ClassTable {
private:
int semant_errors;
bool cycle_found;
ostream& error_stream;
//map from class name to class
std::map<Symbol, class__class*> class_map;
//map from class name and function name to function
std::map<Symbol, std::map<Symbol, method_class*> > method_map;
//inheritance map
std::map<Symbol, std::set<Symbol> > inherit_graph;
//class set
std::set<Symbol> basic_class_set;
void install_basic_classes();
void install_user_classes(Classes);
void install_method_map();
void check_cycle();
void DFS_is_child(std::map<Symbol, int> visited_map, Symbol c, Symbol p, bool &);
void DFS_has_cycle(std::map<Symbol, int> visited_map, Symbol c);
void print_inherit_map();
void print_class_map();
void print_method_map();
void fatal();
public:
ClassTable(Classes);
int errors() {
return semant_errors;
}
ostream& semant_error();
ostream& semant_error(Class_ c);
ostream& semant_error(Symbol filename, tree_node *t);
bool class_exist(Symbol);
bool method_exist(Symbol class_name, Symbol method_name);
bool is_child (Symbol c1, Symbol c2);
Symbol least_upper_bound(Symbol c1, Symbol c2);
class__class * get_parent( Symbol class_name );
method_class* get_method ( Symbol class_name, Symbol method_name);
std::vector<Symbol> get_signature(Symbol class_name, Symbol method_name);
void verify_signature( class__class* cls, method_class* m );
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment