Commit c7ae29b0 authored by zygzagZ's avatar zygzagZ

POC

parent 5f84c1c3
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "Absyn.h" #include "Absyn.h"
#include "Info.h"
/******************** PIdent ********************/ /******************** PIdent ********************/
PIdent::PIdent(String p1, Integer p2) PIdent::PIdent(String p1, Integer p2)
...@@ -1421,13 +1422,11 @@ Array *Array::clone() const ...@@ -1421,13 +1422,11 @@ Array *Array::clone() const
ClassT::ClassT(PIdent *p1) ClassT::ClassT(PIdent *p1)
{ {
pident_ = p1; pident_ = p1;
} }
ClassT::ClassT(const ClassT & other) ClassT::ClassT(const ClassT & other)
{ {
pident_ = other.pident_->clone(); pident_ = other.pident_->clone();
} }
ClassT &ClassT::operator=(const ClassT & other) ClassT &ClassT::operator=(const ClassT & other)
...@@ -1440,7 +1439,7 @@ ClassT &ClassT::operator=(const ClassT & other) ...@@ -1440,7 +1439,7 @@ ClassT &ClassT::operator=(const ClassT & other)
void ClassT::swap(ClassT & other) void ClassT::swap(ClassT & other)
{ {
std::swap(pident_, other.pident_); std::swap(pident_, other.pident_);
std::swap(binding, other.binding);
} }
ClassT::~ClassT() ClassT::~ClassT()
...@@ -2895,6 +2894,18 @@ bool Fun::isEqual(Type const *other) const { ...@@ -2895,6 +2894,18 @@ bool Fun::isEqual(Type const *other) const {
if (*type_ != *casted->type_ || listtype_->size() != casted->listtype_->size()) { if (*type_ != *casted->type_ || listtype_->size() != casted->listtype_->size()) {
return false; return false;
} }
// TODO: czy sprawdzać argumenty?
}
return false;
}
bool ClassT::isEqual(Type const *other) const {
if (const ClassT* casted = dynamic_cast<const ClassT*>(other)) {
BindingPtr ba = binding.lock(), bb = casted->binding.lock();
if (!ba || !bb) {
throw std::runtime_error("Binding nie znaleziony na typie klasy!");
}
return ba->classes[pident_] == bb->classes[pident_];
} }
return false; return false;
} }
...@@ -223,6 +223,8 @@ public: ...@@ -223,6 +223,8 @@ public:
class Type : public Visitable class Type : public Visitable
{ {
public: public:
// Type() {};
// Type(const &Type other) : binding(other.binding) {};
std::weak_ptr<Binding> binding; std::weak_ptr<Binding> binding;
virtual Type *clone() const = 0; virtual Type *clone() const = 0;
virtual std::string printName() const = 0; virtual std::string printName() const = 0;
...@@ -741,11 +743,8 @@ public: ...@@ -741,11 +743,8 @@ 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"; } std::string printName() const { return "class " + pident_->string_; }
bool isEqual(Type const *other) const { bool isEqual(Type const *other) const;
// TODO: implement ClassT comparison
return false;
}
}; };
class Fun : public Type class Fun : public Type
......
#include "Info.h" #include "Info.h"
FunctionInfo::FunctionInfo(FuncDef *expr, ClassInfoPtr klass) FunctionInfo::FunctionInfo(FuncDef *expr, ClassInfoPtr klass)
: VarInfo(expr->pident_, expr->type_), block(expr->block_), klass(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()); arguments.reserve(expr->listarg_->size());
for (auto arg : *expr->listarg_) { for (auto arg : *expr->listarg_) {
arguments.emplace_back(make_shared<VarInfo>((Ar*)arg)); arguments.emplace_back(make_shared<VarInfo>((Ar*)arg));
funArgs->emplace_back(arg->type_);
} }
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "Info.h" #include "Info.h"
#include "ParseError.h" #include "ParseError.h"
#include "TypeDefs.h" #include "TypeDefs.h"
#include <iostream>
template<typename T> template<typename T>
struct Compare struct Compare
......
...@@ -27,6 +27,7 @@ ParseError::ParseError(string reason, Visitable *expr) : runtime_error("ParseErr ...@@ -27,6 +27,7 @@ ParseError::ParseError(string reason, Visitable *expr) : runtime_error("ParseErr
if (expr) { if (expr) {
ss << " Expression: " << PrintAbsyn().print(expr); ss << " Expression: " << PrintAbsyn().print(expr);
} }
msg = ss.str();
} }
RedefinedError::RedefinedError(PIdent *ident, VarInfoPtr orig) { RedefinedError::RedefinedError(PIdent *ident, VarInfoPtr orig) {
......
...@@ -2,12 +2,15 @@ ...@@ -2,12 +2,15 @@
#include "ParseError.h" #include "ParseError.h"
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
#include "Printer.h"
void TypeCheck::visitClassDef(ClassDef *t) { void TypeCheck::visitClassDef(ClassDef *t) {
const string name = t->getName()->string_; const string name = t->getName()->string_;
BindingPtr parent; BindingPtr parent;
if (t->getParent()) { if (t->getParent()) {
parent = scope->classes[t->getParent()]; parent = scope->classes[t->getParent()];
if (!parent) { if (!parent) {
cout << "undef classdef !parent" << endl;
throw UndefinedError(t->getParent()); throw UndefinedError(t->getParent());
} }
} else { } else {
...@@ -31,26 +34,17 @@ void TypeCheck::visitPIdent(PIdent *p_ident) ...@@ -31,26 +34,17 @@ void TypeCheck::visitPIdent(PIdent *p_ident)
void TypeCheck::visitProg(Prog *prog) void TypeCheck::visitProg(Prog *prog)
{ {
/* Code For Prog Goes Here */
prog->listtopdef_->accept(this); prog->listtopdef_->accept(this);
} }
void TypeCheck::visitFnDef(FnDef *fn_def) void TypeCheck::visitFnDef(FnDef *fn_def)
{ {
/* Code For FnDef Goes Here */
fn_def->fundef_->accept(this); fn_def->fundef_->accept(this);
} }
void TypeCheck::visitClDef(ClDef *cl_def) void TypeCheck::visitClDef(ClDef *cl_def)
{ {
/* Code For ClDef Goes Here */
cl_def->classdef_->accept(this); cl_def->classdef_->accept(this);
} }
void TypeCheck::visitFuncDef(FuncDef *def) void TypeCheck::visitFuncDef(FuncDef *def)
...@@ -58,12 +52,12 @@ void TypeCheck::visitFuncDef(FuncDef *def) ...@@ -58,12 +52,12 @@ void TypeCheck::visitFuncDef(FuncDef *def)
FunctionInfoPtr f = make_shared<FunctionInfo>(def, scope->currentClass); FunctionInfoPtr f = make_shared<FunctionInfo>(def, scope->currentClass);
def->type_->accept(this); def->type_->accept(this);
def->pident_->accept(this); // def->pident_->accept(this); // tego nie trzeba bo definiujemy a nie odwołujemy się
// FunctionInfo tworzy argumenty // FunctionInfo tworzy argumenty
def->listarg_->accept(this); def->listarg_->accept(this);
auto &target = scope->currentClass ? scope->currentClass->functions : scope->functions; auto &target = getParentBinding()->functions;
target << f; target << f;
} }
...@@ -136,8 +130,10 @@ void TypeCheck::visitBStmt(BStmt *b_stmt) ...@@ -136,8 +130,10 @@ void TypeCheck::visitBStmt(BStmt *b_stmt)
void TypeCheck::visitDecl(Decl *decl) void TypeCheck::visitDecl(Decl *decl)
{ {
Type* type = decl->type_; Type* type = decl->type_;
type->accept(this);
for (Item * el : *decl->listitem_) { for (Item * el : *decl->listitem_) {
// el->accept(this); // nie trzeba bo el to tylko ident = expr
if (el->expr_) { if (el->expr_) {
el->expr_->accept(this); el->expr_->accept(this);
if (*type != *lastType) { if (*type != *lastType) {
...@@ -184,7 +180,6 @@ void TypeCheck::visitDecr(Decr *decr) ...@@ -184,7 +180,6 @@ void TypeCheck::visitDecr(Decr *decr)
void TypeCheck::visitRet(Ret *ret) void TypeCheck::visitRet(Ret *ret)
{ {
/* Code For Ret Goes Here */
ret->expr_->accept(this); ret->expr_->accept(this);
checkReturnStatement(lastType, ret); checkReturnStatement(lastType, ret);
} }
...@@ -196,8 +191,6 @@ void TypeCheck::visitVRet(VRet *v_ret) ...@@ -196,8 +191,6 @@ void TypeCheck::visitVRet(VRet *v_ret)
void TypeCheck::visitCond(Cond *cond) void TypeCheck::visitCond(Cond *cond)
{ {
/* Code For Cond Goes Here */
cond->expr_->accept(this); cond->expr_->accept(this);
Bool expect; Bool expect;
if (*lastType != expect) { if (*lastType != expect) {
...@@ -209,8 +202,6 @@ void TypeCheck::visitCond(Cond *cond) ...@@ -209,8 +202,6 @@ void TypeCheck::visitCond(Cond *cond)
void TypeCheck::visitCondElse(CondElse *cond_else) void TypeCheck::visitCondElse(CondElse *cond_else)
{ {
/* Code For CondElse Goes Here */
cond_else->expr_->accept(this); cond_else->expr_->accept(this);
Bool expect; Bool expect;
if (*lastType != expect) { if (*lastType != expect) {
...@@ -233,8 +224,6 @@ void TypeCheck::visitCondElse(CondElse *cond_else) ...@@ -233,8 +224,6 @@ void TypeCheck::visitCondElse(CondElse *cond_else)
void TypeCheck::visitWhile(While *while_) void TypeCheck::visitWhile(While *while_)
{ {
/* Code For While Goes Here */
while_->expr_->accept(this); while_->expr_->accept(this);
Bool expect; Bool expect;
if (*lastType != expect) { if (*lastType != expect) {
...@@ -252,6 +241,7 @@ void TypeCheck::visitSExp(SExp *s_exp) ...@@ -252,6 +241,7 @@ void TypeCheck::visitSExp(SExp *s_exp)
void TypeCheck::visitForEach(ForEach *for_each) void TypeCheck::visitForEach(ForEach *for_each)
{ {
BindingPtr binding = make_shared<Binding>(scope->currentBinding); BindingPtr binding = make_shared<Binding>(scope->currentBinding);
for_each->type_->accept(this);
Array expect(for_each->type_); Array expect(for_each->type_);
for_each->expr_->accept(this); for_each->expr_->accept(this);
if (*lastType != expect) { if (*lastType != expect) {
...@@ -262,6 +252,8 @@ void TypeCheck::visitForEach(ForEach *for_each) ...@@ -262,6 +252,8 @@ void TypeCheck::visitForEach(ForEach *for_each)
binding->variables << var; binding->variables << var;
scope->currentBinding = binding; scope->currentBinding = binding;
// TODO: czy chcemy tutaj do blocku przypisać binding?
for_each->stmt_->accept(this); for_each->stmt_->accept(this);
scope->currentBinding = binding->getParent(); scope->currentBinding = binding->getParent();
...@@ -288,12 +280,13 @@ void TypeCheck::visitArray(Array *array) ...@@ -288,12 +280,13 @@ void TypeCheck::visitArray(Array *array)
void TypeCheck::visitClassT(ClassT *class_t) void TypeCheck::visitClassT(ClassT *class_t)
{ {
class_t->binding = scope->currentBinding; class_t->binding = scope->currentBinding;
scope->currentBinding->classes[class_t->pident_]; ClassInfoPtr klass = scope->currentBinding->classes[class_t->pident_];
class_t->pident_->accept(this); class_t->pident_->var = klass;
} }
void TypeCheck::visitFun(Fun *fun) void TypeCheck::visitFun(Fun *fun)
{ {
fun->binding = scope->currentBinding;
fun->type_->accept(this); fun->type_->accept(this);
fun->listtype_->accept(this); fun->listtype_->accept(this);
...@@ -301,37 +294,55 @@ void TypeCheck::visitFun(Fun *fun) ...@@ -301,37 +294,55 @@ void TypeCheck::visitFun(Fun *fun)
void TypeCheck::visitEVar(EVar *e_var) void TypeCheck::visitEVar(EVar *e_var)
{ {
/* Code For EVar Goes Here */
e_var->pident_->accept(this); e_var->pident_->accept(this);
lastType = scope->currentBinding->variables[e_var->pident_]->type;
} }
void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc) void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
{ {
/* Code For EIndexAcc Goes Here */
e_index_acc->expr_1->accept(this); 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);
}
e_index_acc->expr_2->accept(this); e_index_acc->expr_2->accept(this);
Int expect;
if (*lastType != expect) {
throw InvalidTypeError(expect, {lastType}, e_index_acc->expr_2);
}
shared_ptr<Type> last(type->type_->clone());
last->binding = scope->currentBinding;
lastType = last;
} }
void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr) void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
{ {
/* Code For EClsMmbr Goes Here */ /* Code For EClsMmbr Goes Here */
e_cls_mmbr->expr_->accept(this); e_cls_mmbr->expr_->accept(this);
e_cls_mmbr->pident_->accept(this); shared_ptr<ClassT> type = dynamic_pointer_cast<ClassT>(lastType);
if (!type) {
throw ParseError("Oczekiwano klasy", e_cls_mmbr->expr_);
}
ClassInfoPtr klass = scope->currentBinding->classes[type->pident_];
VarInfoPtr var = klass->variables.local(e_cls_mmbr->pident_->string_);
if (!var) {
cout << "undef clsmmbr !var" << endl;
throw UndefinedError(e_cls_mmbr->pident_);
}
lastType = var->type;
} }
void TypeCheck::visitEApp(EApp *e_app) void TypeCheck::visitEApp(EApp *e_app)
{ {
/* Code For EApp Goes Here */
e_app->expr_->accept(this); 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_);
}
e_app->listexpr_->accept(this); e_app->listexpr_->accept(this);
lastType = shared_ptr<Type>(type->type_->clone());
// TODO: sprawdzić parametry funkcji!
} }
void TypeCheck::visitELitInt(ELitInt *e_lit_int) void TypeCheck::visitELitInt(ELitInt *e_lit_int)
...@@ -358,30 +369,41 @@ void TypeCheck::visitEString(EString *e) ...@@ -358,30 +369,41 @@ void TypeCheck::visitEString(EString *e)
void TypeCheck::visitENewArray(ENewArray *e) void TypeCheck::visitENewArray(ENewArray *e)
{ {
/* Code For ENewArray Goes Here */
e->type_->accept(this);
e->expr_->accept(this); e->expr_->accept(this);
auto a = lastType; auto a = lastType;
Array expect(e->type_); Int expect;
if (*a != expect) { if (*a != expect) {
throw InvalidTypeError(expect, {a}, e); throw InvalidTypeError(expect, {a}, e->expr_);
} }
lastType = make_shared<Array>(e->type_); e->type_->accept(this);
if (dynamic_cast<Void*>(e->type_)) {
throw ParseError("Tablica typu void!", e);
}
auto ret = make_shared<Array>(e->type_); // make type
ret->binding = scope->currentBinding;
lastType = ret;
} }
void TypeCheck::visitENewClass(ENewClass *e_new_class) void TypeCheck::visitENewClass(ENewClass *e_new_class)
{ {
e_new_class->pident_->accept(this); e_new_class->pident_->accept(this);
lastType = make_shared<ClassT>(e_new_class->pident_); 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;
} }
void TypeCheck::visitNullCast(NullCast *null_cast) void TypeCheck::visitNullCast(NullCast *null_cast)
{ {
/* Code For NullCast Goes Here */ lastType = nullptr;
null_cast->expr_->accept(this); null_cast->expr_->accept(this);
shared_ptr<ClassT> type = dynamic_pointer_cast<ClassT>(lastType);
if (!type) {
throw ParseError("Oczekiwano klasy", null_cast->expr_);
}
} }
void TypeCheck::visitNeg(Neg *e) void TypeCheck::visitNeg(Neg *e)
...@@ -389,10 +411,9 @@ void TypeCheck::visitNeg(Neg *e) ...@@ -389,10 +411,9 @@ void TypeCheck::visitNeg(Neg *e)
e->expr_->accept(this); e->expr_->accept(this);
auto a = lastType; auto a = lastType;
Int expect; Int expect;
if (*a != expect) { if (!a || *a != expect) {
throw InvalidTypeError(expect, {a}, e); throw InvalidTypeError(expect, {a}, e);
} }
lastType = make_shared<Int>();
} }
void TypeCheck::visitNot(Not *e) void TypeCheck::visitNot(Not *e)
...@@ -400,10 +421,9 @@ void TypeCheck::visitNot(Not *e) ...@@ -400,10 +421,9 @@ void TypeCheck::visitNot(Not *e)
e->expr_->accept(this); e->expr_->accept(this);
auto a = lastType; auto a = lastType;
Bool expect; Bool expect;
if (*a != expect) { if (!a || *a != expect) {
throw InvalidTypeError(expect, {a}, e); throw InvalidTypeError(expect, {a}, e);
} }
lastType = make_shared<Bool>();
} }
void TypeCheck::visitEMul(EMul *e) void TypeCheck::visitEMul(EMul *e)
...@@ -413,10 +433,9 @@ void TypeCheck::visitEMul(EMul *e) ...@@ -413,10 +433,9 @@ void TypeCheck::visitEMul(EMul *e)
e->expr_2->accept(this); e->expr_2->accept(this);
auto b = lastType; auto b = lastType;
Int expect; Int expect;
if (*a != expect || *a != *b) { if (!a || !b || *a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e); throw InvalidTypeError(expect, {a, b}, e);
} }
lastType = make_shared<Int>();
} }
void TypeCheck::visitEAdd(EAdd *e) void TypeCheck::visitEAdd(EAdd *e)
...@@ -426,22 +445,31 @@ void TypeCheck::visitEAdd(EAdd *e) ...@@ -426,22 +445,31 @@ void TypeCheck::visitEAdd(EAdd *e)
e->expr_2->accept(this); e->expr_2->accept(this);
auto b = lastType; auto b = lastType;
Int expect; Int expect;
if (*a != expect || *a != *b) { if (!a || !b || *a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e); throw InvalidTypeError(expect, {a, b}, e);
} }
lastType = make_shared<Int>();
} }
void TypeCheck::visitERel(ERel *e) void TypeCheck::visitERel(ERel *e)
{ {
e->expr_1->accept(this); e->expr_1->accept(this);
auto a = lastType; auto a = lastType;
if (!a) throw ParseError("Brak typu wyrażenia", e->expr_1);
e->expr_2->accept(this); e->expr_2->accept(this);
auto b = lastType; auto b = lastType;
if (!b) throw ParseError("Brak typu wyrażenia", e->expr_2);
if (dynamic_cast<EQU*>(e->relop_)) {
// equal
// TODO: EQUAL
if (*a != *b) {
throw InvalidTypeError(*a, {b}, e);
}
} else {
Int expect; Int expect;
if (*a != expect || *a != *b) { if (*a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e); throw InvalidTypeError(expect, {a, b}, e);
} }
}
lastType = make_shared<Bool>(); lastType = make_shared<Bool>();
} }
...@@ -452,10 +480,9 @@ void TypeCheck::visitEAnd(EAnd *e) ...@@ -452,10 +480,9 @@ void TypeCheck::visitEAnd(EAnd *e)
e->expr_2->accept(this); e->expr_2->accept(this);
auto b = lastType; auto b = lastType;
Bool expect; Bool expect;
if (*a != expect || *a != *b) { if (!a || !b || *a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e); throw InvalidTypeError(expect, {a, b}, e);
} }
lastType = make_shared<Bool>();
} }
void TypeCheck::visitEOr(EOr *e) void TypeCheck::visitEOr(EOr *e)
...@@ -465,10 +492,9 @@ void TypeCheck::visitEOr(EOr *e) ...@@ -465,10 +492,9 @@ void TypeCheck::visitEOr(EOr *e)
e->expr_2->accept(this); e->expr_2->accept(this);
auto b = lastType; auto b = lastType;
Bool expect; Bool expect;
if (*a != expect || *a != *b) { if (!a || !b || *a != expect || *a != *b) {
throw InvalidTypeError(expect, {a, b}, e); throw InvalidTypeError(expect, {a, b}, e);
} }
lastType = make_shared<Bool>();
} }
void TypeCheck::visitListTopDef(ListTopDef *list_top_def) void TypeCheck::visitListTopDef(ListTopDef *list_top_def)
...@@ -529,19 +555,16 @@ void TypeCheck::visitListExpr(ListExpr *list_expr) ...@@ -529,19 +555,16 @@ void TypeCheck::visitListExpr(ListExpr *list_expr)
} }
void TypeCheck::visitInteger(Integer x) void TypeCheck::visitInteger(Integer x) {}
{ void TypeCheck::visitString(String x) {}
/* Code for Integer Goes Here */
}
void TypeCheck::visitString(String x)
{
/* Code for String Goes Here */
}
TypeCheck::TypeCheck() TypeCheck::TypeCheck()
: state(initialized), scope(make_shared<Scope>()) : state(initialized), scope(make_shared<Scope>())
{ {}
void TypeCheck::setupEnv() {
} }
void TypeCheck::check(Visitable *v) void TypeCheck::check(Visitable *v)
...@@ -568,8 +591,13 @@ void TypeCheck::check(Visitable *v) ...@@ -568,8 +591,13 @@ void TypeCheck::check(Visitable *v)
void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) { void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) {
lastType = returnType = type; lastType = returnType = type;
if (*type != *scope->currentFunction->type) { auto f = scope->currentFunction;
throw InvalidTypeError(*scope->currentFunction->type, {type}, stmt); auto funType = dynamic_pointer_cast<Fun>(f->type);
if (!funType) throw runtime_error("FunctionInfo " + f->name + ":" + to_string(f->lineLocation) + " nie ma typu Fun!");
auto funRet = funType->type_;
if (*type != *funRet) {
throw InvalidTypeError(*funRet, {type}, stmt);
} }
} }
...@@ -580,7 +608,7 @@ void TypeCheck::checkFunction(FunctionInfoPtr f) ...@@ -580,7 +608,7 @@ void TypeCheck::checkFunction(FunctionInfoPtr f)
if (f->binding) throw runtime_error("Ale ten binding juz istnieje"); if (f->binding) throw runtime_error("Ale ten binding juz istnieje");
BindingPtr binding = make_shared<Binding>(scope->currentClass); BindingPtr binding = make_shared<Binding>(getParentBinding());
f->binding = binding; f->binding = binding;
for (auto arg : f->arguments) { for (auto arg : f->arguments) {
...@@ -592,6 +620,8 @@ void TypeCheck::checkFunction(FunctionInfoPtr f) ...@@ -592,6 +620,8 @@ void TypeCheck::checkFunction(FunctionInfoPtr f)
f->block->accept(this); f->block->accept(this);
checkFunctionRet();
scope->currentBinding = nullptr; scope->currentBinding = nullptr;
scope->currentFunction = nullptr; scope->currentFunction = nullptr;
...@@ -599,16 +629,19 @@ void TypeCheck::checkFunction(FunctionInfoPtr f) ...@@ -599,16 +629,19 @@ void TypeCheck::checkFunction(FunctionInfoPtr f)
void TypeCheck::checkFunctionRet() { void TypeCheck::checkFunctionRet() {
auto &f = scope->currentFunction; auto &f = scope->currentFunction;
if (*f->type != Void()) { auto funType = dynamic_pointer_cast<Fun>(f->type);
if (!funType) throw runtime_error("FunctionInfo " + f->name + ":" + to_string(f->lineLocation) + " nie ma typu Fun!");
auto funRet = funType->type_;
if (*funRet != Void()) {
if (!returnType || returnType == nullptr) { if (!returnType || returnType == nullptr) {
throw ParseError("Funkcja nie zwróciła wyniku!", f->lineLocation); throw ParseError("Funkcja " + f->name + " nie zwróciła wyniku!", f->lineLocation);
} }
if (*returnType != *f->type) { if (*returnType != *funRet) {
throw InvalidTypeError(*returnType, {f->type}, f->block); throw InvalidTypeError(*returnType, {funRet}, f->block);
} }
} else { } else {
if (returnType && *returnType != *f->type) { if (returnType && *returnType != *funRet) {
throw InvalidTypeError(*returnType, {f->type}, f->block); throw InvalidTypeError(*returnType, {funRet}, f->block);
} }
} }
} }
\ No newline at end of file
...@@ -21,7 +21,9 @@ class TypeCheck : public Visitor ...@@ -21,7 +21,9 @@ class TypeCheck : public Visitor
void checkFunction(FunctionInfoPtr f); void checkFunction(FunctionInfoPtr f);
void checkReturnStatement(shared_ptr<Type> type, Stmt *stmt); void checkReturnStatement(shared_ptr<Type> type, Stmt *stmt);
void checkFunctionRet(); void checkFunctionRet();
void setupEnv();
public: public:
BindingPtr getParentBinding() const { return scope->currentClass ? static_pointer_cast<Binding>(scope->currentClass) : static_pointer_cast<Binding>(scope); }
TypeCheck(); TypeCheck();
void check(Visitable *v); void check(Visitable *v);
protected: protected:
......
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