started build script and went on a massive bug hunt
This commit is contained in:
40
Makefile
Normal file
40
Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
#Makefile for yab2cpp
|
||||
#by Samuel D. Crow
|
||||
|
||||
#presently architecture-neutral
|
||||
|
||||
CC=g++
|
||||
LD=g++
|
||||
#release build
|
||||
#FLAGS=-c -Os -std=c++11
|
||||
#LDFLAGS=
|
||||
|
||||
#debug build
|
||||
FLAGS=-c -g -Og -std=c++11
|
||||
LDFLAGS=
|
||||
|
||||
AR=ar r
|
||||
LD=g++
|
||||
|
||||
default: yab2cpp
|
||||
|
||||
yabDataStructures.o: yabDataStructures.cpp yab2cpp.h
|
||||
$(CC) $(FLAGS) -o yabDataStructures.o yabDataStructures.cpp
|
||||
|
||||
yabCodeStructures.o: yabCodeStructures.cpp yab2cpp.h
|
||||
$(CC) $(FLAGS) -o yabCodeStructures.o yabCodeStructures.cpp
|
||||
|
||||
yabFunctions.o: yabFunctions.cpp yab2cpp.h
|
||||
$(CC) $(FLAGS) -o yabFunctions.o yabFunctions.cpp
|
||||
|
||||
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
|
||||
|
||||
yab2cpp: BASIC_framework.a yab2cpp.o
|
||||
$(LD) $(LDFLAGS) -o buildyab2cpp yab2cpp.o -lBASIC_framework
|
||||
|
||||
clean:
|
||||
rm -f *.o yab2cpp BASIC_framework.a
|
||||
39
yab2cpp.cpp
39
yab2cpp.cpp
@@ -22,9 +22,10 @@ ofstream logfile;
|
||||
ofstream varNames;
|
||||
|
||||
/* private prototypes */
|
||||
void helpText(string &);
|
||||
void helpText(string);
|
||||
void setup();
|
||||
void compile();
|
||||
void shutDown();
|
||||
void logger(string &);
|
||||
|
||||
/* process command line parameters */
|
||||
int main(int argc, char *argv[])
|
||||
@@ -98,29 +99,35 @@ void setUp()
|
||||
if (mode & COMPILE)
|
||||
{
|
||||
/* compile mode */
|
||||
output_cpp=new ofstream("build/output.cpp");
|
||||
funcs_h=new ofstream ("functions.h");
|
||||
consts_h=new ofstream("consts.h");
|
||||
heap_h=new ofstream("heap.h");
|
||||
output_cpp.open("output/output.cpp");
|
||||
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"
|
||||
<< "#include \"heap.h\"\n#include \"functions.h\"\n"
|
||||
<< "unsigned int state=start;\nint run(){\nwhile (state>=start){\n"
|
||||
<< "switch(state){\ncase start:" << endl;
|
||||
if (mode & DEBUG)
|
||||
{
|
||||
varNames=new ofstream("varnames.txt");
|
||||
varNames.open("varnames.txt");
|
||||
}
|
||||
}
|
||||
if (mode & DUMP)
|
||||
{
|
||||
/* dump identifier mode */
|
||||
logfile=fopen("parse.log","w");
|
||||
logfile.open("parse.log");
|
||||
logger("Setup complete.");
|
||||
}
|
||||
}
|
||||
|
||||
void error(enum COMPILE_ERRORS e)
|
||||
{
|
||||
errorLevel=e;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* write a note in the logfile */
|
||||
void logger(string &contents)
|
||||
void logger(string s)
|
||||
{
|
||||
unsigned int count;
|
||||
if (mode & DEBUG)
|
||||
@@ -131,14 +138,14 @@ void logger(string &contents)
|
||||
logfile << '\t';
|
||||
--count;
|
||||
}
|
||||
logfile << contents << endl;
|
||||
logfile << s << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* shutdown the compiler and exit */
|
||||
void shutDown()
|
||||
{
|
||||
if (errorLevel != E_OK) cerr << "\nERROR: " << COMPILEERRORNAMES[errorLevel] << "\n\n" << endl;
|
||||
if (errorLevel != E_OK) cerr << "\nERROR: " << COMPILE_ERROR_NAMES[errorLevel] << "\n\n" << endl;
|
||||
if (fn::isCallStackEmpty())
|
||||
{
|
||||
logger("Stack was empty");
|
||||
@@ -146,26 +153,22 @@ void shutDown()
|
||||
else
|
||||
{
|
||||
logger("Dumping stack.");
|
||||
if (mode & DUMP && logfile != NULL)
|
||||
if (mode & DUMP && (logfile))
|
||||
{
|
||||
fn::dumpCallStack(logfile);
|
||||
fn::dumpCallStack();
|
||||
}
|
||||
}
|
||||
operands::dumpVars();
|
||||
label::dumpLabels();
|
||||
output_cpp << "}\n}return state;\n}"<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* open files and compile */
|
||||
void compile()
|
||||
{
|
||||
setUp();
|
||||
|
||||
/* parse */
|
||||
ctx = mb_create(NULL);
|
||||
while(mb_parse(ctx, NULL)){logger("done");}
|
||||
mb_destroy(ctx);
|
||||
|
||||
|
||||
shutDown();
|
||||
}
|
||||
|
||||
145
yab2cpp.h
145
yab2cpp.h
@@ -13,6 +13,8 @@
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -90,7 +92,7 @@ enum TYPES
|
||||
T_FLOATCALL_ARRAY,
|
||||
T_STRINGCALL_ARRAY,
|
||||
T_VOIDCALL
|
||||
}
|
||||
};
|
||||
/* list of all kinds of other code structures */
|
||||
enum CODES
|
||||
{
|
||||
@@ -194,6 +196,7 @@ enum OPERATORS
|
||||
|
||||
/* global prototype */
|
||||
void error(enum COMPILE_ERRORS err);
|
||||
void logger(string s);
|
||||
|
||||
/* internal states used by the parser */
|
||||
class operands
|
||||
@@ -201,21 +204,23 @@ class operands
|
||||
enum TYPES type;
|
||||
unsigned int id;
|
||||
static unsigned int nextID;
|
||||
static unordered_map<string, operands *> globals;
|
||||
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);
|
||||
public:
|
||||
enum TYPES getType() const {return type;}
|
||||
unsigned int getID() const {return id;}
|
||||
|
||||
static operands *findGlobal(string &s);
|
||||
static void dumpVars(ostream &out);
|
||||
static unsigned int getOrCreateStr(string &s);
|
||||
static operands *createConst(string &s, enum TYPES t);
|
||||
static operands *getOrCreateGlobal(string &s, enum TYPES t);
|
||||
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);
|
||||
virtual string &boxName();
|
||||
virtual string boxName();
|
||||
enum TYPES coerceTypes();
|
||||
|
||||
explicit operands(enum TYPES t);
|
||||
@@ -226,27 +231,27 @@ public:
|
||||
/* expression can be terminal or non-terminal */
|
||||
class expression
|
||||
{
|
||||
operands *op;
|
||||
expression *left;
|
||||
expression *right;
|
||||
shared_ptr<operands>op;
|
||||
shared_ptr<expression>left;
|
||||
shared_ptr<expression>right;
|
||||
enum OPERATORS oper;
|
||||
public:
|
||||
enum OPERATORS getOp() const {return oper;}
|
||||
expression *getLeft() const {return left;}
|
||||
expression *getRight() const {return right;}
|
||||
shared_ptr<expression>getLeft() const {return left;}
|
||||
shared_ptr<expression>getRight() const {return right;}
|
||||
|
||||
bool isBinOp();
|
||||
operands *evaluate();
|
||||
operands *stringEval();
|
||||
shared_ptr<operands>evaluate();
|
||||
shared_ptr<operands>stringEval(shared_ptr<operands>l, shared_ptr<operands>r);
|
||||
|
||||
/* r is NULL for unary operators */
|
||||
expression(expression *l, enum OPERATORS o, expression *r=NULL)
|
||||
expression(shared_ptr<expression>l, enum OPERATORS o, shared_ptr<expression>r=NULL)
|
||||
{
|
||||
this->left=l;
|
||||
this->right=r;
|
||||
this->oper=o;
|
||||
}
|
||||
expression(operands x)
|
||||
expression(shared_ptr<operands>x)
|
||||
{
|
||||
op=x;
|
||||
oper=O_TERM;
|
||||
@@ -259,11 +264,11 @@ public:
|
||||
class codeType
|
||||
{
|
||||
enum CODES type;
|
||||
static list<codeType *> nesting;
|
||||
static list<shared_ptr<codeType> >nesting;
|
||||
public:
|
||||
enum CODES getType() const {return this->type;}
|
||||
|
||||
static codeType *getCurrent();
|
||||
static shared_ptr<codeType> getCurrent();
|
||||
|
||||
virtual void close();
|
||||
virtual void generateBreak()=0;
|
||||
@@ -277,25 +282,27 @@ class label
|
||||
{
|
||||
unsigned int id;
|
||||
static unsigned int nextID;
|
||||
static unordered_map<string, label *> lookup;
|
||||
static unordered_map<string, shared_ptr<label> > lookup;
|
||||
public:
|
||||
static dumpLabels(ostream &v);
|
||||
static void dumpLabels();
|
||||
|
||||
unsigned int getID() const {return id;}
|
||||
|
||||
void generateJumpTo();
|
||||
void generateOnNSkip(list<shared_ptr<label> >dest);
|
||||
void generateOnNTo(expression *e);
|
||||
void generateCondJump(expression *e);
|
||||
/* 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);
|
||||
void generate();
|
||||
|
||||
static label *find(string &s);
|
||||
static shared_ptr<label>find(string &s);
|
||||
|
||||
label(){this->id = ++nextID;}
|
||||
label(string &s)
|
||||
{
|
||||
label();
|
||||
lookup[s]=this;
|
||||
lookup[s]=shared_ptr<label>(this);
|
||||
}
|
||||
|
||||
virtual ~label()
|
||||
@@ -303,77 +310,82 @@ public:
|
||||
};
|
||||
|
||||
/* if statement */
|
||||
class conditional:public codeType
|
||||
class ifStatement:public codeType
|
||||
{
|
||||
label *redo; /* for continue command */
|
||||
label *done; /* for break or after "then" condition */
|
||||
label *chain; /* For elsif command */
|
||||
shared_ptr<label>redo; /* for continue command */
|
||||
shared_ptr<label>done; /* for break or after "then" condition */
|
||||
shared_ptr<label>chain; /* For elsif command */
|
||||
public:
|
||||
void generateContinue();
|
||||
virtual void generateBreak() override;
|
||||
void alternative(expression *e=NULL); /* enable else or elsif condition */
|
||||
void alternative(shared_ptr<expression>e=NULL); /* enable else or elsif condition */
|
||||
virtual void close() override; /* end if */
|
||||
|
||||
explicit conditional(expression *e);
|
||||
virtual ~conditional();
|
||||
explicit ifStatement(shared_ptr<expression>e);
|
||||
virtual ~ifStatement()
|
||||
{}
|
||||
};
|
||||
|
||||
/* looping constructs */
|
||||
class repeatLoop:public codeType
|
||||
{
|
||||
label *loopStart;
|
||||
label *loopEnd;
|
||||
shared_ptr<label>loopStart;
|
||||
shared_ptr<label>loopEnd;
|
||||
public:
|
||||
virtual void generateBreak() override;
|
||||
virtual void close(expression *e) override;
|
||||
virtual void close(shared_ptr<expression>e);
|
||||
|
||||
explicit repeatLoop();
|
||||
virtual ~repeatLoop();
|
||||
virtual ~repeatLoop()
|
||||
{}
|
||||
};
|
||||
|
||||
class doLoop:public codeType
|
||||
{
|
||||
label *loopStart;
|
||||
label *loopEnd;
|
||||
shared_ptr<label>loopStart;
|
||||
shared_ptr<label>loopEnd;
|
||||
public:
|
||||
virtual void generateBreak() override;
|
||||
virtual void close() override;
|
||||
|
||||
explicit doLoop();
|
||||
virtual ~doLoop();
|
||||
virtual ~doLoop()
|
||||
{}
|
||||
};
|
||||
|
||||
class whileLoop:public codeType
|
||||
{
|
||||
label *loopContinue;
|
||||
label *loopStart;
|
||||
label *loopEnd;
|
||||
expression *cond;
|
||||
shared_ptr<label>loopContinue;
|
||||
shared_ptr<label>loopStart;
|
||||
shared_ptr<label>loopEnd;
|
||||
shared_ptr<expression>cond;
|
||||
public:
|
||||
virtual void generateBreak() override;
|
||||
virtual void close() override;
|
||||
|
||||
explicit whileLoop(expression *e);
|
||||
virtual ~whileLoop();
|
||||
explicit whileLoop(shared_ptr<expression>e);
|
||||
virtual ~whileLoop()
|
||||
{}
|
||||
};
|
||||
|
||||
class variable:public operands
|
||||
{
|
||||
ostream &myScope;
|
||||
public:
|
||||
static shared_ptr<variable>getOrCreateVarName(string &name, enum TYPES t);
|
||||
static shared_ptr<variable>getOrCreateVar(string &name, enum TYPES t);
|
||||
|
||||
void assignment(expression *value);
|
||||
void assignment(shared_ptr<expression>value);
|
||||
explicit variable(ostream &scope, string &name, enum TYPES t);
|
||||
virtual variable()
|
||||
variable();
|
||||
~variable()
|
||||
{}
|
||||
}
|
||||
};
|
||||
|
||||
class arrayType:public variable
|
||||
{
|
||||
list<unsigned int> dimensions;
|
||||
public:
|
||||
virtual string &boxName(list<unsigned int>indexes) override;
|
||||
virtual string &boxName(list<unsigned int>indexes);
|
||||
|
||||
explicit arrayType(string &name, enum TYPES t, list<unsigned int>dim);/*:variable(scope, name, t);*/
|
||||
virtual ~arrayType()
|
||||
@@ -382,16 +394,16 @@ public:
|
||||
|
||||
class forLoop:public codeType
|
||||
{
|
||||
variable *var;
|
||||
variable *startTemp;
|
||||
variable *stopTemp;
|
||||
shared_ptr<variable>var;
|
||||
shared_ptr<variable>startTemp;
|
||||
shared_ptr<variable>stopTemp;
|
||||
whileLoop *infrastructure;
|
||||
expression *step;
|
||||
shared_ptr<expression>step;
|
||||
public:
|
||||
virtual void generateBreak();
|
||||
virtual void close();
|
||||
|
||||
explicit forLoop(variable *v, expression *start, expression *stop, expression *stepVal=NULL);
|
||||
explicit forLoop(shared_ptr<variable>v, shared_ptr<expression>start, shared_ptr<expression>stop, shared_ptr<expression>stepVal=NULL);
|
||||
virtual ~forLoop();
|
||||
};
|
||||
|
||||
@@ -408,22 +420,23 @@ class fn:codeType
|
||||
shared_ptr<label>startAddr;
|
||||
shared_ptr<label>ret;
|
||||
/* private constructor used by generateGosub and generateOnNSub*/
|
||||
fn(label *gosub);
|
||||
fn(shared_ptr<label>gosub);
|
||||
public:
|
||||
static variable *getOrCreateVar(enum TYPES t, string &s, bool stat);
|
||||
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);
|
||||
/* must be called after label::generateOnNSkip */
|
||||
static void generateOnNSub(expression *e);
|
||||
static void generateOnNSub(shared_ptr<expression>e, unsigned int skip);
|
||||
|
||||
unsigned int getID() const {return this->id;}
|
||||
int getNumParams() const {return this->params.size;}
|
||||
int getNumParams() const {return this->params.size();}
|
||||
void addParameter(shared_ptr<variable>);
|
||||
|
||||
operands *generateCall(string &name, list<shared_ptr<operands> >¶mList);
|
||||
operands *generateReturn(expression *expr);
|
||||
shared_ptr<operands>generateCall(string &name, list<shared_ptr<operands> >paramList);
|
||||
shared_ptr<operands>generateReturn(shared_ptr<expression>expr);
|
||||
void generateReturn();
|
||||
virtual void generateBreak();
|
||||
virtual void close();
|
||||
@@ -436,15 +449,15 @@ public:
|
||||
/* The next two structures are used to implement the PRINT statement. */
|
||||
class printSegments
|
||||
{
|
||||
expression *cargo;
|
||||
shared_ptr<expression>cargo;
|
||||
enum SEPARATORS kind;
|
||||
public:
|
||||
printSegments(expression *e, enum SEPARATORS k)
|
||||
printSegments(shared_ptr<expression>e, enum SEPARATORS k)
|
||||
{
|
||||
this->cargo=e;
|
||||
this->kind=k;
|
||||
}
|
||||
printSegments(expression *e) {printSegments(e, S_LINEFEED);}
|
||||
printSegments(shared_ptr<expression>e) {printSegments(e, S_LINEFEED);}
|
||||
printSegments() {printSegments(NULL);}
|
||||
virtual ~printSegments()
|
||||
{}
|
||||
@@ -452,7 +465,7 @@ public:
|
||||
|
||||
struct printStatement
|
||||
{
|
||||
list<printSegments *> segments;
|
||||
list<shared_ptr<printSegments> >segments;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
/* base class of all the code structure types */
|
||||
codeType::codeType(enum CODES t)
|
||||
{
|
||||
nesting.push_back(this);
|
||||
nesting.push_back(shared_ptr<codeType>(this));
|
||||
this->type=t;
|
||||
}
|
||||
|
||||
codeType *codeType::getCurrent()
|
||||
shared_ptr<codeType> codeType::getCurrent()
|
||||
{
|
||||
return nesting.back;
|
||||
return nesting.back();
|
||||
}
|
||||
|
||||
void codeType::close()
|
||||
@@ -26,7 +26,7 @@ void codeType::close()
|
||||
}
|
||||
|
||||
/* label definitions and helper routines */
|
||||
label *label::find(string &s)
|
||||
shared_ptr<label>label::find(string &s)
|
||||
{
|
||||
auto ret=lookup.find(s);
|
||||
return(ret==lookup.end()?NULL:ret->second);
|
||||
@@ -47,14 +47,15 @@ void label::generateJumpTo()
|
||||
output_cpp << "state=" << this->getID() << ";\nbreak;\n";
|
||||
}
|
||||
|
||||
void label::generateOnNSkip(list<shared_ptr<label> >dest)
|
||||
/* pass this as second parameter to generateOnNTo or generateOnNSub */
|
||||
unsigned int label::generateOnNSkip(list<shared_ptr<label> >&dest)
|
||||
{
|
||||
if (dest->size()<2)
|
||||
if (dest.size()<2)
|
||||
{
|
||||
errorLevel=E_BAD_SYNTAX;
|
||||
exit(1);
|
||||
}
|
||||
auto iter=dest.start();
|
||||
auto iter=dest.begin();
|
||||
consts_h << "j" << this->getID() << "[]={" << *iter;
|
||||
++iter;
|
||||
while(iter!=dest.end())
|
||||
@@ -62,30 +63,29 @@ void label::generateOnNSkip(list<shared_ptr<label> >dest)
|
||||
consts_h << ", " << *iter;
|
||||
++iter;
|
||||
}
|
||||
consts_h << "}\njs" << this->getID()<< "=" << dest->size() << ";\n";
|
||||
consts_h << "}\njs" << this->getID()<< "=" << dest.size() << ";\n";
|
||||
return this->getID();
|
||||
}
|
||||
|
||||
void label::generateOnNTo(expression *e)
|
||||
void label::generateOnNTo(shared_ptr<expression>e, unsigned int skip)
|
||||
{
|
||||
operands *o=e->evaluate();
|
||||
shared_ptr<operands>o=e->evaluate();
|
||||
if (o->getType()==T_INT||o->getType()==T_INTVAR)
|
||||
{
|
||||
output_cpp<< "if(" << o->boxName() << ">=0 && "
|
||||
<< o->boxName() << "<js" << this->getID() << ")state=j["
|
||||
<< o->boxName() << "<js" << skip << ")state=j["
|
||||
<< o->boxName() << "];\nbreak;\n";
|
||||
}
|
||||
delete e;
|
||||
}
|
||||
|
||||
void label::generateCondJump(expression *e)
|
||||
void label::generateCondJump(shared_ptr<expression>e)
|
||||
{
|
||||
operands *o=e->evaluate();
|
||||
shared_ptr<operands>o=e->evaluate();
|
||||
if (o->getType()==T_INT||o->getType()==T_INTVAR)
|
||||
{
|
||||
output_cpp<< "if(" << o->boxName()
|
||||
<< "!=0)state=" << this->getID() << ";\nbreak;\n";
|
||||
}
|
||||
delete e;
|
||||
}
|
||||
|
||||
void label::generate()
|
||||
@@ -93,43 +93,42 @@ void label::generate()
|
||||
output_cpp<< "case " << this->getID() <<":\n";
|
||||
}
|
||||
|
||||
/* conditional definition */
|
||||
/* ifStatement definition */
|
||||
|
||||
conditional::conditional(expression *e):codeType(T_IF)
|
||||
ifStatement::ifStatement(shared_ptr<expression>e):codeType(T_IF)
|
||||
{
|
||||
this->redo=new label();
|
||||
this->redo=shared_ptr<label>(new label());
|
||||
redo->generate();
|
||||
this->done=new label();
|
||||
expression *f=new expression(e,O_NOT);
|
||||
this->chain=new label();
|
||||
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());
|
||||
chain->generateCondJump(f);
|
||||
}
|
||||
|
||||
void conditional::generateBreak()
|
||||
void ifStatement::generateBreak()
|
||||
{
|
||||
done->generateJumpTo();
|
||||
}
|
||||
|
||||
void conditional::generateContinue()
|
||||
void ifStatement::generateContinue()
|
||||
{
|
||||
redo->generateJumpTo();
|
||||
}
|
||||
|
||||
void conditional::alternative(expression *e=NULL)
|
||||
void ifStatement::alternative(shared_ptr<expression>e=NULL)
|
||||
{
|
||||
done->generateJumpTo();
|
||||
this->chain->generate();
|
||||
delete this->chain;
|
||||
this->chain=NULL;
|
||||
if(e!=NULL)
|
||||
{
|
||||
this->chain=new label();
|
||||
expression *f=new expression(e,O_NOT);
|
||||
chain->generateJumpCond(f);
|
||||
this->chain=shared_ptr<label>(new label());
|
||||
shared_ptr<expression>f=shared_ptr<expression>(new expression(e,O_NOT));
|
||||
chain->generateCondJump(f);
|
||||
}
|
||||
}
|
||||
|
||||
void conditional::close()
|
||||
void ifStatement::close()
|
||||
{
|
||||
if(this->chain)
|
||||
{
|
||||
@@ -140,17 +139,11 @@ void conditional::close()
|
||||
this->done->generate();
|
||||
}
|
||||
|
||||
conditional::~conditional()
|
||||
{
|
||||
delete this->done;
|
||||
delete this->redo;
|
||||
}
|
||||
|
||||
/* Loop definitions */
|
||||
repeatLoop::repeatLoop():codeType(T_REPEATLOOP)
|
||||
{
|
||||
this->loopStart=new label();
|
||||
this->loopEnd=new label();
|
||||
this->loopStart=shared_ptr<label>(new label());
|
||||
this->loopEnd=shared_ptr<label>(new label());
|
||||
loopStart->generate();
|
||||
}
|
||||
|
||||
@@ -159,23 +152,17 @@ void repeatLoop::generateBreak()
|
||||
loopEnd->generateJumpTo();
|
||||
}
|
||||
|
||||
void repeatLoop::close(expression *e)
|
||||
void repeatLoop::close(shared_ptr<expression>e)
|
||||
{
|
||||
expression *f=new expression(e, O_NOT);
|
||||
shared_ptr<expression>f=shared_ptr<expression>(new expression(e, O_NOT));
|
||||
loopStart->generateCondJump(f);
|
||||
loopEnd->generate();
|
||||
}
|
||||
|
||||
repeatLoop::~repeatLoop()
|
||||
{
|
||||
delete loopStart;
|
||||
delete loopEnd;
|
||||
}
|
||||
|
||||
doLoop::doLoop():codeType(T_DOLOOP)
|
||||
{
|
||||
this->loopStart=new label();
|
||||
this->loopEnd=new label();
|
||||
this->loopStart=shared_ptr<label>(new label());
|
||||
this->loopEnd=shared_ptr<label>(new label());
|
||||
loopStart->generate();
|
||||
}
|
||||
|
||||
@@ -190,16 +177,11 @@ void doLoop::close()
|
||||
this->loopEnd->generate();
|
||||
}
|
||||
|
||||
doLoop::~doLoop()
|
||||
{ delete loopStart;
|
||||
delete loopEnd;
|
||||
}
|
||||
|
||||
whileLoop::whileLoop(expression *e):codeType(T_WHILELOOP)
|
||||
whileLoop::whileLoop(shared_ptr<expression>e):codeType(T_WHILELOOP)
|
||||
{
|
||||
loopContinue=new label();
|
||||
loopStart=new label();
|
||||
loopEnd=new label();
|
||||
loopContinue=shared_ptr<label>(new label());
|
||||
loopStart=shared_ptr<label>(new label());
|
||||
loopEnd=shared_ptr<label>(new label());
|
||||
cond=e;
|
||||
loopStart->generateJumpTo();
|
||||
loopContinue->generate();
|
||||
@@ -213,42 +195,44 @@ void whileLoop::generateBreak()
|
||||
void whileLoop::close()
|
||||
{
|
||||
loopStart->generate();
|
||||
loopContinue->generateJumpCond(cond);
|
||||
loopContinue->generateCondJump(cond);
|
||||
loopEnd->generate();
|
||||
}
|
||||
|
||||
whileLoop::~whileLoop()
|
||||
{
|
||||
delete loopStart;
|
||||
delete loopContinue;
|
||||
delete loopEnd;
|
||||
}
|
||||
|
||||
forLoop::forLoop(variable *v, expression *start, expression *stop, expression *stepVal=NULL):codeType(T_FORLOOP)
|
||||
forLoop::forLoop(shared_ptr<variable>v,
|
||||
shared_ptr<expression>start, shared_ptr<expression>stop,
|
||||
shared_ptr<expression>stepVal=NULL):codeType(T_FORLOOP)
|
||||
{
|
||||
/*v=start;
|
||||
stopTemp=stop;*/
|
||||
v->assignment(start);
|
||||
stopTemp->assignment(stop);
|
||||
/* if (v<stopTemp) */
|
||||
conditional *c=new conditional(new expression(new expression(v), O_LESS, new expression(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))))));
|
||||
/* startTemp=v;*/
|
||||
startTemp->assignment(new expression(v));
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(v)));
|
||||
/* else */
|
||||
c->alternative();
|
||||
/* startTemp=stopTemp;
|
||||
stopTemp=v;*/
|
||||
startTemp->assignment(new expression(stopTemp));
|
||||
stopTemp->assignment(new expression(v));
|
||||
startTemp->assignment(shared_ptr<expression>(new expression(stopTemp)));
|
||||
stopTemp->assignment(shared_ptr<expression>(new expression(v)));
|
||||
/* endif */
|
||||
c->close();
|
||||
delete c;
|
||||
/* while (v<=stopTemp && v>=startTemp) */
|
||||
expression *stopper1=new expression(new expression(v), O_LESS_EQUAL, new expression(stopTemp));
|
||||
expression *stopper2=new expression(new expression(v), O_GREATER_EQUAL, new expression(startTemp));
|
||||
expression *stopper=new expression(stopper1, O_AND, stopper2);
|
||||
this->infrastructure=new whileLoop(new expression(stopper, O_UNEQUAL,
|
||||
new expression(operands::createConst("0", T_INT))));
|
||||
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));
|
||||
this->infrastructure=new whileLoop(shared_ptr<expression>(new expression(
|
||||
stopper, O_UNEQUAL, shared_ptr<expression>(new expression(
|
||||
operands::createConst(string("0"), T_INT))))));
|
||||
if (stepVal)
|
||||
{
|
||||
step=stepVal;
|
||||
@@ -256,7 +240,7 @@ forLoop::forLoop(variable *v, expression *start, expression *stop, expression *s
|
||||
else
|
||||
{
|
||||
/* if not present "step" is assumed to be 1 */
|
||||
step=new expression(operands::createConst("1", T_INT));
|
||||
step=shared_ptr<expression>(new expression(operands::createConst("1", T_INT)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,8 +251,9 @@ void forLoop::generateBreak()
|
||||
|
||||
void forLoop::close()
|
||||
{
|
||||
/* v=v+step; */
|
||||
expression *stepper=new expression(new expression(v), O_PLUS, step);
|
||||
v->assignment(stepper)
|
||||
/* var=var+step; */
|
||||
shared_ptr<expression>stepper=shared_ptr<expression>(new expression(
|
||||
shared_ptr<expression>(new expression(var)), O_PLUS, step));
|
||||
var->assignment(stepper);
|
||||
infrastructure->close();
|
||||
}
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
*/
|
||||
#include "yab2cpp.h"
|
||||
|
||||
class fn;
|
||||
|
||||
/* methods for operands */
|
||||
static operands *findGlobal(string &s)
|
||||
shared_ptr<operands>operands::findGlobal(string &s)
|
||||
{
|
||||
auto iter=operands::globals.find(s);
|
||||
if (iter==operands::globals.end())
|
||||
@@ -19,7 +21,7 @@ static operands *findGlobal(string &s)
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
static void operands::dumpVars()
|
||||
void operands::dumpVars()
|
||||
{
|
||||
varNames << "Global Variables\n";
|
||||
for(auto iter=globals.begin(); iter!=globals.end(); ++iter)
|
||||
@@ -29,19 +31,22 @@ static void operands::dumpVars()
|
||||
varNames << endl;
|
||||
}
|
||||
|
||||
unsigned int operands::getOrCreateStr(string &s)
|
||||
shared_ptr<operands> operands::getOrCreateStr(string s)
|
||||
{
|
||||
auto iter=constStr.find(s);
|
||||
if (iter!=constStr.end()) return iter->second;
|
||||
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";
|
||||
constStr[s]=nextID;
|
||||
return nextID;
|
||||
operands::strConst[s]=nextID;
|
||||
return shared_ptr<operands>(new operands(nextID, T_STRING));
|
||||
}
|
||||
|
||||
unsigned int operands::createConst(string &s, enum TYPES t)
|
||||
shared_ptr<operands>operands::createConst(string s, enum TYPES t)
|
||||
{
|
||||
operands *me=new operands(t);
|
||||
shared_ptr<operands>me=shared_ptr<operands>(new operands(t));
|
||||
if (t==T_INT)
|
||||
{
|
||||
consts_h << "const int k";
|
||||
@@ -64,7 +69,7 @@ unsigned int operands::createConst(string &s, enum TYPES t)
|
||||
|
||||
enum TYPES operands::getSimpleVarType()
|
||||
{
|
||||
switch type
|
||||
switch (this->getType())
|
||||
{
|
||||
case T_FLOAT:
|
||||
case T_FLOATCALL_ARRAY:
|
||||
@@ -111,29 +116,31 @@ void operands::generateBox(ostream &scope)
|
||||
scope << this->getID() << ";\n";
|
||||
}
|
||||
|
||||
operands *operands::getOrCreateGlobal(string &s, enum TYPES t)
|
||||
shared_ptr<operands>operands::getOrCreateGlobal(string &s, enum TYPES t)
|
||||
{
|
||||
operands op*=operands::globals->find(s);
|
||||
auto op=globals.find(s);
|
||||
if (op==globals.end())
|
||||
{
|
||||
op=new variable(heap_h, s, t);
|
||||
return shared_ptr<variable>(new variable(heap_h, s, t));
|
||||
}
|
||||
return op;
|
||||
return op->second;
|
||||
}
|
||||
|
||||
void operands::boxName(ostream &scope)
|
||||
string operands::boxName()
|
||||
{
|
||||
ostringstream s;
|
||||
switch (this->getType())
|
||||
{
|
||||
case T_STRINGVAR:
|
||||
case T_INTVAR:
|
||||
case T_FLOATVAR:
|
||||
s << 'v' << this->getID();
|
||||
return s.str();
|
||||
break;
|
||||
|
||||
default:
|
||||
error(E_INTERNAL);
|
||||
}
|
||||
scope << "v" << this->getID();
|
||||
}
|
||||
|
||||
/* expression parsing routines */
|
||||
@@ -141,7 +148,7 @@ void operands::boxName(ostream &scope)
|
||||
/* binary vs. unary ops */
|
||||
bool expression::isBinOp()
|
||||
{
|
||||
switch this->getOp()
|
||||
switch (this->getOp())
|
||||
{
|
||||
case O_NEGATE:
|
||||
case O_NOT:
|
||||
@@ -153,10 +160,11 @@ bool expression::isBinOp()
|
||||
return true;
|
||||
}
|
||||
|
||||
operands *expression::evaluate()
|
||||
shared_ptr<operands>expression::evaluate()
|
||||
{
|
||||
if (this->getOp()==O_TERM) return op;
|
||||
operands *l, *r;
|
||||
shared_ptr<operands>l;
|
||||
shared_ptr<operands>r;
|
||||
enum TYPES t;
|
||||
ostream &scope=scopeGlobal?heap_h:funcs_h;
|
||||
l=this->getLeft()->evaluate();
|
||||
@@ -167,12 +175,12 @@ operands *expression::evaluate()
|
||||
enum TYPES rt=r->getSimpleVarType();
|
||||
if (lt==T_INTVAR && rt==T_FLOATVAR)
|
||||
{
|
||||
l=new expression(new expression(l), 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=new expression(new expression(r), 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);
|
||||
@@ -183,96 +191,96 @@ operands *expression::evaluate()
|
||||
t=l->getSimpleVarType();
|
||||
r=NULL;
|
||||
}
|
||||
if (t==T_STRINGVAR) return expression::stringEval();
|
||||
if (t==T_STRINGVAR) return expression::stringEval(l, r);
|
||||
switch (this->getOp())
|
||||
{
|
||||
case O_INVERT:
|
||||
this->op=new operands(t);
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "= ~" << l->boxName() << ";\n";
|
||||
break;
|
||||
case O_NEGATE:
|
||||
this->op=new operands(t);
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "= -" << l->boxName() << ";\n";
|
||||
break;
|
||||
case O_NOT:
|
||||
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "= !" << l->boxName() << ";\n";
|
||||
break;
|
||||
case O_INT_TO_FLOAT: /*Note: this duplicates functionality of variable assignment */
|
||||
this->op=new operands(T_FLOATVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_FLOATVAR));
|
||||
this->op->generateBox(scope);
|
||||
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=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "%" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_DIVIDE:
|
||||
this->op=new operands(t);
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "/" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_PLUS:
|
||||
this->op=new operands(t);
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "+" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_MINUS:
|
||||
this->op=new operands(t);
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "-" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_MULTIPLY:
|
||||
this->op=new operands(t);
|
||||
this->op=shared_ptr<operands>(new operands(t));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "*" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_OR:
|
||||
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "|" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_AND:
|
||||
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "&" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_GREATER:
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=(" << l->boxName() << ">" << r->boxName() << ")?-1:0;\n";
|
||||
break;
|
||||
case O_LESS:
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=(" << l->boxName() << "<" << r->boxName() << ")?-1:0;\n";
|
||||
break;
|
||||
case O_GREATER_EQUAL:
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=(" << l->boxName() << ">=" << r->boxName() << ")?-1:0;\n";
|
||||
break;
|
||||
case O_LESS_EQUAL:
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=(" << l->boxName() << "<=" << r->boxName() << ")?-1:0;\n";
|
||||
break;
|
||||
case O_EQUAL:
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=(" << l->boxName() << "==" << r->boxName() << ")?-1:0;\n";
|
||||
break;
|
||||
case O_UNEQUAL:
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op=shared_ptr<operands>(new operands(T_INTVAR));
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=(" << l->boxName() << "!=" << r->boxName() << ")?-1:0;\n";
|
||||
break;
|
||||
@@ -282,80 +290,46 @@ operands *expression::evaluate()
|
||||
break;
|
||||
}
|
||||
/* convert expression into single operand */
|
||||
delete this->left;
|
||||
this->left=NULL;
|
||||
if (r)
|
||||
{
|
||||
delete this->right;
|
||||
this->right=NULL;
|
||||
}
|
||||
this->oper=O_TERM;
|
||||
return this->op;
|
||||
}
|
||||
|
||||
operands * expression::stringEval(ostream &scope, operands *l, operands *r)
|
||||
shared_ptr<operands> expression::stringEval(shared_ptr<operands>l, shared_ptr<operands>r)
|
||||
{
|
||||
if (this->getOp()==O_STRING_CONCAT)
|
||||
{
|
||||
this->op=new operands(T_STRINGVAR);
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" l->boxName() << "+" << r->boxName();
|
||||
}
|
||||
else
|
||||
{
|
||||
errorLevel=E_INTERNAL;
|
||||
exit(1);
|
||||
this->op=shared_ptr<operands>(new operands(T_STRINGVAR));
|
||||
this->op->generateBox(scopeGlobal?heap_h:funcs_h);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "+" << r->boxName();
|
||||
}
|
||||
else error(E_INTERNAL);
|
||||
/* convert expression into single operand */
|
||||
delete this->left;
|
||||
this->left=NULL;
|
||||
if (r)
|
||||
{
|
||||
delete this->right;
|
||||
this->right=NULL;
|
||||
}
|
||||
this->oper=O_TERM;
|
||||
return this->op;
|
||||
}
|
||||
|
||||
expression::~expression()
|
||||
{
|
||||
if(this->getOp()==O_TERM)
|
||||
{
|
||||
delete this->op;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete this->left;
|
||||
if (this->isBinOp())
|
||||
{
|
||||
delete this->right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* variable definitions */
|
||||
variable::variable(ostream &scope, string &name, enum TYPES t):operands(t)
|
||||
{
|
||||
this->generateBox(scope); /*TODO: FINISH THIS*/
|
||||
}
|
||||
|
||||
variable *variable::getOrCreateVarName(string &name, enum TYPES t)
|
||||
shared_ptr<variable> variable::getOrCreateVar(string &name, enum TYPES t)
|
||||
{
|
||||
if (!scopeGlobal)
|
||||
{
|
||||
return fn::getOrCreateVar(t, name, false);
|
||||
}
|
||||
/* TODO: verify if type is compatible */
|
||||
shared_ptr<operands>op=operands::getOrCreateGlobal(name);
|
||||
shared_ptr<variable>v=new variable();
|
||||
v->assignment(new expression(op));
|
||||
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)));
|
||||
return v;
|
||||
}
|
||||
|
||||
void variable::assignment(expression *value)
|
||||
void variable::assignment(shared_ptr<expression>value)
|
||||
{
|
||||
operands *op=value->evaluate();
|
||||
shared_ptr<operands>op=value->evaluate();
|
||||
enum TYPES t=op->getSimpleVarType();
|
||||
switch (this->getType())
|
||||
{
|
||||
|
||||
@@ -8,25 +8,27 @@
|
||||
*/
|
||||
#include "yab2cpp.h"
|
||||
|
||||
class label;
|
||||
|
||||
/* function definitions */
|
||||
fn *fn::getCurrentSub()
|
||||
shared_ptr<fn>fn::getCurrentSub()
|
||||
{
|
||||
return callStack.back;
|
||||
return callStack.back();
|
||||
}
|
||||
|
||||
void fn::generateOnNSub(expression *e)
|
||||
void fn::generateOnNSub(shared_ptr<expression>e, unsigned int skip)
|
||||
{
|
||||
shared_ptr<label>r=new label();
|
||||
shared_ptr<fn> self=new fn(r);
|
||||
shared_ptr<label>r=shared_ptr<label>(new label());
|
||||
shared_ptr<fn> self=shared_ptr<fn>(new fn(r));
|
||||
fn::callStack.push_back(self);
|
||||
label::generateOnNTo(e);
|
||||
label::generateOnNTo(e, skip);
|
||||
r->generate();
|
||||
}
|
||||
|
||||
void fn::generateGosub(shared_ptr<label> sub)
|
||||
{
|
||||
shared_ptr<label>r=new label();
|
||||
shared_ptr<fn> self=new fn(r);
|
||||
shared_ptr<label>r=shared_ptr<label>(new label());
|
||||
shared_ptr<fn> self=shared_ptr<fn>(new fn(r));
|
||||
fn::callStack.push_back(self);
|
||||
sub->generateJumpTo();
|
||||
r->generate();
|
||||
@@ -39,50 +41,79 @@ fn::fn(shared_ptr<label>gosub):codeType(T_GOSUB)
|
||||
|
||||
shared_ptr<fn> fn::getSub(string &name)
|
||||
{
|
||||
auto iter=fn::functions.find(name)
|
||||
auto iter=fn::functions.find(name);
|
||||
if(iter==fn::functions.end()) return NULL;
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
operands *fn::generateCall(string &name, list<shared_ptr<operands> >¶mList)
|
||||
shared_ptr<operands>fn::generateCall(string &name,
|
||||
list<shared_ptr<operands> >paramList)
|
||||
{
|
||||
auto v=params.begin();
|
||||
shared_ptr<operands>current;
|
||||
shared_ptr<fn>g=fn::getSub(name);
|
||||
if (g==NULL)
|
||||
{
|
||||
errorLevel=E_SUBROUTINE_NOT_FOUND;
|
||||
exit(1);
|
||||
error(E_SUBROUTINE_NOT_FOUND);
|
||||
}
|
||||
if (paramList.size()>params.size())
|
||||
{
|
||||
errorLevel=E_TOO_MANY_PARAMETERS;
|
||||
exit(1);
|
||||
error(E_TOO_MANY_PARAMETERS);
|
||||
}
|
||||
output_cpp << "struct *f" << /* TODO: finish this */
|
||||
<< "= new struct f" << g->getID();
|
||||
/* TODO CHECK THIS */
|
||||
output_cpp << "struct f" << g->getID()
|
||||
<< "*sub" << this->getID()
|
||||
<< "= new struct f" << g->getID()
|
||||
<< "();\n";
|
||||
while(paramList.size()>0)
|
||||
{
|
||||
current=paramList.front;
|
||||
current= paramList.front();
|
||||
paramList.pop_front();
|
||||
if(current->getSimpleVarType()!=*v->getType())
|
||||
if(current->getSimpleVarType()!=(*v)->getType())
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
error(E_TYPE_MISMATCH);
|
||||
}
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(current)));
|
||||
++v;
|
||||
}
|
||||
/* pad remaining unassigned variables with empty values */
|
||||
while (v!=params.end())
|
||||
{
|
||||
switch ((*v)->getType())
|
||||
{
|
||||
case T_FLOATVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
operands::createConst("0.0", T_FLOAT)
|
||||
)));
|
||||
break;
|
||||
case T_INTVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
operands::createConst("0", T_INT)
|
||||
)));
|
||||
break;
|
||||
case T_STRINGVAR:
|
||||
(*v)->assignment(shared_ptr<expression>(
|
||||
new expression(
|
||||
operands::getOrCreateStr(string("")
|
||||
))));
|
||||
default:
|
||||
error(E_TYPE_MISMATCH);
|
||||
}
|
||||
*v->assignment(new expression(current));
|
||||
++v;
|
||||
}
|
||||
|
||||
return g->/*TODO FINISH THIS*/
|
||||
}
|
||||
|
||||
void fn::generateReturn()
|
||||
{
|
||||
shared_ptr<fn>c=fn::getCurrent();
|
||||
shared_ptr<fn>c=getCurrentSub();
|
||||
switch(c->getType())
|
||||
{
|
||||
case T_UNKNOWNFUNC:
|
||||
/* set return type to NONE */
|
||||
this->kind=T_NONE;
|
||||
/*fallthrough*/
|
||||
case T_GOSUB:
|
||||
@@ -95,9 +126,9 @@ void fn::generateReturn()
|
||||
}
|
||||
}
|
||||
|
||||
operands *fn::generateReturn(expression *expr)
|
||||
shared_ptr<operands>fn::generateReturn(shared_ptr<expression>expr)
|
||||
{
|
||||
operands *out=expr->evaluate();
|
||||
shared_ptr<operands>out=expr->evaluate();
|
||||
this->kind=out->getSimpleVarType();
|
||||
this->ret->generateJumpTo();
|
||||
fn::callStack.pop_back();
|
||||
@@ -153,7 +184,7 @@ void fn::close()
|
||||
(t==T_UNKNOWNFUNC||t==T_VOIDFUNC))
|
||||
{
|
||||
/* generate a typeless return */
|
||||
this->generateReturn()
|
||||
this->generateReturn();
|
||||
}
|
||||
funcs_h << "};\n";
|
||||
fn::locals.clear();
|
||||
@@ -165,10 +196,10 @@ void fn::close()
|
||||
fn::fn(string &s, enum CODES t):codeType(t)
|
||||
{
|
||||
if (!scopeGlobal) error(E_END_FUNCTION);
|
||||
if (fn::functions->find(s)!=fn::functions.end()) error(E_DUPLICATE_SYMBOL);
|
||||
if (fn::functions.find(s)!=fn::functions.end()) error(E_DUPLICATE_SYMBOL);
|
||||
this->id= ++nextID;
|
||||
funcs_h << "struct f" << this->id <<"\n{\n";
|
||||
this->ret=new label();
|
||||
this->ret=shared_ptr<label>(new label());
|
||||
fn::functions[s]=this;
|
||||
scopeGlobal=false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user