saving progress on functions and variables
This commit is contained in:
112
yab2cpp.h
112
yab2cpp.h
@@ -40,7 +40,12 @@ enum COMPILE_ERRORS {
|
|||||||
E_BAD_ALLOC,
|
E_BAD_ALLOC,
|
||||||
E_STACK_UNDERFLOW,
|
E_STACK_UNDERFLOW,
|
||||||
E_INTERNAL,
|
E_INTERNAL,
|
||||||
E_DUPLICATE_SYMBOL
|
E_DUPLICATE_SYMBOL,
|
||||||
|
E_END_FUNCTION,
|
||||||
|
E_GOSUB_CANNOT_RETURN_VALUE,
|
||||||
|
E_SUBROUTINE_NOT_FOUND,
|
||||||
|
E_TOO_MANY_PARAMETERS,
|
||||||
|
E_UNASSIGNABLE_TYPE
|
||||||
};
|
};
|
||||||
|
|
||||||
extern enum COMPILE_ERRORS errorLevel;
|
extern enum COMPILE_ERRORS errorLevel;
|
||||||
@@ -56,11 +61,14 @@ const char *COMPILE_ERROR_NAMES[]={
|
|||||||
"failed allocation",
|
"failed allocation",
|
||||||
"stack underflow",
|
"stack underflow",
|
||||||
"internal compiler error",
|
"internal compiler error",
|
||||||
"duplicated label"
|
"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"
|
||||||
};
|
};
|
||||||
|
|
||||||
extern enum COMPILEERRORS errorLevel;
|
|
||||||
|
|
||||||
/* flags used internally by the compiler
|
/* flags used internally by the compiler
|
||||||
(must be powers of 2) */
|
(must be powers of 2) */
|
||||||
#define COMPILE 1
|
#define COMPILE 1
|
||||||
@@ -70,7 +78,8 @@ extern enum COMPILEERRORS errorLevel;
|
|||||||
/* list of all variable and constant types */
|
/* list of all variable and constant types */
|
||||||
enum TYPES
|
enum TYPES
|
||||||
{
|
{
|
||||||
T_NONE=0,
|
T_UNKNOWN=0,
|
||||||
|
T_NONE,
|
||||||
T_STRING,
|
T_STRING,
|
||||||
T_INT,
|
T_INT,
|
||||||
T_FLOAT,
|
T_FLOAT,
|
||||||
@@ -80,6 +89,7 @@ enum TYPES
|
|||||||
T_INTCALL_ARRAY,
|
T_INTCALL_ARRAY,
|
||||||
T_FLOATCALL_ARRAY,
|
T_FLOATCALL_ARRAY,
|
||||||
T_STRINGCALL_ARRAY,
|
T_STRINGCALL_ARRAY,
|
||||||
|
T_VOIDCALL
|
||||||
}
|
}
|
||||||
/* list of all kinds of other code structures */
|
/* list of all kinds of other code structures */
|
||||||
enum CODES
|
enum CODES
|
||||||
@@ -97,11 +107,17 @@ enum CODES
|
|||||||
T_ASSIGNMENT,
|
T_ASSIGNMENT,
|
||||||
T_LABEL,
|
T_LABEL,
|
||||||
T_PARAMLIST,
|
T_PARAMLIST,
|
||||||
T_DATAITEM
|
T_DATAITEM,
|
||||||
|
T_STRINGFUNC,
|
||||||
|
T_FLOATFUNC,
|
||||||
|
T_INTFUNC,
|
||||||
|
T_VOIDFUNC,
|
||||||
|
T_UNKNOWNFUNC
|
||||||
};
|
};
|
||||||
|
|
||||||
/* These correspond to the types of enum TYPES. */
|
/* These correspond to the types of enum TYPES. */
|
||||||
const string TYPENAMES[]={
|
const string TYPENAMES[]={
|
||||||
|
"unknown",
|
||||||
"none",
|
"none",
|
||||||
"string constant",
|
"string constant",
|
||||||
"integer constant",
|
"integer constant",
|
||||||
@@ -111,7 +127,9 @@ const string TYPENAMES[]={
|
|||||||
"floating point variable",
|
"floating point variable",
|
||||||
"string array or function",
|
"string array or function",
|
||||||
"integer array or function",
|
"integer array or function",
|
||||||
"floating point array or function"
|
"floating point array or function",
|
||||||
|
"string array or function",
|
||||||
|
"function"
|
||||||
};
|
};
|
||||||
|
|
||||||
const string CODETYPES[]={
|
const string CODETYPES[]={
|
||||||
@@ -127,7 +145,12 @@ const string CODETYPES[]={
|
|||||||
"assignment",
|
"assignment",
|
||||||
"label",
|
"label",
|
||||||
"parameter list or array index",
|
"parameter list or array index",
|
||||||
"data item"
|
"data item",
|
||||||
|
"function returning string",
|
||||||
|
"function returning floating point",
|
||||||
|
"function returning integer",
|
||||||
|
"function returning nothing",
|
||||||
|
"function"
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union
|
typedef union
|
||||||
@@ -165,25 +188,30 @@ enum OPERATORS
|
|||||||
O_OR,
|
O_OR,
|
||||||
O_AND,
|
O_AND,
|
||||||
O_STRING_CONCAT,
|
O_STRING_CONCAT,
|
||||||
|
O_INT_TO_FLOAT,
|
||||||
O_TERM
|
O_TERM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* global prototype */
|
||||||
|
void error(enum COMPILE_ERRORS err);
|
||||||
|
|
||||||
/* internal states used by the parser */
|
/* internal states used by the parser */
|
||||||
class operands
|
class operands
|
||||||
{
|
{
|
||||||
enum TYPES type;
|
enum TYPES type;
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
static unsigned int nextID;
|
static unsigned int nextID;
|
||||||
static unordered_map<string &, operands *> globals;
|
static unordered_map<string, operands *> globals;
|
||||||
static unordered_map<string &, unsigned int> strConst;
|
static unordered_map<string, unsigned int> strConst;
|
||||||
public:
|
public:
|
||||||
enum TYPES getType() const {return type;}
|
enum TYPES getType() const {return type;}
|
||||||
unsigned int getID() const {return id;}
|
unsigned int getID() const {return id;}
|
||||||
|
|
||||||
|
static operands *findGlobal(string &s);
|
||||||
static void dumpVars(ostream &out);
|
static void dumpVars(ostream &out);
|
||||||
static unsigned int getOrCreateStr(ostream &k, string &s);
|
static unsigned int getOrCreateStr(string &s);
|
||||||
static operands *createConst(ostream &k, string &s, enum TYPES t);
|
static operands *createConst(string &s, enum TYPES t);
|
||||||
static operands *getOrCreateGlobal(ostream &heap, string &s, enum TYPES t);
|
static operands *getOrCreateGlobal(string &s, enum TYPES t);
|
||||||
|
|
||||||
enum TYPES getSimpleVarType();
|
enum TYPES getSimpleVarType();
|
||||||
void generateBox(ostream &scope);
|
void generateBox(ostream &scope);
|
||||||
@@ -223,19 +251,17 @@ public:
|
|||||||
op=x;
|
op=x;
|
||||||
oper=O_TERM;
|
oper=O_TERM;
|
||||||
}
|
}
|
||||||
|
/*TODO: Recycle temporary variables when not in debug mode*/
|
||||||
virtual ~expression();
|
virtual ~expression();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* parent class of all code types */
|
/* parent class of all code types */
|
||||||
class codeType
|
class codeType
|
||||||
{
|
{
|
||||||
unsigned int id;
|
|
||||||
enum CODES type;
|
enum CODES type;
|
||||||
static unsigned int nextID;
|
|
||||||
static list<codeType *> nesting;
|
static list<codeType *> nesting;
|
||||||
public:
|
public:
|
||||||
enum CODES getType() const {return this->type;}
|
enum CODES getType() const {return this->type;}
|
||||||
unsigned int getID() const {return this->id;}
|
|
||||||
|
|
||||||
static codeType *getCurrent();
|
static codeType *getCurrent();
|
||||||
|
|
||||||
@@ -258,7 +284,7 @@ public:
|
|||||||
unsigned int getID() const {return id;}
|
unsigned int getID() const {return id;}
|
||||||
|
|
||||||
void generateJumpTo();
|
void generateJumpTo();
|
||||||
void generateOnNSkip(ostream &k, list<label *> &dest);
|
void generateOnNSkip(list<shared_ptr<label> >dest);
|
||||||
void generateOnNTo(expression *e);
|
void generateOnNTo(expression *e);
|
||||||
void generateCondJump(expression *e);
|
void generateCondJump(expression *e);
|
||||||
void generate();
|
void generate();
|
||||||
@@ -313,7 +339,7 @@ public:
|
|||||||
virtual void generateBreak() override;
|
virtual void generateBreak() override;
|
||||||
virtual void close() override;
|
virtual void close() override;
|
||||||
|
|
||||||
explicit doLoop():codeType(T_DOLOOP);
|
explicit doLoop();
|
||||||
virtual ~doLoop();
|
virtual ~doLoop();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -327,14 +353,15 @@ public:
|
|||||||
virtual void generateBreak() override;
|
virtual void generateBreak() override;
|
||||||
virtual void close() override;
|
virtual void close() override;
|
||||||
|
|
||||||
explicit whileLoop(expression *e):codeType(T_WHILELOOP);
|
explicit whileLoop(expression *e);
|
||||||
virtual ~whileLoop();
|
virtual ~whileLoop();
|
||||||
};
|
};
|
||||||
|
|
||||||
class variable:public operands
|
class variable:public operands
|
||||||
{
|
{
|
||||||
|
ostream &myScope;
|
||||||
public:
|
public:
|
||||||
static variable *getOrCreateVarName(ostream &func, ostream &heap, string &name, enum TYPES t);
|
static shared_ptr<variable>getOrCreateVarName(string &name, enum TYPES t);
|
||||||
|
|
||||||
void assignment(expression *value);
|
void assignment(expression *value);
|
||||||
explicit variable(ostream &scope, string &name, enum TYPES t);
|
explicit variable(ostream &scope, string &name, enum TYPES t);
|
||||||
@@ -348,7 +375,7 @@ class arrayType:public variable
|
|||||||
public:
|
public:
|
||||||
virtual string &boxName(list<unsigned int>indexes) override;
|
virtual string &boxName(list<unsigned int>indexes) override;
|
||||||
|
|
||||||
explicit arrayType(ostream &heap, string &name, enum TYPES t, list<unsigned int>dim);/*:variable(scope, name, t);*/
|
explicit arrayType(string &name, enum TYPES t, list<unsigned int>dim);/*:variable(scope, name, t);*/
|
||||||
virtual ~arrayType()
|
virtual ~arrayType()
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
@@ -364,37 +391,46 @@ public:
|
|||||||
virtual void generateBreak();
|
virtual void generateBreak();
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
explicit forLoop(ostream &k, variable *v, expression *start, expression *stop, expression *stepVal=NULL);
|
explicit forLoop(variable *v, expression *start, expression *stop, expression *stepVal=NULL);
|
||||||
virtual ~forLoop();
|
virtual ~forLoop();
|
||||||
};
|
};
|
||||||
|
|
||||||
class fn:codeType
|
class fn:codeType
|
||||||
{
|
{
|
||||||
static unordered_map<string, operands *>locals;
|
static unordered_map<string, shared_ptr<variable> >locals;
|
||||||
static unordered_map<string, operands *>statics;
|
static unordered_map<string, shared_ptr<variable> >statics;
|
||||||
static unordered_map<string, fn>functions;
|
static unordered_map<string, shared_ptr<fn> >functions;
|
||||||
static list<fn *> callStack;
|
static list<shared_ptr<fn> > callStack;
|
||||||
|
static unsigned int nextID;
|
||||||
|
list<shared_ptr<variable> >params;
|
||||||
|
unsigned int id;
|
||||||
enum TYPES kind;
|
enum TYPES kind;
|
||||||
|
shared_ptr<label>startAddr;
|
||||||
shared_ptr<label>ret;
|
shared_ptr<label>ret;
|
||||||
unsigned int parameters;
|
/* private constructor used by generateGosub and generateOnNSub*/
|
||||||
|
fn(label *gosub);
|
||||||
public:
|
public:
|
||||||
static variable *getOrCreateVar(enum TYPES t, string &s, bool stat);
|
static variable *getOrCreateVar(enum TYPES t, string &s, bool stat);
|
||||||
static void dumpCallStack();
|
static void dumpCallStack();
|
||||||
static fn *getCurrentSub();
|
static shared_ptr<fn>getCurrentSub();
|
||||||
|
static shared_ptr<fn>getSub(string &name);
|
||||||
void setParameters(unsigned int num) const {this->parameters=num;}
|
static void generateGosub(shared_ptr<label> sub);
|
||||||
|
|
||||||
void generateCall(string &name, unsigned int params);
|
|
||||||
void generateReturn(expression *expr=NULL);
|
|
||||||
void generateGosub(shared_ptr<label> sub);
|
|
||||||
/* must be called after label::generateOnNSkip */
|
/* must be called after label::generateOnNSkip */
|
||||||
void generateOnNSub(expression *e);
|
static void generateOnNSub(expression *e);
|
||||||
|
|
||||||
|
unsigned int getID() const {return this->id;}
|
||||||
|
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);
|
||||||
|
void generateReturn();
|
||||||
virtual void generateBreak();
|
virtual void generateBreak();
|
||||||
virtual void close();
|
virtual void close();
|
||||||
|
|
||||||
fn(string &name);
|
fn(string &name, enum CODES t);
|
||||||
fn(label *gosub);
|
virtual ~fn()
|
||||||
virtual ~fn();
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The next two structures are used to implement the PRINT statement. */
|
/* The next two structures are used to implement the PRINT statement. */
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
/* base class of all the code structure types */
|
/* base class of all the code structure types */
|
||||||
codeType::codeType(enum CODES t)
|
codeType::codeType(enum CODES t)
|
||||||
{
|
{
|
||||||
this->id= ++nextID;
|
|
||||||
nesting.push_back(this);
|
nesting.push_back(this);
|
||||||
this->type=t;
|
this->type=t;
|
||||||
}
|
}
|
||||||
@@ -48,7 +47,7 @@ void label::generateJumpTo()
|
|||||||
output_cpp << "state=" << this->getID() << ";\nbreak;\n";
|
output_cpp << "state=" << this->getID() << ";\nbreak;\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void label::generateOnNSkip(list<label *> &dest)
|
void label::generateOnNSkip(list<shared_ptr<label> >dest)
|
||||||
{
|
{
|
||||||
if (dest->size()<2)
|
if (dest->size()<2)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,6 +9,16 @@
|
|||||||
#include "yab2cpp.h"
|
#include "yab2cpp.h"
|
||||||
|
|
||||||
/* methods for operands */
|
/* methods for operands */
|
||||||
|
static operands *findGlobal(string &s)
|
||||||
|
{
|
||||||
|
auto iter=operands::globals.find(s);
|
||||||
|
if (iter==operands::globals.end())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
static void operands::dumpVars()
|
static void operands::dumpVars()
|
||||||
{
|
{
|
||||||
varNames << "Global Variables\n";
|
varNames << "Global Variables\n";
|
||||||
@@ -48,7 +58,7 @@ unsigned int operands::createConst(string &s, enum TYPES t)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
k << me->getID() << "=" << s << ";\n";
|
consts_h << me->getID() << "=" << s << ";\n";
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,40 +79,7 @@ enum TYPES operands::getSimpleVarType()
|
|||||||
case T_STRINGVAR:
|
case T_STRINGVAR:
|
||||||
return T_STRINGVAR;
|
return T_STRINGVAR;
|
||||||
}
|
}
|
||||||
return T_NONE;
|
error(E_UNASSIGNABLE_TYPE);
|
||||||
}
|
|
||||||
|
|
||||||
enum TYPES operands::coerceTypes(enum TYPES l, enum TYPES r)
|
|
||||||
{
|
|
||||||
if this->isBinOp()
|
|
||||||
{
|
|
||||||
if (l==T_INTVAR && r==T_FLOATVAR)
|
|
||||||
{
|
|
||||||
/* promote l to float */
|
|
||||||
t=T_FLOATVAR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (l==T_FLOAT && r==T_INT)
|
|
||||||
{
|
|
||||||
/* promote r to float */
|
|
||||||
t=T_FLOATVAR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (l==r)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
errorLevel=E_TYPE_MISMATCH;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (t==T_NONE)
|
|
||||||
{
|
|
||||||
errorLevel=E_TYPE_MISMATCH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* operands used by expression parser and variables */
|
/* operands used by expression parser and variables */
|
||||||
@@ -154,9 +131,7 @@ void operands::boxName(ostream &scope)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
errorLevel=E_INTERNAL;
|
error(E_INTERNAL);
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
scope << "v" << this->getID();
|
scope << "v" << this->getID();
|
||||||
}
|
}
|
||||||
@@ -171,6 +146,7 @@ bool expression::isBinOp()
|
|||||||
case O_NEGATE:
|
case O_NEGATE:
|
||||||
case O_NOT:
|
case O_NOT:
|
||||||
case O_INVERT:
|
case O_INVERT:
|
||||||
|
case O_INT_TO_FLOAT:
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -187,7 +163,20 @@ operands *expression::evaluate()
|
|||||||
if (this->isBinOp())
|
if (this->isBinOp())
|
||||||
{
|
{
|
||||||
r=this->getRight()->evaluate();
|
r=this->getRight()->evaluate();
|
||||||
t=this->coerceTypes(l->getSimpleVarType(), r->getSimpleVarType());
|
enum TYPES lt=l->getSimpleVarType();
|
||||||
|
enum TYPES rt=r->getSimpleVarType();
|
||||||
|
if (lt==T_INTVAR && rt==T_FLOATVAR)
|
||||||
|
{
|
||||||
|
l=new 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();
|
||||||
|
rt=T_FLOATVAR;
|
||||||
|
}
|
||||||
|
if (lt!=rt)error(E_TYPE_MISMATCH);
|
||||||
|
t=lt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -208,13 +197,20 @@ operands *expression::evaluate()
|
|||||||
output_cpp << this->op->boxName() << "= -" << l->boxName() << ";\n";
|
output_cpp << this->op->boxName() << "= -" << l->boxName() << ";\n";
|
||||||
break;
|
break;
|
||||||
case O_NOT:
|
case O_NOT:
|
||||||
this->op=new operands(t);
|
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||||
|
this->op=new operands(T_INTVAR);
|
||||||
this->op->generateBox(scope);
|
this->op->generateBox(scope);
|
||||||
output_cpp << this->op->boxName() << "= !" << l->boxName() << ";\n";
|
output_cpp << this->op->boxName() << "= !" << l->boxName() << ";\n";
|
||||||
break;
|
break;
|
||||||
|
case O_INT_TO_FLOAT: /*Note: this duplicates functionality of variable assignment */
|
||||||
|
this->op=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 */
|
/* TODO: Check for divide by zero error and modulo zero error */
|
||||||
case O_REMAINDER:
|
case O_REMAINDER:
|
||||||
this->op=new operands(t);
|
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||||
|
this->op=new operands(T_INTVAR);
|
||||||
this->op->generateBox(scope);
|
this->op->generateBox(scope);
|
||||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "%" << r->boxName() << ";\n";
|
output_cpp << this->op->boxName() << "=" << l->boxName() << "%" << r->boxName() << ";\n";
|
||||||
break;
|
break;
|
||||||
@@ -239,22 +235,14 @@ operands *expression::evaluate()
|
|||||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "*" << r->boxName() << ";\n";
|
output_cpp << this->op->boxName() << "=" << l->boxName() << "*" << r->boxName() << ";\n";
|
||||||
break;
|
break;
|
||||||
case O_OR:
|
case O_OR:
|
||||||
if (t!=T_INTVAR)
|
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||||
{
|
this->op=new operands(T_INTVAR);
|
||||||
errorLevel=E_TYPE_MISMATCH;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
this->op=new operands(t);
|
|
||||||
this->op->generateBox(scope);
|
this->op->generateBox(scope);
|
||||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "|" << r->boxName() << ";\n";
|
output_cpp << this->op->boxName() << "=" << l->boxName() << "|" << r->boxName() << ";\n";
|
||||||
break;
|
break;
|
||||||
case O_AND:
|
case O_AND:
|
||||||
if (t!=T_INTVAR)
|
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||||
{
|
this->op=new operands(T_INTVAR);
|
||||||
errorLevel=E_TYPE_MISMATCH;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
this->op=new operands(t);
|
|
||||||
this->op->generateBox(scope);
|
this->op->generateBox(scope);
|
||||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "&" << r->boxName() << ";\n";
|
output_cpp << this->op->boxName() << "=" << l->boxName() << "&" << r->boxName() << ";\n";
|
||||||
break;
|
break;
|
||||||
@@ -349,7 +337,7 @@ expression::~expression()
|
|||||||
/* variable definitions */
|
/* variable definitions */
|
||||||
variable::variable(ostream &scope, string &name, enum TYPES t):operands(t)
|
variable::variable(ostream &scope, string &name, enum TYPES t):operands(t)
|
||||||
{
|
{
|
||||||
this->generateBox(scope);
|
this->generateBox(scope); /*TODO: FINISH THIS*/
|
||||||
}
|
}
|
||||||
|
|
||||||
variable *variable::getOrCreateVarName(string &name, enum TYPES t)
|
variable *variable::getOrCreateVarName(string &name, enum TYPES t)
|
||||||
@@ -359,8 +347,10 @@ variable *variable::getOrCreateVarName(string &name, enum TYPES t)
|
|||||||
return fn::getOrCreateVar(t, name, false);
|
return fn::getOrCreateVar(t, name, false);
|
||||||
}
|
}
|
||||||
/* TODO: verify if type is compatible */
|
/* TODO: verify if type is compatible */
|
||||||
operands op=operands::getOrCreateGlobal(name);
|
shared_ptr<operands>op=operands::getOrCreateGlobal(name);
|
||||||
return reinterpret_cast<variable *>op;
|
shared_ptr<variable>v=new variable();
|
||||||
|
v->assignment(new expression(op));
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void variable::assignment(expression *value)
|
void variable::assignment(expression *value)
|
||||||
@@ -372,25 +362,21 @@ void variable::assignment(expression *value)
|
|||||||
case T_FLOATVAR:
|
case T_FLOATVAR:
|
||||||
if (t==T_INTVAR)
|
if (t==T_INTVAR)
|
||||||
{
|
{
|
||||||
/* TODO: convert int to float */
|
output_cpp << this->boxName() << "="
|
||||||
|
<< "static_cast<double>("
|
||||||
|
<< op->boxName() << ");\n";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (t!=T_FLOATVAR)
|
if (t!=T_FLOATVAR) error(E_TYPE_MISMATCH);
|
||||||
{
|
|
||||||
errorLevel=E_TYPE_MISMATCH;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
output_cpp << this->boxName() << "="
|
||||||
|
<< op->boxName() << ";\n";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (t!=this->getType())
|
if (t!=this->getType()) error(E_TYPE_MISMATCH);
|
||||||
{
|
output_cpp << this->boxName() << "="
|
||||||
errorLevel=E_TYPE_MISMATCH;
|
<< op->boxName() << ";\n";
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
output_cpp << this->boxName() << "="
|
|
||||||
<< op->boxName() << ";\n";
|
|
||||||
}
|
}
|
||||||
|
|||||||
157
yabFunctions.cpp
157
yabFunctions.cpp
@@ -16,16 +16,159 @@ fn *fn::getCurrentSub()
|
|||||||
|
|
||||||
void fn::generateOnNSub(expression *e)
|
void fn::generateOnNSub(expression *e)
|
||||||
{
|
{
|
||||||
this->ret=new label();
|
shared_ptr<label>r=new label();
|
||||||
fn::callStack.push_back(this);
|
shared_ptr<fn> self=new fn(r);
|
||||||
|
fn::callStack.push_back(self);
|
||||||
label::generateOnNTo(e);
|
label::generateOnNTo(e);
|
||||||
output_cpp << "case " << ret->getID() << ":\n";
|
r->generate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fn::generateGosub(shared_ptr<label> sub)
|
void fn::generateGosub(shared_ptr<label> sub)
|
||||||
{
|
{
|
||||||
this->ret=new label();
|
shared_ptr<label>r=new label();
|
||||||
fn::callStack.push_back(this);
|
shared_ptr<fn> self=new fn(r);
|
||||||
output_cpp << "state=" << sub->getID() << ";\nbreak;\n";
|
fn::callStack.push_back(self);
|
||||||
output_cpp << "case " << ret->getID() << ":\n";
|
sub->generateJumpTo();
|
||||||
|
r->generate();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn::fn(shared_ptr<label>gosub):codeType(T_GOSUB)
|
||||||
|
{
|
||||||
|
this->ret=gosub;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_ptr<fn> fn::getSub(string &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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
if (paramList.size()>params.size())
|
||||||
|
{
|
||||||
|
errorLevel=E_TOO_MANY_PARAMETERS;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
output_cpp << "struct *f" << /* TODO: finish this */
|
||||||
|
<< "= new struct f" << g->getID();
|
||||||
|
while(paramList.size()>0)
|
||||||
|
{
|
||||||
|
current=paramList.front;
|
||||||
|
paramList.pop_front();
|
||||||
|
if(current->getSimpleVarType()!=*v->getType())
|
||||||
|
{
|
||||||
|
errorLevel=E_TYPE_MISMATCH;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
*v->assignment(new expression(current));
|
||||||
|
++v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g->/*TODO FINISH THIS*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void fn::generateReturn()
|
||||||
|
{
|
||||||
|
shared_ptr<fn>c=fn::getCurrent();
|
||||||
|
switch(c->getType())
|
||||||
|
{
|
||||||
|
case T_UNKNOWNFUNC:
|
||||||
|
this->kind=T_NONE;
|
||||||
|
/*fallthrough*/
|
||||||
|
case T_GOSUB:
|
||||||
|
c->ret->generateJumpTo();
|
||||||
|
fn::callStack.pop_back();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errorLevel=E_TYPE_MISMATCH;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
operands *fn::generateReturn(expression *expr)
|
||||||
|
{
|
||||||
|
operands *out=expr->evaluate();
|
||||||
|
this->kind=out->getSimpleVarType();
|
||||||
|
this->ret->generateJumpTo();
|
||||||
|
fn::callStack.pop_back();
|
||||||
|
switch (this->getType())
|
||||||
|
{
|
||||||
|
case T_UNKNOWNFUNC:
|
||||||
|
return out;
|
||||||
|
case T_STRINGFUNC:
|
||||||
|
if (kind!=T_STRINGVAR)
|
||||||
|
{
|
||||||
|
errorLevel=E_TYPE_MISMATCH;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
case T_INTFUNC:
|
||||||
|
if (kind!=T_INTVAR&&kind!=T_FLOATVAR)
|
||||||
|
{
|
||||||
|
errorLevel=E_TYPE_MISMATCH;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
case T_FLOATFUNC:
|
||||||
|
if(kind!=T_FLOATVAR)
|
||||||
|
{
|
||||||
|
errorLevel=E_TYPE_MISMATCH;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
case T_GOSUB:
|
||||||
|
{
|
||||||
|
errorLevel=E_GOSUB_CANNOT_RETURN_VALUE;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
errorLevel=E_BAD_SYNTAX;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* not allowed in function definitions directly */
|
||||||
|
void fn::generateBreak()
|
||||||
|
{
|
||||||
|
error(E_BAD_SYNTAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fn::close()
|
||||||
|
{
|
||||||
|
/* check if no returns and no return type */
|
||||||
|
enum CODES t=this->getType();
|
||||||
|
if (this->kind==T_UNKNOWN&&
|
||||||
|
(t==T_UNKNOWNFUNC||t==T_VOIDFUNC))
|
||||||
|
{
|
||||||
|
/* generate a typeless return */
|
||||||
|
this->generateReturn()
|
||||||
|
}
|
||||||
|
funcs_h << "};\n";
|
||||||
|
fn::locals.clear();
|
||||||
|
fn::statics.clear();
|
||||||
|
this->params.clear();
|
||||||
|
scopeGlobal=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
this->id= ++nextID;
|
||||||
|
funcs_h << "struct f" << this->id <<"\n{\n";
|
||||||
|
this->ret=new label();
|
||||||
|
fn::functions[s]=this;
|
||||||
|
scopeGlobal=false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user