it builds but doesn't link yet

This commit is contained in:
Samuel D. Crow
2021-03-17 18:56:14 -05:00
parent 1dae0a4b54
commit b6e8984e62
7 changed files with 286 additions and 197 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@ bison.output
yab
*.o
*.so
.vscode/*

View File

@@ -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

View File

@@ -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
View File

@@ -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()
{}
};

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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();
}