Commit c7ae29b0 authored by zygzagZ's avatar zygzagZ

POC

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