added static initializers and now it builds and links!
This commit is contained in:
20
yab2cpp.cpp
20
yab2cpp.cpp
@@ -8,6 +8,10 @@
|
||||
*/
|
||||
#include "yab2cpp.h"
|
||||
|
||||
unordered_map<string, shared_ptr<variable> >globals;
|
||||
unordered_map<string, shared_ptr<variable> >locals;
|
||||
unordered_map<string, shared_ptr<variable> >statics;
|
||||
|
||||
/* These correspond to the enum COMPILE_ERRORS. */
|
||||
const char *COMPILE_ERROR_NAMES[]={
|
||||
"no error",
|
||||
@@ -200,19 +204,17 @@ void logger(string s)
|
||||
void shutDown()
|
||||
{
|
||||
if (errorLevel != E_OK) cerr << "\nERROR: " << COMPILE_ERROR_NAMES[errorLevel] << "\n\n" << endl;
|
||||
if (fn::isCallStackEmpty())
|
||||
logger("Dumping stack.");
|
||||
if (mode & DUMP && (logfile))
|
||||
{
|
||||
logger("Stack was empty");
|
||||
fn::dumpCallStack();
|
||||
}
|
||||
else
|
||||
varNames << "Global Variables\n";
|
||||
for(auto iter=globals.begin(); iter!=globals.end(); ++iter)
|
||||
{
|
||||
logger("Dumping stack.");
|
||||
if (mode & DUMP && (logfile))
|
||||
{
|
||||
fn::dumpCallStack();
|
||||
}
|
||||
varNames << "variable " << iter->first << " has ID " << iter->second << "\n";
|
||||
}
|
||||
operands::dumpVars();
|
||||
varNames << endl;
|
||||
label::dumpLabels();
|
||||
output_cpp << "}\n}return state;\n}"<< endl;
|
||||
}
|
||||
|
||||
44
yab2cpp.h
44
yab2cpp.h
@@ -22,13 +22,16 @@ using namespace std;
|
||||
#define VER_MINOR 0
|
||||
#define VER_RELEASE 1
|
||||
|
||||
class variable;
|
||||
extern ofstream output_cpp;
|
||||
extern ofstream funcs_h;
|
||||
extern ofstream heap_h;
|
||||
extern ofstream consts_h;
|
||||
extern ofstream logfile;
|
||||
extern ofstream varNames;
|
||||
|
||||
extern unordered_map<string, shared_ptr<variable> >globals;
|
||||
extern unordered_map<string, shared_ptr<variable> >locals;
|
||||
extern unordered_map<string, shared_ptr<variable> >statics;
|
||||
/*
|
||||
** list of all compiler errors
|
||||
**
|
||||
@@ -151,7 +154,7 @@ enum OPERATORS
|
||||
/* global prototype */
|
||||
[[noreturn]] void error(enum COMPILE_ERRORS err);
|
||||
void logger(string s);
|
||||
|
||||
|
||||
/* internal states used by the parser */
|
||||
class scope:public ofstream
|
||||
{
|
||||
@@ -172,16 +175,10 @@ class operands
|
||||
static unsigned int nextID;
|
||||
/* private constructor for parameter passing only */
|
||||
explicit operands(unsigned int id, enum TYPES t);
|
||||
protected:
|
||||
static unordered_map<string, shared_ptr<operands>> globals;
|
||||
public:
|
||||
enum TYPES getType() const {return type;}
|
||||
unsigned int getID() const {return id;}
|
||||
|
||||
static shared_ptr<operands>findGlobal(string &s);
|
||||
static void dumpVars();
|
||||
static shared_ptr<operands>getOrCreateGlobal(string &s, enum TYPES t);
|
||||
|
||||
enum TYPES getSimpleVarType();
|
||||
void generateBox(enum SCOPES s);
|
||||
virtual string boxName();
|
||||
@@ -233,26 +230,24 @@ public:
|
||||
this->right=r;
|
||||
this->oper=o;
|
||||
}
|
||||
expression(operands *x)
|
||||
expression(shared_ptr<operands>x)
|
||||
{
|
||||
op=shared_ptr<operands>(x);
|
||||
op=x;
|
||||
oper=O_TERM;
|
||||
}
|
||||
/*TODO: Recycle temporary variables when not in debug mode*/
|
||||
virtual ~expression();
|
||||
virtual ~expression()
|
||||
{}
|
||||
};
|
||||
|
||||
/* parent class of all code types */
|
||||
class codeType
|
||||
{
|
||||
enum CODES type;
|
||||
static list<shared_ptr<codeType> >nesting;
|
||||
public:
|
||||
enum CODES getType() const {return this->type;}
|
||||
|
||||
static shared_ptr<codeType> getCurrent();
|
||||
|
||||
virtual void close();
|
||||
virtual void close()=0;
|
||||
virtual void generateBreak()=0;
|
||||
|
||||
explicit codeType(enum CODES t);
|
||||
@@ -283,8 +278,9 @@ public:
|
||||
label(){this->id = ++nextID;}
|
||||
label(string &s)
|
||||
{
|
||||
unordered_map<string, shared_ptr<label> >lookup;
|
||||
label();
|
||||
lookup[s]=shared_ptr<label>(this);
|
||||
label::lookup[s]=shared_ptr<label>(this);
|
||||
}
|
||||
|
||||
virtual ~label()
|
||||
@@ -357,7 +353,7 @@ public:
|
||||
static shared_ptr<variable>getOrCreateVar(string &name, enum TYPES t);
|
||||
|
||||
void assignment(shared_ptr<expression>value);
|
||||
explicit variable(enum SCOPES s, string &name, enum TYPES t);
|
||||
variable(enum SCOPES s, string &name, enum TYPES t);
|
||||
variable();
|
||||
~variable()
|
||||
{}
|
||||
@@ -386,29 +382,27 @@ public:
|
||||
virtual void close();
|
||||
|
||||
explicit forLoop(shared_ptr<variable>v, shared_ptr<expression>start, shared_ptr<expression>stop, shared_ptr<expression>stepVal=NULL);
|
||||
virtual ~forLoop();
|
||||
virtual ~forLoop()
|
||||
{}
|
||||
};
|
||||
|
||||
class fn:codeType
|
||||
{
|
||||
friend variable;
|
||||
static unordered_map<string, shared_ptr<fn> >functions;
|
||||
static unordered_map<string, shared_ptr<fn> > functions;
|
||||
static list<shared_ptr<fn> > callStack;
|
||||
static unsigned int nextID;
|
||||
list<shared_ptr<variable> >params;
|
||||
string funcName;
|
||||
unsigned int id;
|
||||
enum TYPES kind;
|
||||
shared_ptr<operands>rc;
|
||||
/* two labels common to all subroutine calls */
|
||||
shared_ptr<label>startAddr;
|
||||
shared_ptr<label>ret;
|
||||
/* private constructor used by generateGosub and generateOnNSub*/
|
||||
fn(shared_ptr<label>gosub);
|
||||
static unordered_map<string, shared_ptr<variable> >locals;
|
||||
static unordered_map<string, shared_ptr<variable> >statics;
|
||||
public:
|
||||
static shared_ptr<variable>getOrCreateVar(enum TYPES t, string &s, bool stat);
|
||||
static void dumpCallStack();
|
||||
static bool isCallStackEmpty(){return callStack.begin()==callStack.end();}
|
||||
static shared_ptr<fn>getCurrentSub();
|
||||
static shared_ptr<fn>getSub(string &name);
|
||||
static void generateGosub(shared_ptr<label> sub);
|
||||
@@ -419,7 +413,7 @@ public:
|
||||
int getNumParams() const {return this->params.size();}
|
||||
void addParameter(shared_ptr<variable>);
|
||||
|
||||
shared_ptr<operands>generateCall(string &name, list<shared_ptr<operands> >paramList);
|
||||
shared_ptr<operands>generateCall(string &name, list<shared_ptr<operands> >¶mList);
|
||||
void generateReturn(shared_ptr<expression>expr);
|
||||
void generateReturn();
|
||||
virtual void generateBreak();
|
||||
|
||||
@@ -8,28 +8,22 @@
|
||||
*/
|
||||
#include "yab2cpp.h"
|
||||
|
||||
/* static initializers */
|
||||
unordered_map<string, shared_ptr<label> > label::lookup;
|
||||
unsigned int label::nextID;
|
||||
|
||||
/* base class of all the code structure types */
|
||||
codeType::codeType(enum CODES t)
|
||||
{
|
||||
nesting.push_back(shared_ptr<codeType>(this));
|
||||
this->type=t;
|
||||
}
|
||||
|
||||
shared_ptr<codeType> codeType::getCurrent()
|
||||
{
|
||||
return nesting.back();
|
||||
}
|
||||
|
||||
void codeType::close()
|
||||
{
|
||||
nesting.pop_back();
|
||||
}
|
||||
|
||||
/* label definitions and helper routines */
|
||||
shared_ptr<label>label::find(string &s)
|
||||
{
|
||||
auto ret=lookup.find(s);
|
||||
return(ret==lookup.end()?NULL:ret->second);
|
||||
unordered_map<string, shared_ptr<label> >lookup;
|
||||
auto ret=label::lookup.find(s);
|
||||
return(ret==label::lookup.end()?NULL:ret->second);
|
||||
}
|
||||
|
||||
void label::dumpLabels()
|
||||
@@ -201,30 +195,30 @@ forLoop::forLoop(shared_ptr<variable>v,
|
||||
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.get())),
|
||||
O_LESS, shared_ptr<expression>(new expression(stopTemp.get()))))));
|
||||
shared_ptr<expression>(new expression(shared_ptr<expression>(new expression(v)),
|
||||
O_LESS, shared_ptr<expression>(new expression(stopTemp))))));
|
||||
/* startTemp=v;*/
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(v.get())));
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(v)));
|
||||
/* else */
|
||||
c->alternative();
|
||||
/* startTemp=stopTemp;
|
||||
stopTemp=v;*/
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(stopTemp.get())));
|
||||
stopTemp->assignment(shared_ptr<expression>(new expression(v.get())));
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(stopTemp)));
|
||||
stopTemp->assignment(shared_ptr<expression>(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.get())), O_LESS_EQUAL,
|
||||
shared_ptr<expression>(new expression(stopTemp.get()))));
|
||||
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.get())), O_GREATER_EQUAL,
|
||||
shared_ptr<expression>(new expression(startTemp.get()))));
|
||||
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));
|
||||
this->infrastructure=new whileLoop(shared_ptr<expression>(new expression(
|
||||
stopper, O_UNEQUAL, shared_ptr<expression>(new expression(
|
||||
new constOp("0", T_INT))))));
|
||||
shared_ptr<constOp>(new constOp("0", T_INT)))))));
|
||||
if (stepVal)
|
||||
{
|
||||
step=stepVal;
|
||||
@@ -232,7 +226,8 @@ forLoop::forLoop(shared_ptr<variable>v,
|
||||
else
|
||||
{
|
||||
/* if not present "step" is assumed to be 1 */
|
||||
step=shared_ptr<expression>(new expression(new constOp("1", T_INT)));
|
||||
step=shared_ptr<expression>(new expression(
|
||||
shared_ptr<constOp>(new constOp("1", T_INT))));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +240,7 @@ void forLoop::close()
|
||||
{
|
||||
/* var=var+step; */
|
||||
shared_ptr<expression>stepper=shared_ptr<expression>(new expression(
|
||||
shared_ptr<expression>(new expression(var.get())), O_PLUS, step));
|
||||
shared_ptr<expression>(new expression(var)), O_PLUS, step));
|
||||
var->assignment(stepper);
|
||||
infrastructure->close();
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@
|
||||
*/
|
||||
#include "yab2cpp.h"
|
||||
|
||||
/* forward declaration and static initializers */
|
||||
class fn;
|
||||
unsigned int operands::nextID;
|
||||
unordered_map<string, unsigned int> constOp::strConst;
|
||||
|
||||
/* scope methods */
|
||||
ofstream &scope::operator<<(ostream &in)
|
||||
@@ -24,26 +27,6 @@ ofstream &scope::operator<<(ostream &in)
|
||||
}
|
||||
|
||||
/* methods for operands */
|
||||
shared_ptr<operands>operands::findGlobal(string &s)
|
||||
{
|
||||
auto iter=operands::globals.find(s);
|
||||
if (iter==operands::globals.end())
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
enum TYPES operands::getSimpleVarType()
|
||||
{
|
||||
switch (this->getType())
|
||||
@@ -96,16 +79,6 @@ void operands::generateBox(enum SCOPES s)
|
||||
y << x;
|
||||
}
|
||||
|
||||
shared_ptr<operands>operands::getOrCreateGlobal(string &s, enum TYPES t)
|
||||
{
|
||||
auto op=globals.find(s);
|
||||
if (op==globals.end())
|
||||
{
|
||||
return shared_ptr<variable>(new variable(S_GLOBAL, s, t));
|
||||
}
|
||||
return op->second;
|
||||
}
|
||||
|
||||
string operands::boxName()
|
||||
{
|
||||
ostringstream s;
|
||||
@@ -143,6 +116,8 @@ void constOp::processConst( const string &s)
|
||||
/* constructor for constOp */
|
||||
constOp::constOp(const string &s, enum TYPES t):operands(t)
|
||||
{
|
||||
/* make sure string folder is initialized */
|
||||
unordered_map<string, shared_ptr<operands> >strConst;
|
||||
switch (t)
|
||||
{
|
||||
case T_INT:
|
||||
@@ -155,8 +130,8 @@ constOp::constOp(const string &s, enum TYPES t):operands(t)
|
||||
break;
|
||||
case T_STRING:
|
||||
{
|
||||
auto i=strConst.find(s);
|
||||
if (i!=strConst.end())
|
||||
auto i=constOp::strConst.find(s);
|
||||
if (i!=constOp::strConst.end())
|
||||
{
|
||||
processConst((*i).second);
|
||||
}
|
||||
@@ -164,7 +139,7 @@ constOp::constOp(const string &s, enum TYPES t):operands(t)
|
||||
{
|
||||
consts_h << "const string ";
|
||||
processConst(s);
|
||||
strConst[s]=getID();
|
||||
constOp::strConst[s]=getID();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -206,12 +181,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.get())), O_INT_TO_FLOAT))->evaluate());
|
||||
l=shared_ptr<operands>((new expression(shared_ptr<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.get())), O_INT_TO_FLOAT))->evaluate());
|
||||
r=shared_ptr<operands>((new expression(shared_ptr<expression>(new expression(r)), O_INT_TO_FLOAT))->evaluate());
|
||||
rt=T_FLOATVAR;
|
||||
}
|
||||
if (lt!=rt)error(E_TYPE_MISMATCH);
|
||||
@@ -346,18 +321,18 @@ variable::variable(enum SCOPES s, string &name, enum TYPES t):operands(t)
|
||||
switch (s)
|
||||
{
|
||||
case S_LOCAL:
|
||||
if(fn::locals.find(name)!=fn::locals.end() ||
|
||||
fn::statics.find(name)!=fn::statics.end() ) error(E_DUPLICATE_SYMBOL);
|
||||
fn::locals[name]=shared_ptr<variable>(this);
|
||||
if(locals.find(name)!=locals.end() ||
|
||||
statics.find(name)!=statics.end() ) error(E_DUPLICATE_SYMBOL);
|
||||
locals[name]=shared_ptr<variable>(this);
|
||||
break;
|
||||
case S_GLOBAL:
|
||||
if(findGlobal(name)!=NULL) error(E_DUPLICATE_SYMBOL);
|
||||
if(globals.find(name)!=globals.end()) error(E_DUPLICATE_SYMBOL);
|
||||
globals[name]=shared_ptr<variable>(this);
|
||||
break;
|
||||
case S_STATIC:
|
||||
if(fn::locals.find(name)!=fn::locals.end() ||
|
||||
fn::statics.find(name)!=fn::statics.end() ) error(E_DUPLICATE_SYMBOL);
|
||||
fn::statics[name]=shared_ptr<variable>(this);
|
||||
if(locals.find(name)!=locals.end() ||
|
||||
statics.find(name)!=statics.end() ) error(E_DUPLICATE_SYMBOL);
|
||||
statics[name]=shared_ptr<variable>(this);
|
||||
break;
|
||||
default:
|
||||
error(E_INTERNAL);
|
||||
@@ -369,13 +344,13 @@ shared_ptr<variable> variable::getOrCreateVar(string &name, enum TYPES t)
|
||||
{
|
||||
if (!scopeGlobal)
|
||||
{
|
||||
return fn::getOrCreateVar(t, name, false);
|
||||
auto i=locals.find(name);
|
||||
if(i!=locals.end())return i->second;
|
||||
i=statics.find(name);
|
||||
if(i!=statics.end())return i->second;
|
||||
}
|
||||
/* TODO: verify if type is compatible */
|
||||
shared_ptr<operands>op=operands::getOrCreateGlobal(name, t);
|
||||
shared_ptr<variable>v=shared_ptr<variable>(new variable());
|
||||
v->assignment(shared_ptr<expression>(new expression(op.get())));
|
||||
return v;
|
||||
if (globals.find(name)!=globals.end())return globals[name];
|
||||
return shared_ptr<variable>(new variable(scopeGlobal?S_GLOBAL:S_LOCAL, name, t));
|
||||
}
|
||||
|
||||
void variable::assignment(shared_ptr<expression>value)
|
||||
|
||||
@@ -8,11 +8,30 @@
|
||||
*/
|
||||
#include "yab2cpp.h"
|
||||
|
||||
class label;
|
||||
/* static initializers */
|
||||
unordered_map<string, shared_ptr<fn> > fn::functions;
|
||||
list<shared_ptr<fn> >fn::callStack;
|
||||
unsigned int fn::nextID;
|
||||
|
||||
/* function definitions */
|
||||
void fn::dumpCallStack()
|
||||
{
|
||||
auto i=callStack.rbegin();
|
||||
if (i==callStack.rend())
|
||||
{
|
||||
logfile << "call stack was empty\n";
|
||||
return;
|
||||
}
|
||||
do
|
||||
{
|
||||
logfile << (*i)->funcName << "\n";
|
||||
++i;
|
||||
} while(i!=callStack.rend());
|
||||
}
|
||||
|
||||
shared_ptr<fn>fn::getCurrentSub()
|
||||
{
|
||||
list<shared_ptr<fn> >callStack;
|
||||
return callStack.back();
|
||||
}
|
||||
|
||||
@@ -36,6 +55,7 @@ void fn::generateGosub(shared_ptr<label> sub)
|
||||
|
||||
fn::fn(shared_ptr<label>gosub):codeType(T_GOSUB)
|
||||
{
|
||||
this->funcName="unnamed gosub";
|
||||
this->ret=gosub;
|
||||
}
|
||||
|
||||
@@ -47,7 +67,7 @@ shared_ptr<fn> fn::getSub(string &name)
|
||||
}
|
||||
|
||||
shared_ptr<operands>fn::generateCall(string &name,
|
||||
list<shared_ptr<operands> >paramList)
|
||||
list<shared_ptr<operands> >¶mList)
|
||||
{
|
||||
auto v=params.begin();
|
||||
shared_ptr<operands>current;
|
||||
@@ -76,7 +96,7 @@ shared_ptr<operands>fn::generateCall(string &name,
|
||||
error(E_TYPE_MISMATCH);
|
||||
}
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(current.get())));
|
||||
new expression(current)));
|
||||
++v;
|
||||
}
|
||||
/* pad remaining unassigned variables with empty values */
|
||||
@@ -87,19 +107,19 @@ shared_ptr<operands>fn::generateCall(string &name,
|
||||
case T_FLOATVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
new constOp("0.0", T_FLOAT)
|
||||
shared_ptr<constOp>(new constOp("0.0", T_FLOAT))
|
||||
)));
|
||||
break;
|
||||
case T_INTVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
new constOp("0", T_INT)
|
||||
shared_ptr<constOp>(new constOp("0", T_INT))
|
||||
)));
|
||||
break;
|
||||
case T_STRINGVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
new constOp("", T_STRING)
|
||||
shared_ptr<constOp>(new constOp("", T_STRING))
|
||||
)));
|
||||
default:
|
||||
error(E_INTERNAL);
|
||||
@@ -172,8 +192,8 @@ void fn::close()
|
||||
this->generateReturn();
|
||||
}
|
||||
funcs_h << "};\n";
|
||||
fn::locals.clear();
|
||||
fn::statics.clear();
|
||||
locals.clear();
|
||||
statics.clear();
|
||||
this->params.clear();
|
||||
scopeGlobal=true;
|
||||
}
|
||||
@@ -184,6 +204,7 @@ fn::fn(string &s, enum CODES t, shared_ptr<operands>returnCode):codeType(t)
|
||||
if (!scopeGlobal) error(E_END_FUNCTION);
|
||||
/*check if this function name is already used*/
|
||||
if (fn::functions.find(s)!=fn::functions.end()) error(E_DUPLICATE_SYMBOL);
|
||||
this->funcName=s;
|
||||
this->id= ++nextID;
|
||||
/*define storage for locals*/
|
||||
funcs_h << "struct f" << this->id <<"\n{\n";
|
||||
|
||||
Reference in New Issue
Block a user