it builds but doesn't link yet
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,3 +5,4 @@ bison.output
|
||||
yab
|
||||
*.o
|
||||
*.so
|
||||
.vscode/*
|
||||
|
||||
16
Makefile
16
Makefile
@@ -5,16 +5,16 @@
|
||||
|
||||
CC=g++
|
||||
LD=g++
|
||||
|
||||
#release build
|
||||
#FLAGS=-c -Os -std=c++11
|
||||
#LDFLAGS=
|
||||
#LDFLAGS=LDFLAGS=-std=c++11
|
||||
|
||||
#debug build
|
||||
FLAGS=-c -g -Og -std=c++11
|
||||
LDFLAGS=
|
||||
LDFLAGS=-std=c++11
|
||||
|
||||
AR=ar r
|
||||
LD=g++
|
||||
|
||||
default: yab2cpp
|
||||
|
||||
@@ -30,11 +30,13 @@ yabFunctions.o: yabFunctions.cpp yab2cpp.h
|
||||
yab2cpp.o: yab2cpp.cpp yab2cpp.h
|
||||
$(CC) $(FLAGS) -o yab2cpp.o yab2cpp.cpp
|
||||
|
||||
BASIC_framework.a: yabDataStructures.o yabCodeStructures.o yabFunctions.o
|
||||
$(AR) yabDataStructures.o yabCodeStructures.o yabFunctions.o
|
||||
#BASIC_framework.a: yabDataStructures.o yabCodeStructures.o yabFunctions.o
|
||||
# $(AR) BASIC_framework.a yabDataStructures.o yabCodeStructures.o yabFunctions.o
|
||||
|
||||
yab2cpp: BASIC_framework.a yab2cpp.o
|
||||
$(LD) $(LDFLAGS) -o buildyab2cpp yab2cpp.o -lBASIC_framework
|
||||
#yab2cpp: BASIC_framework.a yab2cpp.o
|
||||
yab2cpp: yab2cpp.o yabCodeStructures.o yabDataStructures.o yabFunctions.o
|
||||
$(LD) $(LDFLAGS) -o yab2cpp yab2cpp.o yabCodeStructures.o yabDataStructures.o yabFunctions.o
|
||||
#BASIC_framework.a
|
||||
|
||||
clean:
|
||||
rm -f *.o yab2cpp BASIC_framework.a
|
||||
|
||||
54
yab2cpp.cpp
54
yab2cpp.cpp
@@ -8,6 +8,60 @@
|
||||
*/
|
||||
#include "yab2cpp.h"
|
||||
|
||||
/* These correspond to the enum COMPILE_ERRORS. */
|
||||
const char *COMPILE_ERROR_NAMES[]={
|
||||
"no error",
|
||||
"incorrect syntax",
|
||||
"wrong type",
|
||||
"failed allocation",
|
||||
"stack underflow",
|
||||
"internal compiler error",
|
||||
"duplicated label",
|
||||
"previous subroutine didn't end",
|
||||
"value returned from gosub call",
|
||||
"undefined subroutine name",
|
||||
"too many parameters in function call",
|
||||
"value cannot be assigned"
|
||||
};
|
||||
|
||||
/* These correspond to the types of enum TYPES. */
|
||||
const string TYPENAMES[]={
|
||||
"unknown",
|
||||
"none",
|
||||
"string constant",
|
||||
"integer constant",
|
||||
"floating point constant",
|
||||
"string variable",
|
||||
"integer variable",
|
||||
"floating point variable",
|
||||
"string array or function",
|
||||
"integer array or function",
|
||||
"floating point array or function",
|
||||
"string array or function",
|
||||
"function"
|
||||
};
|
||||
|
||||
const string CODETYPES[]={
|
||||
"print sequence",
|
||||
"print segment",
|
||||
"while loop",
|
||||
"for loop",
|
||||
"repeat loop",
|
||||
"do loop",
|
||||
"if statement",
|
||||
"procedure statement",
|
||||
"function statement",
|
||||
"assignment",
|
||||
"label",
|
||||
"parameter list or array index",
|
||||
"data item",
|
||||
"function returning string",
|
||||
"function returning floating point",
|
||||
"function returning integer",
|
||||
"function returning nothing",
|
||||
"function"
|
||||
};
|
||||
|
||||
enum COMPILE_ERRORS errorLevel=E_OK;
|
||||
unsigned int mode=0;
|
||||
unsigned int indentLevel=0;
|
||||
|
||||
118
yab2cpp.h
118
yab2cpp.h
@@ -55,22 +55,6 @@ extern unsigned int mode;
|
||||
extern unsigned int indentLevel;
|
||||
extern bool scopeGlobal;
|
||||
|
||||
/* These correspond to the enum COMPILE_ERRORS. */
|
||||
const char *COMPILE_ERROR_NAMES[]={
|
||||
"no error",
|
||||
"incorrect syntax",
|
||||
"wrong type",
|
||||
"failed allocation",
|
||||
"stack underflow",
|
||||
"internal compiler error",
|
||||
"duplicated label",
|
||||
"previous subroutine didn't end",
|
||||
"value returned from gosub call",
|
||||
"undefined subroutine name",
|
||||
"too many parameters in function call",
|
||||
"value cannot be assigned"
|
||||
};
|
||||
|
||||
/* flags used internally by the compiler
|
||||
(must be powers of 2) */
|
||||
#define COMPILE 1
|
||||
@@ -117,44 +101,6 @@ enum CODES
|
||||
T_UNKNOWNFUNC
|
||||
};
|
||||
|
||||
/* These correspond to the types of enum TYPES. */
|
||||
const string TYPENAMES[]={
|
||||
"unknown",
|
||||
"none",
|
||||
"string constant",
|
||||
"integer constant",
|
||||
"floating point constant",
|
||||
"string variable",
|
||||
"integer variable",
|
||||
"floating point variable",
|
||||
"string array or function",
|
||||
"integer array or function",
|
||||
"floating point array or function",
|
||||
"string array or function",
|
||||
"function"
|
||||
};
|
||||
|
||||
const string CODETYPES[]={
|
||||
"print sequence",
|
||||
"print segment",
|
||||
"while loop",
|
||||
"for loop",
|
||||
"repeat loop",
|
||||
"do loop",
|
||||
"if statement",
|
||||
"procedure statement",
|
||||
"function statement",
|
||||
"assignment",
|
||||
"label",
|
||||
"parameter list or array index",
|
||||
"data item",
|
||||
"function returning string",
|
||||
"function returning floating point",
|
||||
"function returning integer",
|
||||
"function returning nothing",
|
||||
"function"
|
||||
};
|
||||
|
||||
typedef union
|
||||
{
|
||||
double d;
|
||||
@@ -170,6 +116,14 @@ enum SEPARATORS
|
||||
S_LINEFEED
|
||||
};
|
||||
|
||||
enum SCOPES
|
||||
{
|
||||
S_UNKNOWN,
|
||||
S_LOCAL,
|
||||
S_STATIC,
|
||||
S_GLOBAL
|
||||
};
|
||||
|
||||
enum OPERATORS
|
||||
{
|
||||
O_PLUS,
|
||||
@@ -199,27 +153,37 @@ void error(enum COMPILE_ERRORS err);
|
||||
void logger(string s);
|
||||
|
||||
/* internal states used by the parser */
|
||||
class scope:public ofstream
|
||||
{
|
||||
enum SCOPES myscope;
|
||||
public:
|
||||
ofstream &operator<<(ostream &in);
|
||||
enum SCOPES getScope() const {return myscope;}
|
||||
|
||||
scope(enum SCOPES s){myscope=s;}
|
||||
~scope()
|
||||
{}
|
||||
};
|
||||
|
||||
class operands
|
||||
{
|
||||
enum TYPES type;
|
||||
unsigned int id;
|
||||
static unsigned int nextID;
|
||||
static unordered_map<string, shared_ptr<operands>> globals;
|
||||
static unordered_map<string, unsigned int> strConst;
|
||||
/* 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>getOrCreateStr(string s);
|
||||
static shared_ptr<operands>createConst(string s, enum TYPES t);
|
||||
static shared_ptr<operands>getOrCreateGlobal(string &s, enum TYPES t);
|
||||
|
||||
enum TYPES getSimpleVarType();
|
||||
void generateBox(ostream &scope);
|
||||
void generateBox(enum SCOPES s);
|
||||
virtual string boxName();
|
||||
enum TYPES coerceTypes();
|
||||
|
||||
@@ -228,6 +192,24 @@ public:
|
||||
{}
|
||||
};
|
||||
|
||||
class constOp:public operands
|
||||
{
|
||||
/* box is defined once in the constructor */
|
||||
string box;
|
||||
static unordered_map<string, unsigned int> strConst;
|
||||
|
||||
/* const for id that exists already */
|
||||
void processConst(unsigned int i);
|
||||
/* const that must be defined still */
|
||||
void processConst(const string &s);
|
||||
public:
|
||||
virtual string boxName(){return box;}
|
||||
|
||||
constOp(const string &s, enum TYPES t);
|
||||
~constOp()
|
||||
{}
|
||||
};
|
||||
|
||||
/* expression can be terminal or non-terminal */
|
||||
class expression
|
||||
{
|
||||
@@ -251,9 +233,9 @@ public:
|
||||
this->right=r;
|
||||
this->oper=o;
|
||||
}
|
||||
expression(shared_ptr<operands>x)
|
||||
expression(operands *x)
|
||||
{
|
||||
op=x;
|
||||
op=shared_ptr<operands>(x);
|
||||
oper=O_TERM;
|
||||
}
|
||||
/*TODO: Recycle temporary variables when not in debug mode*/
|
||||
@@ -370,12 +352,12 @@ public:
|
||||
|
||||
class variable:public operands
|
||||
{
|
||||
ostream &myScope;
|
||||
enum SCOPES myScope;
|
||||
public:
|
||||
static shared_ptr<variable>getOrCreateVar(string &name, enum TYPES t);
|
||||
|
||||
void assignment(shared_ptr<expression>value);
|
||||
explicit variable(ostream &scope, string &name, enum TYPES t);
|
||||
explicit variable(enum SCOPES s, string &name, enum TYPES t);
|
||||
variable();
|
||||
~variable()
|
||||
{}
|
||||
@@ -409,18 +391,20 @@ public:
|
||||
|
||||
class fn:codeType
|
||||
{
|
||||
static unordered_map<string, shared_ptr<variable> >locals;
|
||||
static unordered_map<string, shared_ptr<variable> >statics;
|
||||
friend variable;
|
||||
static unordered_map<string, shared_ptr<fn> >functions;
|
||||
static list<shared_ptr<fn> > callStack;
|
||||
static unsigned int nextID;
|
||||
list<shared_ptr<variable> >params;
|
||||
unsigned int id;
|
||||
enum TYPES kind;
|
||||
shared_ptr<operands>rc;
|
||||
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();
|
||||
@@ -436,12 +420,12 @@ public:
|
||||
void addParameter(shared_ptr<variable>);
|
||||
|
||||
shared_ptr<operands>generateCall(string &name, list<shared_ptr<operands> >paramList);
|
||||
shared_ptr<operands>generateReturn(shared_ptr<expression>expr);
|
||||
void generateReturn(shared_ptr<expression>expr);
|
||||
void generateReturn();
|
||||
virtual void generateBreak();
|
||||
virtual void close();
|
||||
|
||||
fn(string &name, enum CODES t);
|
||||
fn(string &name, enum CODES t, shared_ptr<operands>returnCode=NULL);
|
||||
virtual ~fn()
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -115,7 +115,7 @@ void ifStatement::generateContinue()
|
||||
redo->generateJumpTo();
|
||||
}
|
||||
|
||||
void ifStatement::alternative(shared_ptr<expression>e=NULL)
|
||||
void ifStatement::alternative(shared_ptr<expression>e)
|
||||
{
|
||||
done->generateJumpTo();
|
||||
this->chain->generate();
|
||||
@@ -201,7 +201,7 @@ void whileLoop::close()
|
||||
|
||||
forLoop::forLoop(shared_ptr<variable>v,
|
||||
shared_ptr<expression>start, shared_ptr<expression>stop,
|
||||
shared_ptr<expression>stepVal=NULL):codeType(T_FORLOOP)
|
||||
shared_ptr<expression>stepVal):codeType(T_FORLOOP)
|
||||
{
|
||||
/*v=start;
|
||||
stopTemp=stop;*/
|
||||
@@ -209,30 +209,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)),
|
||||
O_LESS, shared_ptr<expression>(new expression(stopTemp))))));
|
||||
shared_ptr<expression>(new expression(shared_ptr<expression>(new expression(v.get())),
|
||||
O_LESS, shared_ptr<expression>(new expression(stopTemp.get()))))));
|
||||
/* startTemp=v;*/
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(v)));
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(v.get())));
|
||||
/* 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(shared_ptr<expression>(new expression(stopTemp.get())));
|
||||
stopTemp->assignment(shared_ptr<expression>(new expression(v.get())));
|
||||
/* 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>(new expression(v.get())), O_LESS_EQUAL,
|
||||
shared_ptr<expression>(new expression(stopTemp.get()))));
|
||||
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>(new expression(v.get())), O_GREATER_EQUAL,
|
||||
shared_ptr<expression>(new expression(startTemp.get()))));
|
||||
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(
|
||||
operands::createConst(string("0"), T_INT))))));
|
||||
new constOp("0", T_INT))))));
|
||||
if (stepVal)
|
||||
{
|
||||
step=stepVal;
|
||||
@@ -240,7 +240,7 @@ forLoop::forLoop(shared_ptr<variable>v,
|
||||
else
|
||||
{
|
||||
/* if not present "step" is assumed to be 1 */
|
||||
step=shared_ptr<expression>(new expression(operands::createConst("1", T_INT)));
|
||||
step=shared_ptr<expression>(new expression(new constOp("1", T_INT)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ void forLoop::close()
|
||||
{
|
||||
/* var=var+step; */
|
||||
shared_ptr<expression>stepper=shared_ptr<expression>(new expression(
|
||||
shared_ptr<expression>(new expression(var)), O_PLUS, step));
|
||||
shared_ptr<expression>(new expression(var.get())), O_PLUS, step));
|
||||
var->assignment(stepper);
|
||||
infrastructure->close();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,19 @@
|
||||
|
||||
class fn;
|
||||
|
||||
/* scope methods */
|
||||
ofstream &scope::operator<<(ostream &in)
|
||||
{
|
||||
switch (this->myscope)
|
||||
{
|
||||
case S_LOCAL:
|
||||
return funcs_h;
|
||||
case S_GLOBAL:
|
||||
case S_STATIC:
|
||||
return heap_h;
|
||||
}
|
||||
}
|
||||
|
||||
/* methods for operands */
|
||||
shared_ptr<operands>operands::findGlobal(string &s)
|
||||
{
|
||||
@@ -31,42 +44,6 @@ void operands::dumpVars()
|
||||
varNames << endl;
|
||||
}
|
||||
|
||||
shared_ptr<operands> operands::getOrCreateStr(string s)
|
||||
{
|
||||
auto iter=operands::strConst.find(s);
|
||||
if (iter!=operands::strConst.end())
|
||||
{
|
||||
return shared_ptr<operands>(new operands(iter->second, T_STRING));
|
||||
}
|
||||
++nextID;
|
||||
consts_h << "const string k" << nextID << "=\"" << s << "\";\n";
|
||||
operands::strConst[s]=nextID;
|
||||
return shared_ptr<operands>(new operands(nextID, T_STRING));
|
||||
}
|
||||
|
||||
shared_ptr<operands>operands::createConst(string s, enum TYPES t)
|
||||
{
|
||||
shared_ptr<operands>me=shared_ptr<operands>(new operands(t));
|
||||
if (t==T_INT)
|
||||
{
|
||||
consts_h << "const int k";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t==T_FLOAT)
|
||||
{
|
||||
consts_h << "const double k";
|
||||
}
|
||||
else
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
consts_h << me->getID() << "=" << s << ";\n";
|
||||
return me;
|
||||
}
|
||||
|
||||
enum TYPES operands::getSimpleVarType()
|
||||
{
|
||||
switch (this->getType())
|
||||
@@ -95,25 +72,28 @@ operands::operands(enum TYPES t)
|
||||
this->type=t;
|
||||
}
|
||||
|
||||
void operands::generateBox(ostream &scope)
|
||||
void operands::generateBox(enum SCOPES s)
|
||||
{
|
||||
string x;
|
||||
scope y(s);
|
||||
stringstream ss;
|
||||
switch (this->getSimpleVarType())
|
||||
{
|
||||
case T_INTVAR:
|
||||
scope << "int v";
|
||||
ss << "int v";
|
||||
break;
|
||||
case T_FLOATVAR:
|
||||
scope << "double v";
|
||||
ss << "double v";
|
||||
break;
|
||||
case T_STRINGVAR:
|
||||
scope << "string v";
|
||||
ss << "string v";
|
||||
break;
|
||||
default:
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
break;
|
||||
error(E_TYPE_MISMATCH);
|
||||
}
|
||||
scope << this->getID() << ";\n";
|
||||
ss << this->getID() << ";\n";
|
||||
ss.str(x);
|
||||
y << x;
|
||||
}
|
||||
|
||||
shared_ptr<operands>operands::getOrCreateGlobal(string &s, enum TYPES t)
|
||||
@@ -121,7 +101,7 @@ 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(heap_h, s, t));
|
||||
return shared_ptr<variable>(new variable(S_GLOBAL, s, t));
|
||||
}
|
||||
return op->second;
|
||||
}
|
||||
@@ -129,13 +109,16 @@ shared_ptr<operands>operands::getOrCreateGlobal(string &s, enum TYPES t)
|
||||
string operands::boxName()
|
||||
{
|
||||
ostringstream s;
|
||||
string x;
|
||||
switch (this->getType())
|
||||
{
|
||||
case T_STRINGVAR:
|
||||
case T_INTVAR:
|
||||
case T_FLOATVAR:
|
||||
s << 'v' << this->getID();
|
||||
return s.str();
|
||||
s.str(x);
|
||||
s.clear();
|
||||
return x;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -143,6 +126,54 @@ string operands::boxName()
|
||||
}
|
||||
}
|
||||
|
||||
void constOp::processConst(unsigned int i)
|
||||
{
|
||||
stringstream me;
|
||||
me << 'k' << i;
|
||||
me.str(box);
|
||||
}
|
||||
|
||||
void constOp::processConst( const string &s)
|
||||
{
|
||||
processConst(getID());
|
||||
consts_h << box << "=" << s << ";\n";
|
||||
}
|
||||
|
||||
|
||||
/* constructor for constOp */
|
||||
constOp::constOp(const string &s, enum TYPES t):operands(t)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case T_INT:
|
||||
consts_h << "const int ";
|
||||
processConst(s);
|
||||
break;
|
||||
case T_FLOAT:
|
||||
consts_h << "const double ";
|
||||
processConst(s);
|
||||
break;
|
||||
case T_STRING:
|
||||
{
|
||||
auto i=strConst.find(s);
|
||||
if (i!=strConst.end())
|
||||
{
|
||||
processConst((*i).second);
|
||||
}
|
||||
else
|
||||
{
|
||||
consts_h << "const string ";
|
||||
processConst(s);
|
||||
strConst[s]=getID();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error(E_TYPE_MISMATCH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* expression parsing routines */
|
||||
|
||||
/* binary vs. unary ops */
|
||||
@@ -166,7 +197,7 @@ shared_ptr<operands>expression::evaluate()
|
||||
shared_ptr<operands>l;
|
||||
shared_ptr<operands>r;
|
||||
enum TYPES t;
|
||||
ostream &scope=scopeGlobal?heap_h:funcs_h;
|
||||
enum SCOPES scopeVar=(scopeGlobal?S_GLOBAL:S_LOCAL);
|
||||
l=this->getLeft()->evaluate();
|
||||
if (this->isBinOp())
|
||||
{
|
||||
@@ -175,12 +206,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=shared_ptr<operands>((new expression(shared_ptr<expression>(new expression(l.get())), 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=shared_ptr<operands>((new expression(shared_ptr<expression>(new expression(r.get())), O_INT_TO_FLOAT))->evaluate());
|
||||
rt=T_FLOATVAR;
|
||||
}
|
||||
if (lt!=rt)error(E_TYPE_MISMATCH);
|
||||
@@ -196,92 +227,92 @@ shared_ptr<operands>expression::evaluate()
|
||||
{
|
||||
case O_INVERT:
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
output_cpp << this->op->boxName() << "= ~" << l->boxName() << ";\n";
|
||||
break;
|
||||
case O_NEGATE:
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
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(scope);
|
||||
this->op->generateBox(scopeVar);
|
||||
output_cpp << this->op->boxName() << "=(" << l->boxName() << "!=" << r->boxName() << ")?-1:0;\n";
|
||||
break;
|
||||
default:
|
||||
@@ -299,7 +330,7 @@ shared_ptr<operands> expression::stringEval(shared_ptr<operands>l, shared_ptr<op
|
||||
if (this->getOp()==O_STRING_CONCAT)
|
||||
{
|
||||
this->op=shared_ptr<operands>(new operands(T_STRINGVAR));
|
||||
this->op->generateBox(scopeGlobal?heap_h:funcs_h);
|
||||
this->op->generateBox(scopeGlobal?S_GLOBAL:S_LOCAL);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "+" << r->boxName();
|
||||
}
|
||||
else error(E_INTERNAL);
|
||||
@@ -309,9 +340,29 @@ shared_ptr<operands> expression::stringEval(shared_ptr<operands>l, shared_ptr<op
|
||||
}
|
||||
|
||||
/* variable definitions */
|
||||
variable::variable(ostream &scope, string &name, enum TYPES t):operands(t)
|
||||
variable::variable(enum SCOPES s, string &name, enum TYPES t):operands(t)
|
||||
{
|
||||
this->generateBox(scope); /*TODO: FINISH THIS*/
|
||||
this->myScope=s;
|
||||
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);
|
||||
break;
|
||||
case S_GLOBAL:
|
||||
if(findGlobal(name)!=NULL) 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);
|
||||
break;
|
||||
default:
|
||||
error(E_INTERNAL);
|
||||
}
|
||||
this->generateBox(s);
|
||||
}
|
||||
|
||||
shared_ptr<variable> variable::getOrCreateVar(string &name, enum TYPES t)
|
||||
@@ -323,7 +374,7 @@ shared_ptr<variable> variable::getOrCreateVar(string &name, enum TYPES t)
|
||||
/* 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)));
|
||||
v->assignment(shared_ptr<expression>(new expression(op.get())));
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
@@ -65,6 +65,8 @@ shared_ptr<operands>fn::generateCall(string &name,
|
||||
<< "*sub" << this->getID()
|
||||
<< "= new struct f" << g->getID()
|
||||
<< "();\n";
|
||||
|
||||
/* TODO Make parameter processing a separate function */
|
||||
while(paramList.size()>0)
|
||||
{
|
||||
current= paramList.front();
|
||||
@@ -74,7 +76,7 @@ shared_ptr<operands>fn::generateCall(string &name,
|
||||
error(E_TYPE_MISMATCH);
|
||||
}
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(current)));
|
||||
new expression(current.get())));
|
||||
++v;
|
||||
}
|
||||
/* pad remaining unassigned variables with empty values */
|
||||
@@ -85,26 +87,28 @@ shared_ptr<operands>fn::generateCall(string &name,
|
||||
case T_FLOATVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
operands::createConst("0.0", T_FLOAT)
|
||||
new constOp("0.0", T_FLOAT)
|
||||
)));
|
||||
break;
|
||||
case T_INTVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
operands::createConst("0", T_INT)
|
||||
new constOp("0", T_INT)
|
||||
)));
|
||||
break;
|
||||
case T_STRINGVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
operands::getOrCreateStr(string("")
|
||||
))));
|
||||
new constOp("", T_STRING)
|
||||
)));
|
||||
default:
|
||||
error(E_TYPE_MISMATCH);
|
||||
error(E_INTERNAL);
|
||||
}
|
||||
++v;
|
||||
}
|
||||
return g->/*TODO FINISH THIS*/
|
||||
g->startAddr->generateJumpTo();
|
||||
g->ret->generate();
|
||||
return g->rc;
|
||||
}
|
||||
|
||||
void fn::generateReturn()
|
||||
@@ -126,47 +130,29 @@ void fn::generateReturn()
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<operands>fn::generateReturn(shared_ptr<expression>expr)
|
||||
void fn::generateReturn(shared_ptr<expression>expr)
|
||||
{
|
||||
shared_ptr<operands>out=expr->evaluate();
|
||||
this->kind=out->getSimpleVarType();
|
||||
this->rc=expr->evaluate();
|
||||
this->kind=rc->getSimpleVarType();
|
||||
this->ret->generateJumpTo();
|
||||
fn::callStack.pop_back();
|
||||
switch (this->getType())
|
||||
{
|
||||
case T_UNKNOWNFUNC:
|
||||
return out;
|
||||
return;
|
||||
case T_STRINGFUNC:
|
||||
if (kind!=T_STRINGVAR)
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
return out;
|
||||
if (kind!=T_STRINGVAR) error(E_TYPE_MISMATCH);
|
||||
return;
|
||||
case T_INTFUNC:
|
||||
if (kind!=T_INTVAR&&kind!=T_FLOATVAR)
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
return out;
|
||||
if (kind!=T_INTVAR&&kind!=T_FLOATVAR) error(E_TYPE_MISMATCH);
|
||||
return;
|
||||
case T_FLOATFUNC:
|
||||
if(kind!=T_FLOATVAR)
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
return out;
|
||||
if(kind!=T_FLOATVAR) error(E_TYPE_MISMATCH);
|
||||
return;
|
||||
case T_GOSUB:
|
||||
{
|
||||
errorLevel=E_GOSUB_CANNOT_RETURN_VALUE;
|
||||
exit(1);
|
||||
}
|
||||
error(E_GOSUB_CANNOT_RETURN_VALUE);
|
||||
default:
|
||||
{
|
||||
errorLevel=E_BAD_SYNTAX;
|
||||
exit(1);
|
||||
}
|
||||
error(E_BAD_SYNTAX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,13 +179,24 @@ void fn::close()
|
||||
scopeGlobal=true;
|
||||
}
|
||||
|
||||
fn::fn(string &s, enum CODES t):codeType(t)
|
||||
fn::fn(string &s, enum CODES t, shared_ptr<operands>returnCode):codeType(t)
|
||||
{
|
||||
/*check for nesting error */
|
||||
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->id= ++nextID;
|
||||
/*define storage for locals*/
|
||||
funcs_h << "struct f" << this->id <<"\n{\n";
|
||||
/*define label space for return*/
|
||||
this->ret=shared_ptr<label>(new label());
|
||||
fn::functions[s]=this;
|
||||
/*allocate function name*/
|
||||
fn::functions[s]=shared_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());
|
||||
startAddr->generate();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user