Commit 5f84c1c3 authored by zygzagZ's avatar zygzagZ

Scope dziedziczy z binding i kazda klasa ma jako parent binding global

scope
parent 08a16dd0
...@@ -1200,7 +1200,10 @@ Item::~Item() ...@@ -1200,7 +1200,10 @@ Item::~Item()
void Item::accept(Visitor *v) void Item::accept(Visitor *v)
{ {
v->visitItem(this); if (this->expr_)
v->visitInit(this);
else
v->visitNoInit(this);
} }
Item *Item::clone() const Item *Item::clone() const
...@@ -2888,9 +2891,10 @@ std::string Fun::printName() const{ ...@@ -2888,9 +2891,10 @@ std::string Fun::printName() const{
} }
bool Fun::isEqual(Type const *other) const { bool Fun::isEqual(Type const *other) const {
if (const Fun* casted = dynamic_cast<const Fun*>(other)) { if (const Fun* casted = dynamic_cast<const Fun*>(other)) {
if (*type_ != *casted->type_ || listtype_->size() != casted->listtype_->size()) return false; if (*type_ != *casted->type_ || listtype_->size() != casted->listtype_->size()) {
return false;
} }
return false; }
} return false;
\ No newline at end of file }
...@@ -223,6 +223,7 @@ public: ...@@ -223,6 +223,7 @@ public:
class Type : public Visitable class Type : public Visitable
{ {
public: public:
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;
virtual bool isEqual(Type const *f) const = 0; virtual bool isEqual(Type const *f) const = 0;
...@@ -258,7 +259,6 @@ public: ...@@ -258,7 +259,6 @@ public:
}; };
class VarInfo; class VarInfo;
class PIdent : public Visitable class PIdent : public Visitable
{ {
......
...@@ -11,7 +11,9 @@ FunctionInfo::FunctionInfo(FuncDef *expr, ClassInfoPtr klass) ...@@ -11,7 +11,9 @@ FunctionInfo::FunctionInfo(FuncDef *expr, ClassInfoPtr klass)
Binding::Binding(shared_ptr<Binding> parent) Binding::Binding(shared_ptr<Binding> parent)
: variables(parent ? parent->variables : nullptr), : variables(parent ? &parent->variables : nullptr),
classes(parent ? &parent->classes : nullptr, &variables),
functions(parent ? &parent->functions : nullptr, &variables),
parent(parent) parent(parent)
{ {
...@@ -19,16 +21,16 @@ Binding::Binding(shared_ptr<Binding> parent) ...@@ -19,16 +21,16 @@ Binding::Binding(shared_ptr<Binding> parent)
ClassInfo::ClassInfo(PIdent *ident, ClassInfoPtr parent /*= nullptr*/) ClassInfo::ClassInfo(PIdent *ident, BindingPtr parent /*= nullptr*/)
: VarInfo(ident), : VarInfo(ident),
Binding(parent), Binding(parent)
functions(parent ? parent->functions : nullptr)
{ {
}; };
Scope::Scope() Scope::Scope()
: currentClass(nullptr) : currentClass()
{ {
} }
\ No newline at end of file
...@@ -10,12 +10,14 @@ using namespace std; ...@@ -10,12 +10,14 @@ using namespace std;
class VarInfo { class VarInfo {
public: public:
VarInfo(PIdent* ident, Type* type = NULL) : ident(ident), name(ident->string_), type(type), lineLocation(ident->lineno) {} 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(Ar* arg) : VarInfo(arg->pident_, arg->type_) {} VarInfo(Ar* arg) : VarInfo(arg->pident_, arg->type_) {}
virtual ~VarInfo() {}
PIdent *ident; PIdent *ident;
string name; string name;
Type *type; TypePtr type;
int lineLocation; int lineLocation;
bool operator<(const VarInfo &other) const { bool operator<(const VarInfo &other) const {
...@@ -29,7 +31,7 @@ public: ...@@ -29,7 +31,7 @@ public:
Block * block; Block * block;
vector<VarInfoPtr> arguments; vector<VarInfoPtr> arguments;
weak_ptr<ClassInfo> klass; weak_ptr<ClassInfo> klass;
weak_ptr<Binding> binding; shared_ptr<Binding> binding;
FunctionInfo(FuncDef *expr, ClassInfoPtr klass = nullptr); FunctionInfo(FuncDef *expr, ClassInfoPtr klass = nullptr);
// FunctionInfo(PIdent *ident, ClassInfoPtr klass = nullptr) : VarInfo(ident), block(NULL), klass(klass) {}; // FunctionInfo(PIdent *ident, ClassInfoPtr klass = nullptr) : VarInfo(ident), block(NULL), klass(klass) {};
}; };
...@@ -39,8 +41,11 @@ public: ...@@ -39,8 +41,11 @@ public:
class Binding { class Binding {
public: public:
InfoList<VarInfo> variables; InfoList<VarInfo> variables;
InfoList<ClassInfo> classes;
InfoList<FunctionInfo> functions;
BindingPtr parent; BindingPtr parent;
Binding(BindingPtr parent); Binding(BindingPtr parent = nullptr);
BindingPtr getParent() const { return parent; }; BindingPtr getParent() const { return parent; };
}; };
...@@ -48,22 +53,19 @@ public: ...@@ -48,22 +53,19 @@ public:
class ClassInfo : public VarInfo, public Binding class ClassInfo : public VarInfo, public Binding
{ {
public: public:
InfoList<FunctionInfo> functions;
ClassInfo(PIdent *ident, ClassInfoPtr parent = nullptr); ClassInfo(PIdent *ident, BindingPtr parent = nullptr);
ClassInfoPtr getParent() const { return static_pointer_cast<ClassInfo>(parent); }; // ClassInfoPtr getParent() const { return dynamic_pointer_cast<ClassInfo>(parent); };
}; };
class Scope { class Scope : public Binding {
public: public:
InfoList<ClassInfo> classes;
InfoList<FunctionInfo> functions;
BindingPtr currentBinding; BindingPtr currentBinding;
ClassInfoPtr currentClass; ClassInfoPtr currentClass;
FunctionInfoPtr currentFunction; FunctionInfoPtr currentFunction;
Scope(); Scope();
}; };
#endif #endif
\ No newline at end of file
...@@ -17,13 +17,12 @@ struct Compare ...@@ -17,13 +17,12 @@ struct Compare
}; };
template<typename T, template<typename T, typename TPtr = shared_ptr<T>>
typename = typename std::enable_if<std::is_base_of<VarInfo, T>::value>::type,
typename TPtr = shared_ptr<T>>
class InfoList : public set<TPtr, Compare<TPtr>> { class InfoList : public set<TPtr, Compare<TPtr>> {
public: public:
InfoList<T> *parent; InfoList<T> *parent;
InfoList(InfoList<T> *p = nullptr) { parent = p; }; InfoList<VarInfo> *broader;
InfoList(InfoList<T> *p = nullptr, InfoList<VarInfo> *b = nullptr) : parent(p), broader(b) {};
TPtr operator[](PIdent *ident) const { TPtr operator[](PIdent *ident) const {
TPtr ret = local(ident->string_); TPtr ret = local(ident->string_);
if (ret) return ret; if (ret) return ret;
...@@ -37,6 +36,9 @@ public: ...@@ -37,6 +36,9 @@ public:
} }
void add(TPtr obj) { void add(TPtr obj) {
if (broader) {
broader->add(obj);
}
auto ret = this->emplace(obj); auto ret = this->emplace(obj);
if (!ret.second) { if (!ret.second) {
throw RedefinedError(obj->ident, *ret.first); throw RedefinedError(obj->ident, *ret.first);
......
...@@ -69,7 +69,7 @@ int main(int argc, char ** argv) ...@@ -69,7 +69,7 @@ int main(int argc, char ** argv)
TypeCheck checker; TypeCheck checker;
checker.check(parse_tree); checker.check(parse_tree);
} catch (ParseError const &e) { } catch (ParseError const &e) {
std::cerr << e.what() << std::endl; std::cerr << "Error: " << e.what() << std::endl;
return 1; return 1;
} }
std::cout << "OK!" << endl; std::cout << "OK!" << endl;
......
...@@ -4,6 +4,31 @@ ...@@ -4,6 +4,31 @@
#include <sstream> #include <sstream>
using namespace std; 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();
}
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);
}
}
RedefinedError::RedefinedError(PIdent *ident, VarInfoPtr orig) { RedefinedError::RedefinedError(PIdent *ident, VarInfoPtr orig) {
stringstream ss; stringstream ss;
ss << "Variable \"" << ident->string_ << "\" at line " << ident->lineno << " redeclared! First declaration at line " << orig->lineLocation; ss << "Variable \"" << ident->string_ << "\" at line " << ident->lineno << " redeclared! First declaration at line " << orig->lineLocation;
...@@ -18,7 +43,6 @@ UndefinedError::UndefinedError(PIdent *ident) { ...@@ -18,7 +43,6 @@ UndefinedError::UndefinedError(PIdent *ident) {
line = ident->lineno; line = ident->lineno;
} }
InvalidTypeError::InvalidTypeError(Type &expected, vector<shared_ptr<Type>> received, Visitable *expr) { InvalidTypeError::InvalidTypeError(Type &expected, vector<shared_ptr<Type>> received, Visitable *expr) {
stringstream ss; stringstream ss;
ss << "Invalid expression type at line " << expr->lineno << ". Expected \"" << expected.printName() << "\", instead received "; ss << "Invalid expression type at line " << expr->lineno << ". Expected \"" << expected.printName() << "\", instead received ";
...@@ -36,5 +60,23 @@ InvalidTypeError::InvalidTypeError(Type &expected, vector<shared_ptr<Type>> rece ...@@ -36,5 +60,23 @@ InvalidTypeError::InvalidTypeError(Type &expected, vector<shared_ptr<Type>> rece
} }
msg = ss.str(); msg = ss.str();
line = expr->lineno; line = expr->lineno;
}
} InvalidTypeError::InvalidTypeError(Type &expected, vector<Type*> received, Visitable *expr) {
\ No newline at end of file stringstream ss;
ss << "Invalid expression type at line " << expr->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 << " In: ";
PrintAbsyn p;
ss << p.print(expr);
}
msg = ss.str();
line = expr->lineno;
}
...@@ -14,9 +14,10 @@ class ParseError : std::runtime_error { ...@@ -14,9 +14,10 @@ class ParseError : std::runtime_error {
protected: protected:
string msg; string msg;
int line; int line;
ParseError() : runtime_error("ParseError"), line(-1) {} ParseError() : runtime_error("ParseError") {}
public: public:
ParseError(string reason, int line = -1) : runtime_error("ParseError"), line(line) {} ParseError(string reason, int line = -1);
ParseError(string reason, Visitable *expr);
virtual const char * what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { return msg.data(); } virtual const char * what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { return msg.data(); }
}; };
...@@ -35,6 +36,7 @@ public: ...@@ -35,6 +36,7 @@ public:
class InvalidTypeError : public ParseError { class InvalidTypeError : public ParseError {
public: public:
InvalidTypeError(Type &expected, vector<shared_ptr<Type>> received, Visitable *expr = NULL); InvalidTypeError(Type &expected, vector<shared_ptr<Type>> received, Visitable *expr = NULL);
InvalidTypeError(Type &expected, vector<Type*> received, Visitable *expr = NULL);
}; };
#endif #endif
\ No newline at end of file
...@@ -103,6 +103,9 @@ PrintAbsyn::PrintAbsyn(void) ...@@ -103,6 +103,9 @@ PrintAbsyn::PrintAbsyn(void)
PrintAbsyn::~PrintAbsyn(void) PrintAbsyn::~PrintAbsyn(void)
{ {
if (buf_) {
free(buf_);
}
} }
char *PrintAbsyn::print(Visitable *v) char *PrintAbsyn::print(Visitable *v)
......
...@@ -4,24 +4,29 @@ ...@@ -4,24 +4,29 @@
#include <iostream> #include <iostream>
void TypeCheck::visitClassDef(ClassDef *t) { void TypeCheck::visitClassDef(ClassDef *t) {
const string name = t->getName()->string_; const string name = t->getName()->string_;
ClassInfoPtr parent = NULL; BindingPtr parent;
if (t->getParent()) { if (t->getParent()) {
parent = scope.classes[t->getParent()]; parent = scope->classes[t->getParent()];
if (!parent) { if (!parent) {
throw UndefinedError(t->getParent()); throw UndefinedError(t->getParent());
} }
} else {
parent = scope;
} }
auto c = make_shared<ClassInfo>(t->getName(), parent); auto c = make_shared<ClassInfo>(t->getName(), parent);
scope.classes << c; scope->classes << c;
scope.currentClass = c; scope->currentBinding = scope->currentClass = c;
t->getBlock()->accept(this); t->getBlock()->accept(this);
scope.currentClass = NULL; scope->currentBinding = scope->currentClass = nullptr;
} }
void TypeCheck::visitPIdent(PIdent *p_ident) void TypeCheck::visitPIdent(PIdent *p_ident)
{ {
visitString(p_ident->string_); // visitString(p_ident->string_);
auto var = scope->currentBinding->variables[p_ident];
p_ident->var = var;
lastType = var->type;
} }
void TypeCheck::visitProg(Prog *prog) void TypeCheck::visitProg(Prog *prog)
...@@ -50,12 +55,16 @@ void TypeCheck::visitClDef(ClDef *cl_def) ...@@ -50,12 +55,16 @@ void TypeCheck::visitClDef(ClDef *cl_def)
void TypeCheck::visitFuncDef(FuncDef *def) 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->pident_->accept(this);
// FunctionInfo tworzy argumenty // FunctionInfo tworzy argumenty
def->listarg_->accept(this);
auto &targetVector = scope.currentClass ? scope.currentClass->functions : scope.functions; auto &target = scope->currentClass ? scope->currentClass->functions : scope->functions;
targetVector << f; target << f;
} }
void TypeCheck::visitClassDefN(ClassDefN *class_def_n) void TypeCheck::visitClassDefN(ClassDefN *class_def_n)
...@@ -84,12 +93,23 @@ void TypeCheck::visitClassMthd(ClassMthd *class_mthd) ...@@ -84,12 +93,23 @@ void TypeCheck::visitClassMthd(ClassMthd *class_mthd)
} }
void TypeCheck::visitClassFld(ClassFld *class_fld) void TypeCheck::visitClassFld(ClassFld *decl)
{ {
/* Code For ClassFld Goes Here */ decl->type_->accept(this);
decl->listitem_->accept(this);
class_fld->type_->accept(this); Type* type = decl->type_;
class_fld->listitem_->accept(this);
for (Item * el : *decl->listitem_) {
if (el->expr_) {
throw ParseError("Initialization in class variable definition", 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;
}
} }
...@@ -97,15 +117,15 @@ void TypeCheck::visitBlk(Blk *blk) ...@@ -97,15 +117,15 @@ void TypeCheck::visitBlk(Blk *blk)
{ {
BindingPtr binding = blk->binding.lock(); BindingPtr binding = blk->binding.lock();
if (!binding) { if (!binding) {
binding = make_shared<Binding>(scope.currentBinding); binding = make_shared<Binding>(scope->currentBinding);
blk->binding = binding; blk->binding = binding;
} }
scope.currentBinding = binding; scope->currentBinding = binding;
blk->liststmt_->accept(this); blk->liststmt_->accept(this);
scope.currentBinding = binding->getParent(); scope->currentBinding = binding->getParent();
} }
void TypeCheck::visitBStmt(BStmt *b_stmt) void TypeCheck::visitBStmt(BStmt *b_stmt)
...@@ -118,11 +138,16 @@ void TypeCheck::visitDecl(Decl *decl) ...@@ -118,11 +138,16 @@ void TypeCheck::visitDecl(Decl *decl)
Type* type = decl->type_; Type* type = decl->type_;
for (Item * el : *decl->listitem_) { for (Item * el : *decl->listitem_) {
el->expr_->accept(this); if (el->expr_) {
el->expr_->accept(this);
if (*type != *lastType) {
throw InvalidTypeError(*type, {lastType}, el->expr_);
}
}
VarInfoPtr var = make_shared<VarInfo>(el->pident_, type); VarInfoPtr var = make_shared<VarInfo>(el->pident_, type);
el->pident_->var = var; el->pident_->var = var;
scope.currentBinding->variables << var; scope->currentBinding->variables << var;
} }
} }
...@@ -161,12 +186,12 @@ void TypeCheck::visitRet(Ret *ret) ...@@ -161,12 +186,12 @@ void TypeCheck::visitRet(Ret *ret)
{ {
/* Code For Ret Goes Here */ /* Code For Ret Goes Here */
ret->expr_->accept(this); ret->expr_->accept(this);
checkReturn(lastType, ret); checkReturnStatement(lastType, ret);
} }
void TypeCheck::visitVRet(VRet *v_ret) void TypeCheck::visitVRet(VRet *v_ret)
{ {
checkReturn(make_shared<Void>(), v_ret); checkReturnStatement(make_shared<Void>(), v_ret);
} }
void TypeCheck::visitCond(Cond *cond) void TypeCheck::visitCond(Cond *cond)
...@@ -221,71 +246,54 @@ void TypeCheck::visitWhile(While *while_) ...@@ -221,71 +246,54 @@ void TypeCheck::visitWhile(While *while_)
void TypeCheck::visitSExp(SExp *s_exp) void TypeCheck::visitSExp(SExp *s_exp)
{ {
/* Code For SExp Goes Here */
s_exp->expr_->accept(this); s_exp->expr_->accept(this);
} }
void TypeCheck::visitForEach(ForEach *for_each) void TypeCheck::visitForEach(ForEach *for_each)
{ {
/* Code For ForEach Goes Here */ BindingPtr binding = make_shared<Binding>(scope->currentBinding);
Array expect(for_each->type_);
for_each->type_->accept(this);
for_each->pident_->accept(this);
for_each->expr_->accept(this); for_each->expr_->accept(this);
if (*lastType != expect) {
throw InvalidTypeError(expect, {lastType}, for_each->expr_);
}
VarInfoPtr var = make_shared<VarInfo>(for_each->pident_, lastType);
binding->variables << var;
scope->currentBinding = binding;
for_each->stmt_->accept(this); for_each->stmt_->accept(this);
scope->currentBinding = binding->getParent();
} }
void TypeCheck::visitInt(Int *int_) void TypeCheck::visitInt(Int *int_)
{ {}
/* Code For Int Goes Here */
}
void TypeCheck::visitStr(Str *str) void TypeCheck::visitStr(Str *str)
{ {}
/* Code For Str Goes Here */
}
void TypeCheck::visitBool(Bool *bool_) void TypeCheck::visitBool(Bool *bool_)
{ {}
/* Code For Bool Goes Here */
}
void TypeCheck::visitVoid(Void *void_) void TypeCheck::visitVoid(Void *void_)
{ {}
/* Code For Void Goes Here */
}
void TypeCheck::visitArray(Array *array) void TypeCheck::visitArray(Array *array)
{ {
/* Code For Array Goes Here */ array->binding = scope->currentBinding;
array->type_->accept(this); array->type_->accept(this);
} }
void TypeCheck::visitClassT(ClassT *class_t) void TypeCheck::visitClassT(ClassT *class_t)
{ {
/* Code For ClassT Goes Here */ class_t->binding = scope->currentBinding;
scope->currentBinding->classes[class_t->pident_];
class_t->pident_->accept(this); class_t->pident_->accept(this);
} }
void TypeCheck::visitFun(Fun *fun) void TypeCheck::visitFun(Fun *fun)
{ {
/* Code For Fun Goes Here */
fun->type_->accept(this); fun->type_->accept(this);
fun->listtype_->accept(this); fun->listtype_->accept(this);
...@@ -344,14 +352,7 @@ void TypeCheck::visitELitFalse(ELitFalse *e_lit_false) ...@@ -344,14 +352,7 @@ void TypeCheck::visitELitFalse(ELitFalse *e_lit_false)
void TypeCheck::visitEString(EString *e) void TypeCheck::visitEString(EString *e)
{ {
/* Code For EString Goes Here */
visitString(e->string_); visitString(e->string_);
auto a = lastType;
Str expect;
if (*a != expect) {
throw InvalidTypeError(expect, {a}, e);
}
lastType = make_shared<Str>(); lastType = make_shared<Str>();
} }
...@@ -383,49 +384,6 @@ void TypeCheck::visitNullCast(NullCast *null_cast) ...@@ -383,49 +384,6 @@ void TypeCheck::visitNullCast(NullCast *null_cast)
} }
// void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
// {
// /* Code For EClsMmbr Goes Here */
// e_cls_mmbr->expr_->accept(this);
// e_cls_mmbr->pident_->accept(this);
// }
// void TypeCheck::visitEClsMthd(EClsMthd *e_cls_mthd)
// {
// /* Code For EClsMthd Goes Here */
// e_cls_mthd->expr_->accept(this);
// e_cls_mthd->pident_->accept(this);
// e_cls_mthd->listexpr_->accept(this);
// }
// void TypeCheck::visitNull(Null *e)
// {
// PIdent *ident = new PIdent("null", e->lineno);
// lastType = make_shared<ClassT>(ident); // TODO
// }
// void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
// {
// /* Code For EIndexAcc Goes Here */
// e_index_acc->pident_->accept(this);
// e_index_acc->expr_->accept(this);
// throw UndefinedError(e_index_acc->pident_); // TODO
// }
// void TypeCheck::visitECast(ECast *e_cast)
// {
// /* Code For ECast Goes Here */
// e_cast->pident_->accept(this);
// e_cast->expr_->accept(this);
// lastType = make_shared<ClassT>(e_cast->pident_);
// }
void TypeCheck::visitNeg(Neg *e) void TypeCheck::visitNeg(Neg *e)
{ {
e->expr_->accept(this); e->expr_->accept(this);
...@@ -582,7 +540,7 @@ void TypeCheck::visitString(String x) ...@@ -582,7 +540,7 @@ void TypeCheck::visitString(String x)
} }
TypeCheck::TypeCheck() TypeCheck::TypeCheck()
: state(initialized) : state(initialized), scope(make_shared<Scope>())
{ {
} }
...@@ -594,55 +552,63 @@ void TypeCheck::check(Visitable *v) ...@@ -594,55 +552,63 @@ void TypeCheck::check(Visitable *v)
state = State::checkType; state = State::checkType;
v->accept(this); v->accept(this);
for (auto c : scope.classes) { for (auto c : scope->classes) {
scope.currentClass = c; scope->currentClass = c;
for (auto f : c->functions) { for (auto f : c->functions) {
checkFunction(f); checkFunction(f);
} }
scope.currentClass = nullptr; scope->currentClass = nullptr;
} }
for (auto f : scope.functions) { for (auto f : scope->functions) {
checkFunction(f); checkFunction(f);
} }
} }
void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) {
lastType = returnType = type;
if (*type != *scope->currentFunction->type) {
throw InvalidTypeError(*scope->currentFunction->type, {type}, stmt);
}
}
void TypeCheck::checkFunction(FunctionInfoPtr f) void TypeCheck::checkFunction(FunctionInfoPtr f)
{ {
scope.currentFunction = f; scope->currentFunction = f;
std::cout << "checking fun " << f->name << " at line " << f->lineLocation << endl; if (f->binding) throw runtime_error("Ale ten binding juz istnieje");
BindingPtr binding = make_shared<Binding>(nullptr); BindingPtr binding = make_shared<Binding>(scope->currentClass);
f->binding = binding; f->binding = binding;
for (auto arg : f->arguments) { for (auto arg : f->arguments) {
binding->variables << arg; binding->variables << arg;
} }
scope->currentBinding = binding;
returnType = lastType = nullptr;
f->block->accept(this); f->block->accept(this);
scope->currentBinding = nullptr;
scope->currentFunction = nullptr;
}
void TypeCheck::checkFunctionRet() {
auto &f = scope->currentFunction;
if (*f->type != Void()) { if (*f->type != Void()) {
if (!returnType) { if (!returnType || returnType == nullptr) {
throw ParseError("Funkcja nie zwróciła wyniku!", f->lineLocation); throw ParseError("Funkcja nie zwróciła wyniku!", f->lineLocation);
} }
if (*returnType != *f->type) { if (*returnType != *f->type) {
throw InvalidTypeError(*returnType, {&*f->type}, f->block); throw InvalidTypeError(*returnType, {f->type}, f->block);
} }
} else { } else {
if (returnType && *returnType != *f->type) { if (returnType && *returnType != *f->type) {
throw InvalidTypeError(*returnType, {&*f->type}, f->block); throw InvalidTypeError(*returnType, {f->type}, f->block);
} }
} }
scope.currentFunction = nullptr;
}
void TypeCheck::checkReturn(shared_ptr<Type> type, Stmt *stmt) {
lastType = returnType = type;
if (*type != *scope.currentFunction->type) {
throw InvalidTypeError(*scope.currentFunction->type, {type}, stmt);
}
} }
\ No newline at end of file
...@@ -15,11 +15,12 @@ class TypeCheck : public Visitor ...@@ -15,11 +15,12 @@ class TypeCheck : public Visitor
checkType checkType
} state; } state;
Scope scope; shared_ptr<Scope> scope;
shared_ptr<Type> lastType, returnType; shared_ptr<Type> lastType, returnType;
void checkFunction(FunctionInfoPtr f); void checkFunction(FunctionInfoPtr f);
void checkReturn(shared_ptr<Type> type, Stmt *stmt); void checkReturnStatement(shared_ptr<Type> type, Stmt *stmt);
void checkFunctionRet();
public: public:
TypeCheck(); TypeCheck();
void check(Visitable *v); void check(Visitable *v);
...@@ -106,9 +107,9 @@ protected: ...@@ -106,9 +107,9 @@ protected:
// stmts // stmts
void visitEmpty(Empty *p) {}; void visitEmpty(Empty *p) {};
void visitNoInit(NoInit *p) {}; void visitNoInit(NoInit *p) { };
void visitInit(Init *p) {}; void visitInit(Init *p) { };
void visitAr(Ar *p) {}; void visitAr(Ar *p) { p->type_->accept(this); };
// exprs // exprs
void visitPlus(Plus *p) {}; void visitPlus(Plus *p) {};
......
...@@ -14,6 +14,7 @@ using VarInfoPtr = shared_ptr<VarInfo>; ...@@ -14,6 +14,7 @@ using VarInfoPtr = shared_ptr<VarInfo>;
using FunctionInfoPtr = shared_ptr<FunctionInfo>; using FunctionInfoPtr = shared_ptr<FunctionInfo>;
using ClassInfoPtr = shared_ptr<ClassInfo>; using ClassInfoPtr = shared_ptr<ClassInfo>;
using BindingPtr = shared_ptr<Binding>; using BindingPtr = shared_ptr<Binding>;
using TypePtr = shared_ptr<Type>;
class Visitable; class Visitable;
......
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