Commit 167d5a8c authored by zygzagZ's avatar zygzagZ

WIP type system

parent e83a94b3
...@@ -3165,3 +3165,24 @@ ListExpr *ListExpr::clone() const ...@@ -3165,3 +3165,24 @@ ListExpr *ListExpr::clone() const
{ {
return new ListExpr(*this); return new ListExpr(*this);
} }
std::string Fun::printName() const{
std::string ret = type_->printName() + "(";
bool fst = true;
for (auto i : *listtype_) {
if (fst) fst = false;
else ret += ", ";
ret += i->printName();
}
return ret + ")";
}
bool Fun::isEqual(Type const *other) const {
if (const Fun* casted = dynamic_cast<const Fun*>(other)) {
if (*type_ != *casted->type_ || listtype_->size() != casted->listtype_->size()) return false;
}
return false;
}
\ No newline at end of file
...@@ -304,12 +304,16 @@ class Type : public Visitable ...@@ -304,12 +304,16 @@ class Type : public Visitable
{ {
public: public:
virtual Type *clone() const = 0; virtual Type *clone() const = 0;
virtual std::string printName() const = 0;
virtual bool isEqual(Type const *f) const = 0;
bool operator==(Type const & f) { return isEqual(&f); }
bool operator!=(Type const & f) { return !isEqual(&f); }
}; };
class Expr : public Visitable class Expr : public Visitable
{ {
public: public:
int lineno;
virtual Expr *clone() const = 0; virtual Expr *clone() const = 0;
}; };
...@@ -789,7 +793,6 @@ public: ...@@ -789,7 +793,6 @@ public:
class Int : public Type class Int : public Type
{ {
public: public:
Int(const Int &); Int(const Int &);
Int &operator=(const Int &); Int &operator=(const Int &);
Int(); Int();
...@@ -797,12 +800,17 @@ public: ...@@ -797,12 +800,17 @@ public:
virtual void accept(Visitor *v); virtual void accept(Visitor *v);
virtual Int *clone() const; virtual Int *clone() const;
void swap(Int &); void swap(Int &);
std::string printName() const { return "int"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Int*>(other))
return true;
return false;
}
}; };
class Str : public Type class Str : public Type
{ {
public: public:
Str(const Str &); Str(const Str &);
Str &operator=(const Str &); Str &operator=(const Str &);
Str(); Str();
...@@ -810,6 +818,12 @@ public: ...@@ -810,6 +818,12 @@ public:
virtual void accept(Visitor *v); virtual void accept(Visitor *v);
virtual Str *clone() const; virtual Str *clone() const;
void swap(Str &); void swap(Str &);
std::string printName() const { return "str"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Str*>(other))
return true;
return false;
}
}; };
class Bool : public Type class Bool : public Type
...@@ -823,6 +837,12 @@ public: ...@@ -823,6 +837,12 @@ public:
virtual void accept(Visitor *v); virtual void accept(Visitor *v);
virtual Bool *clone() const; virtual Bool *clone() const;
void swap(Bool &); void swap(Bool &);
std::string printName() const { return "bool"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Bool*>(other))
return true;
return false;
}
}; };
class Void : public Type class Void : public Type
...@@ -836,6 +856,12 @@ public: ...@@ -836,6 +856,12 @@ public:
virtual void accept(Visitor *v); virtual void accept(Visitor *v);
virtual Void *clone() const; virtual Void *clone() const;
void swap(Void &); void swap(Void &);
std::string printName() const { return "void"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Void*>(other))
return true;
return false;
}
}; };
class Array : public Type class Array : public Type
...@@ -850,6 +876,12 @@ public: ...@@ -850,6 +876,12 @@ public:
virtual void accept(Visitor *v); virtual void accept(Visitor *v);
virtual Array *clone() const; virtual Array *clone() const;
void swap(Array &); void swap(Array &);
std::string printName() const { return type_->printName() + "[]"; }
bool isEqual(Type const *other) const {
if (const Array* casted = dynamic_cast<const Array*>(other))
return *type_ == *casted->type_;
return false;
}
}; };
class ClassT : public Type class ClassT : public Type
...@@ -864,6 +896,11 @@ public: ...@@ -864,6 +896,11 @@ public:
virtual void accept(Visitor *v); virtual void accept(Visitor *v);
virtual ClassT *clone() const; virtual ClassT *clone() const;
void swap(ClassT &); void swap(ClassT &);
std::string printName() const { return "class"; }
bool isEqual(Type const *other) const {
// TODO: implement ClassT comparison
return false;
}
}; };
class Fun : public Type class Fun : public Type
...@@ -879,6 +916,8 @@ public: ...@@ -879,6 +916,8 @@ public:
virtual void accept(Visitor *v); virtual void accept(Visitor *v);
virtual Fun *clone() const; virtual Fun *clone() const;
void swap(Fun &); void swap(Fun &);
std::string printName() const;
bool isEqual(Type const *other) const;
}; };
class EVar : public Expr class EVar : public Expr
......
#include "Info.h" #include "Info.h"
Scope g_scope;
...@@ -5,34 +5,100 @@ ...@@ -5,34 +5,100 @@
using namespace std; using namespace std;
class VarInfo { class VarInfo {
public:
VarInfo(string n, int l)
: name(n), lineLocation(l) {}
VarInfo(PIdent* ident)
: VarInfo(ident->string_, ident->integer_) {}
string name; string name;
string type; Type *type;
int lineLocation;
bool operator<(const VarInfo &other) const { bool operator<(const VarInfo &other) const {
return name != other.name ? name < other.name : type < other.type; return name != other.name ? name < other.name : type < other.type;
} }
}; };
class FunctionInfo : VarInfo { class ClassInfo;
vector<VarInfo> arguments;
class FunctionInfo : public VarInfo {
public:
Block * block;
vector<VarInfo*> arguments;
ClassInfo *klass;
FunctionInfo(PIdent *ident, ClassInfo *klass = NULL) : VarInfo(ident), klass(klass) {};
~FunctionInfo() {
for (auto &a : arguments)
delete a;
}
}; };
class ClassInfo : VarInfo class ClassInfo : public VarInfo
{ {
ClassInfo * parent; ClassInfo * parent;
public: public:
vector<FunctionInfo*> functions;
vector<VarInfo*> variables;
ClassInfo(PIdent *ident, ClassInfo *parent = NULL) : VarInfo(ident), parent(parent) {};
ClassInfo * getParent() const { return parent; }; ClassInfo * getParent() const { return parent; };
vector<FunctionInfo> functions; FunctionInfo* getFunction(string name) const {
vector<VarInfo> variables; for (auto i : functions)
if (i->name == name)
return i;
return parent ? parent->getFunction(name) : NULL;
}
}; VarInfo* getVar(string name) const {
for (auto i : variables)
if (i->name == name)
return i;
return parent ? parent->getVar(name) : NULL;
}
~ClassInfo() {
for (auto &f : functions)
delete f;
for (auto &v : variables)
delete v;
}
};
class Scope { class Scope {
public: public:
vector<ClassInfo> classes; vector<ClassInfo*> classes;
vector<FunctionInfo> functions; vector<FunctionInfo*> functions;
ClassInfo *currentClass;
Scope() : currentClass(NULL) {}
~Scope() {
for (auto &c : classes)
delete c;
for (auto &f : functions)
delete f;
}
ClassInfo* getClass(string name) const {
for (auto i : classes)
if (i->name == name)
return i;
return NULL;
}
FunctionInfo* getFunction(string name, bool local = false) const {
if (currentClass && !local)
if (auto *f = currentClass->getFunction(name))
return f;
for (auto i : functions)
if (i->name == name)
return i;
return NULL;
}
}; };
extern Scope g_scope;
#endif #endif
\ No newline at end of file
...@@ -50,7 +50,7 @@ int main(int argc, char ** argv) ...@@ -50,7 +50,7 @@ int main(int argc, char ** argv)
/* The default entry point is used. For other options see Parser.H */ /* The default entry point is used. For other options see Parser.H */
Program *parse_tree = pProgram(input); Program *parse_tree = pProgram(input);
if (!parse_tree) { if (!parse_tree) {
fprintf(stderr, "Parser error, invalid syntax!"); fprintf(stderr, "Parser error, invalid syntax!\n");
return 1; return 1;
} }
...@@ -64,12 +64,13 @@ int main(int argc, char ** argv) ...@@ -64,12 +64,13 @@ int main(int argc, char ** argv)
} }
binaryPath = argv[0]; binaryPath = argv[0];
std::filesystem::path file(filename ? filename : "Instant"); std::filesystem::path file(filename ? filename : "Latte");
TypeCheck checker;
try { try {
TypeCheck checker;
checker.check(parse_tree); checker.check(parse_tree);
} catch (ParseError &e) { } catch (ParseError const &e) {
std::cerr << e.what() << std::endl; std::cerr << e.what() << std::endl;
return 1;
} }
/*Compiler c(file); /*Compiler c(file);
std::string out = c.compile(parse_tree); std::string out = c.compile(parse_tree);
......
...@@ -7,7 +7,7 @@ FLEX_OPTS=-PGrammar ...@@ -7,7 +7,7 @@ FLEX_OPTS=-PGrammar
BISON=bison BISON=bison
BISON_OPTS=-t -pGrammar BISON_OPTS=-t -pGrammar
OBJS=Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o OBJS=Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o ParseError.o
.PHONY : clean distclean .PHONY : clean distclean
...@@ -16,9 +16,6 @@ all : latc ...@@ -16,9 +16,6 @@ all : latc
clean : clean :
rm -f *.o latc Grammar.aux Grammar.log Grammar.pdf Grammar.dvi Grammar.ps Grammar rm -f *.o latc Grammar.aux Grammar.log Grammar.pdf Grammar.dvi Grammar.ps Grammar
# distclean : clean
# rm -f Absyn.cpp Absyn.h Latte.cpp Parser.cpp Parser.h Lexer.cpp Skeleton.cpp Skeleton.h Printer.cpp Printer.h Makefile Grammar.l Grammar.y Grammar.tex
latc : ${OBJS} Latte.o latc : ${OBJS} Latte.o
@echo "Linking latc..." @echo "Linking latc..."
${CC} ${CCFLAGS} ${OBJS} Latte.o -o latc ${CC} ${CCFLAGS} ${OBJS} Latte.o -o latc
...@@ -44,11 +41,14 @@ Printer.o : Printer.cpp Printer.h Absyn.h ...@@ -44,11 +41,14 @@ Printer.o : Printer.cpp Printer.h Absyn.h
Skeleton.o : Skeleton.cpp Skeleton.h Absyn.h Skeleton.o : Skeleton.cpp Skeleton.h Absyn.h
${CC} ${CCFLAGS} -Wno-unused-parameter -c Skeleton.cpp ${CC} ${CCFLAGS} -Wno-unused-parameter -c Skeleton.cpp
Latte.o : Latte.cpp Parser.h Printer.h Absyn.h ParseError.h Latte.o : Latte.cpp Parser.h Printer.h Absyn.h ParseError.h TypeCheck.h Info.h
${CC} ${CCFLAGS} -c Latte.cpp ${CC} ${CCFLAGS} -c Latte.cpp
TypeCheck.o : TypeCheck.cpp TypeCheck.h Absyn.h ParseError.h TypeCheck.o : TypeCheck.cpp TypeCheck.h Info.h Absyn.h ParseError.h
${CC} ${CCFLAGS} -c TypeCheck.cpp ${CC} ${CCFLAGS} -c TypeCheck.cpp
Info.o : Info.cpp Info.h Absyn.h Info.o : Info.cpp Info.h Absyn.h
${CC} ${CCFLAGS} -c Info.cpp ${CC} ${CCFLAGS} -c Info.cpp
ParseError.o : ParseError.cpp Info.h Absyn.h ParseError.h
${CC} ${CCFLAGS} -c ParseError.cpp
#include "ParseError.h"
#include "Info.h"
#include "Printer.h"
#include <sstream>
using namespace std;
RedefinedError::RedefinedError(PIdent *ident, VarInfo *orig) {
stringstream ss;
ss << "Variable \"" << ident->string_ << "\" at line " << ident->integer_ << " redeclared! First declaration at line " << orig->lineLocation;
msg = ss.str();
line = ident->integer_;
}
UndefinedError::UndefinedError(PIdent *ident) {
stringstream ss;
ss << "Undefined reference to \"" << ident->string_ << "\" at line " << ident->integer_;
msg = ss.str();
line = ident->integer_;
}
InvalidTypeError::InvalidTypeError(int lineno, Type &expected, vector<shared_ptr<Type>> received, Expr *expr) {
stringstream ss;
ss << "Invalid expression type at line " << lineno << ". Expected \"" << expected.printName() << "\", instead received ";
bool fst = true;
for (auto i : received) {
if (fst) fst = false;
else ss << ", ";
ss << i->printName();
}
ss << ".";
if (expr) {
ss << " Expression: ";
PrintAbsyn p;
ss << p.print(expr);
}
msg = ss.str();
line = lineno;
}
\ No newline at end of file
#ifndef ERROR_HEADER #ifndef ERROR_HEADER
#define ERROR_HEADER #define ERROR_HEADER
#include "Absyn.h"
#include <string> #include <string>
#include <stdexcept>
#include <memory>
using namespace std; using namespace std;
class ParseError : std::exception {
class ParseError : std::runtime_error {
protected:
string msg; string msg;
int line;
ParseError() : runtime_error("ParseError"), line(-1) {}
public:
ParseError(string reason, int line = -1) : runtime_error("ParseError"), line(line) {}
virtual const char * what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { return msg.data(); }
};
class PIdent;
class VarInfo;
class RedefinedError : public ParseError {
public:
RedefinedError(PIdent *ident, VarInfo *orig);
};
class UndefinedError : public ParseError {
public:
UndefinedError(PIdent *ident);
};
class InvalidTypeError : public ParseError {
public: public:
ParseError(string reason) : msg(reason) {} InvalidTypeError(int lineno, Type &expected, vector<shared_ptr<Type>> received, Expr *expr = NULL);
const char * what() { return msg.data(); }
}; };
#endif #endif
\ No newline at end of file
...@@ -2000,6 +2000,7 @@ yyreduce: ...@@ -2000,6 +2000,7 @@ yyreduce:
default: break; default: break;
} }
// if (yyval.expr_) yyval.expr_->lineno = yy_mylinenumber;
/* User semantic actions sometimes alter yychar, and that requires /* User semantic actions sometimes alter yychar, and that requires
that yytoken be updated with the new translation. We take the that yytoken be updated with the new translation. We take the
approach of translating immediately before every use of yytoken. approach of translating immediately before every use of yytoken.
......
#include "TypeCheck.h" #include "TypeCheck.h"
#include "ParseError.h"
#include <stdexcept> #include <stdexcept>
void TypeCheck::visitProgram(Program *t) {} //abstract class void TypeCheck::visitProgram(Program *t) {} //abstract class
...@@ -6,10 +7,25 @@ void TypeCheck::visitTopDef(TopDef *t) {} //abstract class ...@@ -6,10 +7,25 @@ void TypeCheck::visitTopDef(TopDef *t) {} //abstract class
void TypeCheck::visitFunDef(FunDef *t) {} //abstract class void TypeCheck::visitFunDef(FunDef *t) {} //abstract class
void TypeCheck::visitArg(Arg *t) {} //abstract class void TypeCheck::visitArg(Arg *t) {} //abstract class
void TypeCheck::visitClassDef(ClassDef *t) { void TypeCheck::visitClassDef(ClassDef *t) {
t->getName()->accept(this); const string name = t->getName()->string_;
if (t->getParent()) ClassInfo *c = scope.getClass(name);
t->getParent()->accept(this); if (c) {
throw RedefinedError(t->getName(), c);
}
ClassInfo *parent = NULL;
if (t->getParent()) {
const string parentName = t->getParent()->string_;
parent = scope.getClass(parentName);
if (!parent) {
throw UndefinedError(t->getParent());
}
}
c = new ClassInfo(t->getName(), parent);
scope.classes.push_back(c);
scope.currentClass = c;
t->getBlock()->accept(this); t->getBlock()->accept(this);
scope.currentClass = NULL;
} }
void TypeCheck::visitClassBlock(ClassBlock *t) {} //abstract class void TypeCheck::visitClassBlock(ClassBlock *t) {} //abstract class
...@@ -56,15 +72,19 @@ void TypeCheck::visitClDef(ClDef *cl_def) ...@@ -56,15 +72,19 @@ void TypeCheck::visitClDef(ClDef *cl_def)
} }
void TypeCheck::visitFuncDef(FuncDef *func_def) void TypeCheck::visitFuncDef(FuncDef *def)
{ {
/* Code For FuncDef Goes Here */ const string name = def->pident_->string_;
FunctionInfo *f = scope.getFunction(name);
if (f) {
throw RedefinedError(def->pident_, f);
}
func_def->type_->accept(this); f = new FunctionInfo(def->pident_, scope.currentClass);
func_def->pident_->accept(this);
func_def->listarg_->accept(this);
func_def->block_->accept(this);
f->block = def->block_;
auto &targetVector = scope.currentClass ? scope.currentClass->functions : scope.functions;
targetVector.push_back(f);
} }
void TypeCheck::visitAr(Ar *ar) void TypeCheck::visitAr(Ar *ar)
...@@ -338,24 +358,18 @@ void TypeCheck::visitEVar(EVar *e_var) ...@@ -338,24 +358,18 @@ void TypeCheck::visitEVar(EVar *e_var)
void TypeCheck::visitELitInt(ELitInt *e_lit_int) void TypeCheck::visitELitInt(ELitInt *e_lit_int)
{ {
/* Code For ELitInt Goes Here */
visitInteger(e_lit_int->integer_); visitInteger(e_lit_int->integer_);
lastType = make_shared<Int>();
} }
void TypeCheck::visitELitTrue(ELitTrue *e_lit_true) void TypeCheck::visitELitTrue(ELitTrue *e_lit_true)
{ {
/* Code For ELitTrue Goes Here */ lastType = make_shared<Bool>();
} }
void TypeCheck::visitELitFalse(ELitFalse *e_lit_false) void TypeCheck::visitELitFalse(ELitFalse *e_lit_false)
{ {
/* Code For ELitFalse Goes Here */ lastType = make_shared<Bool>();
} }
void TypeCheck::visitEApp(EApp *e_app) void TypeCheck::visitEApp(EApp *e_app)
...@@ -367,29 +381,37 @@ void TypeCheck::visitEApp(EApp *e_app) ...@@ -367,29 +381,37 @@ void TypeCheck::visitEApp(EApp *e_app)
} }
void TypeCheck::visitEString(EString *e_string) void TypeCheck::visitEString(EString *e)
{ {
/* Code For EString Goes Here */ /* Code For EString Goes Here */
visitString(e_string->string_); visitString(e->string_);
auto a = lastType;
Str expect;
if (*a != expect) {
throw InvalidTypeError(e->lineno, expect, {a}, e);
}
lastType = make_shared<Str>();
} }
void TypeCheck::visitENewArray(ENewArray *e_new_array) void TypeCheck::visitENewArray(ENewArray *e)
{ {
/* Code For ENewArray Goes Here */ /* Code For ENewArray Goes Here */
e_new_array->type_->accept(this); e->type_->accept(this);
e_new_array->expr_->accept(this); e->expr_->accept(this);
auto a = lastType;
Array expect(e->type_);
if (*a != expect) {
throw InvalidTypeError(e->lineno, expect, {a}, e);
}
lastType = make_shared<Array>(e->type_);
} }
void TypeCheck::visitENewClass(ENewClass *e_new_class) void TypeCheck::visitENewClass(ENewClass *e_new_class)
{ {
/* Code For ENewClass Goes Here */
e_new_class->pident_->accept(this); e_new_class->pident_->accept(this);
lastType = make_shared<ClassT>(e_new_class->pident_);
} }
void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr) void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
...@@ -411,11 +433,10 @@ void TypeCheck::visitEClsMthd(EClsMthd *e_cls_mthd) ...@@ -411,11 +433,10 @@ void TypeCheck::visitEClsMthd(EClsMthd *e_cls_mthd)
} }
void TypeCheck::visitNull(Null *null) void TypeCheck::visitNull(Null *e)
{ {
/* Code For Null Goes Here */ PIdent *ident = new PIdent("null", e->lineno);
lastType = make_shared<ClassT>(ident); // TODO
} }
void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc) void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
...@@ -424,7 +445,7 @@ void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc) ...@@ -424,7 +445,7 @@ void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
e_index_acc->pident_->accept(this); e_index_acc->pident_->accept(this);
e_index_acc->expr_->accept(this); e_index_acc->expr_->accept(this);
throw UndefinedError(e_index_acc->pident_); // TODO
} }
void TypeCheck::visitECast(ECast *e_cast) void TypeCheck::visitECast(ECast *e_cast)
...@@ -433,151 +454,96 @@ void TypeCheck::visitECast(ECast *e_cast) ...@@ -433,151 +454,96 @@ void TypeCheck::visitECast(ECast *e_cast)
e_cast->pident_->accept(this); e_cast->pident_->accept(this);
e_cast->expr_->accept(this); e_cast->expr_->accept(this);
lastType = make_shared<ClassT>(e_cast->pident_);
}
void TypeCheck::visitNeg(Neg *neg)
{
/* Code For Neg Goes Here */
neg->expr_->accept(this);
} }
void TypeCheck::visitNot(Not *not_) void TypeCheck::visitNeg(Neg *e)
{ {
/* Code For Not Goes Here */ e->expr_->accept(this);
auto a = lastType;
not_->expr_->accept(this); Int expect;
if (*a != expect) {
} throw InvalidTypeError(e->lineno, expect, {a}, e);
}
void TypeCheck::visitEMul(EMul *e_mul) lastType = make_shared<Int>();
{
/* Code For EMul Goes Here */
e_mul->expr_1->accept(this);
e_mul->mulop_->accept(this);
e_mul->expr_2->accept(this);
}
void TypeCheck::visitEAdd(EAdd *e_add)
{
/* Code For EAdd Goes Here */
e_add->expr_1->accept(this);
e_add->addop_->accept(this);
e_add->expr_2->accept(this);
}
void TypeCheck::visitERel(ERel *e_rel)
{
/* Code For ERel Goes Here */
e_rel->expr_1->accept(this);
e_rel->relop_->accept(this);
e_rel->expr_2->accept(this);
}
void TypeCheck::visitEAnd(EAnd *e_and)
{
/* Code For EAnd Goes Here */
e_and->expr_1->accept(this);
e_and->expr_2->accept(this);
}
void TypeCheck::visitEOr(EOr *e_or)
{
/* Code For EOr Goes Here */
e_or->expr_1->accept(this);
e_or->expr_2->accept(this);
}
void TypeCheck::visitPlus(Plus *plus)
{
/* Code For Plus Goes Here */
}
void TypeCheck::visitMinus(Minus *minus)
{
/* Code For Minus Goes Here */
}
void TypeCheck::visitTimes(Times *times)
{
/* Code For Times Goes Here */
}
void TypeCheck::visitDiv(Div *div)
{
/* Code For Div Goes Here */
}
void TypeCheck::visitMod(Mod *mod)
{
/* Code For Mod Goes Here */
} }
void TypeCheck::visitLTH(LTH *lth) void TypeCheck::visitNot(Not *e)
{ {
/* Code For LTH Goes Here */ e->expr_->accept(this);
auto a = lastType;
Bool expect;
if (*a != expect) {
throw InvalidTypeError(e->lineno, expect, {a}, e);
}
lastType = make_shared<Bool>();
} }
void TypeCheck::visitLE(LE *le) void TypeCheck::visitEMul(EMul *e)
{ {
/* Code For LE Goes Here */ e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Int>();
} }
void TypeCheck::visitGTH(GTH *gth) void TypeCheck::visitEAdd(EAdd *e)
{ {
/* Code For GTH Goes Here */ e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Int>();
} }
void TypeCheck::visitGE(GE *ge) void TypeCheck::visitERel(ERel *e)
{ {
/* Code For GE Goes Here */ e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Bool>();
} }
void TypeCheck::visitEQU(EQU *equ) void TypeCheck::visitEAnd(EAnd *e)
{ {
/* Code For EQU Goes Here */ e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Bool expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Bool>();
} }
void TypeCheck::visitNE(NE *ne) void TypeCheck::visitEOr(EOr *e)
{ {
/* Code For NE Goes Here */ e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Bool expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Bool>();
} }
void TypeCheck::visitListTopDef(ListTopDef *list_top_def) void TypeCheck::visitListTopDef(ListTopDef *list_top_def)
{ {
for (ListTopDef::iterator i = list_top_def->begin() ; i != list_top_def->end() ; ++i) for (ListTopDef::iterator i = list_top_def->begin() ; i != list_top_def->end() ; ++i)
...@@ -664,14 +630,18 @@ void TypeCheck::visitIdent(Ident x) ...@@ -664,14 +630,18 @@ void TypeCheck::visitIdent(Ident x)
TypeCheck::TypeCheck()
: state(initialized)
{
}
void TypeCheck::check(Visitable *v) void TypeCheck::check(Visitable *v)
{ {
if (state != State::initialized) { if (state != State::initialized) {
throw std::runtime_error("already initialized"); throw std::runtime_error("already initialized");
} }
state = State::buildInfo;
v->accept(this);
state = State::checkType; state = State::checkType;
v->accept(this); v->accept(this);
} }
\ No newline at end of file
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
/* You might want to change the above name. */ /* You might want to change the above name. */
#include "Absyn.h" #include "Absyn.h"
#include "Info.h"
#include <memory>
class TypeCheck : public Visitor class TypeCheck : public Visitor
...@@ -12,8 +14,11 @@ class TypeCheck : public Visitor ...@@ -12,8 +14,11 @@ class TypeCheck : public Visitor
buildInfo, buildInfo,
checkType checkType
} state; } state;
Scope scope;
shared_ptr<Type> lastType;
public: public:
TypeCheck() : state(initialized) {}; TypeCheck();
void check(Visitable *v); void check(Visitable *v);
protected: protected:
void visitProgram(Program *p); void visitProgram(Program *p);
...@@ -87,17 +92,17 @@ protected: ...@@ -87,17 +92,17 @@ protected:
void visitERel(ERel *p); void visitERel(ERel *p);
void visitEAnd(EAnd *p); void visitEAnd(EAnd *p);
void visitEOr(EOr *p); void visitEOr(EOr *p);
void visitPlus(Plus *p); void visitPlus(Plus *p) {};
void visitMinus(Minus *p); void visitMinus(Minus *p) {};
void visitTimes(Times *p); void visitTimes(Times *p) {};
void visitDiv(Div *p); void visitDiv(Div *p) {};
void visitMod(Mod *p); void visitMod(Mod *p) {};
void visitLTH(LTH *p); void visitLTH(LTH *p) {};
void visitLE(LE *p); void visitLE(LE *p) {};
void visitGTH(GTH *p); void visitGTH(GTH *p) {};
void visitGE(GE *p); void visitGE(GE *p) {};
void visitEQU(EQU *p); void visitEQU(EQU *p) {};
void visitNE(NE *p); void visitNE(NE *p) {};
void visitListTopDef(ListTopDef *p); void visitListTopDef(ListTopDef *p);
void visitListArg(ListArg *p); void visitListArg(ListArg *p);
void visitListClassBlockDef(ListClassBlockDef *p); void visitListClassBlockDef(ListClassBlockDef *p);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment