Commit f608a142 authored by zygzagZ's avatar zygzagZ

arguments check in Fun Type compare, check const integer overflow, check void: arg, declaration

parent 519005ca
...@@ -2896,7 +2896,12 @@ bool Fun::isEqual(Type const *other, bool sub) const { ...@@ -2896,7 +2896,12 @@ bool Fun::isEqual(Type const *other, bool sub) const {
if (!type_->isEqual(casted->type_, sub) || listtype_->size() != casted->listtype_->size()) { if (!type_->isEqual(casted->type_, sub) || listtype_->size() != casted->listtype_->size()) {
return false; return false;
} }
// TODO: czy sprawdzać argumenty? for (unsigned int i = 0; i < listtype_->size(); i++) {
if (!casted->listtype_->at(i)->isEqual(listtype_->at(i), true)) {
return false;
}
}
return true;
} }
return false; return false;
} }
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
/******************** TypeDef Section ********************/ /******************** TypeDef Section ********************/
typedef int Integer; typedef long long int Integer;
typedef char Char; typedef char Char;
typedef double Double; typedef double Double;
typedef std::string String; typedef std::string String;
...@@ -229,6 +229,8 @@ public: ...@@ -229,6 +229,8 @@ public:
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, bool sub = false) const = 0; virtual bool isEqual(Type const *f, bool sub = false) const = 0;
template<typename T>
bool isEqual(shared_ptr<T> f, bool sub = false) const { return isEqual((T*)&*f, sub); };
bool operator==(Type const & f) const { return isEqual(&f); } bool operator==(Type const & f) const { return isEqual(&f); }
bool operator!=(Type const & f) const { return !isEqual(&f); } bool operator!=(Type const & f) const { return !isEqual(&f); }
}; };
......
...@@ -1137,7 +1137,7 @@ YY_BUFFER_APPEND(yytext); BEGIN STRING; ...@@ -1137,7 +1137,7 @@ YY_BUFFER_APPEND(yytext); BEGIN STRING;
case 60: case 60:
YY_RULE_SETUP YY_RULE_SETUP
#line 90 "Grammar.l" #line 90 "Grammar.l"
yylval.int_ = atoi(yytext); return _INTEGER_; yylval.int_ = ((strlen(yytext) > 18) ? (1ll<<60) : atoll(yytext)); return _INTEGER_;
YY_BREAK YY_BREAK
case 61: case 61:
/* rule 61 can match eol */ /* rule 61 can match eol */
......
...@@ -6,7 +6,9 @@ using namespace std; ...@@ -6,7 +6,9 @@ using namespace std;
ParseError::ParseError(string reason, int line) : runtime_error("ParseError"), line(line) ParseError::ParseError(string reason, int line) : runtime_error("ParseError"), line(line)
{ {
msg = reason + "\nAt line " + to_string(line); msg = reason;
if (line != -1)
msg += "\nAt line " + to_string(line);
} }
ParseError::ParseError(string reason, Visitable *expr) : runtime_error("ParseError") ParseError::ParseError(string reason, Visitable *expr) : runtime_error("ParseError")
......
...@@ -262,7 +262,7 @@ union YYSTYPE ...@@ -262,7 +262,7 @@ union YYSTYPE
{ {
#line 100 "Grammar.y" #line 100 "Grammar.y"
int int_; long long int int_;
char char_; char char_;
double double_; double double_;
char* string_; char* string_;
......
...@@ -30,7 +30,7 @@ class RelOp; ...@@ -30,7 +30,7 @@ class RelOp;
typedef union typedef union
{ {
int int_; long long int int_;
char char_; char char_;
double double_; double double_;
char* string_; char* string_;
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
#include "Printer.h" #include "Printer.h"
#include <climits>
void TypeCheck::visitClassDef(ClassDef *t) { void TypeCheck::visitClassDef(ClassDef *t) {
const string name = t->getName()->string_; const string name = t->getName()->string_;
...@@ -134,11 +135,15 @@ void TypeCheck::visitDecl(Decl *decl) ...@@ -134,11 +135,15 @@ void TypeCheck::visitDecl(Decl *decl)
Type* type = decl->type_; Type* type = decl->type_;
type->accept(this); type->accept(this);
if (dynamic_cast<Void*>(type)) {
throw ParseError("Void variable", type);
}
for (Item * el : *decl->listitem_) { for (Item * el : *decl->listitem_) {
// el->accept(this); // nie trzeba bo el to tylko ident = expr // el->accept(this); // nie trzeba bo el to tylko ident = expr
if (el->expr_) { if (el->expr_) {
auto exprType = evalExpr(el->expr_); auto exprType = evalExpr(el->expr_);
if (!type->isEqual(&*exprType, true)) { if (!type->isEqual(exprType, true)) {
throw InvalidTypeError(*type, {exprType}, el->expr_); throw InvalidTypeError(*type, {exprType}, el->expr_);
} }
} }
...@@ -153,7 +158,7 @@ void TypeCheck::visitAss(Ass *ass) ...@@ -153,7 +158,7 @@ void TypeCheck::visitAss(Ass *ass)
{ {
auto a = evalExpr(ass->expr_1); auto a = evalExpr(ass->expr_1);
auto b = evalExpr(ass->expr_2); auto b = evalExpr(ass->expr_2);
if (!a->isEqual(&*b, true)) { if (!a->isEqual(b, true)) {
throw InvalidTypeError(*a, {b}, ass->expr_1); throw InvalidTypeError(*a, {b}, ass->expr_1);
} }
} }
...@@ -214,7 +219,10 @@ void TypeCheck::visitWhile(While *while_) ...@@ -214,7 +219,10 @@ void TypeCheck::visitWhile(While *while_)
{ {
evalExpr<Bool>(while_->expr_); evalExpr<Bool>(while_->expr_);
while_->stmt_->accept(this); while_->stmt_->accept(this);
returnType = nullptr;
if (!dynamic_cast<ELitTrue*>(while_->expr_)) {
returnType = nullptr;
}
} }
void TypeCheck::visitSExp(SExp *s_exp) void TypeCheck::visitSExp(SExp *s_exp)
...@@ -228,7 +236,7 @@ void TypeCheck::visitForEach(ForEach *for_each) ...@@ -228,7 +236,7 @@ void TypeCheck::visitForEach(ForEach *for_each)
for_each->type_->accept(this); for_each->type_->accept(this);
Array expect(for_each->type_); Array expect(for_each->type_);
auto arrType = evalExpr<Array>(for_each->expr_); auto arrType = evalExpr<Array>(for_each->expr_);
if (*arrType != expect) { if (!expect.isEqual(&*arrType, true)) {
throw InvalidTypeError(expect, {arrType}, for_each->expr_); throw InvalidTypeError(expect, {arrType}, for_each->expr_);
} }
...@@ -328,7 +336,7 @@ void TypeCheck::visitEApp(EApp *e_app) ...@@ -328,7 +336,7 @@ void TypeCheck::visitEApp(EApp *e_app)
Expr *expr = e_app->listexpr_->at(i); Expr *expr = e_app->listexpr_->at(i);
auto exprType = evalExpr(expr); auto exprType = evalExpr(expr);
auto *expect = type->listtype_->at(i); auto *expect = type->listtype_->at(i);
if (*expect != *exprType) { if (!expect->isEqual(exprType, true)) {
throw InvalidTypeError(*expect, {exprType}, expr); throw InvalidTypeError(*expect, {exprType}, expr);
} }
} catch (const ParseError &e) { } catch (const ParseError &e) {
...@@ -345,6 +353,9 @@ void TypeCheck::visitEApp(EApp *e_app) ...@@ -345,6 +353,9 @@ void TypeCheck::visitEApp(EApp *e_app)
void TypeCheck::visitELitInt(ELitInt *e_lit_int) void TypeCheck::visitELitInt(ELitInt *e_lit_int)
{ {
visitInteger(e_lit_int->integer_); visitInteger(e_lit_int->integer_);
if (e_lit_int->integer_ > INT_MAX || e_lit_int->integer_ < INT_MIN) {
throw ParseError("constant too big", e_lit_int->lineno);
}
lastType = make_shared<Int>(); lastType = make_shared<Int>();
} }
...@@ -369,7 +380,7 @@ void TypeCheck::visitENewArray(ENewArray *e) ...@@ -369,7 +380,7 @@ void TypeCheck::visitENewArray(ENewArray *e)
evalExpr<Int>(e->expr_); evalExpr<Int>(e->expr_);
e->type_->accept(this); e->type_->accept(this);
if (dynamic_cast<Void*>(e->type_)) { if (dynamic_cast<Void*>(e->type_)) {
throw ParseError("Tablica typu void!", e); throw ParseError("Void table", e);
} }
auto ret = make_shared<Array>(e->type_->clone()); // make type auto ret = make_shared<Array>(e->type_->clone()); // make type
ret->type_->binding = scope->currentBinding; ret->type_->binding = scope->currentBinding;
...@@ -437,7 +448,7 @@ void TypeCheck::visitERel(ERel *e) ...@@ -437,7 +448,7 @@ void TypeCheck::visitERel(ERel *e)
auto a = evalExpr(e->expr_1); auto a = evalExpr(e->expr_1);
auto b = evalExpr(e->expr_2); auto b = evalExpr(e->expr_2);
if (dynamic_cast<EQU*>(e->relop_) || dynamic_cast<NE*>(e->relop_)) { if (dynamic_cast<EQU*>(e->relop_) || dynamic_cast<NE*>(e->relop_)) {
if (*a != *b) { if (!a->isEqual(b, true) && !b->isEqual(a, true)) {
throw InvalidTypeError(*a, {b}, e); throw InvalidTypeError(*a, {b}, e);
} }
} else { } else {
...@@ -591,6 +602,16 @@ void TypeCheck::check(Visitable *v) ...@@ -591,6 +602,16 @@ void TypeCheck::check(Visitable *v)
for (auto f : scope->functions) { for (auto f : scope->functions) {
checkFunction(f); checkFunction(f);
} }
if (FunctionInfoPtr main = scope->functions.local("main")) {
Fun expected(new Int(), new ListType());
if (!main->type->isEqual(&expected, false)) {
throw InvalidTypeError(expected, {main->type}, main->ident);
}
} else {
throw ParseError("No \"main\" function declared");
}
} }
void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) { void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) {
...@@ -600,7 +621,7 @@ void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) { ...@@ -600,7 +621,7 @@ void TypeCheck::checkReturnStatement(shared_ptr<Type> type, Stmt *stmt) {
if (!funType) throw runtime_error("FunctionInfo " + f->name + ":" + to_string(f->lineLocation) + " nie ma typu Fun!"); if (!funType) throw runtime_error("FunctionInfo " + f->name + ":" + to_string(f->lineLocation) + " nie ma typu Fun!");
auto funRet = funType->type_; auto funRet = funType->type_;
if (*type != *funRet) { if (!funRet->isEqual(type, true)) {
throw InvalidTypeError(*funRet, {type}, stmt); throw InvalidTypeError(*funRet, {type}, stmt);
} }
} }
...@@ -648,11 +669,11 @@ void TypeCheck::checkFunctionRet() { ...@@ -648,11 +669,11 @@ void TypeCheck::checkFunctionRet() {
if (!returnType || returnType == nullptr) { if (!returnType || returnType == nullptr) {
throw ParseError("Function " + f->name + " did not return!", f->lineLocation); throw ParseError("Function " + f->name + " did not return!", f->lineLocation);
} }
if (*returnType != *funRet) { if (!funRet->isEqual(returnType, true)) {
throw InvalidTypeError(*returnType, {funRet}, f->block); throw InvalidTypeError(*returnType, {funRet}, f->block);
} }
} else { } else {
if (returnType && *returnType != *funRet) { if (returnType && !funRet->isEqual(returnType, true)) {
throw InvalidTypeError(*returnType, {funRet}, f->block); throw InvalidTypeError(*returnType, {funRet}, f->block);
} }
} }
......
...@@ -147,7 +147,12 @@ protected: ...@@ -147,7 +147,12 @@ protected:
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) { p->type_->accept(this); }; void visitAr(Ar *p) {
p->type_->accept(this);
if (dynamic_cast<Void*>(p->type_)) {
throw ParseError("Void argument", p->type_);
}
};
// exprs // exprs
void visitPlus(Plus *p) {}; void visitPlus(Plus *p) {};
......
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