Commit 37fabd11 authored by zygzagZ's avatar zygzagZ

refactor evalExpr

parent eb4aaa96
......@@ -75,7 +75,7 @@ void Prog::swap(Prog & other)
Prog::~Prog()
{
delete(listtopdef_);
if (listtopdef_) delete(listtopdef_);
}
......@@ -119,7 +119,7 @@ void FnDef::swap(FnDef & other)
FnDef::~FnDef()
{
delete(fundef_);
if (fundef_) delete(fundef_);
}
......@@ -163,7 +163,7 @@ void ClDef::swap(ClDef & other)
ClDef::~ClDef()
{
delete(classdef_);
if (classdef_) delete(classdef_);
}
......@@ -216,10 +216,10 @@ void FuncDef::swap(FuncDef & other)
FuncDef::~FuncDef()
{
delete(type_);
delete(pident_);
delete(listarg_);
delete(block_);
if (type_) delete(type_);
if (pident_) delete(pident_);
if (listarg_) delete(listarg_);
if (block_) delete(block_);
}
......@@ -266,8 +266,8 @@ void Ar::swap(Ar & other)
Ar::~Ar()
{
delete(type_);
delete(pident_);
if (type_) delete(type_);
if (pident_) delete(pident_);
}
......@@ -314,8 +314,8 @@ void ClassDefN::swap(ClassDefN & other)
ClassDefN::~ClassDefN()
{
delete(pident_);
delete(classblock_);
if (pident_) delete(pident_);
if (classblock_) delete(classblock_);
}
......@@ -365,9 +365,9 @@ void ClassDefE::swap(ClassDefE & other)
ClassDefE::~ClassDefE()
{
delete(pident_1);
delete(pident_2);
delete(classblock_);
if (pident_1) delete(pident_1);
if (pident_2) delete(pident_2);
if (classblock_) delete(classblock_);
}
......@@ -411,7 +411,7 @@ void ClassBl::swap(ClassBl & other)
ClassBl::~ClassBl()
{
delete(listclassblockdef_);
if (listclassblockdef_) delete(listclassblockdef_);
}
......@@ -455,7 +455,7 @@ void ClassMthd::swap(ClassMthd & other)
ClassMthd::~ClassMthd()
{
delete(fundef_);
if (fundef_) delete(fundef_);
}
......@@ -502,8 +502,8 @@ void ClassFld::swap(ClassFld & other)
ClassFld::~ClassFld()
{
delete(type_);
delete(listitem_);
if (type_) delete(type_);
if (listitem_) delete(listitem_);
}
......@@ -547,7 +547,7 @@ void Blk::swap(Blk & other)
Blk::~Blk()
{
delete(liststmt_);
if (liststmt_) delete(liststmt_);
}
......@@ -631,7 +631,7 @@ void BStmt::swap(BStmt & other)
BStmt::~BStmt()
{
delete(block_);
if (block_) delete(block_);
}
......@@ -678,8 +678,8 @@ void Decl::swap(Decl & other)
Decl::~Decl()
{
delete(type_);
delete(listitem_);
if (type_) delete(type_);
if (listitem_) delete(listitem_);
}
......@@ -726,8 +726,8 @@ void Ass::swap(Ass & other)
Ass::~Ass()
{
delete(expr_1);
delete(expr_2);
if (expr_1) delete(expr_1);
if (expr_2) delete(expr_2);
}
......@@ -771,7 +771,7 @@ void Incr::swap(Incr & other)
Incr::~Incr()
{
delete(expr_);
if (expr_) delete(expr_);
}
......@@ -815,7 +815,7 @@ void Decr::swap(Decr & other)
Decr::~Decr()
{
delete(expr_);
if (expr_) delete(expr_);
}
......@@ -859,7 +859,7 @@ void Ret::swap(Ret & other)
Ret::~Ret()
{
delete(expr_);
if (expr_) delete(expr_);
}
......@@ -946,8 +946,8 @@ void Cond::swap(Cond & other)
Cond::~Cond()
{
delete(expr_);
delete(stmt_);
if (expr_) delete(expr_);
if (stmt_) delete(stmt_);
}
......@@ -997,9 +997,9 @@ void CondElse::swap(CondElse & other)
CondElse::~CondElse()
{
delete(expr_);
delete(stmt_1);
delete(stmt_2);
if (expr_) delete(expr_);
if (stmt_1) delete(stmt_1);
if (stmt_2) delete(stmt_2);
}
......@@ -1046,8 +1046,8 @@ void While::swap(While & other)
While::~While()
{
delete(expr_);
delete(stmt_);
if (expr_) delete(expr_);
if (stmt_) delete(stmt_);
}
......@@ -1091,7 +1091,7 @@ void SExp::swap(SExp & other)
SExp::~SExp()
{
delete(expr_);
if (expr_) delete(expr_);
}
......@@ -1144,10 +1144,10 @@ void ForEach::swap(ForEach & other)
ForEach::~ForEach()
{
delete(type_);
delete(pident_);
delete(expr_);
delete(stmt_);
if (type_) delete(type_);
if (pident_) delete(pident_);
if (expr_) delete(expr_);
if (stmt_) delete(stmt_);
}
......@@ -1194,8 +1194,8 @@ void Item::swap(Item & other)
Item::~Item()
{
delete(pident_);
delete(expr_);
if (pident_) delete(pident_);
if (expr_) delete(expr_);
}
......@@ -1402,7 +1402,7 @@ void Array::swap(Array & other)
Array::~Array()
{
delete(type_);
if (type_) delete(type_);
}
......@@ -1444,7 +1444,7 @@ void ClassT::swap(ClassT & other)
ClassT::~ClassT()
{
delete(pident_);
if (pident_) delete(pident_);
}
......@@ -1491,8 +1491,8 @@ void Fun::swap(Fun & other)
Fun::~Fun()
{
delete(type_);
delete(listtype_);
if (type_) delete(type_);
if (listtype_) delete(listtype_);
}
......@@ -1536,7 +1536,7 @@ void EVar::swap(EVar & other)
EVar::~EVar()
{
delete(pident_);
if (pident_) delete(pident_);
}
......@@ -1583,8 +1583,8 @@ void EIndexAcc::swap(EIndexAcc & other)
EIndexAcc::~EIndexAcc()
{
delete(expr_1);
delete(expr_2);
if (expr_1) delete(expr_1);
if (expr_2) delete(expr_2);
}
......@@ -1631,8 +1631,8 @@ void EClsMmbr::swap(EClsMmbr & other)
EClsMmbr::~EClsMmbr()
{
delete(expr_);
delete(pident_);
if (expr_) delete(expr_);
if (pident_) delete(pident_);
}
......@@ -1679,8 +1679,8 @@ void EApp::swap(EApp & other)
EApp::~EApp()
{
delete(expr_);
delete(listexpr_);
if (expr_) delete(expr_);
if (listexpr_) delete(listexpr_);
}
......@@ -1893,8 +1893,8 @@ void ENewArray::swap(ENewArray & other)
ENewArray::~ENewArray()
{
delete(type_);
delete(expr_);
if (type_) delete(type_);
if (expr_) delete(expr_);
}
......@@ -1938,7 +1938,7 @@ void ENewClass::swap(ENewClass & other)
ENewClass::~ENewClass()
{
delete(pident_);
if (pident_) delete(pident_);
}
......@@ -1982,7 +1982,7 @@ void NullCast::swap(NullCast & other)
NullCast::~NullCast()
{
delete(expr_);
if (expr_) delete(expr_);
}
......@@ -2026,7 +2026,7 @@ void Neg::swap(Neg & other)
Neg::~Neg()
{
delete(expr_);
if (expr_) delete(expr_);
}
......@@ -2070,7 +2070,7 @@ void Not::swap(Not & other)
Not::~Not()
{
delete(expr_);
if (expr_) delete(expr_);
}
......@@ -2120,9 +2120,9 @@ void EMul::swap(EMul & other)
EMul::~EMul()
{
delete(expr_1);
delete(mulop_);
delete(expr_2);
if (expr_1) delete(expr_1);
if (mulop_) delete(mulop_);
if (expr_2) delete(expr_2);
}
......@@ -2172,9 +2172,9 @@ void EAdd::swap(EAdd & other)
EAdd::~EAdd()
{
delete(expr_1);
delete(addop_);
delete(expr_2);
if (expr_1) delete(expr_1);
if (addop_) delete(addop_);
if (expr_2) delete(expr_2);
}
......@@ -2224,9 +2224,9 @@ void ERel::swap(ERel & other)
ERel::~ERel()
{
delete(expr_1);
delete(relop_);
delete(expr_2);
if (expr_1) delete(expr_1);
if (relop_) delete(relop_);
if (expr_2) delete(expr_2);
}
......@@ -2273,8 +2273,8 @@ void EAnd::swap(EAnd & other)
EAnd::~EAnd()
{
delete(expr_1);
delete(expr_2);
if (expr_1) delete(expr_1);
if (expr_2) delete(expr_2);
}
......@@ -2321,8 +2321,8 @@ void EOr::swap(EOr & other)
EOr::~EOr()
{
delete(expr_1);
delete(expr_2);
if (expr_1) delete(expr_1);
if (expr_2) delete(expr_2);
}
......@@ -2879,6 +2879,7 @@ ListExpr *ListExpr::clone() const
std::string Fun::printName() const{
if (!type_) return "function";
std::string ret = type_->printName() + "(";
bool fst = true;
for (auto i : *listtype_) {
......
......@@ -665,7 +665,7 @@ public:
virtual void accept(Visitor *v);
virtual Str *clone() const;
void swap(Str &);
std::string printName() const { return "str"; }
std::string printName() const { return "string"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Str*>(other))
return true;
......@@ -739,11 +739,12 @@ public:
ClassT(const ClassT &);
ClassT &operator=(const ClassT &);
ClassT(PIdent *p1);
ClassT() : pident_(nullptr) {};
~ClassT();
virtual void accept(Visitor *v);
virtual ClassT *clone() const;
void swap(ClassT &);
std::string printName() const { return "class " + pident_->string_; }
std::string printName() const { return pident_ ? ("class " + pident_->string_) : "class"; }
bool isEqual(Type const *other) const;
};
......@@ -754,6 +755,7 @@ public:
ListType *listtype_;
Fun(const Fun &);
Fun() : type_(nullptr), listtype_(nullptr) {};
Fun &operator=(const Fun &);
Fun(Type *p1, ListType *p2);
~Fun();
......
......@@ -3,8 +3,6 @@
FunctionInfo::FunctionInfo(FuncDef *expr, ClassInfoPtr klass)
: VarInfo(expr->pident_, nullptr), block(expr->block_), klass(klass)
{
// TODO: tutaj leakujemy listtype
ListType *funArgs = new ListType();
type = make_shared<Fun>(expr->type_, funArgs);
arguments.reserve(expr->listarg_->size());
......@@ -29,6 +27,8 @@ ClassInfo::ClassInfo(PIdent *ident, BindingPtr parent /*= nullptr*/)
: VarInfo(ident),
Binding(parent)
{
type = make_shared<ClassT>(ident->clone());
type->binding = parent;
};
......
......@@ -12,8 +12,11 @@ class VarInfo {
public:
VarInfo(PIdent* ident, TypePtr type) : ident(ident), name(ident->string_), type(type), lineLocation(ident->lineno) {}
VarInfo(PIdent* ident, Type* type = nullptr) : ident(ident), name(ident->string_), type(type), lineLocation(ident->lineno) {}
VarInfo(string name, TypePtr type) : name(name), type(type), lineLocation(-1) {}
VarInfo(Ar* arg) : VarInfo(arg->pident_, arg->type_) {}
virtual ~VarInfo() {}
virtual string kind() const { return "variable"; }
string describe() const { return kind() + " " + name + " at line " + to_string(lineLocation); }
PIdent *ident;
string name;
......@@ -33,7 +36,10 @@ public:
weak_ptr<ClassInfo> klass;
weak_ptr<Binding> binding;
FunctionInfo(FuncDef *expr, ClassInfoPtr klass = nullptr);
FunctionInfo(string name, TypePtr type) : VarInfo(name, type) {};
// FunctionInfo(PIdent *ident, ClassInfoPtr klass = nullptr) : VarInfo(ident), block(NULL), klass(klass) {};
virtual string kind() const { return "function"; }
};
......@@ -56,7 +62,7 @@ public:
ClassInfo(PIdent *ident, BindingPtr parent = nullptr);
// ClassInfoPtr getParent() const { return dynamic_pointer_cast<ClassInfo>(parent); };
virtual string kind() const { return "class"; }
};
......
......@@ -70,7 +70,7 @@ int main(int argc, char ** argv)
TypeCheck checker;
checker.check(parse_tree);
} catch (ParseError const &e) {
std::cerr << "Error: " << e.what() << std::endl;
std::cerr << e.what() << std::endl;
return 1;
}
std::cout << "OK!" << endl;
......
......@@ -6,28 +6,17 @@ using namespace std;
ParseError::ParseError(string reason, int line) : runtime_error("ParseError"), line(line)
{
stringstream ss;
ss << "ParseError";
if (line != -1) {
ss << " at line " << line;
}
ss << ": " << reason;
msg = ss.str();
msg = reason + "\nAt line " + to_string(line);
}
ParseError::ParseError(string reason, Visitable *expr) : runtime_error("ParseError")
{
stringstream ss;
ss << "ParseError";
if (expr) {
line = expr->lineno;
ss << " at line " << line;
}
ss << ": " << reason;
if (expr) {
ss << " Expression: " << PrintAbsyn().print(expr);
}
msg = ss.str();
line = expr->lineno;
msg = reason + "\nIn expression at line " + to_string(line) + ": " + PrintAbsyn().print(expr);
}
ParseError::ParseError(string reason, VarInfo &var) : runtime_error("ParseError") {
msg = reason + "\nIn " + var.describe();
}
RedefinedError::RedefinedError(PIdent *ident, VarInfoPtr orig) {
......@@ -46,7 +35,7 @@ UndefinedError::UndefinedError(PIdent *ident) {
InvalidTypeError::InvalidTypeError(Type &expected, vector<shared_ptr<Type>> received, Visitable *expr) {
stringstream ss;
ss << "Invalid expression type at line " << expr->lineno << ". Expected \"" << expected.printName() << "\", instead received ";
ss << "Invalid expression type: Expected " << expected.printName() << ", instead received ";
bool fst = true;
for (auto i : received) {
if (fst) fst = false;
......@@ -55,17 +44,15 @@ InvalidTypeError::InvalidTypeError(Type &expected, vector<shared_ptr<Type>> rece
}
ss << ".";
if (expr) {
ss << " In: ";
PrintAbsyn p;
ss << p.print(expr);
line = expr->lineno;
ss << "\nIn expression at line " << line << ": " << PrintAbsyn().print(expr);
}
msg = ss.str();
line = expr->lineno;
}
InvalidTypeError::InvalidTypeError(Type &expected, vector<Type*> received, Visitable *expr) {
stringstream ss;
ss << "Invalid expression type at line " << expr->lineno << ". Expected \"" << expected.printName() << "\", instead received ";
ss << "Invalid expression type: Expected " << expected.printName() << ", instead received ";
bool fst = true;
for (auto i : received) {
if (fst) fst = false;
......@@ -74,9 +61,8 @@ InvalidTypeError::InvalidTypeError(Type &expected, vector<Type*> received, Visit
}
ss << ".";
if (expr) {
ss << " In: ";
PrintAbsyn p;
ss << p.print(expr);
line = expr->lineno;
ss << "\nIn expression at line " << line << ": " << PrintAbsyn().print(expr);
}
msg = ss.str();
line = expr->lineno;
......
......@@ -18,6 +18,8 @@ protected:
public:
ParseError(string reason, int line = -1);
ParseError(string reason, Visitable *expr);
ParseError(string reason, VarInfo &var);
ParseError(const ParseError &e, Visitable *expr) : ParseError(e.what(), expr) {};
virtual const char * what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { return msg.data(); }
};
......
......@@ -52,8 +52,7 @@ void TypeCheck::visitFuncDef(FuncDef *def)
FunctionInfoPtr f = make_shared<FunctionInfo>(def, scope->currentClass);
def->type_->accept(this);
// def->pident_->accept(this); // tego nie trzeba bo definiujemy a nie odwołujemy się
// pident nie trzeba bo definiujemy a nie odwołujemy się
// FunctionInfo tworzy argumenty
def->listarg_->accept(this);
......@@ -102,7 +101,6 @@ void TypeCheck::visitClassFld(ClassFld *decl)
VarInfoPtr var = make_shared<VarInfo>(el->pident_, type);
el->pident_->var = var;
scope->currentClass->variables << var;
cout << "class " << scope->currentClass << " adding ident " << el->pident_->string_ << endl;
}
}
......@@ -135,13 +133,13 @@ void TypeCheck::visitDecl(Decl *decl)
for (Item * el : *decl->listitem_) {
// el->accept(this); // nie trzeba bo el to tylko ident = expr
if (el->expr_) {
el->expr_->accept(this);
if (*type != *lastType) {
throw InvalidTypeError(*type, {lastType}, el->expr_);
auto exprType = evalExpr(el->expr_);
if (*type != *exprType) {
throw InvalidTypeError(*type, {exprType}, el->expr_);
}
}
VarInfoPtr var = make_shared<VarInfo>(el->pident_, type);
VarInfoPtr var = make_shared<VarInfo>(el->pident_, type->clone());
el->pident_->var = var;
scope->currentBinding->variables << var;
}
......@@ -149,10 +147,8 @@ void TypeCheck::visitDecl(Decl *decl)
void TypeCheck::visitAss(Ass *ass)
{
ass->expr_1->accept(this);
auto a = lastType;
ass->expr_2->accept(this);
auto b = lastType;
auto a = evalExpr(ass->expr_1);
auto b = evalExpr(ass->expr_2);
if (*a != *b) {
throw InvalidTypeError(*a, {b}, ass->expr_1);
}
......@@ -160,28 +156,18 @@ void TypeCheck::visitAss(Ass *ass)
void TypeCheck::visitIncr(Incr *incr)
{
Expr *e = incr->expr_;
e->accept(this);
Int expect;
if (*lastType != expect) {
throw InvalidTypeError(expect, {lastType}, e);
}
evalExpr<Int>(incr->expr_);
}
void TypeCheck::visitDecr(Decr *decr)
{
Expr *e = decr->expr_;
e->accept(this);
Int expect;
if (*lastType != expect) {
throw InvalidTypeError(expect, {lastType}, e);
}
evalExpr<Int>(decr->expr_);
}
void TypeCheck::visitRet(Ret *ret)
{
ret->expr_->accept(this);
checkReturnStatement(lastType, ret);
auto type = evalExpr(ret->expr_);
checkReturnStatement(type, ret);
}
void TypeCheck::visitVRet(VRet *v_ret)
......@@ -191,28 +177,26 @@ void TypeCheck::visitVRet(VRet *v_ret)
void TypeCheck::visitCond(Cond *cond)
{
cond->expr_->accept(this);
Bool expect;
if (*lastType != expect) {
throw InvalidTypeError(expect, {lastType}, cond->expr_);
}
auto type = evalExpr<Bool>(cond->expr_);
cond->stmt_->accept(this);
returnType = nullptr;
if (!dynamic_cast<ELitTrue*>(cond->expr_)) {
returnType = nullptr;
}
}
void TypeCheck::visitCondElse(CondElse *cond_else)
{
cond_else->expr_->accept(this);
Bool expect;
if (*lastType != expect) {
throw InvalidTypeError(expect, {lastType}, cond_else->expr_);
}
evalExpr<Bool>(cond_else->expr_);
cond_else->stmt_1->accept(this);
auto ret1 = returnType;
returnType = nullptr;
cond_else->stmt_2->accept(this);
auto ret2 = returnType;
if (ret1 && ret2) {
if (dynamic_cast<ELitTrue*>(cond_else->expr_)) {
returnType = ret1;
} else if (dynamic_cast<ELitFalse*>(cond_else->expr_)) {
returnType = ret2;
} else if (ret1 && ret2) {
if (*ret1 != *ret2) {
throw InvalidTypeError(*ret1, {ret2}, cond_else);
}
......@@ -242,6 +226,7 @@ void TypeCheck::visitForEach(ForEach *for_each)
{
BindingPtr binding = make_shared<Binding>(scope->currentBinding);
for_each->type_->accept(this);
Type &iterType = *lastType;
Array expect(for_each->type_);
for_each->expr_->accept(this);
if (*lastType != expect) {
......@@ -252,8 +237,6 @@ void TypeCheck::visitForEach(ForEach *for_each)
binding->variables << var;
scope->currentBinding = binding;
// TODO: czy chcemy tutaj do blocku przypisać binding?
for_each->stmt_->accept(this);
scope->currentBinding = binding->getParent();
......@@ -303,7 +286,7 @@ void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
e_index_acc->expr_1->accept(this);
shared_ptr<Array> type = dynamic_pointer_cast<Array>(lastType);
if (!type) {
throw ParseError("Oczekiwano tablicy", e_index_acc->expr_1);
throw ParseError("Table expected", e_index_acc->expr_1);
}
e_index_acc->expr_2->accept(this);
Int expect;
......@@ -317,11 +300,17 @@ void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
{
/* Code For EClsMmbr Goes Here */
e_cls_mmbr->expr_->accept(this);
shared_ptr<ClassT> type = dynamic_pointer_cast<ClassT>(lastType);
if (!type) {
throw ParseError("Oczekiwano klasy", e_cls_mmbr->expr_);
// it is an array and we ask for length
if (dynamic_pointer_cast<Array>(lastType)) {
if (e_cls_mmbr->pident_->string_ == "length") {
lastType = make_shared<Int>();
return;
}
}
throw ParseError("Class expected", e_cls_mmbr->expr_);
}
ClassInfoPtr klass = scope->currentBinding->classes[type->pident_];
VarInfoPtr var = klass->variables.local(e_cls_mmbr->pident_->string_);
......@@ -334,15 +323,25 @@ void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
void TypeCheck::visitEApp(EApp *e_app)
{
e_app->expr_->accept(this);
// FunctionInfo type nie jest poprawny, powinien być Fun!
shared_ptr<Fun> type = dynamic_pointer_cast<Fun>(lastType);
if (!type) {
throw ParseError("Oczekiwano funkcji", e_app->expr_);
shared_ptr<Fun> type = evalExpr<Fun>(e_app->expr_);
if (type->listtype_->size() != e_app->listexpr_->size()) {
throw ParseError("Expected " + to_string(type->listtype_->size()) + " arguments, " + to_string(e_app->listexpr_->size()) + " given", e_app);
}
for (unsigned int i = 0; i < type->listtype_->size(); i++) {
try {
Expr *expr = e_app->listexpr_->at(i);
expr->accept(this);
if (!lastType) throw ParseError("No expr return type", expr);
auto *expect = type->listtype_->at(i);
if (*expect != *lastType) {
throw InvalidTypeError(*expect, {lastType}, expr);
}
} catch (const ParseError &e) {
throw ParseError(string(e.what()) + "\nIn argument " + to_string(i+1) + " of function call:", e_app);
}
}
e_app->listexpr_->accept(this);
lastType = shared_ptr<Type>(type->type_->clone());
// TODO: sprawdzić parametry funkcji!
}
void TypeCheck::visitELitInt(ELitInt *e_lit_int)
......@@ -386,81 +385,62 @@ void TypeCheck::visitENewArray(ENewArray *e)
void TypeCheck::visitENewClass(ENewClass *e_new_class)
{
e_new_class->pident_->accept(this);
ClassInfoPtr klass = dynamic_pointer_cast<ClassInfo>(e_new_class->pident_->var.lock());
if (!klass) {
throw ParseError("Oczekiwano nazwy klasy", e_new_class->pident_);
}
auto ret = make_shared<ClassT>(e_new_class->pident_); // make type
ret->binding = scope->currentBinding;
lastType = ret;
// e_new_class->pident_->accept(this);
lastType = evalExpr<ClassT>(e_new_class->pident_);
// ClassInfoPtr klass = dynamic_pointer_cast<ClassInfo>(e_new_class->pident_->var.lock());
// if (!klass) {
// throw ParseError("Class expected", e_new_class->pident_);
// }
// auto ret = make_shared<ClassT>(e_new_class->pident_); // make type
// ret->binding = scope->currentBinding;
// lastType = ret;
}
void TypeCheck::visitNullCast(NullCast *null_cast)
{
lastType = nullptr;
null_cast->expr_->accept(this);
shared_ptr<ClassT> type = dynamic_pointer_cast<ClassT>(lastType);
if (!type) {
throw ParseError("Oczekiwano klasy", null_cast->expr_);
}
lastType = evalExpr<ClassT>(null_cast->expr_);
}
void TypeCheck::visitNeg(Neg *e)
{
e->expr_->accept(this);
auto a = lastType;
Int expect;
if (!a || *a != expect) {
throw InvalidTypeError(expect, {a}, e);
}
lastType = evalExpr<Int>(e->expr_);
}
void TypeCheck::visitNot(Not *e)
{
e->expr_->accept(this);
auto a = lastType;
Bool expect;
if (!a || *a != expect) {
throw InvalidTypeError(expect, {a}, e);
}
lastType = evalExpr<Bool>(e->expr_);
}
void TypeCheck::visitEMul(EMul *e)
{
e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (!a || !b || *a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e);
}
auto a = evalExpr<Int>(e->expr_1);
auto b = evalExpr<Int>(e->expr_2);
lastType = b;
}
void TypeCheck::visitEAdd(EAdd *e)
{
e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (!a || !b || *a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e);
auto a = evalExpr(e->expr_1);
auto b = evalExpr(e->expr_2);
if (dynamic_cast<Plus*>(e->addop_)) {
if (*a != *b) {
throw InvalidTypeError(*a, {b}, e);
}
} else {
Int expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e);
}
}
lastType = b;
}
void TypeCheck::visitERel(ERel *e)
{
e->expr_1->accept(this);
auto a = lastType;
if (!a) throw ParseError("Brak typu wyrażenia", e->expr_1);
e->expr_2->accept(this);
auto b = lastType;
if (!b) throw ParseError("Brak typu wyrażenia", e->expr_2);
auto a = evalExpr(e->expr_1);
auto b = evalExpr(e->expr_2);
if (dynamic_cast<EQU*>(e->relop_)) {
// equal
// TODO: EQUAL
if (*a != *b) {
throw InvalidTypeError(*a, {b}, e);
}
......@@ -563,25 +543,48 @@ TypeCheck::TypeCheck()
: state(initialized), scope(make_shared<Scope>())
{}
void TypeCheck::setupEnv() {
void TypeCheck::addIOFunctions(Type &type) {
string name = type.printName();
name[0] += 'A' - 'a';
TypePtr fun = make_shared<Fun>(type.clone(), new ListType()); // read
FunctionInfoPtr read = make_shared<FunctionInfo>("read" + name, fun);
scope->functions << read;
auto *v = new ListType();
v->push_back(type.clone());
fun = make_shared<Fun>(new Void(), v); // print
FunctionInfoPtr print = make_shared<FunctionInfo>("print" + name, fun);
scope->functions << print;
}
void TypeCheck::setupEnv() {
{ Int x; addIOFunctions(x); }
{ Str x; addIOFunctions(x); }
// { Bool x; addIOFunctions(x); }
}
void TypeCheck::check(Visitable *v)
{
if (state != State::initialized) {
throw std::runtime_error("already initialized");
}
setupEnv();
state = State::checkType;
v->accept(this);
for (auto c : scope->classes) {
scope->currentClass = c;
for (auto f : c->functions) {
checkFunction(f);
try {
for (auto f : c->functions) {
checkFunction(f);
}
} catch (const ParseError &e) {
throw ParseError(e.what(), *c);
}
scope->currentClass = nullptr;
}
for (auto f : scope->functions) {
......@@ -604,27 +607,32 @@ void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) {
void TypeCheck::checkFunction(FunctionInfoPtr f)
{
scope->currentFunction = f;
if (!f->block) return;
try {
scope->currentFunction = f;
if (f->binding.lock()) throw runtime_error("Ale ten binding juz istnieje");
if (f->binding.lock()) throw runtime_error("Ale ten binding juz istnieje");
BindingPtr binding = make_shared<Binding>(getParentBinding());
f->binding = binding;
BindingPtr binding = make_shared<Binding>(getParentBinding());
f->binding = binding;
for (auto arg : f->arguments) {
binding->variables << arg;
}
for (auto arg : f->arguments) {
binding->variables << arg;
}
scope->currentBinding = binding;
returnType = lastType = nullptr;
scope->currentBinding = binding;
returnType = lastType = nullptr;
f->block->accept(this);
f->block->accept(this);
checkFunctionRet();
checkFunctionRet();
scope->currentBinding = nullptr;
scope->currentBinding = nullptr;
scope->currentFunction = nullptr;
scope->currentFunction = nullptr;
} catch (const ParseError &e) {
throw ParseError(e.what(), *f);
}
}
void TypeCheck::checkFunctionRet() {
......@@ -634,7 +642,7 @@ void TypeCheck::checkFunctionRet() {
auto funRet = funType->type_;
if (*funRet != Void()) {
if (!returnType || returnType == nullptr) {
throw ParseError("Funkcja " + f->name + " nie zwróciła wyniku!", f->lineLocation);
throw ParseError("Function " + f->name + " did not return!", f->lineLocation);
}
if (*returnType != *funRet) {
throw InvalidTypeError(*returnType, {funRet}, f->block);
......@@ -644,4 +652,4 @@ void TypeCheck::checkFunctionRet() {
throw InvalidTypeError(*returnType, {funRet}, f->block);
}
}
}
\ No newline at end of file
}
......@@ -4,6 +4,7 @@
#include "Absyn.h"
#include "Info.h"
#include "ParseError.h"
#include <memory>
......@@ -17,11 +18,44 @@ class TypeCheck : public Visitor
shared_ptr<Scope> scope;
shared_ptr<Type> lastType, returnType;
set<int> posv;
void checkFunction(FunctionInfoPtr f);
void checkReturnStatement(shared_ptr<Type> type, Stmt *stmt);
void checkFunctionRet();
void addIOFunctions(Type &type);
void setupEnv();
template<typename T>
shared_ptr<T> evalExpr(Visitable *expr) {
if (!expr) throw runtime_error("No expr to eval");
lastType = nullptr;
try {
expr->accept(this);
} catch (const ParseError &err) {
throw ParseError(err, expr);
}
shared_ptr<T> ret = dynamic_pointer_cast<T>(lastType);
if (!ret) {
T expect;
throw InvalidTypeError(expect, {lastType}, expr);
}
lastType = nullptr;
return ret;
};
shared_ptr<Type> evalExpr(Visitable *expr) {
if (!expr) throw runtime_error("No expr to eval");
try {
expr->accept(this);
} catch (const ParseError &err) {
throw ParseError(err, expr);
}
if (!lastType) throw ParseError("No expression type", expr);
auto ret = lastType;
lastType = nullptr;
return ret;
};
public:
BindingPtr getParentBinding() const { return scope->currentClass ? static_pointer_cast<Binding>(scope->currentClass) : static_pointer_cast<Binding>(scope); }
TypeCheck();
......
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