removed most of the shared_ptr usage and retooled temporary variables to recycle

This commit is contained in:
Samuel D. Crow
2021-03-28 22:35:35 -05:00
parent fd89b1a054
commit bb2be9c16c
7 changed files with 452 additions and 291 deletions

View File

@@ -10,9 +10,9 @@
#include "yab2cpp.h"
#include <cassert>
unordered_map<string, shared_ptr<variableType> >globals;
unordered_map<string, shared_ptr<variableType> >locals;
unordered_map<string, shared_ptr<variableType> >statics;
unordered_map<string, unique_ptr<variableType> >globals;
unordered_map<string, unique_ptr<variableType> >locals;
unordered_map<string, unique_ptr<variableType> >statics;
/* These correspond to the enum COMPILE_ERRORS. */
const char *COMPILE_ERROR_NAMES[]={
@@ -27,7 +27,8 @@ const char *COMPILE_ERROR_NAMES[]={
"value returned from gosub call",
"undefined subroutine name",
"too many parameters in function call",
"value cannot be assigned"
"value cannot be assigned",
"undimensioned array or undeclared function"
};
/* These correspond to the types of enum TYPES. */
@@ -214,8 +215,8 @@ void setUp()
[[noreturn]] void error(enum COMPILE_ERRORS e)
{
cerr << COMPILE_ERROR_NAMES[e] << endl;
errorLevel=e;
shutDown();
exit(1);
}
@@ -245,6 +246,8 @@ void shutDown()
{
if (errorLevel != E_OK) cerr << "\nERROR: "
<< COMPILE_ERROR_NAMES[errorLevel] << "\n\n" << endl;
logger("Purging tempVar queues");
tempVar::eraseQueues();
logger("Dumping stack.");
if (DUMP && (logfile)) fn::dumpCallStack();
if (DUMP)
@@ -271,17 +274,14 @@ void shutDown()
statics.clear();
}
shared_ptr<string>name;
shared_ptr<variableType>v;
shared_ptr<printSegment>print;
variableType *v;
printSegment *print;
void testInt()
{
name=shared_ptr<string>(new string("v"));
v=variableType::getOrCreateVar(*name, T_INTVAR);
v->assignment(shared_ptr<expression>(new expression(
shared_ptr<operands>(new constOp("2", T_INT)))));
print=shared_ptr<printSegment>(
new printSegment(shared_ptr<expression>(new expression(v))));
string name=string("v");
v=variableType::getOrCreateVar(name, T_INTVAR);
v->assignment(new expression(new constOp("2", T_INT)));
print=new printSegment(new expression(v));
print->generate();
label::generateEnd();
}

View File

@@ -7,10 +7,11 @@
**
*/
#include "yab2cpp.h"
#include <cassert>
unordered_map<string, shared_ptr<variableType> >globals;
unordered_map<string, shared_ptr<variableType> >locals;
unordered_map<string, shared_ptr<variableType> >statics;
unordered_map<string, unique_ptr<variableType> >globals;
unordered_map<string, unique_ptr<variableType> >locals;
unordered_map<string, unique_ptr<variableType> >statics;
/* These correspond to the enum COMPILE_ERRORS. */
const char *COMPILE_ERROR_NAMES[]={
@@ -25,7 +26,8 @@ const char *COMPILE_ERROR_NAMES[]={
"value returned from gosub call",
"undefined subroutine name",
"too many parameters in function call",
"value cannot be assigned"
"value cannot be assigned",
"undimensioned array or undeclared function"
};
/* These correspond to the types of enum TYPES. */
@@ -92,7 +94,6 @@ void shutDown();
/* process command line parameters */
int main(int argc, char *argv[])
{
atexit(shutDown);
switch (argc)
{
case 1:
@@ -150,6 +151,7 @@ int main(int argc, char *argv[])
helpText(argv[0]);
break;
}
cout << "program exiting" <<endl;
return 0;
}
@@ -177,15 +179,26 @@ void setUp()
funcs_h.open("output/functions.h");
consts_h.open("output/consts.h");
heap_h.open("output/heap.h");
output_cpp << "#include <runtime.h>\n#include \"consts.h\"\n"
output_cpp << "#include \"../runtime/runtime.h\"\n#include \"consts.h\"\n"
<< "#include \"heap.h\"\n#include \"functions.h\"\n"
<< "int main(int argc, char *argv[])\n{\n"
<< "unsigned int state=start;\nint run(){\nwhile (state>=start){\n"
<< "switch(state){\ncase start:" << endl;
if (DUMP)
{
varNames.open("varnames.txt");
}
<< "unsigned int state=START;\nunsigned int run(){\n"
<< "while (state>=START){\n"
<< "switch(state){\ncase START:" << endl;
}
else
{
output_cpp.open("/dev/null");
funcs_h.open("/dev/null");
consts_h.open("/dev/null");
heap_h.open("/dev/null");
}
if (DUMP)
{
varNames.open("varnames.log");
}
else
{
varNames.open("/dev/null");
}
if (DEBUG)
{
@@ -193,11 +206,16 @@ void setUp()
logfile.open("parse.log");
logger("Setup complete.");
}
else
{
logfile.open("/dev/null");
}
}
[[noreturn]] void error(enum COMPILE_ERRORS e)
{
errorLevel=e;
shutDown();
exit(1);
}
@@ -218,27 +236,41 @@ void logger(string s)
if (DEBUG)
{
indent();
logfile << s << endl;
logfile << s << "\n";
}
}
/* shutdown the compiler and exit */
void shutDown()
{
if (errorLevel != E_OK) cerr << "\nERROR: " << COMPILE_ERROR_NAMES[errorLevel] << "\n\n" << endl;
if (errorLevel != E_OK) cerr << "\nERROR: "
<< COMPILE_ERROR_NAMES[errorLevel] << "\n\n" << endl;
logger("Purging tempVar queues");
tempVar::eraseQueues();
logger("Dumping stack.");
if (DUMP && (logfile))
if (DUMP && (logfile)) fn::dumpCallStack();
if (DUMP)
{
fn::dumpCallStack();
}
varNames << "Global Variables\n";
for(auto iter=globals.begin(); iter!=globals.end(); ++iter)
{
varNames << "variable " << iter->first << " has ID " << iter->second << "\n";
}
varNames << endl;
varNames << "Global Variables\n";
for(auto iter=globals.begin(); iter!=globals.end(); ++iter)
{
varNames << "variable " << iter->first
<< " has ID " << iter->second->getID() << "\n";
}
varNames << endl;
label::dumpLabels();
output_cpp << "}\n}return state;\n}"<< endl;
}
if (COMPILE)
{
output_cpp << "default:\nstate=UNDEFINED_STATE_ERROR;\n"
<< "break;\n}\n}\nreturn state;\n}"<< endl;
funcs_h.flush();
consts_h.flush();
heap_h.flush();
}
globals.clear();
locals.clear();
statics.clear();
}
/* open files and compile */
@@ -250,4 +282,3 @@ void compile()
shutDown();
}

183
yab2cpp.h
View File

@@ -29,9 +29,9 @@ extern ofstream heap_h;
extern ofstream consts_h;
extern ofstream logfile;
extern ofstream varNames;
extern unordered_map<string, shared_ptr<variableType> >globals;
extern unordered_map<string, shared_ptr<variableType> >locals;
extern unordered_map<string, shared_ptr<variableType> >statics;
extern unordered_map<string, unique_ptr<variableType> >globals;
extern unordered_map<string, unique_ptr<variableType> >locals;
extern unordered_map<string, unique_ptr<variableType> >statics;
extern const string CODETYPES[];
extern const string TYPENAMES[];
@@ -41,7 +41,8 @@ extern const string TYPENAMES[];
** Note: There must be a corresponding error message
** to each entry in the COMPILE_ERROR_NAMES constant array.
*/
enum COMPILE_ERRORS {
enum COMPILE_ERRORS:unsigned int
{
E_OK=0,
E_BAD_SYNTAX,
E_TYPE_MISMATCH,
@@ -68,7 +69,7 @@ extern bool DEBUG;
extern bool TRACE;
/* list of all variableType and constant types */
enum TYPES
enum TYPES:unsigned int
{
T_UNKNOWN=0,
T_NONE,
@@ -85,7 +86,7 @@ enum TYPES
};
/* list of all kinds of other code structures */
enum CODES
enum CODES:unsigned int
{
T_PRINT=0,
T_PRINTSEGMENT,
@@ -116,14 +117,14 @@ typedef union
}boxTypes;
/* subtypes of the T_PRINTSEPARATOR type */
enum SEPARATORS
enum SEPARATORS:unsigned int
{
S_COMMA,
S_SEMICOLON,
S_LINEFEED
};
enum SCOPES
enum SCOPES:unsigned int
{
S_UNKNOWN,
S_LOCAL,
@@ -131,7 +132,7 @@ enum SCOPES
S_GLOBAL
};
enum OPERATORS
enum OPERATORS:unsigned int
{
O_PLUS,
O_MINUS,
@@ -165,20 +166,46 @@ class operands
enum TYPES type;
unsigned int id;
static unsigned int nextID;
/* private constructor for parameter passing only */
explicit operands(unsigned int id, enum TYPES t);
protected:
void generateBox(enum SCOPES s);
explicit operands(enum TYPES t);
virtual ~operands()
{}
public:
enum TYPES getType() const {return type;}
unsigned int getID() const {return id;}
enum TYPES getSimpleVarType();
void generateBox(enum SCOPES s);
virtual string boxName();
enum TYPES coerceTypes();
static enum TYPES getSimpleVarType(enum TYPES t);
explicit operands(enum TYPES t);
virtual ~operands()
/* abstract factory */
static operands *createOp(enum TYPES t);
virtual void dispose();
};
class tempVar:public operands
{
static list<tempVar *>intQueue;
static list<tempVar *>floatQueue;
static list<tempVar *>stringQueue;
/* private constructor called by getOrCreateVar */
explicit tempVar(enum TYPES t);
/* private destructor called by eraseQueues */
virtual ~tempVar()
{}
public:
/* factory method to recycle existing tempVar */
static tempVar *getOrCreateVar(enum TYPES t);
/* purge queues at end of compile */
static void eraseQueues();
/* recycle tempVar in a queue */
virtual void dispose();
};
/* constant operands */
@@ -203,36 +230,23 @@ public:
/* expression can be terminal or non-terminal node */
class expression
{
shared_ptr<operands>op;
shared_ptr<expression>left;
shared_ptr<expression>right;
operands *op;
expression *left;
expression *right;
enum OPERATORS oper;
public:
enum OPERATORS getOp() const {return oper;}
shared_ptr<expression>getLeft() const {return left;}
shared_ptr<expression>getRight() const {return right;}
expression *getLeft() const {return left;}
expression *getRight() const {return right;}
bool isBinOp();
shared_ptr<operands>evaluate();
shared_ptr<operands>stringEval(shared_ptr<operands>l,
shared_ptr<operands>r);
operands *evaluate();
/* r is NULL for unary operators */
expression(shared_ptr<expression>l, enum OPERATORS o,
shared_ptr<expression>r=NULL)
{
this->left=l;
this->right=r;
this->oper=o;
}
expression(expression *l, enum OPERATORS o, expression *r=nullptr);
/* Terminal expression node */
expression(shared_ptr<operands>x)
{
op=x;
oper=O_TERM;
}
/*TODO: Recycle temporary variableTypes when not in debug mode*/
expression(operands *x);
virtual ~expression()
{}
};
@@ -252,7 +266,7 @@ class label
{
unsigned int id;
static unsigned int nextID;
static unordered_map<string, shared_ptr<label> > lookup;
static unordered_map<string, unique_ptr<label> > lookup;
public:
static void dumpLabels();
static void generateEnd();
@@ -262,19 +276,18 @@ public:
void generateJumpTo();
/* pass generateOnNSkip as second paramater
to generateOnNTo or generateOnNSub */
unsigned int generateOnNSkip(list<shared_ptr<label> >&dest);
static void generateOnNTo(shared_ptr<expression>e, unsigned int skip);
void generateCondJump(shared_ptr<expression>e);
unsigned int generateOnNSkip(list<label *>&dest);
static void generateOnNTo(expression *e, unsigned int skip);
void generateCondJump(expression *e);
void generate();
static shared_ptr<label>find(string &s);
static label *find(string &s);
label(){this->id = ++nextID;}
label(string &s)
{
unordered_map<string, shared_ptr<label> >lookup;
label();
label::lookup[s]=shared_ptr<label>(this);
label::lookup[s]=unique_ptr<label>(this);
}
virtual ~label()
@@ -285,20 +298,20 @@ public:
class ifStatement:public codeType
{
/* for continue command */
shared_ptr<label>redo;
label *redo;
/* for break or after "then" condition */
shared_ptr<label>done;
label *done;
/* For elsif command */
shared_ptr<label>chain;
label *chain;
public:
void generateContinue();
virtual void generateBreak();
/* enable else or elsif condition */
void alternative(shared_ptr<expression>e=NULL);
void alternative(expression *e=nullptr);
/* end if */
virtual void close();
explicit ifStatement(shared_ptr<expression>e);
explicit ifStatement(expression *e);
virtual ~ifStatement()
{}
};
@@ -306,11 +319,11 @@ public:
/* looping constructs */
class repeatLoop:public codeType
{
shared_ptr<label>loopStart;
shared_ptr<label>loopEnd;
label *loopStart;
label *loopEnd;
public:
virtual void generateBreak();
virtual void close(shared_ptr<expression>e);
virtual void close(expression *e);
explicit repeatLoop();
virtual ~repeatLoop()
@@ -319,8 +332,8 @@ public:
class doLoop:public codeType
{
shared_ptr<label>loopStart;
shared_ptr<label>loopEnd;
label *loopStart;
label *loopEnd;
public:
virtual void generateBreak();
virtual void close();
@@ -332,15 +345,15 @@ public:
class whileLoop:public codeType
{
shared_ptr<label>loopContinue;
shared_ptr<label>loopStart;
shared_ptr<label>loopEnd;
shared_ptr<expression>cond;
label *loopContinue;
label *loopStart;
label *loopEnd;
expression *cond;
public:
virtual void generateBreak();
virtual void close();
explicit whileLoop(shared_ptr<expression>e);
explicit whileLoop(expression *e);
virtual ~whileLoop()
{}
};
@@ -349,9 +362,9 @@ class variableType:public operands
{
enum SCOPES myScope;
public:
static shared_ptr<variableType>getOrCreateVar(string &name, enum TYPES t);
static variableType *getOrCreateVar(string &name, enum TYPES t);
void assignment(shared_ptr<expression>value);
void assignment(expression *value);
/* always call generateBox() after new variableType() */
variableType(enum SCOPES s, string &name, enum TYPES t);
variableType();
@@ -364,11 +377,10 @@ class arrayType:public variableType
list<unsigned int> dimensions;
public:
string generateBox(enum SCOPES s);
virtual string boxName(list<shared_ptr<operands> >indexes);
virtual string boxName(list<operands *>indexes);
virtual string boxName(){error(E_UNDIMENSIONED_ARRAY);}
void assignment(list<shared_ptr<expression> >indexes,
shared_ptr<expression>value);
void assignment(list<expression *>indexes, expression *value);
explicit arrayType(string &name, enum TYPES t, list<unsigned int>dim);
/*:variableType(scope, name, t);*/
@@ -378,67 +390,66 @@ public:
class forLoop:public codeType
{
shared_ptr<variableType>var;
shared_ptr<variableType>startTemp;
shared_ptr<variableType>stopTemp;
shared_ptr<whileLoop>infrastructure;
shared_ptr<expression>step;
variableType *var;
variableType *startTemp;
variableType *stopTemp;
whileLoop *infrastructure;
expression *step;
public:
virtual void generateBreak();
virtual void close();
explicit forLoop(shared_ptr<variableType>v, shared_ptr<expression>start,
shared_ptr<expression>stop, shared_ptr<expression>stepVal=NULL);
explicit forLoop(variableType *v, expression *start, expression *stop,
expression *stepVal=nullptr);
virtual ~forLoop()
{}
};
class fn:codeType
{
static unordered_map<string, shared_ptr<fn> > functions;
static list<shared_ptr<fn> > callStack;
static unordered_map<string, unique_ptr<fn> > functions;
static list<fn *> callStack;
static unsigned int nextID;
list<shared_ptr<variableType> >params;
list<variableType * >params;
string funcName;
unsigned int id;
enum TYPES kind;
shared_ptr<operands>rc;
operands *rc;
/* two labels common to all subroutine calls */
shared_ptr<label>startAddr;
shared_ptr<label>ret;
label *startAddr;
label *ret;
/* private constructor used by generateGosub and generateOnNSub*/
fn(shared_ptr<label>gosub);
fn(label *gosub);
public:
static void dumpCallStack();
static shared_ptr<fn>getCurrentSub();
static shared_ptr<fn>getSub(string &name);
static void generateGosub(shared_ptr<label> sub);
static fn *getCurrentSub();
static fn *getSub(string &name);
static void generateGosub(label * sub);
/* must be called after label::generateOnNSkip */
static void generateOnNSub(shared_ptr<expression>e, unsigned int skip);
static void generateOnNSub(expression *e, unsigned int skip);
unsigned int getID() const {return this->id;}
int getNumParams() const {return this->params.size();}
void addParameter(shared_ptr<variableType>);
void addParameter(variableType *);
shared_ptr<operands>generateCall(string &name,
list<shared_ptr<operands> >&paramList);
void generateReturn(shared_ptr<expression>expr);
operands *generateCall(string &name, list<operands *>&paramList);
void generateReturn(expression *expr);
void generateReturn();
virtual void generateBreak();
virtual void close();
fn(string &name, enum CODES t, shared_ptr<operands>returnCode=NULL);
fn(string &name, enum CODES t, operands *returnCode=nullptr);
virtual ~fn()
{}
};
class printSegment
{
shared_ptr<expression>cargo;
expression *cargo;
enum SEPARATORS sep;
public:
void generate();
printSegment(shared_ptr<expression>e=NULL, enum SEPARATORS s=S_LINEFEED);
printSegment(expression *e=nullptr, enum SEPARATORS s=S_LINEFEED);
virtual ~printSegment()
{}
};

View File

@@ -10,7 +10,7 @@
#include "runtime/runtime.h"
/* static initializers */
unordered_map<string, shared_ptr<label> > label::lookup;
unordered_map<string, unique_ptr<label> > label::lookup;
unsigned int label::nextID=START;
/* base class of all the code structure types */
@@ -36,11 +36,11 @@ codeType::~codeType()
}
/* label definitions and helper routines */
shared_ptr<label>label::find(string &s)
label *label::find(string &s)
{
unordered_map<string, shared_ptr<label> >lookup;
auto ret=label::lookup.find(s);
return(ret==label::lookup.end()?NULL:ret->second);
return(ret==label::lookup.end()?nullptr:ret->second.get());
}
void label::dumpLabels()
@@ -65,7 +65,7 @@ void label::generateJumpTo()
}
/* pass this as second parameter to generateOnNTo or generateOnNSub */
unsigned int label::generateOnNSkip(list<shared_ptr<label> >&dest)
unsigned int label::generateOnNSkip(list<label *>&dest)
{
if (dest.size()<2)error(E_BAD_SYNTAX);
auto iter=dest.begin();
@@ -80,25 +80,33 @@ unsigned int label::generateOnNSkip(list<shared_ptr<label> >&dest)
return this->getID();
}
void label::generateOnNTo(shared_ptr<expression>e, unsigned int skip)
void label::generateOnNTo(expression *e, unsigned int skip)
{
shared_ptr<operands>o=e->evaluate();
operands *o=e->evaluate();
if (o->getType()==T_INT||o->getType()==T_INTVAR)
{
output_cpp<< "if(" << o->boxName() << ">=0 && "
<< o->boxName() << "<js" << skip << ")state=j["
<< o->boxName() << "];\nbreak;\n";
o->dispose();
delete e;
return;
}
error(E_TYPE_MISMATCH);
}
void label::generateCondJump(shared_ptr<expression>e)
void label::generateCondJump(expression *e)
{
shared_ptr<operands>o=e->evaluate();
operands *o=e->evaluate();
if (o->getType()==T_INT||o->getType()==T_INTVAR)
{
output_cpp<< "if(" << o->boxName()
<< "!=0)state=" << this->getID() << ";\nbreak;\n";
o->dispose();
delete e;
return;
}
error(E_TYPE_MISMATCH);
}
void label::generate()
@@ -108,13 +116,13 @@ void label::generate()
/* ifStatement definition */
ifStatement::ifStatement(shared_ptr<expression>e):codeType(T_IF)
ifStatement::ifStatement(expression *e):codeType(T_IF)
{
this->redo=shared_ptr<label>(new label());
this->redo=new label();
redo->generate();
this->done=shared_ptr<label>(new label());
shared_ptr<expression>f=shared_ptr<expression>(new expression(e,O_NOT));
this->chain=shared_ptr<label>(new label());
this->done=new label();
expression *f=new expression(e,O_NOT);
this->chain=new label();
chain->generateCondJump(f);
}
@@ -128,16 +136,15 @@ void ifStatement::generateContinue()
redo->generateJumpTo();
}
void ifStatement::alternative(shared_ptr<expression>e)
void ifStatement::alternative(expression *e)
{
done->generateJumpTo();
this->chain->generate();
this->chain=NULL;
if(e!=NULL)
this->chain=nullptr;
if(e!=nullptr)
{
this->chain=shared_ptr<label>(new label());
shared_ptr<expression>f=shared_ptr<expression>(
new expression(e,O_NOT));
this->chain=new label();
expression *f=new expression(e,O_NOT);
chain->generateCondJump(f);
}
}
@@ -152,8 +159,8 @@ void ifStatement::close()
/* Loop definitions */
repeatLoop::repeatLoop():codeType(T_REPEATLOOP)
{
this->loopStart=shared_ptr<label>(new label());
this->loopEnd=shared_ptr<label>(new label());
this->loopStart=new label();
this->loopEnd=new label();
loopStart->generate();
}
@@ -162,17 +169,17 @@ void repeatLoop::generateBreak()
loopEnd->generateJumpTo();
}
void repeatLoop::close(shared_ptr<expression>e)
void repeatLoop::close(expression *e)
{
shared_ptr<expression>f=shared_ptr<expression>(new expression(e, O_NOT));
expression *f=new expression(e, O_NOT);
loopStart->generateCondJump(f);
loopEnd->generate();
}
doLoop::doLoop():codeType(T_DOLOOP)
{
this->loopStart=shared_ptr<label>(new label());
this->loopEnd=shared_ptr<label>(new label());
this->loopStart=new label();
this->loopEnd=new label();
loopStart->generate();
}
@@ -187,11 +194,11 @@ void doLoop::close()
this->loopEnd->generate();
}
whileLoop::whileLoop(shared_ptr<expression>e):codeType(T_WHILELOOP)
whileLoop::whileLoop(expression *e):codeType(T_WHILELOOP)
{
loopContinue=shared_ptr<label>(new label());
loopStart=shared_ptr<label>(new label());
loopEnd=shared_ptr<label>(new label());
loopContinue=new label();
loopStart=new label();
loopEnd=new label();
cond=e;
loopStart->generateJumpTo();
loopContinue->generate();
@@ -209,42 +216,34 @@ void whileLoop::close()
loopEnd->generate();
}
forLoop::forLoop(shared_ptr<variableType>v,
shared_ptr<expression>start, shared_ptr<expression>stop,
shared_ptr<expression>stepVal):codeType(T_FORLOOP)
forLoop::forLoop(variableType *v, expression *start, expression *stop,
expression *stepVal):codeType(T_FORLOOP)
{
/*v=start;
stopTemp=stop;*/
v->assignment(start);
stopTemp->assignment(stop);
/* if (v<stopTemp) */
shared_ptr<ifStatement>c=shared_ptr<ifStatement>(new ifStatement(
shared_ptr<expression>(new expression(shared_ptr<expression>(
new expression(v)), O_LESS, shared_ptr<expression>(
new expression(stopTemp))))));
ifStatement *c=new ifStatement(new expression(new expression(v), O_LESS,
new expression(stopTemp)));
/* startTemp=v;*/
startTemp->assignment(shared_ptr<expression>(new expression(v)));
startTemp->assignment(new expression(v));
/* else */
c->alternative();
/* startTemp=stopTemp;
stopTemp=v;*/
startTemp->assignment(shared_ptr<expression>(new expression(stopTemp)));
stopTemp->assignment(shared_ptr<expression>(new expression(v)));
startTemp->assignment(new expression(stopTemp));
stopTemp->assignment(new expression(v));
/* endif */
c->close();
/* while (v<=stopTemp && v>=startTemp) */
shared_ptr<expression>stopper1=shared_ptr<expression>(new expression(
shared_ptr<expression>(new expression(v)), O_LESS_EQUAL,
shared_ptr<expression>(new expression(stopTemp))));
shared_ptr<expression>stopper2=shared_ptr<expression>(new expression(
shared_ptr<expression>(new expression(v)), O_GREATER_EQUAL,
shared_ptr<expression>(new expression(startTemp))));
shared_ptr<expression>stopper=shared_ptr<expression>(new expression(
stopper1, O_AND, stopper2));
shared_ptr<whileLoop>infrastructure=shared_ptr<whileLoop>(new whileLoop(
shared_ptr<expression>(new expression(stopper, O_UNEQUAL,
shared_ptr<expression>(new expression(
shared_ptr<constOp>(new constOp("0", T_INT))))))));
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);
infrastructure=new whileLoop(new expression(stopper, O_UNEQUAL,
new expression(new constOp("0", T_INT))));
if (stepVal)
{
step=stepVal;
@@ -252,8 +251,7 @@ forLoop::forLoop(shared_ptr<variableType>v,
else
{
/* if not present "step" is assumed to be 1 */
step=shared_ptr<expression>(new expression(
shared_ptr<constOp>(new constOp("1", T_INT))));
step=new expression(new constOp("1", T_INT));
}
}
@@ -265,8 +263,7 @@ void forLoop::generateBreak()
void forLoop::close()
{
/* var=var+step; */
shared_ptr<expression>stepper=shared_ptr<expression>(new expression(
shared_ptr<expression>(new expression(var)), O_PLUS, step));
expression *stepper=new expression(new expression(var), O_PLUS, step);
var->assignment(stepper);
infrastructure->close();
}

View File

@@ -12,11 +12,15 @@
class fn;
unsigned int operands::nextID=0;
unordered_map<string, unsigned int> constOp::strConst;
list<tempVar *>tempVar::intQueue;
list<tempVar *>tempVar::floatQueue;
list<tempVar *>tempVar::stringQueue;
/* methods for operands */
enum TYPES operands::getSimpleVarType()
enum TYPES operands::getSimpleVarType(enum TYPES t)
{
switch (this->getType())
switch (t)
{
case T_FLOAT:
case T_FLOATCALL_ARRAY:
@@ -36,8 +40,12 @@ enum TYPES operands::getSimpleVarType()
error(E_UNASSIGNABLE_TYPE);
}
/* operands used by expression parser and variables */
enum TYPES operands::getSimpleVarType()
{
return getSimpleVarType(this->getType());
}
/* operands used by expression parser and variables */
operands::operands(enum TYPES t)
{
this->id = ++nextID;
@@ -77,6 +85,22 @@ void operands::generateBox(enum SCOPES s)
error(E_INTERNAL);
}
operands *operands::createOp(enum TYPES t)
{
if (DEBUG)
{
operands *x=createOp(t);
x->generateBox(scopeGlobal?S_GLOBAL:S_LOCAL);
return x;
}
return tempVar::getOrCreateVar(t);
}
void operands::dispose()
{
delete this;
}
string operands::boxName()
{
ostringstream s;
@@ -97,6 +121,119 @@ string operands::boxName()
}
}
tempVar::tempVar(enum TYPES t):operands(t)
{
generateBox(S_GLOBAL);
}
tempVar *tempVar::getOrCreateVar(enum TYPES t)
{
if (t!=getSimpleVarType(t))
{
error(E_TYPE_MISMATCH);
}
switch (t)
{
case T_INTVAR:
if (intQueue.empty())
{
return new tempVar(t);
}
else
{
tempVar *x=intQueue.back();
intQueue.pop_back();
return x;
}
break;
case T_FLOATVAR:
if (floatQueue.empty())
{
return new tempVar(t);
}
else
{
tempVar *x=floatQueue.back();
floatQueue.pop_back();
return x;
}
break;
case T_STRINGVAR:
if (stringQueue.empty())
{
return new tempVar(t);
}
else
{
tempVar *x=stringQueue.back();
stringQueue.pop_back();
return x;
}
default:
break;
}
/* unreachable code */
error(E_INTERNAL);
}
void tempVar::dispose()
{
switch(this->getType())
{
case T_STRINGVAR:
stringQueue.emplace_front(this);
return;
case T_FLOATVAR:
floatQueue.emplace_front(this);
return;
case T_INTVAR:
intQueue.emplace_front(this);
return;
default:
break;
}
error(E_INTERNAL);
}
void tempVar::eraseQueues()
{
tempVar *i;
while(!intQueue.empty())
{
i=intQueue.back();
if (DUMP)
{
logfile << "variable " << i->boxName()
<< " is a temporary integer\n";
}
delete i;
intQueue.pop_back();
}
while(!floatQueue.empty())
{
i=floatQueue.back();
if (DUMP)
{
logfile << "variable " << i->boxName()
<< " is a temporary floating point\n";
}
delete i;
floatQueue.pop_back();
}
while(!stringQueue.empty())
{
i=stringQueue.back();
if (DUMP)
{
logfile << "variable " << i->boxName()
<< " is a temporary string\n";
}
delete i;
stringQueue.pop_back();
}
if (DUMP) logfile << endl;
}
void constOp::processConst(unsigned int i)
{
stringstream me;
@@ -136,7 +273,8 @@ constOp::constOp(const string &s, enum TYPES t):operands(t)
else
{
consts_h << "const string ";
processConst(s);
processConst(getID());
consts_h << box << "=\"" << s << "\";\n";
constOp::strConst[s]=getID();
}
}
@@ -148,6 +286,18 @@ constOp::constOp(const string &s, enum TYPES t):operands(t)
}
/* expression parsing routines */
expression::expression(expression *l, enum OPERATORS o, expression *r)
{
this->left=l;
this->right=r;
this->oper=o;
}
expression::expression(operands *x)
{
op=x;
oper=O_TERM;
}
/* binary vs. unary ops */
bool expression::isBinOp()
@@ -167,13 +317,12 @@ bool expression::isBinOp()
error(E_INTERNAL);
}
shared_ptr<operands>expression::evaluate()
operands *expression::evaluate()
{
if (this->getOp()==O_TERM) return op;
shared_ptr<operands>l;
shared_ptr<operands>r;
operands *l;
operands *r;
enum TYPES t;
enum SCOPES scopeVar=(scopeGlobal?S_GLOBAL:S_LOCAL);
l=this->getLeft()->evaluate();
if (this->isBinOp())
{
@@ -182,14 +331,12 @@ shared_ptr<operands>expression::evaluate()
enum TYPES rt=r->getSimpleVarType();
if (lt==T_INTVAR && rt==T_FLOATVAR)
{
l=shared_ptr<operands>((new expression(shared_ptr<expression>(
new expression(l)), O_INT_TO_FLOAT))->evaluate());
l=(new expression(new expression(l), O_INT_TO_FLOAT))->evaluate();
lt=T_FLOATVAR;
}
if (lt==T_FLOATVAR && rt==T_INTVAR)
{
r=shared_ptr<operands>((new expression(shared_ptr<expression>(
new expression(r)), O_INT_TO_FLOAT))->evaluate());
r=(new expression(new expression(r), O_INT_TO_FLOAT))->evaluate();
rt=T_FLOATVAR;
}
if (lt!=rt)error(E_TYPE_MISMATCH);
@@ -198,127 +345,111 @@ shared_ptr<operands>expression::evaluate()
else
{
t=l->getSimpleVarType();
r=NULL;
r=nullptr;
}
switch (this->getOp())
{
case O_STRING_CONCAT:
if (t!=T_STRINGVAR) error(E_BAD_SYNTAX);
this->op=shared_ptr<operands>(new operands(T_STRINGVAR));
this->op->generateBox(scopeGlobal?S_GLOBAL:S_LOCAL);
this->op=operands::createOp(T_STRINGVAR);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "+" << r->boxName();
break;
case O_INVERT:
this->op=shared_ptr<operands>(new operands(t));
this->op->generateBox(scopeVar);
this->op=operands::createOp(t);
output_cpp << this->op->boxName() << "= ~" << l->boxName() << ";\n";
break;
case O_NEGATE:
this->op=shared_ptr<operands>(new operands(t));
this->op->generateBox(scopeVar);
this->op=operands::createOp(t);
output_cpp << this->op->boxName() << "= -" << l->boxName() << ";\n";
break;
case O_NOT:
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "= !" << l->boxName() << ";\n";
break;
case O_INT_TO_FLOAT: /*Note: this duplicates functionality of variable assignment */
this->op=shared_ptr<operands>(new operands(T_FLOATVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_FLOATVAR);
output_cpp << this->op->boxName() << "= const_cast<double>("
<< l->boxName() << ");\n";
/* TODO: Check for divide by zero error and modulo zero error */
case O_REMAINDER:
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "%" << r->boxName() << ";\n";
break;
case O_DIVIDE:
this->op=shared_ptr<operands>(new operands(t));
this->op->generateBox(scopeVar);
this->op=operands::createOp(t);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "/" << r->boxName() << ";\n";
break;
case O_PLUS:
this->op=shared_ptr<operands>(new operands(t));
this->op->generateBox(scopeVar);
this->op=operands::createOp(t);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "+" << r->boxName() << ";\n";
break;
case O_MINUS:
this->op=shared_ptr<operands>(new operands(t));
this->op->generateBox(scopeVar);
this->op=operands::createOp(t);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "-" << r->boxName() << ";\n";
break;
case O_MULTIPLY:
this->op=shared_ptr<operands>(new operands(t));
this->op->generateBox(scopeVar);
this->op=operands::createOp(t);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "*" << r->boxName() << ";\n";
break;
case O_OR:
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "|" << r->boxName() << ";\n";
break;
case O_AND:
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=" << l->boxName()
<< "&" << r->boxName() << ";\n";
break;
case O_GREATER:
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=(" << l->boxName()
<< ">" << r->boxName() << ")?-1:0;\n";
break;
case O_LESS:
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=(" << l->boxName()
<< "<" << r->boxName() << ")?-1:0;\n";
break;
case O_GREATER_EQUAL:
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=(" << l->boxName()
<< ">=" << r->boxName() << ")?-1:0;\n";
break;
case O_LESS_EQUAL:
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=(" << l->boxName()
<< "<=" << r->boxName() << ")?-1:0;\n";
break;
case O_EQUAL:
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=(" << l->boxName()
<< "==" << r->boxName() << ")?-1:0;\n";
break;
case O_UNEQUAL:
this->op=shared_ptr<operands>(new operands(T_INTVAR));
this->op->generateBox(scopeVar);
this->op=operands::createOp(T_INTVAR);
output_cpp << this->op->boxName() << "=(" << l->boxName()
<< "!=" << r->boxName() << ")?-1:0;\n";
break;
default:
errorLevel=E_INTERNAL;
exit(1);
break;
error(E_INTERNAL);
}
/* convert expression into single operand */
this->oper=O_TERM;
l->dispose();
delete left;
r->dispose();
delete right;
return this->op;
}
@@ -331,41 +462,40 @@ variableType::variableType(enum SCOPES s, string &name, enum TYPES t):operands(t
case S_LOCAL:
if(locals.find(name)!=locals.end() ||
statics.find(name)!=statics.end() ) error(E_DUPLICATE_SYMBOL);
locals[name]=shared_ptr<variableType>(this);
locals[name]=unique_ptr<variableType>(this);
break;
case S_GLOBAL:
if(globals.find(name)!=globals.end()) error(E_DUPLICATE_SYMBOL);
globals[name]=shared_ptr<variableType>(this);
globals[name]=unique_ptr<variableType>(this);
break;
case S_STATIC:
if(locals.find(name)!=locals.end() ||
statics.find(name)!=statics.end() ) error(E_DUPLICATE_SYMBOL);
statics[name]=shared_ptr<variableType>(this);
statics[name]=unique_ptr<variableType>(this);
break;
default:
error(E_INTERNAL);
}
}
shared_ptr<variableType> variableType::getOrCreateVar(string &name, enum TYPES t)
variableType *variableType::getOrCreateVar(string &name, enum TYPES t)
{
if (!scopeGlobal)
{
auto i=locals.find(name);
if(i!=locals.end())return i->second;
if(i!=locals.end())return i->second.get();
i=statics.find(name);
if(i!=statics.end())return i->second;
if(i!=statics.end())return i->second.get();
}
if (globals.find(name)!=globals.end())return globals[name];
shared_ptr<variableType>v=shared_ptr<variableType>(new variableType(
scopeGlobal?S_GLOBAL:S_LOCAL, name, t));
if (globals.find(name)!=globals.end())return globals[name].get();
variableType *v=new variableType(scopeGlobal?S_GLOBAL:S_LOCAL, name, t);
v->generateBox(scopeGlobal?S_GLOBAL:S_LOCAL);
return v;
}
void variableType::assignment(shared_ptr<expression>value)
void variableType::assignment(expression *value)
{
shared_ptr<operands>op=value->evaluate();
operands *op=value->evaluate();
enum TYPES t=op->getSimpleVarType();
switch (this->getType())
{
@@ -389,9 +519,11 @@ void variableType::assignment(shared_ptr<expression>value)
<< op->boxName() << ";\n";
break;
}
op->dispose();
delete value;
}
string arrayType::boxName(list<shared_ptr<operands> >indexes)
string arrayType::boxName(list<operands *>indexes)
{
ostringstream out;
auto i=indexes.begin();
@@ -436,11 +568,10 @@ arrayType::arrayType(string &name, enum TYPES t, list<unsigned int>dim):
this->dimensions=dim;
}
void arrayType::assignment(list<shared_ptr<expression> >indexes,
shared_ptr<expression>value)
void arrayType::assignment(list<expression *>indexes, expression *value)
{
list<shared_ptr<operands>>x;
shared_ptr<operands>op=value->evaluate();
list<operands *>x;
operands *op=value->evaluate();
enum TYPES t=op->getSimpleVarType();
auto i=indexes.begin();
while(i!=indexes.end())
@@ -470,4 +601,6 @@ void arrayType::assignment(list<shared_ptr<expression> >indexes,
error(E_INTERNAL);
}
output_cpp << this->boxName(x) << '=' << op->boxName() <<";\n";
op->dispose();
delete value;
}

View File

@@ -9,8 +9,8 @@
#include "yab2cpp.h"
/* static initializers */
unordered_map<string, shared_ptr<fn> > fn::functions;
list<shared_ptr<fn> >fn::callStack;
unordered_map<string, unique_ptr<fn> > fn::functions;
list<fn *>fn::callStack;
unsigned int fn::nextID=0;
/* function definitions */
@@ -29,50 +29,48 @@ void fn::dumpCallStack()
} while(i!=callStack.rend());
}
shared_ptr<fn>fn::getCurrentSub()
fn *fn::getCurrentSub()
{
list<shared_ptr<fn> >callStack;
return callStack.back();
}
void fn::generateOnNSub(shared_ptr<expression>e, unsigned int skip)
void fn::generateOnNSub(expression *e, unsigned int skip)
{
shared_ptr<label>r=shared_ptr<label>(new label());
shared_ptr<fn> self=shared_ptr<fn>(new fn(r));
label *r=new label();
fn *self=new fn(r);
fn::callStack.push_back(self);
label::generateOnNTo(e, skip);
r->generate();
}
void fn::generateGosub(shared_ptr<label> sub)
void fn::generateGosub(label *sub)
{
shared_ptr<label>r=shared_ptr<label>(new label());
shared_ptr<fn> self=shared_ptr<fn>(new fn(r));
label *r=new label();
fn *self=new fn(r);
fn::callStack.push_back(self);
sub->generateJumpTo();
r->generate();
}
fn::fn(shared_ptr<label>gosub):codeType(T_GOSUB)
fn::fn(label *gosub):codeType(T_GOSUB)
{
this->funcName="unnamed gosub";
this->ret=gosub;
}
shared_ptr<fn> fn::getSub(string &name)
fn *fn::getSub(string &name)
{
auto iter=fn::functions.find(name);
if(iter==fn::functions.end()) return NULL;
return iter->second;
if(iter==fn::functions.end()) return nullptr;
return iter->second.get();
}
shared_ptr<operands>fn::generateCall(string &name,
list<shared_ptr<operands> >&paramList)
operands *fn::generateCall(string &name, list<operands *>&paramList)
{
auto v=params.begin();
shared_ptr<operands>current;
shared_ptr<fn>g=fn::getSub(name);
if (g==NULL)
operands *current;
fn *g=fn::getSub(name);
if (g==nullptr)
{
error(E_SUBROUTINE_NOT_FOUND);
}
@@ -95,8 +93,7 @@ shared_ptr<operands>fn::generateCall(string &name,
{
error(E_TYPE_MISMATCH);
}
(*v)->assignment(shared_ptr<expression>(
new expression(current)));
(*v)->assignment(new expression(current));
++v;
}
/* pad remaining unassigned variables with empty values */
@@ -105,22 +102,13 @@ shared_ptr<operands>fn::generateCall(string &name,
switch ((*v)->getType())
{
case T_FLOATVAR:
(*v)->assignment(shared_ptr<expression>(
new expression(
shared_ptr<constOp>(new constOp("0.0", T_FLOAT))
)));
(*v)->assignment(new expression(new constOp("0.0", T_FLOAT)));
break;
case T_INTVAR:
(*v)->assignment(shared_ptr<expression>(
new expression(
shared_ptr<constOp>(new constOp("0", T_INT))
)));
(*v)->assignment(new expression(new constOp("0", T_INT)));
break;
case T_STRINGVAR:
(*v)->assignment(shared_ptr<expression>(
new expression(
shared_ptr<constOp>(new constOp("", T_STRING))
)));
(*v)->assignment(new expression(new constOp("", T_STRING)));
default:
error(E_INTERNAL);
}
@@ -133,7 +121,7 @@ shared_ptr<operands>fn::generateCall(string &name,
void fn::generateReturn()
{
shared_ptr<fn>c=getCurrentSub();
fn *c=getCurrentSub();
switch(c->getType())
{
case T_UNKNOWNFUNC:
@@ -149,12 +137,13 @@ void fn::generateReturn()
}
}
void fn::generateReturn(shared_ptr<expression>expr)
void fn::generateReturn(expression *expr)
{
this->rc=expr->evaluate();
this->kind=rc->getSimpleVarType();
this->ret->generateJumpTo();
fn::callStack.pop_back();
delete expr;
switch (this->getType())
{
case T_UNKNOWNFUNC:
@@ -198,7 +187,7 @@ void fn::close()
scopeGlobal=true;
}
fn::fn(string &s, enum CODES t, shared_ptr<operands>returnCode):codeType(t)
fn::fn(string &s, enum CODES t, operands *returnCode):codeType(t)
{
/*check for nesting error */
if (!scopeGlobal) error(E_END_FUNCTION);
@@ -209,14 +198,14 @@ fn::fn(string &s, enum CODES t, shared_ptr<operands>returnCode):codeType(t)
/*define storage for locals*/
funcs_h << "struct f" << this->id <<"\n{\n";
/*define label space for return*/
this->ret=shared_ptr<label>(new label());
this->ret=new label();
/*allocate function name*/
fn::functions[s]=shared_ptr<fn>(this);
fn::functions[s]=unique_ptr<fn>(this);
/* initiate local scope */
scopeGlobal=false;
/*keep track of where the return code will be sent to*/
this->rc=returnCode;
/*allocate and generate start address label*/
this->startAddr=shared_ptr<label>(new label());
this->startAddr=new label();
startAddr->generate();
}

View File

@@ -8,7 +8,7 @@
*/
#include "yab2cpp.h"
printSegment::printSegment(shared_ptr<expression>e, enum SEPARATORS s)
printSegment::printSegment(expression *e, enum SEPARATORS s)
{
cargo=e;
sep=s;
@@ -18,11 +18,11 @@ void printSegment::generate()
{
if (cargo!=NULL)
{
shared_ptr<operands>op=cargo->evaluate();
operands *op=cargo->evaluate();
switch (op->getSimpleVarType())
{
case T_STRINGVAR:
output_cpp << "printf(\"%s\", " << op->boxName() << ");\n";
output_cpp << "puts(" << op->boxName() << ");\n";
break;
case T_INTVAR:
output_cpp << "printf(\"%d\", " << op->boxName() << ");\n";