Commit 167d5a8c authored by zygzagZ's avatar zygzagZ

WIP type system

parent e83a94b3
......@@ -3165,3 +3165,24 @@ ListExpr *ListExpr::clone() const
{
return new ListExpr(*this);
}
std::string Fun::printName() const{
std::string ret = type_->printName() + "(";
bool fst = true;
for (auto i : *listtype_) {
if (fst) fst = false;
else ret += ", ";
ret += i->printName();
}
return ret + ")";
}
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;
}
return false;
}
\ No newline at end of file
......@@ -304,12 +304,16 @@ class Type : public Visitable
{
public:
virtual Type *clone() const = 0;
virtual std::string printName() const = 0;
virtual bool isEqual(Type const *f) const = 0;
bool operator==(Type const & f) { return isEqual(&f); }
bool operator!=(Type const & f) { return !isEqual(&f); }
};
class Expr : public Visitable
{
public:
int lineno;
virtual Expr *clone() const = 0;
};
......@@ -789,7 +793,6 @@ public:
class Int : public Type
{
public:
Int(const Int &);
Int &operator=(const Int &);
Int();
......@@ -797,12 +800,17 @@ public:
virtual void accept(Visitor *v);
virtual Int *clone() const;
void swap(Int &);
std::string printName() const { return "int"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Int*>(other))
return true;
return false;
}
};
class Str : public Type
{
public:
Str(const Str &);
Str &operator=(const Str &);
Str();
......@@ -810,6 +818,12 @@ public:
virtual void accept(Visitor *v);
virtual Str *clone() const;
void swap(Str &);
std::string printName() const { return "str"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Str*>(other))
return true;
return false;
}
};
class Bool : public Type
......@@ -823,6 +837,12 @@ public:
virtual void accept(Visitor *v);
virtual Bool *clone() const;
void swap(Bool &);
std::string printName() const { return "bool"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Bool*>(other))
return true;
return false;
}
};
class Void : public Type
......@@ -836,6 +856,12 @@ public:
virtual void accept(Visitor *v);
virtual Void *clone() const;
void swap(Void &);
std::string printName() const { return "void"; }
bool isEqual(Type const *other) const {
if (dynamic_cast<const Void*>(other))
return true;
return false;
}
};
class Array : public Type
......@@ -850,6 +876,12 @@ public:
virtual void accept(Visitor *v);
virtual Array *clone() const;
void swap(Array &);
std::string printName() const { return type_->printName() + "[]"; }
bool isEqual(Type const *other) const {
if (const Array* casted = dynamic_cast<const Array*>(other))
return *type_ == *casted->type_;
return false;
}
};
class ClassT : public Type
......@@ -864,6 +896,11 @@ 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;
}
};
class Fun : public Type
......@@ -879,6 +916,8 @@ public:
virtual void accept(Visitor *v);
virtual Fun *clone() const;
void swap(Fun &);
std::string printName() const;
bool isEqual(Type const *other) const;
};
class EVar : public Expr
......
#include "Info.h"
\ No newline at end of file
Scope g_scope;
......@@ -5,34 +5,100 @@
using namespace std;
class VarInfo {
public:
VarInfo(string n, int l)
: name(n), lineLocation(l) {}
VarInfo(PIdent* ident)
: VarInfo(ident->string_, ident->integer_) {}
string name;
string type;
Type *type;
int lineLocation;
bool operator<(const VarInfo &other) const {
return name != other.name ? name < other.name : type < other.type;
}
};
class FunctionInfo : VarInfo {
vector<VarInfo> arguments;
class ClassInfo;
class FunctionInfo : public VarInfo {
public:
Block * block;
vector<VarInfo*> arguments;
ClassInfo *klass;
FunctionInfo(PIdent *ident, ClassInfo *klass = NULL) : VarInfo(ident), klass(klass) {};
~FunctionInfo() {
for (auto &a : arguments)
delete a;
}
};
class ClassInfo : VarInfo
class ClassInfo : public VarInfo
{
ClassInfo * parent;
public:
vector<FunctionInfo*> functions;
vector<VarInfo*> variables;
ClassInfo(PIdent *ident, ClassInfo *parent = NULL) : VarInfo(ident), parent(parent) {};
ClassInfo * getParent() const { return parent; };
vector<FunctionInfo> functions;
vector<VarInfo> variables;
FunctionInfo* getFunction(string name) const {
for (auto i : functions)
if (i->name == name)
return i;
return parent ? parent->getFunction(name) : NULL;
}
};
VarInfo* getVar(string name) const {
for (auto i : variables)
if (i->name == name)
return i;
return parent ? parent->getVar(name) : NULL;
}
~ClassInfo() {
for (auto &f : functions)
delete f;
for (auto &v : variables)
delete v;
}
};
class Scope {
public:
vector<ClassInfo> classes;
vector<FunctionInfo> functions;
vector<ClassInfo*> classes;
vector<FunctionInfo*> functions;
ClassInfo *currentClass;
Scope() : currentClass(NULL) {}
~Scope() {
for (auto &c : classes)
delete c;
for (auto &f : functions)
delete f;
}
ClassInfo* getClass(string name) const {
for (auto i : classes)
if (i->name == name)
return i;
return NULL;
}
FunctionInfo* getFunction(string name, bool local = false) const {
if (currentClass && !local)
if (auto *f = currentClass->getFunction(name))
return f;
for (auto i : functions)
if (i->name == name)
return i;
return NULL;
}
};
extern Scope g_scope;
#endif
\ No newline at end of file
......@@ -50,7 +50,7 @@ int main(int argc, char ** argv)
/* The default entry point is used. For other options see Parser.H */
Program *parse_tree = pProgram(input);
if (!parse_tree) {
fprintf(stderr, "Parser error, invalid syntax!");
fprintf(stderr, "Parser error, invalid syntax!\n");
return 1;
}
......@@ -64,12 +64,13 @@ int main(int argc, char ** argv)
}
binaryPath = argv[0];
std::filesystem::path file(filename ? filename : "Instant");
TypeCheck checker;
std::filesystem::path file(filename ? filename : "Latte");
try {
TypeCheck checker;
checker.check(parse_tree);
} catch (ParseError &e) {
} catch (ParseError const &e) {
std::cerr << e.what() << std::endl;
return 1;
}
/*Compiler c(file);
std::string out = c.compile(parse_tree);
......
......@@ -7,7 +7,7 @@ FLEX_OPTS=-PGrammar
BISON=bison
BISON_OPTS=-t -pGrammar
OBJS=Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o
OBJS=Absyn.o Lexer.o Parser.o Printer.o TypeCheck.o Info.o ParseError.o
.PHONY : clean distclean
......@@ -16,9 +16,6 @@ all : latc
clean :
rm -f *.o latc Grammar.aux Grammar.log Grammar.pdf Grammar.dvi Grammar.ps Grammar
# distclean : clean
# rm -f Absyn.cpp Absyn.h Latte.cpp Parser.cpp Parser.h Lexer.cpp Skeleton.cpp Skeleton.h Printer.cpp Printer.h Makefile Grammar.l Grammar.y Grammar.tex
latc : ${OBJS} Latte.o
@echo "Linking latc..."
${CC} ${CCFLAGS} ${OBJS} Latte.o -o latc
......@@ -44,11 +41,14 @@ Printer.o : Printer.cpp Printer.h Absyn.h
Skeleton.o : Skeleton.cpp Skeleton.h Absyn.h
${CC} ${CCFLAGS} -Wno-unused-parameter -c Skeleton.cpp
Latte.o : Latte.cpp Parser.h Printer.h Absyn.h ParseError.h
Latte.o : Latte.cpp Parser.h Printer.h Absyn.h ParseError.h TypeCheck.h Info.h
${CC} ${CCFLAGS} -c Latte.cpp
TypeCheck.o : TypeCheck.cpp TypeCheck.h Absyn.h ParseError.h
TypeCheck.o : TypeCheck.cpp TypeCheck.h Info.h Absyn.h ParseError.h
${CC} ${CCFLAGS} -c TypeCheck.cpp
Info.o : Info.cpp Info.h Absyn.h
${CC} ${CCFLAGS} -c Info.cpp
ParseError.o : ParseError.cpp Info.h Absyn.h ParseError.h
${CC} ${CCFLAGS} -c ParseError.cpp
#include "ParseError.h"
#include "Info.h"
#include "Printer.h"
#include <sstream>
using namespace std;
RedefinedError::RedefinedError(PIdent *ident, VarInfo *orig) {
stringstream ss;
ss << "Variable \"" << ident->string_ << "\" at line " << ident->integer_ << " redeclared! First declaration at line " << orig->lineLocation;
msg = ss.str();
line = ident->integer_;
}
UndefinedError::UndefinedError(PIdent *ident) {
stringstream ss;
ss << "Undefined reference to \"" << ident->string_ << "\" at line " << ident->integer_;
msg = ss.str();
line = ident->integer_;
}
InvalidTypeError::InvalidTypeError(int lineno, Type &expected, vector<shared_ptr<Type>> received, Expr *expr) {
stringstream ss;
ss << "Invalid expression type at line " << 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 << " Expression: ";
PrintAbsyn p;
ss << p.print(expr);
}
msg = ss.str();
line = lineno;
}
\ No newline at end of file
#ifndef ERROR_HEADER
#define ERROR_HEADER
#include "Absyn.h"
#include <string>
#include <stdexcept>
#include <memory>
using namespace std;
class ParseError : std::exception {
class ParseError : std::runtime_error {
protected:
string msg;
int line;
ParseError() : runtime_error("ParseError"), line(-1) {}
public:
ParseError(string reason, int line = -1) : runtime_error("ParseError"), line(line) {}
virtual const char * what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW { return msg.data(); }
};
class PIdent;
class VarInfo;
class RedefinedError : public ParseError {
public:
RedefinedError(PIdent *ident, VarInfo *orig);
};
class UndefinedError : public ParseError {
public:
UndefinedError(PIdent *ident);
};
class InvalidTypeError : public ParseError {
public:
ParseError(string reason) : msg(reason) {}
const char * what() { return msg.data(); }
InvalidTypeError(int lineno, Type &expected, vector<shared_ptr<Type>> received, Expr *expr = NULL);
};
#endif
\ No newline at end of file
......@@ -2000,6 +2000,7 @@ yyreduce:
default: break;
}
// if (yyval.expr_) yyval.expr_->lineno = yy_mylinenumber;
/* User semantic actions sometimes alter yychar, and that requires
that yytoken be updated with the new translation. We take the
approach of translating immediately before every use of yytoken.
......
#include "TypeCheck.h"
#include "ParseError.h"
#include <stdexcept>
void TypeCheck::visitProgram(Program *t) {} //abstract class
......@@ -6,10 +7,25 @@ void TypeCheck::visitTopDef(TopDef *t) {} //abstract class
void TypeCheck::visitFunDef(FunDef *t) {} //abstract class
void TypeCheck::visitArg(Arg *t) {} //abstract class
void TypeCheck::visitClassDef(ClassDef *t) {
t->getName()->accept(this);
if (t->getParent())
t->getParent()->accept(this);
const string name = t->getName()->string_;
ClassInfo *c = scope.getClass(name);
if (c) {
throw RedefinedError(t->getName(), c);
}
ClassInfo *parent = NULL;
if (t->getParent()) {
const string parentName = t->getParent()->string_;
parent = scope.getClass(parentName);
if (!parent) {
throw UndefinedError(t->getParent());
}
}
c = new ClassInfo(t->getName(), parent);
scope.classes.push_back(c);
scope.currentClass = c;
t->getBlock()->accept(this);
scope.currentClass = NULL;
}
void TypeCheck::visitClassBlock(ClassBlock *t) {} //abstract class
......@@ -56,15 +72,19 @@ void TypeCheck::visitClDef(ClDef *cl_def)
}
void TypeCheck::visitFuncDef(FuncDef *func_def)
void TypeCheck::visitFuncDef(FuncDef *def)
{
/* Code For FuncDef Goes Here */
const string name = def->pident_->string_;
FunctionInfo *f = scope.getFunction(name);
if (f) {
throw RedefinedError(def->pident_, f);
}
func_def->type_->accept(this);
func_def->pident_->accept(this);
func_def->listarg_->accept(this);
func_def->block_->accept(this);
f = new FunctionInfo(def->pident_, scope.currentClass);
f->block = def->block_;
auto &targetVector = scope.currentClass ? scope.currentClass->functions : scope.functions;
targetVector.push_back(f);
}
void TypeCheck::visitAr(Ar *ar)
......@@ -338,24 +358,18 @@ void TypeCheck::visitEVar(EVar *e_var)
void TypeCheck::visitELitInt(ELitInt *e_lit_int)
{
/* Code For ELitInt Goes Here */
visitInteger(e_lit_int->integer_);
lastType = make_shared<Int>();
}
void TypeCheck::visitELitTrue(ELitTrue *e_lit_true)
{
/* Code For ELitTrue Goes Here */
lastType = make_shared<Bool>();
}
void TypeCheck::visitELitFalse(ELitFalse *e_lit_false)
{
/* Code For ELitFalse Goes Here */
lastType = make_shared<Bool>();
}
void TypeCheck::visitEApp(EApp *e_app)
......@@ -367,29 +381,37 @@ void TypeCheck::visitEApp(EApp *e_app)
}
void TypeCheck::visitEString(EString *e_string)
void TypeCheck::visitEString(EString *e)
{
/* Code For EString Goes Here */
visitString(e_string->string_);
visitString(e->string_);
auto a = lastType;
Str expect;
if (*a != expect) {
throw InvalidTypeError(e->lineno, expect, {a}, e);
}
lastType = make_shared<Str>();
}
void TypeCheck::visitENewArray(ENewArray *e_new_array)
void TypeCheck::visitENewArray(ENewArray *e)
{
/* Code For ENewArray Goes Here */
e_new_array->type_->accept(this);
e_new_array->expr_->accept(this);
e->type_->accept(this);
e->expr_->accept(this);
auto a = lastType;
Array expect(e->type_);
if (*a != expect) {
throw InvalidTypeError(e->lineno, expect, {a}, e);
}
lastType = make_shared<Array>(e->type_);
}
void TypeCheck::visitENewClass(ENewClass *e_new_class)
{
/* Code For ENewClass Goes Here */
e_new_class->pident_->accept(this);
lastType = make_shared<ClassT>(e_new_class->pident_);
}
void TypeCheck::visitEClsMmbr(EClsMmbr *e_cls_mmbr)
......@@ -411,11 +433,10 @@ void TypeCheck::visitEClsMthd(EClsMthd *e_cls_mthd)
}
void TypeCheck::visitNull(Null *null)
void TypeCheck::visitNull(Null *e)
{
/* Code For Null Goes Here */
PIdent *ident = new PIdent("null", e->lineno);
lastType = make_shared<ClassT>(ident); // TODO
}
void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
......@@ -424,7 +445,7 @@ void TypeCheck::visitEIndexAcc(EIndexAcc *e_index_acc)
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)
......@@ -433,151 +454,96 @@ void TypeCheck::visitECast(ECast *e_cast)
e_cast->pident_->accept(this);
e_cast->expr_->accept(this);
}
void TypeCheck::visitNeg(Neg *neg)
{
/* Code For Neg Goes Here */
neg->expr_->accept(this);
lastType = make_shared<ClassT>(e_cast->pident_);
}
void TypeCheck::visitNot(Not *not_)
void TypeCheck::visitNeg(Neg *e)
{
/* Code For Not Goes Here */
not_->expr_->accept(this);
}
void TypeCheck::visitEMul(EMul *e_mul)
{
/* Code For EMul Goes Here */
e_mul->expr_1->accept(this);
e_mul->mulop_->accept(this);
e_mul->expr_2->accept(this);
}
void TypeCheck::visitEAdd(EAdd *e_add)
{
/* Code For EAdd Goes Here */
e_add->expr_1->accept(this);
e_add->addop_->accept(this);
e_add->expr_2->accept(this);
}
void TypeCheck::visitERel(ERel *e_rel)
{
/* Code For ERel Goes Here */
e_rel->expr_1->accept(this);
e_rel->relop_->accept(this);
e_rel->expr_2->accept(this);
}
void TypeCheck::visitEAnd(EAnd *e_and)
{
/* Code For EAnd Goes Here */
e_and->expr_1->accept(this);
e_and->expr_2->accept(this);
}
void TypeCheck::visitEOr(EOr *e_or)
{
/* Code For EOr Goes Here */
e_or->expr_1->accept(this);
e_or->expr_2->accept(this);
}
void TypeCheck::visitPlus(Plus *plus)
{
/* Code For Plus Goes Here */
}
void TypeCheck::visitMinus(Minus *minus)
{
/* Code For Minus Goes Here */
}
void TypeCheck::visitTimes(Times *times)
{
/* Code For Times Goes Here */
}
void TypeCheck::visitDiv(Div *div)
{
/* Code For Div Goes Here */
}
void TypeCheck::visitMod(Mod *mod)
{
/* Code For Mod Goes Here */
e->expr_->accept(this);
auto a = lastType;
Int expect;
if (*a != expect) {
throw InvalidTypeError(e->lineno, expect, {a}, e);
}
lastType = make_shared<Int>();
}
void TypeCheck::visitLTH(LTH *lth)
void TypeCheck::visitNot(Not *e)
{
/* Code For LTH Goes Here */
e->expr_->accept(this);
auto a = lastType;
Bool expect;
if (*a != expect) {
throw InvalidTypeError(e->lineno, expect, {a}, e);
}
lastType = make_shared<Bool>();
}
void TypeCheck::visitLE(LE *le)
void TypeCheck::visitEMul(EMul *e)
{
/* Code For LE Goes Here */
e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Int>();
}
void TypeCheck::visitGTH(GTH *gth)
void TypeCheck::visitEAdd(EAdd *e)
{
/* Code For GTH Goes Here */
e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Int>();
}
void TypeCheck::visitGE(GE *ge)
void TypeCheck::visitERel(ERel *e)
{
/* Code For GE Goes Here */
e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Int expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Bool>();
}
void TypeCheck::visitEQU(EQU *equ)
void TypeCheck::visitEAnd(EAnd *e)
{
/* Code For EQU Goes Here */
e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Bool expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Bool>();
}
void TypeCheck::visitNE(NE *ne)
void TypeCheck::visitEOr(EOr *e)
{
/* Code For NE Goes Here */
e->expr_1->accept(this);
auto a = lastType;
e->expr_2->accept(this);
auto b = lastType;
Bool expect;
if (*a != expect || *a != *b) {
throw InvalidTypeError(e->lineno, expect, {a, b}, e);
}
lastType = make_shared<Bool>();
}
void TypeCheck::visitListTopDef(ListTopDef *list_top_def)
{
for (ListTopDef::iterator i = list_top_def->begin() ; i != list_top_def->end() ; ++i)
......@@ -664,14 +630,18 @@ void TypeCheck::visitIdent(Ident x)
TypeCheck::TypeCheck()
: state(initialized)
{
}
void TypeCheck::check(Visitable *v)
{
if (state != State::initialized) {
throw std::runtime_error("already initialized");
}
state = State::buildInfo;
v->accept(this);
state = State::checkType;
v->accept(this);
}
\ No newline at end of file
......@@ -3,6 +3,8 @@
/* You might want to change the above name. */
#include "Absyn.h"
#include "Info.h"
#include <memory>
class TypeCheck : public Visitor
......@@ -12,8 +14,11 @@ class TypeCheck : public Visitor
buildInfo,
checkType
} state;
Scope scope;
shared_ptr<Type> lastType;
public:
TypeCheck() : state(initialized) {};
TypeCheck();
void check(Visitable *v);
protected:
void visitProgram(Program *p);
......@@ -87,17 +92,17 @@ protected:
void visitERel(ERel *p);
void visitEAnd(EAnd *p);
void visitEOr(EOr *p);
void visitPlus(Plus *p);
void visitMinus(Minus *p);
void visitTimes(Times *p);
void visitDiv(Div *p);
void visitMod(Mod *p);
void visitLTH(LTH *p);
void visitLE(LE *p);
void visitGTH(GTH *p);
void visitGE(GE *p);
void visitEQU(EQU *p);
void visitNE(NE *p);
void visitPlus(Plus *p) {};
void visitMinus(Minus *p) {};
void visitTimes(Times *p) {};
void visitDiv(Div *p) {};
void visitMod(Mod *p) {};
void visitLTH(LTH *p) {};
void visitLE(LE *p) {};
void visitGTH(GTH *p) {};
void visitGE(GE *p) {};
void visitEQU(EQU *p) {};
void visitNE(NE *p) {};
void visitListTopDef(ListTopDef *p);
void visitListArg(ListArg *p);
void visitListClassBlockDef(ListClassBlockDef *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