Skip to content

Commit

Permalink
to begin MC
Browse files Browse the repository at this point in the history
research x86 ISA
  • Loading branch information
rechardchen committed May 17, 2017
1 parent 0a1e33e commit afcfcec
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 46 deletions.
4 changes: 2 additions & 2 deletions absyn.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,14 +167,14 @@ namespace tiger
VarDec() :BaseASTNode(A_VarDec) {}
std::string name, type;
ASTNode init=nullptr;
bool escape = false;
bool escape = true;
};
struct Field : public BaseASTNode
{
Field() : BaseASTNode(A_Field) {}
std::string name;
std::string type;
bool escape = false;
bool escape = true;
};
struct TyFields : public BaseASTNode
{
Expand Down
202 changes: 169 additions & 33 deletions semant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "type.h"
#include "translate.h"

//TODO:
//error recovery policy:1. add position info in reportErr 2.report error like gcc
namespace tiger {

#define VALID_VAR_TYPE(ty) ((ty)->tt != Ty_Void)
Expand All @@ -14,8 +16,8 @@ namespace tiger {
{
Translator = new (C) Translate(C);
}

Semant::ExpTy Semant::TransExp(ASTNode n)
Semant::ExpTy Semant::TransExp(ASTNode n,Label loopExit)
{
ExpTy ret;
switch (n->type) {
Expand Down Expand Up @@ -47,15 +49,15 @@ namespace tiger {
auto ax = static_cast<ArrayExp*>(n);
auto ty = TENV.Look(ax->type);
if (ty) {
auto expty = TransExp(ax->init);
auto expty = TransExp(ax->init); //break can not in array init exp
if (expty.second == nullptr)
goto TRANS_EXP_ERR;
if (!ValidateTypeCheck(ty, expty.second)) {
reportErr("type mismatch!");
goto TRANS_EXP_ERR;
}
auto initExp = expty.first;
expty = TransExp(ax->size);
expty = TransExp(ax->size); //break can not in array size exp
if (expty.second == nullptr)
goto TRANS_EXP_ERR;
if (expty.second != IntType()) {
Expand Down Expand Up @@ -336,9 +338,9 @@ namespace tiger {
case A_If:
{
auto ix = static_cast<IfExp*>(n);
ExpTy test = TransExp(ix->test), then = TransExp(ix->then), elsee;
ExpTy test = TransExp(ix->test), then = TransExp(ix->then, loopExit), elsee;//breakexp can in then
bool hasElse = ix->elsee != nullptr;
if (hasElse) elsee = TransExp(ix->elsee);
if (hasElse) elsee = TransExp(ix->elsee, loopExit);
if (test.second == nullptr)
goto TRANS_EXP_ERR;
if (!VALID_VAR_TYPE(test.second)) {
Expand Down Expand Up @@ -373,21 +375,129 @@ namespace tiger {

case A_While:
{
auto wx = static_cast<WhileExp*>(n);

Label end = temp::newLabel(); //TODO: refactor
ExpTy test = TransExp(wx->test), body = TransExp(wx->body, end);
if (test.second == nullptr || body.second == nullptr)
goto TRANS_EXP_ERR;
if (!VALID_VAR_TYPE(test.second)) {
reportErr("test oprand type invalid");
goto TRANS_EXP_ERR;
}

ret.second = VoidType();
ret.first = Translator->TransWhile(test.first, body.first, end);
}
break;

case A_For:
{
auto fx = static_cast<ForExp*>(n);

auto low = TransExp(fx->lo), high = TransExp(fx->hi);
if (low.second == nullptr || high.second == nullptr)
goto TRANS_EXP_ERR;
if (low.second != IntType() || high.second != IntType()) {
if (low.second != IntType())
reportErr("invalid oprand type!");
if (high.second != IntType())
reportErr("invalid oprand type!");
goto TRANS_EXP_ERR;
}
VENV.BeginScope();
auto ventry = new(C)VarEntry;
ventry->access = Translator->CurLevel()->AllocLocal(true); //TODO: escape analysis
ventry->type = IntType();
VENV.Enter(fx->var, ventry);

Label end = temp::newLabel();
auto body = TransExp(fx->body, end);
if (body.second == nullptr) {
VENV.EndScope();
goto TRANS_EXP_ERR;
}

ret.second = VoidType();
ret.first = Translator->TransFor(ventry->access, low.first,
high.first, body.first, end);

VENV.EndScope();
}
break;

case A_Break:
{
if (!loopExit) {
reportErr("break exp not in a loop!");
goto TRANS_EXP_ERR;
}

ret.second = VoidType();
ret.first = Translator->TransBreak(loopExit);
}
break;

case A_Let:
{
auto lx = static_cast<LetExp*>(n);

VENV.BeginScope();
TENV.BeginScope();
FENV.BeginScope();

auto decs = TransDecs(lx->decs), body = TransExp(lx->exps, loopExit);
if (decs.second == nullptr || body.second == nullptr) {
FENV.EndScope();
TENV.EndScope();
VENV.EndScope();
goto TRANS_EXP_ERR;
}

ret.second = body.second;
ret.first = Translator->CombineESeq(decs.first, body.first);
FENV.EndScope();
TENV.EndScope();
VENV.EndScope();
}
break;

case A_ExpList:
{
auto ex = static_cast<ExpList*>(n);
Type*ty = VoidType();
for (auto exp : ex->exps) {
auto expty = TransExp(exp, loopExit);
if (expty.second == nullptr) ty = nullptr;
else ty = expty.second;

exps
}
if (ty != nullptr) {
ret.second = ty;
ret.first = nullptr;

}
}
break;

case A_Assign:
{
auto ax = static_cast<AssignExp*>(n);
auto var = TransVar(ax->var);
auto exp = TransExp(ax->exp);
if (var.second == nullptr || exp.second == nullptr) {
goto TRANS_EXP_ERR;
}
if (!ValidateTypeCheck(var.second, exp.second)) {
reportErr("type mismatch!");
goto TRANS_EXP_ERR;
}
ret.second = VoidType();
ret.first = Translator->TransAssign(var.first, exp.first);
}
break;

default:
assert(0);
break;
Expand All @@ -399,10 +509,11 @@ namespace tiger {

Semant::ExpTy Semant::TransDecs(ASTNode n)
{
//TODO: handle class definitions
//TODO: object-oriented features
assert(n->type == A_DeclareList);
DeclareList* dl = static_cast<DeclareList*>(n);
TrExp* initExp = nullptr;
Type* decType = VoidType();

//first pass only process type headers
for (auto dec : dl->decs) {
Expand All @@ -428,31 +539,45 @@ namespace tiger {
auto ty = TENV.Look(typeName);
assert(ty->tt == Ty_Name);
auto nt = static_cast<NameType*>(ty);
nt->type = TransTy(tydec);

//check: recursive define and incomplete define
Type* realTy = nt->type;
while (realTy != nt && realTy->tt == Ty_Name) {
auto realNT = static_cast<NameType*>(realTy);
if (realNT->type == nullptr) {
reportErr("type %s has an incomplete definition!", tydec->name.c_str());
//TODO: pop error type
break;
auto type = TransTy(tydec);
if (type) {
nt->type = type;
//check: recursive define and incomplete define
Type* realTy = nt->type;
while (realTy != nt && realTy->tt == Ty_Name) {
auto realNT = static_cast<NameType*>(realTy);
if (realNT->type == nullptr) {
reportErr("type %s has an incomplete definition!", tydec->name.c_str());
TENV.Pop(typeName);
decType = nullptr;
break;
}
else
realTy = realNT->type;
}
if (realTy == nt) {
reportErr("type %s has a recursive definition!", tydec->name.c_str());
TENV.Pop(typeName);
decType = nullptr;
}
else
realTy = realNT->type;
}
if (realTy == nt)
reportErr("type %s has a recursive definition!", tydec->name.c_str());
}
else if (dec->type == A_VarDec) {
}

//when type info process finished,process var dec and func decs
for (auto dec : dl->decs) {
if (dec->type == A_VarDec) {
auto vardec = static_cast<VarDec*>(dec);
auto expty = TransVarDec(vardec);
if (expty.second) {
if (initExp == nullptr)
/*if (initExp == nullptr)
initExp = expty.first;
else
initExp = Translator->CombineStm(initExp, expty.first);
else
initExp = Translator->CombineStm(initExp, expty.first);*/
initExp = Translator->CombineStm(initExp, expty.first);
}
else {
decType = nullptr;
}
}
else if (dec->type == A_FuncDec) {
Expand All @@ -474,9 +599,9 @@ namespace tiger {
std::vector<Type*> formalTypes;
std::vector<bool> formalEscape;
for (auto para : fundec->params->fields) {
Type* ty = TENV.Look(para->name);
Type* ty = TENV.Look(para->type);
if (!ty) {
reportErr("para %s has invalid type %s", para->name.c_str(),
reportErr("param %s has invalid type %s", para->name.c_str(),
para->type.c_str());
validParam = false;
break;
Expand Down Expand Up @@ -504,7 +629,7 @@ namespace tiger {
TENV.BeginScope();
VENV.BeginScope();
FENV.BeginScope();

for (size_t i = 0; i < formalName.size(); ++i) {
auto entry = new(C)VarEntry;
entry->access = newLevel->Argument(i);
Expand All @@ -518,20 +643,29 @@ namespace tiger {
VENV.EndScope();
TENV.EndScope();
//check return type
if (expty.second == NULL ||
!ValidateTypeCheck(retType, expty.second)) {
reportErr("return type mismatch!");
if (expty.second == nullptr) {
FENV.Pop(fundec->name);
Translator->ExitLevel(nullptr);
}
else {
Translator->ExitLevel(expty.first);
if (!ValidateTypeCheck(retType, expty.second)) {
reportErr("return type mismatch!");
FENV.Pop(fundec->name);
Translator->ExitLevel(nullptr);
decType = nullptr;
}
else {
Translator->ExitLevel(expty.first);
}
}
}
else {
decType = nullptr;
}
}
}

return ExpTy(initExp, nullptr);
return ExpTy(initExp, decType);
}

Semant::ExpTy Semant::TransVar(ASTNode n)
Expand Down Expand Up @@ -691,6 +825,8 @@ namespace tiger {
}

Semant::ExpTy Semant::TransVarDec(VarDec* vardec) {
//TODO: can not handle following recursive format
//var a := recType{ptr=a}
Type* ty = nullptr;
TrExp* exp = nullptr;
ExpTy ret(nullptr, nullptr);
Expand Down
4 changes: 3 additions & 1 deletion semant.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "env.h"
#include "absyn.h"
#include "allocator.h"
#include "temp.h"
#include <utility>

namespace tiger {
Expand All @@ -20,7 +21,8 @@ namespace tiger {
Semant(BumpPtrAllocator& allocator);

//make sure if ExpTy returned is successful, then ty is actual typed
ExpTy TransExp(ASTNode); //expty.second null if trans failed, else is actualed type
//loopExit is the outer loop to break
ExpTy TransExp(ASTNode,Label=""); //expty.second null if trans failed, else is actualed type
ExpTy TransDecs(ASTNode);//Declaration list
ExpTy TransVar(ASTNode);
Type* TransTy(ASTNode);
Expand Down
3 changes: 3 additions & 0 deletions symbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ namespace tiger
inline operator std::string() const {
return mName ? std::string(mName) : std::string("");
}
inline operator bool() const {
return mName != nullptr;
}

public:
struct Hasher {
Expand Down
1 change: 1 addition & 0 deletions tiger.g4
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ exp
| 'let' decs 'in' exps 'end' #LetExp
;

// Can not handle lvalue such as F(x,y), todo add this
lvalue
: ID #SimpleVar
| lvalue '.' ID #FieldVar
Expand Down
Loading

0 comments on commit afcfcec

Please sign in to comment.