removed parameter passing of globals and fixed expression evaluator some

This commit is contained in:
Samuel D. Crow
2021-03-13 16:49:58 -06:00
parent 43319754a8
commit 4b2b567a42
5 changed files with 532 additions and 476 deletions

View File

@@ -170,369 +170,3 @@ void compile()
shutDown();
}
/* methods for operands */
static void operands::dumpVars(ostream &out)
{
out << "Global Variables\n";
for(auto iter=globals.begin(); iter!=globals.end(); ++iter)
{
out << "variable " << iter->first << " has ID " << iter->second << "\n";
}
out << endl;
}
unsigned int operands::getOrCreateStr(ostream &k, string &s)
{
auto iter=constStr.find(s);
if (iter!=constStr.end()) return iter->second;
++nextID;
k << "const string k" << nextID << "=\"" << s << "\";\n";
constStr[s]=nextID;
return nextID;
}
unsigned int operands::createConst(ostream &k, string &s, enum TYPES t)
{
operands *me=new operands(t);
if (t==T_INT)
{
k << "const int k";
}
else
{
if (t==T_FLOAT)
{
k << "const double k";
}
else
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
}
k << me->getID() << "=" << s << ";\n";
return me;
}
enum TYPES operands::getSimpleVarType()
{
switch type
{
case T_FLOAT:
case T_FLOATCALL_ARRAY:
case T_FLOATVAR:
return T_FLOATVAR;
case T_INT:
case T_INTCALL_ARRAY:
case T_INTVAR:
return T_INTVAR;
case T_STRING:
case T_STRINGCALL_ARRAY:
case T_STRINGVAR:
return T_STRINGVAR;
}
return T_NONE;
}
enum TYPES operands::coerceTypes()
{
if this->isBinOp()
{
if (l->getSimpleVarType()==T_INTVAR && r->getSimpleVarType()==T_FLOATVAR)
{
/* promote l to float */
t=T_FLOATVAR;
break;
}
if (l->getSimpleVarType()==T_FLOAT && r->getSimpleVarType()==T_INT)
{
/* promote r to float */
t=T_FLOATVAR;
break;
}
if (l->getSimpleVarType()==r->getSimpleVarType())
{
break;
}
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
else
{
if (t==T_NONE)
{
errorLevel=E_TYPE_MISMATCH;
}
}
}
/* operands used by expression parser and variables */
operands::operands(enum TYPES t)
{
this->id = ++nextID;
this->type=t;
}
void operands::generateBox(ostream &out)
{
switch (this->getSimpleVarType())
{
case T_INTVAR:
out << "int v";
break;
case T_FLOATVAR:
out << "double v";
break;
case T_STRINGVAR:
out << "string v";
break;
default:
errorLevel=E_TYPE_MISMATCH;
exit(1);
break;
}
out << this->getID() << ";\n";
}
operands *operands::getOrCreateGlobal(ostream &heap, string &s, enum TYPES t)
{
operands op*=operands::globals->find(s);
if (op==globals.end())
{
op=new variable(heap, s, t);
}
return op;
}
void operands::boxName(ostream &out)
{
switch (this->getType())
{
case T_STRINGVAR:
case T_INTVAR:
case T_FLOATVAR:
break;
default:
errorLevel=E_INTERNAL;
exit(1);
break;
}
out << "v" << this->getID();
}
/* expression parsing routines */
/* binary vs. unary ops */
bool expression::isBinOp()
{
switch this->getOp()
{
case O_NEGATE:
case O_NOT:
case O_INVERT:
return false;
break;
}
return true;
}
operands *expression::evaluate(ostream &scope, ostream &output_cpp)
{
operands *l, *r;
if (this->getOp()==O_TERM) return op;
l=this->getLeft()->evaluate();
enum TYPES t=this->coerceTypes();
l->getSimpleVarType();
r=(this->isBinOp()?this->getRight()->evaluate():NULL);
switch (this->getOp())
{
case O_INVERT:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "= ~" << l->boxName() << ";\n";
break;
case O_NEGATE:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "= -" << l->boxName() << ";\n";
break;
case O_NOT:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "= !" << l->boxName() << ";\n";
break;
/* TODO: Check for divide by zero error and modulo zero error */
case O_REMAINDER:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "%" << r->boxName() << ";\n";
break;
case O_DIVIDE:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "/" << r->boxName() << ";\n";
break;
case O_PLUS:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "+" << r->boxName() << ";\n";
break;
case O_MINUS:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "-" << r->boxName() << ";\n";
break;
case O_MULTIPLY:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "*" << r->boxName() << ";\n";
break;
case O_OR:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "|" << r->boxName() << ";\n";
break;
case O_AND:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "&" << r->boxName() << ";\n";
break;
case O_GREATER:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << ">" << r->boxName() << ")?-1:0;\n";
break;
case O_LESS:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "<" << r->boxName() << ")?-1:0;\n";
break;
case O_GREATER_EQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << ">=" << r->boxName() << ")?-1:0;\n";
break;
case O_LESS_EQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "<=" << r->boxName() << ")?-1:0;\n";
break;
case O_EQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "==" << r->boxName() << ")?-1:0;\n";
break;
case O_UNEQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "!=" << r->boxName() << ")?-1:0;\n";
break;
default:
errorLevel=E_INTERNAL;
exit(1);
break;
}
delete this->left;
this->left=NULL;
if (this->isBinOp())
{
delete this->right;
this->right=NULL;
}
this->oper=O_TERM;
return this->op;
}
expression::~expression()
{
if(this->getOp()==O_TERM)
{
delete this->op;
}
else
{
delete this->left;
if (this->isBinOp())
{
delete this->right;
}
}
}
/* variable definitions */
variable::variable(ostream &scope, string &name, enum TYPES t):operands(t)
{
this->generateBox(scope);
}
variable *variable::getOrCreateVarName(ostream &func, ostream &heap, string &name, enum TYPES t)
{
variable *v;
if (!scopeGlobal)
{
fn *currentFunc=fn::getCurrentSub();
v=fn::getOrCreateVar(func, heap, t, name, false);
return v;
}
return reinterpret_cast<variable *>operands::getOrCreateGlobal(heap, name);
}
void variable::assignment(expression *value)
{
operands *op=value->evaluate();
enum TYPES t=op->getSimpleVarType();
switch (this->getType())
{
case T_FLOATVAR:
if (t==T_INTVAR)
{
/* TODO: convert int to float */
}
else
{
if (t!=T_FLOATVAR)
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
}
break;
default:
if (t!=this->getType())
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
break;
}
this->boxName(output_cpp);
output_cpp << "=";
op->boxName(output_cpp);
output_cpp << ";\n";
}
/* function definitions */
fn *fn::getCurrentSub()
{
return callStack.back;
}
void fn::generateOnNSub(ostream &out, expression *e)
{
this->ret=new label();
fn::callStack.push_back(this);
label::generateOnNTo(out, e);
out << "case " << ret->getID() << ":\n";
}
void fn::generateGosub(ostream &out, shared_ptr<label> sub)
{
this->ret=new label();
fn::callStack.push_back(this);
out << "state=" << sub->getID() << ";\nbreak;\n";
out << "case " << ret->getID() << ":\n";
}

View File

@@ -164,6 +164,7 @@ enum OPERATORS
O_INVERT,
O_OR,
O_AND,
O_STRING_CONCAT,
O_TERM
};
@@ -185,8 +186,8 @@ public:
static operands *getOrCreateGlobal(ostream &heap, string &s, enum TYPES t);
enum TYPES getSimpleVarType();
void generateBox(ostream &out);
virtual void boxName(ostream &out);
void generateBox(ostream &scope);
virtual string &boxName();
enum TYPES coerceTypes();
explicit operands(enum TYPES t);
@@ -208,6 +209,7 @@ public:
bool isBinOp();
operands *evaluate();
operands *stringEval();
/* r is NULL for unary operators */
expression(expression *l, enum OPERATORS o, expression *r=NULL)
@@ -238,7 +240,7 @@ public:
static codeType *getCurrent();
virtual void close();
virtual void generateBreak(ostream &out)=0;
virtual void generateBreak()=0;
explicit codeType(enum CODES t);
virtual ~codeType()
@@ -255,11 +257,11 @@ public:
unsigned int getID() const {return id;}
void generateJumpTo(ostream &out);
void generateJumpTo();
void generateOnNSkip(ostream &k, list<label *> &dest);
void generateOnNTo(ostream &out, expression *e);
void generateCondJump(ostream &out, expression *e);
void generate(ostream &out);
void generateOnNTo(expression *e);
void generateCondJump(expression *e);
void generate();
static label *find(string &s);
@@ -281,12 +283,12 @@ class conditional:public codeType
label *done; /* for break or after "then" condition */
label *chain; /* For elsif command */
public:
void generateContinue(ostream &out);
virtual void generateBreak(ostream &out) override;
void alternative(ostream &out, expression *e=NULL); /* enable else or elsif condition */
virtual void close(ostream &out) override; /* end if */
void generateContinue();
virtual void generateBreak() override;
void alternative(expression *e=NULL); /* enable else or elsif condition */
virtual void close() override; /* end if */
explicit conditional(ostream &out, expression *e);
explicit conditional(expression *e);
virtual ~conditional();
};
@@ -296,10 +298,10 @@ class repeatLoop:public codeType
label *loopStart;
label *loopEnd;
public:
virtual void generateBreak(ostream &out) override;
virtual void close(ostream &out, expression *e) override;
virtual void generateBreak() override;
virtual void close(expression *e) override;
explicit repeatLoop(ostream &out);
explicit repeatLoop();
virtual ~repeatLoop();
};
@@ -308,8 +310,8 @@ class doLoop:public codeType
label *loopStart;
label *loopEnd;
public:
virtual void generateBreak(ostream &out) override;
virtual void close(ostream &out) override;
virtual void generateBreak() override;
virtual void close() override;
explicit doLoop():codeType(T_DOLOOP);
virtual ~doLoop();
@@ -322,10 +324,10 @@ class whileLoop:public codeType
label *loopEnd;
expression *cond;
public:
virtual void generateBreak(ostream &out) override;
virtual void close(ostream &out) override;
virtual void generateBreak() override;
virtual void close() override;
explicit whileLoop(ostream &out, expression *e):codeType(T_WHILELOOP);
explicit whileLoop(expression *e):codeType(T_WHILELOOP);
virtual ~whileLoop();
};
@@ -334,7 +336,7 @@ class variable:public operands
public:
static variable *getOrCreateVarName(ostream &func, ostream &heap, string &name, enum TYPES t);
void assignment(ostream &out, expression *value);
void assignment(expression *value);
explicit variable(ostream &scope, string &name, enum TYPES t);
virtual variable()
{}
@@ -344,7 +346,7 @@ class arrayType:public variable
{
list<unsigned int> dimensions;
public:
virtual void boxName(ostream &out, list<unsigned int>indexes) override;
virtual string &boxName(list<unsigned int>indexes) override;
explicit arrayType(ostream &heap, string &name, enum TYPES t, list<unsigned int>dim);/*:variable(scope, name, t);*/
virtual ~arrayType()
@@ -359,10 +361,10 @@ class forLoop:public codeType
whileLoop *infrastructure;
expression *step;
public:
virtual void generateBreak(ostream &out);
virtual void close(ostream &out);
virtual void generateBreak();
virtual void close();
explicit forLoop(ostream &out, ostream &k, variable *v, expression *start, expression *stop, expression *stepVal=NULL);
explicit forLoop(ostream &k, variable *v, expression *start, expression *stop, expression *stepVal=NULL);
virtual ~forLoop();
};
@@ -376,19 +378,19 @@ class fn:codeType
shared_ptr<label>ret;
unsigned int parameters;
public:
static variable *getOrCreateVar(ostream &func, ostream &heap, enum TYPES t, string &s, bool stat);
static void dumpCallStack(ostream &out);
static variable *getOrCreateVar(enum TYPES t, string &s, bool stat);
static void dumpCallStack();
static fn *getCurrentSub();
void setParameters(unsigned int num) const {this->parameters=num;}
void generateCall(ostream &out, string &name, unsigned int params);
void generateReturn(ostream &out, expression *expr=NULL);
void generateGosub(ostream &out, shared_ptr<label> sub);
void generateCall(string &name, unsigned int params);
void generateReturn(expression *expr=NULL);
void generateGosub(shared_ptr<label> sub);
/* must be called after label::generateOnNSkip */
void generateOnNSub(ostream &out, expression *e);
virtual void generateBreak(ostream &out);
virtual void close(ostream &out);
void generateOnNSub(expression *e);
virtual void generateBreak();
virtual void close();
fn(string &name);
fn(label *gosub);

View File

@@ -9,7 +9,6 @@
#include "yab2cpp.h"
/* base class of all the code structure types */
codeType::codeType(enum CODES t)
{
this->id= ++nextID;
@@ -28,29 +27,28 @@ void codeType::close()
}
/* label definitions and helper routines */
label *label::find(string &s)
{
auto ret=lookup.find(s);
return(ret==lookup.end()?NULL:ret->second);
}
void label::dumpLabels(ostream &v)
void label::dumpLabels()
{
v << "Global Labels\n\n";
varNames << "Global Labels\n\n";
for(auto iter=lookup.begin(); iter!=lookup.end(); ++iter)
{
v << "label " << iter->first << " has ID " << iter->second->getID() << "\n" ;
varNames << "label " << iter->first << " has ID " << iter->second->getID() << "\n" ;
}
v << endl;
varNames << endl;
}
void label::generateJumpTo(ostream &out)
void label::generateJumpTo()
{
out << "state=" << this->getID() << ";\nbreak;\n";
output_cpp << "state=" << this->getID() << ";\nbreak;\n";
}
void label::generateOnNSkip(ostream &k, list<label *> &dest)
void label::generateOnNSkip(list<label *> &dest)
{
if (dest->size()<2)
{
@@ -58,74 +56,69 @@ void label::generateOnNSkip(ostream &k, list<label *> &dest)
exit(1);
}
auto iter=dest.start();
k << "j" << this->getID() << "[]={" << *iter;
consts_h << "j" << this->getID() << "[]={" << *iter;
++iter;
while(iter!=dest.end())
{
k << ", " << *iter;
consts_h << ", " << *iter;
++iter;
}
k << "}\njs" << this->getID()<< "=" << dest->size() << ";\n";
consts_h << "}\njs" << this->getID()<< "=" << dest->size() << ";\n";
}
void label::generateOnNTo(ostream &out, expression *e)
void label::generateOnNTo(expression *e)
{
operands *o=e->evaluate();
if (o->getType()==T_INT||o->getType()==T_INTVAR)
{
out << "if(";
o->boxName(out);
out << ">=0 && ";
o->boxName(out);
out << "<js" << this->getID() << ")state=j[";
o->boxName(out);
out << "];\nbreak;\n";
output_cpp<< "if(" << o->boxName() << ">=0 && "
<< o->boxName() << "<js" << this->getID() << ")state=j["
<< o->boxName() << "];\nbreak;\n";
}
delete e;
}
void label::generateCondJump(ostream &out, expression *e)
void label::generateCondJump(expression *e)
{
operands *o=e->evaluate();
if (o->getType()==T_INT||o->getType()==T_INTVAR)
{
out << "if(";
o->boxName(out);
out << "!=0)state=" << this->getID() << ";\nbreak;\n";
output_cpp<< "if(" << o->boxName()
<< "!=0)state=" << this->getID() << ";\nbreak;\n";
}
delete e;
}
void label::generate(ostream &out)
void label::generate()
{
out << "case " << this->getID() <<":\n";
output_cpp<< "case " << this->getID() <<":\n";
}
/* conditional definition */
conditional::conditional(ostream &out, expression *e):codeType(T_IF)
conditional::conditional(expression *e):codeType(T_IF)
{
this->redo=new label();
redo->generate(out);
redo->generate();
this->done=new label();
expression *f=new expression(e,O_NOT);
this->chain=new label();
chain->generateCondJump(out, f);
chain->generateCondJump(f);
}
void conditional::generateBreak(ostream &out)
void conditional::generateBreak()
{
done->generateJumpTo(out);
done->generateJumpTo();
}
void conditional::generateContinue(ostream &out)
void conditional::generateContinue()
{
redo->generateJumpTo(out);
redo->generateJumpTo();
}
void conditional::alternative(ostream &out, expression *e=NULL)
void conditional::alternative(expression *e=NULL)
{
done->generateJumpTo(out);
done->generateJumpTo();
this->chain->generate();
delete this->chain;
this->chain=NULL;
@@ -133,11 +126,11 @@ void conditional::alternative(ostream &out, expression *e=NULL)
{
this->chain=new label();
expression *f=new expression(e,O_NOT);
chain->generateJumpCond(out, f);
chain->generateJumpCond(f);
}
}
void conditional::close(ostream &out)
void conditional::close()
{
if(this->chain)
{
@@ -155,23 +148,23 @@ conditional::~conditional()
}
/* Loop definitions */
repeatLoop::repeatLoop(ostream &out):codeType(T_REPEATLOOP)
repeatLoop::repeatLoop():codeType(T_REPEATLOOP)
{
this->loopStart=new label();
this->loopEnd=new label();
loopStart->generate(out;)
loopStart->generate();
}
void repeatLoop::generateBreak(ostream &out)
void repeatLoop::generateBreak()
{
loopEnd->generateJumpTo(out);
loopEnd->generateJumpTo();
}
void repeatLoop::close(ostream &out, expression *e)
void repeatLoop::close(expression *e)
{
expression *f=new expression(e, O_NOT);
loopStart->generateCondJump(out, f);
loopEnd->generate(out);
loopStart->generateCondJump(f);
loopEnd->generate();
}
repeatLoop::~repeatLoop()
@@ -180,22 +173,22 @@ repeatLoop::~repeatLoop()
delete loopEnd;
}
doLoop::doLoop(ostream &out):codeType(T_DOLOOP)
doLoop::doLoop():codeType(T_DOLOOP)
{
this->loopStart=new label();
this->loopEnd=new label();
loopStart->generate(out;)
loopStart->generate();
}
void doLoop::generateBreak(ostream &out)
void doLoop::generateBreak()
{
loopEnd->generateJumpTo(out);
loopEnd->generateJumpTo();
}
void doLoop::close(ostream &out)
void doLoop::close()
{
this->loopStart->generateJumpTo(out);
this->loopEnd->generate(out);
this->loopStart->generateJumpTo();
this->loopEnd->generate();
}
doLoop::~doLoop()
@@ -203,26 +196,26 @@ doLoop::~doLoop()
delete loopEnd;
}
whileLoop::whileLoop(ostream &out, expression *e):codeType(T_WHILELOOP)
whileLoop::whileLoop(expression *e):codeType(T_WHILELOOP)
{
loopContinue=new label();
loopStart=new label();
loopEnd=new label();
cond=e;
loopStart->generateJumpTo(out);
loopContinue->generate(out);
loopStart->generateJumpTo();
loopContinue->generate();
}
void whileLoop::generateBreak(ostream &out)
void whileLoop::generateBreak()
{
loopEnd->generateJumpTo(out);
loopEnd->generateJumpTo();
}
void whileLoop::close(ostream &out)
void whileLoop::close()
{
loopStart->generate(out);
loopContinue->generateJumpCond(out, cond);
loopEnd->generate(out);
loopStart->generate();
loopContinue->generateJumpCond(cond);
loopEnd->generate();
}
whileLoop::~whileLoop()
@@ -232,31 +225,31 @@ whileLoop::~whileLoop()
delete loopEnd;
}
forLoop::forLoop(ostream &out, ostream &k, variable *v, expression *start, expression *stop, expression *stepVal=NULL):codeType(T_FORLOOP)
forLoop::forLoop(variable *v, expression *start, expression *stop, expression *stepVal=NULL):codeType(T_FORLOOP)
{
/*v=start;
stopTemp=stop;*/
v->assignment(out, start);
stopTemp->assignment(out, stop);
v->assignment(start);
stopTemp->assignment(stop);
/* if (v<stopTemp) */
conditional *c=new conditional(out, new expression(new expression(v), O_LESS, new expression(stopTemp)));
conditional *c=new conditional(new expression(new expression(v), O_LESS, new expression(stopTemp)));
/* startTemp=v;*/
startTemp->assignment(out, new expression(v));
startTemp->assignment(new expression(v));
/* else */
c->alternative(out);
c->alternative();
/* startTemp=stopTemp;
stopTemp=v;*/
startTemp->assignment(out, new expression(stopTemp));
stopTemp->assignment(out, new expression(v));
startTemp->assignment(new expression(stopTemp));
stopTemp->assignment(new expression(v));
/* endif */
c->close(out);
c->close();
delete c;
/* while (v<=stopTemp && v>=startTemp) */
expression *stopper1=new expression(new expression(v), O_LESS_EQUAL, new expression(stopTemp));
expression *stopper2=new expression(new expression(v), O_GREATER_EQUAL, new expression(startTemp));
expression *stopper=new expression(stopper1, O_AND, stopper2);
this->infrastructure=new whileLoop(out, new expression(stopper, O_UNEQUAL,
new expression(operands::createConst(k, "0", T_INT))));
this->infrastructure=new whileLoop(new expression(stopper, O_UNEQUAL,
new expression(operands::createConst("0", T_INT))));
if (stepVal)
{
step=stepVal;
@@ -264,19 +257,19 @@ forLoop::forLoop(ostream &out, ostream &k, variable *v, expression *start, expre
else
{
/* if not present "step" is assumed to be 1 */
step=new expression(operands::createConst(k, "1", T_INT));
step=new expression(operands::createConst("1", T_INT));
}
}
void forLoop::generateBreak(ostream &out)
void forLoop::generateBreak()
{
infrastructure->generateBreak(out);
infrastructure->generateBreak();
}
void forLoop::close(ostream &out)
void forLoop::close()
{
/* v=v+step; */
expression *stepper=new expression(new expression(v), O_PLUS, step);
v->assignment(out, stepper)
infrastructure->close(ostream &out);
v->assignment(stepper)
infrastructure->close();
}

396
yabDataStructures.cpp Normal file
View File

@@ -0,0 +1,396 @@
/*
** Yab2Cpp
**
** Transpiler by Samuel D. Crow
**
** Based on Yab
**
*/
#include "yab2cpp.h"
/* methods for operands */
static void operands::dumpVars()
{
varNames << "Global Variables\n";
for(auto iter=globals.begin(); iter!=globals.end(); ++iter)
{
varNames << "variable " << iter->first << " has ID " << iter->second << "\n";
}
varNames << endl;
}
unsigned int operands::getOrCreateStr(string &s)
{
auto iter=constStr.find(s);
if (iter!=constStr.end()) return iter->second;
++nextID;
consts_h << "const string k" << nextID << "=\"" << s << "\";\n";
constStr[s]=nextID;
return nextID;
}
unsigned int operands::createConst(string &s, enum TYPES t)
{
operands *me=new operands(t);
if (t==T_INT)
{
consts_h << "const int k";
}
else
{
if (t==T_FLOAT)
{
consts_h << "const double k";
}
else
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
}
k << me->getID() << "=" << s << ";\n";
return me;
}
enum TYPES operands::getSimpleVarType()
{
switch type
{
case T_FLOAT:
case T_FLOATCALL_ARRAY:
case T_FLOATVAR:
return T_FLOATVAR;
case T_INT:
case T_INTCALL_ARRAY:
case T_INTVAR:
return T_INTVAR;
case T_STRING:
case T_STRINGCALL_ARRAY:
case T_STRINGVAR:
return T_STRINGVAR;
}
return T_NONE;
}
enum TYPES operands::coerceTypes(enum TYPES l, enum TYPES r)
{
if this->isBinOp()
{
if (l==T_INTVAR && r==T_FLOATVAR)
{
/* promote l to float */
t=T_FLOATVAR;
break;
}
if (l==T_FLOAT && r==T_INT)
{
/* promote r to float */
t=T_FLOATVAR;
break;
}
if (l==r)
{
break;
}
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
else
{
if (t==T_NONE)
{
errorLevel=E_TYPE_MISMATCH;
}
}
}
/* operands used by expression parser and variables */
operands::operands(enum TYPES t)
{
this->id = ++nextID;
this->type=t;
}
void operands::generateBox(ostream &scope)
{
switch (this->getSimpleVarType())
{
case T_INTVAR:
scope << "int v";
break;
case T_FLOATVAR:
scope << "double v";
break;
case T_STRINGVAR:
scope << "string v";
break;
default:
errorLevel=E_TYPE_MISMATCH;
exit(1);
break;
}
scope << this->getID() << ";\n";
}
operands *operands::getOrCreateGlobal(string &s, enum TYPES t)
{
operands op*=operands::globals->find(s);
if (op==globals.end())
{
op=new variable(heap_h, s, t);
}
return op;
}
void operands::boxName(ostream &scope)
{
switch (this->getType())
{
case T_STRINGVAR:
case T_INTVAR:
case T_FLOATVAR:
break;
default:
errorLevel=E_INTERNAL;
exit(1);
break;
}
scope << "v" << this->getID();
}
/* expression parsing routines */
/* binary vs. unary ops */
bool expression::isBinOp()
{
switch this->getOp()
{
case O_NEGATE:
case O_NOT:
case O_INVERT:
return false;
break;
}
return true;
}
operands *expression::evaluate()
{
if (this->getOp()==O_TERM) return op;
operands *l, *r;
enum TYPES t;
ostream &scope=scopeGlobal?heap_h:funcs_h;
l=this->getLeft()->evaluate();
if (this->isBinOp())
{
r=this->getRight()->evaluate();
t=this->coerceTypes(l->getSimpleVarType(), r->getSimpleVarType());
}
else
{
t=l->getSimpleVarType();
r=NULL;
}
if (t==T_STRINGVAR) return expression::stringEval();
switch (this->getOp())
{
case O_INVERT:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "= ~" << l->boxName() << ";\n";
break;
case O_NEGATE:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "= -" << l->boxName() << ";\n";
break;
case O_NOT:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "= !" << l->boxName() << ";\n";
break;
/* TODO: Check for divide by zero error and modulo zero error */
case O_REMAINDER:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "%" << r->boxName() << ";\n";
break;
case O_DIVIDE:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "/" << r->boxName() << ";\n";
break;
case O_PLUS:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "+" << r->boxName() << ";\n";
break;
case O_MINUS:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "-" << r->boxName() << ";\n";
break;
case O_MULTIPLY:
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "*" << r->boxName() << ";\n";
break;
case O_OR:
if (t!=T_INTVAR)
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "|" << r->boxName() << ";\n";
break;
case O_AND:
if (t!=T_INTVAR)
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
this->op=new operands(t);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" << l->boxName() << "&" << r->boxName() << ";\n";
break;
case O_GREATER:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << ">" << r->boxName() << ")?-1:0;\n";
break;
case O_LESS:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "<" << r->boxName() << ")?-1:0;\n";
break;
case O_GREATER_EQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << ">=" << r->boxName() << ")?-1:0;\n";
break;
case O_LESS_EQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "<=" << r->boxName() << ")?-1:0;\n";
break;
case O_EQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "==" << r->boxName() << ")?-1:0;\n";
break;
case O_UNEQUAL:
this->op=new operands(T_INTVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=(" << l->boxName() << "!=" << r->boxName() << ")?-1:0;\n";
break;
default:
errorLevel=E_INTERNAL;
exit(1);
break;
}
/* convert expression into single operand */
delete this->left;
this->left=NULL;
if (r)
{
delete this->right;
this->right=NULL;
}
this->oper=O_TERM;
return this->op;
}
operands * expression::stringEval(ostream &scope, operands *l, operands *r)
{
if (this->getOp()==O_STRING_CONCAT)
{
this->op=new operands(T_STRINGVAR);
this->op->generateBox(scope);
output_cpp << this->op->boxName() << "=" l->boxName() << "+" << r->boxName();
}
else
{
errorLevel=E_INTERNAL;
exit(1);
}
/* convert expression into single operand */
delete this->left;
this->left=NULL;
if (r)
{
delete this->right;
this->right=NULL;
}
this->oper=O_TERM;
return this->op;
}
expression::~expression()
{
if(this->getOp()==O_TERM)
{
delete this->op;
}
else
{
delete this->left;
if (this->isBinOp())
{
delete this->right;
}
}
}
/* variable definitions */
variable::variable(ostream &scope, string &name, enum TYPES t):operands(t)
{
this->generateBox(scope);
}
variable *variable::getOrCreateVarName(string &name, enum TYPES t)
{
if (!scopeGlobal)
{
return fn::getOrCreateVar(t, name, false);
}
/* TODO: verify if type is compatible */
operands op=operands::getOrCreateGlobal(name);
return reinterpret_cast<variable *>op;
}
void variable::assignment(expression *value)
{
operands *op=value->evaluate();
enum TYPES t=op->getSimpleVarType();
switch (this->getType())
{
case T_FLOATVAR:
if (t==T_INTVAR)
{
/* TODO: convert int to float */
}
else
{
if (t!=T_FLOATVAR)
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
}
break;
default:
if (t!=this->getType())
{
errorLevel=E_TYPE_MISMATCH;
exit(1);
}
break;
}
output_cpp << this->boxName() << "="
<< op->boxName() << ";\n";
}

31
yabFunctions.cpp Normal file
View File

@@ -0,0 +1,31 @@
/*
** Yab2Cpp
**
** Transpiler by Samuel D. Crow
**
** Based on Yab
**
*/
#include "yab2cpp.h"
/* function definitions */
fn *fn::getCurrentSub()
{
return callStack.back;
}
void fn::generateOnNSub(expression *e)
{
this->ret=new label();
fn::callStack.push_back(this);
label::generateOnNTo(e);
output_cpp << "case " << ret->getID() << ":\n";
}
void fn::generateGosub(shared_ptr<label> sub)
{
this->ret=new label();
fn::callStack.push_back(this);
output_cpp << "state=" << sub->getID() << ";\nbreak;\n";
output_cpp << "case " << ret->getID() << ":\n";
}