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