removed most of the shared_ptr usage and retooled temporary variables to recycle
This commit is contained in:
28
tester.cpp
28
tester.cpp
@@ -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();
|
||||
}
|
||||
|
||||
83
yab2cpp.cpp
83
yab2cpp.cpp
@@ -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
183
yab2cpp.h
@@ -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> >¶mList);
|
||||
void generateReturn(shared_ptr<expression>expr);
|
||||
operands *generateCall(string &name, list<operands *>¶mList);
|
||||
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()
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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> >¶mList)
|
||||
operands *fn::generateCall(string &name, list<operands *>¶mList)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user