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_STACK_UNDERFLOW,
|
||||
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;
|
||||
@@ -56,11 +61,14 @@ const char *COMPILE_ERROR_NAMES[]={
|
||||
"failed allocation",
|
||||
"stack underflow",
|
||||
"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
|
||||
(must be powers of 2) */
|
||||
#define COMPILE 1
|
||||
@@ -70,7 +78,8 @@ extern enum COMPILEERRORS errorLevel;
|
||||
/* list of all variable and constant types */
|
||||
enum TYPES
|
||||
{
|
||||
T_NONE=0,
|
||||
T_UNKNOWN=0,
|
||||
T_NONE,
|
||||
T_STRING,
|
||||
T_INT,
|
||||
T_FLOAT,
|
||||
@@ -80,6 +89,7 @@ enum TYPES
|
||||
T_INTCALL_ARRAY,
|
||||
T_FLOATCALL_ARRAY,
|
||||
T_STRINGCALL_ARRAY,
|
||||
T_VOIDCALL
|
||||
}
|
||||
/* list of all kinds of other code structures */
|
||||
enum CODES
|
||||
@@ -97,11 +107,17 @@ enum CODES
|
||||
T_ASSIGNMENT,
|
||||
T_LABEL,
|
||||
T_PARAMLIST,
|
||||
T_DATAITEM
|
||||
T_DATAITEM,
|
||||
T_STRINGFUNC,
|
||||
T_FLOATFUNC,
|
||||
T_INTFUNC,
|
||||
T_VOIDFUNC,
|
||||
T_UNKNOWNFUNC
|
||||
};
|
||||
|
||||
/* These correspond to the types of enum TYPES. */
|
||||
const string TYPENAMES[]={
|
||||
"unknown",
|
||||
"none",
|
||||
"string constant",
|
||||
"integer constant",
|
||||
@@ -111,7 +127,9 @@ const string TYPENAMES[]={
|
||||
"floating point variable",
|
||||
"string 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[]={
|
||||
@@ -127,7 +145,12 @@ const string CODETYPES[]={
|
||||
"assignment",
|
||||
"label",
|
||||
"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
|
||||
@@ -165,25 +188,30 @@ enum OPERATORS
|
||||
O_OR,
|
||||
O_AND,
|
||||
O_STRING_CONCAT,
|
||||
O_INT_TO_FLOAT,
|
||||
O_TERM
|
||||
};
|
||||
|
||||
/* global prototype */
|
||||
void error(enum COMPILE_ERRORS err);
|
||||
|
||||
/* internal states used by the parser */
|
||||
class operands
|
||||
{
|
||||
enum TYPES type;
|
||||
unsigned int id;
|
||||
static unsigned int nextID;
|
||||
static unordered_map<string &, operands *> globals;
|
||||
static unordered_map<string &, unsigned int> strConst;
|
||||
static unordered_map<string, operands *> globals;
|
||||
static unordered_map<string, unsigned int> strConst;
|
||||
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(ostream &k, string &s);
|
||||
static operands *createConst(ostream &k, string &s, enum TYPES t);
|
||||
static operands *getOrCreateGlobal(ostream &heap, string &s, enum TYPES t);
|
||||
static unsigned int getOrCreateStr(string &s);
|
||||
static operands *createConst(string &s, enum TYPES t);
|
||||
static operands *getOrCreateGlobal(string &s, enum TYPES t);
|
||||
|
||||
enum TYPES getSimpleVarType();
|
||||
void generateBox(ostream &scope);
|
||||
@@ -223,19 +251,17 @@ public:
|
||||
op=x;
|
||||
oper=O_TERM;
|
||||
}
|
||||
/*TODO: Recycle temporary variables when not in debug mode*/
|
||||
virtual ~expression();
|
||||
};
|
||||
|
||||
/* parent class of all code types */
|
||||
class codeType
|
||||
{
|
||||
unsigned int id;
|
||||
enum CODES type;
|
||||
static unsigned int nextID;
|
||||
static list<codeType *> nesting;
|
||||
public:
|
||||
enum CODES getType() const {return this->type;}
|
||||
unsigned int getID() const {return this->id;}
|
||||
|
||||
static codeType *getCurrent();
|
||||
|
||||
@@ -258,7 +284,7 @@ public:
|
||||
unsigned int getID() const {return id;}
|
||||
|
||||
void generateJumpTo();
|
||||
void generateOnNSkip(ostream &k, list<label *> &dest);
|
||||
void generateOnNSkip(list<shared_ptr<label> >dest);
|
||||
void generateOnNTo(expression *e);
|
||||
void generateCondJump(expression *e);
|
||||
void generate();
|
||||
@@ -313,7 +339,7 @@ public:
|
||||
virtual void generateBreak() override;
|
||||
virtual void close() override;
|
||||
|
||||
explicit doLoop():codeType(T_DOLOOP);
|
||||
explicit doLoop();
|
||||
virtual ~doLoop();
|
||||
};
|
||||
|
||||
@@ -327,14 +353,15 @@ public:
|
||||
virtual void generateBreak() override;
|
||||
virtual void close() override;
|
||||
|
||||
explicit whileLoop(expression *e):codeType(T_WHILELOOP);
|
||||
explicit whileLoop(expression *e);
|
||||
virtual ~whileLoop();
|
||||
};
|
||||
|
||||
class variable:public operands
|
||||
{
|
||||
ostream &myScope;
|
||||
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);
|
||||
explicit variable(ostream &scope, string &name, enum TYPES t);
|
||||
@@ -348,7 +375,7 @@ class arrayType:public variable
|
||||
public:
|
||||
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()
|
||||
{}
|
||||
};
|
||||
@@ -364,37 +391,46 @@ public:
|
||||
virtual void generateBreak();
|
||||
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();
|
||||
};
|
||||
|
||||
class fn:codeType
|
||||
{
|
||||
static unordered_map<string, operands *>locals;
|
||||
static unordered_map<string, operands *>statics;
|
||||
static unordered_map<string, fn>functions;
|
||||
static list<fn *> callStack;
|
||||
static unordered_map<string, shared_ptr<variable> >locals;
|
||||
static unordered_map<string, shared_ptr<variable> >statics;
|
||||
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<label>startAddr;
|
||||
shared_ptr<label>ret;
|
||||
unsigned int parameters;
|
||||
/* private constructor used by generateGosub and generateOnNSub*/
|
||||
fn(label *gosub);
|
||||
public:
|
||||
static variable *getOrCreateVar(enum TYPES t, string &s, bool stat);
|
||||
static void dumpCallStack();
|
||||
static fn *getCurrentSub();
|
||||
|
||||
void setParameters(unsigned int num) const {this->parameters=num;}
|
||||
|
||||
void generateCall(string &name, unsigned int params);
|
||||
void generateReturn(expression *expr=NULL);
|
||||
void generateGosub(shared_ptr<label> sub);
|
||||
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 */
|
||||
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 close();
|
||||
|
||||
fn(string &name);
|
||||
fn(label *gosub);
|
||||
virtual ~fn();
|
||||
fn(string &name, enum CODES t);
|
||||
virtual ~fn()
|
||||
{}
|
||||
};
|
||||
|
||||
/* The next two structures are used to implement the PRINT statement. */
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
/* base class of all the code structure types */
|
||||
codeType::codeType(enum CODES t)
|
||||
{
|
||||
this->id= ++nextID;
|
||||
nesting.push_back(this);
|
||||
this->type=t;
|
||||
}
|
||||
@@ -48,7 +47,7 @@ void label::generateJumpTo()
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,16 @@
|
||||
#include "yab2cpp.h"
|
||||
|
||||
/* 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()
|
||||
{
|
||||
varNames << "Global Variables\n";
|
||||
@@ -48,7 +58,7 @@ unsigned int operands::createConst(string &s, enum TYPES t)
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
k << me->getID() << "=" << s << ";\n";
|
||||
consts_h << me->getID() << "=" << s << ";\n";
|
||||
return me;
|
||||
}
|
||||
|
||||
@@ -69,40 +79,7 @@ enum TYPES operands::getSimpleVarType()
|
||||
case T_STRINGVAR:
|
||||
return T_STRINGVAR;
|
||||
}
|
||||
return T_NONE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
error(E_UNASSIGNABLE_TYPE);
|
||||
}
|
||||
|
||||
/* operands used by expression parser and variables */
|
||||
@@ -154,9 +131,7 @@ void operands::boxName(ostream &scope)
|
||||
break;
|
||||
|
||||
default:
|
||||
errorLevel=E_INTERNAL;
|
||||
exit(1);
|
||||
break;
|
||||
error(E_INTERNAL);
|
||||
}
|
||||
scope << "v" << this->getID();
|
||||
}
|
||||
@@ -171,6 +146,7 @@ bool expression::isBinOp()
|
||||
case O_NEGATE:
|
||||
case O_NOT:
|
||||
case O_INVERT:
|
||||
case O_INT_TO_FLOAT:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
@@ -187,7 +163,20 @@ operands *expression::evaluate()
|
||||
if (this->isBinOp())
|
||||
{
|
||||
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
|
||||
{
|
||||
@@ -208,13 +197,20 @@ operands *expression::evaluate()
|
||||
output_cpp << this->op->boxName() << "= -" << l->boxName() << ";\n";
|
||||
break;
|
||||
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);
|
||||
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->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:
|
||||
this->op=new operands(t);
|
||||
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "%" << r->boxName() << ";\n";
|
||||
break;
|
||||
@@ -239,22 +235,14 @@ operands *expression::evaluate()
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "*" << r->boxName() << ";\n";
|
||||
break;
|
||||
case O_OR:
|
||||
if (t!=T_INTVAR)
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
this->op=new operands(t);
|
||||
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||
this->op=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)
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
this->op=new operands(t);
|
||||
if (t!=T_INTVAR) error(E_TYPE_MISMATCH);
|
||||
this->op=new operands(T_INTVAR);
|
||||
this->op->generateBox(scope);
|
||||
output_cpp << this->op->boxName() << "=" << l->boxName() << "&" << r->boxName() << ";\n";
|
||||
break;
|
||||
@@ -349,7 +337,7 @@ expression::~expression()
|
||||
/* variable definitions */
|
||||
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)
|
||||
@@ -359,8 +347,10 @@ variable *variable::getOrCreateVarName(string &name, enum TYPES t)
|
||||
return fn::getOrCreateVar(t, name, false);
|
||||
}
|
||||
/* TODO: verify if type is compatible */
|
||||
operands op=operands::getOrCreateGlobal(name);
|
||||
return reinterpret_cast<variable *>op;
|
||||
shared_ptr<operands>op=operands::getOrCreateGlobal(name);
|
||||
shared_ptr<variable>v=new variable();
|
||||
v->assignment(new expression(op));
|
||||
return v;
|
||||
}
|
||||
|
||||
void variable::assignment(expression *value)
|
||||
@@ -372,25 +362,21 @@ void variable::assignment(expression *value)
|
||||
case T_FLOATVAR:
|
||||
if (t==T_INTVAR)
|
||||
{
|
||||
/* TODO: convert int to float */
|
||||
output_cpp << this->boxName() << "="
|
||||
<< "static_cast<double>("
|
||||
<< op->boxName() << ");\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t!=T_FLOATVAR)
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
if (t!=T_FLOATVAR) error(E_TYPE_MISMATCH);
|
||||
}
|
||||
output_cpp << this->boxName() << "="
|
||||
<< op->boxName() << ";\n";
|
||||
break;
|
||||
default:
|
||||
if (t!=this->getType())
|
||||
{
|
||||
errorLevel=E_TYPE_MISMATCH;
|
||||
exit(1);
|
||||
}
|
||||
if (t!=this->getType()) error(E_TYPE_MISMATCH);
|
||||
output_cpp << this->boxName() << "="
|
||||
<< op->boxName() << ";\n";
|
||||
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)
|
||||
{
|
||||
this->ret=new label();
|
||||
fn::callStack.push_back(this);
|
||||
shared_ptr<label>r=new label();
|
||||
shared_ptr<fn> self=new fn(r);
|
||||
fn::callStack.push_back(self);
|
||||
label::generateOnNTo(e);
|
||||
output_cpp << "case " << ret->getID() << ":\n";
|
||||
r->generate();
|
||||
}
|
||||
|
||||
void fn::generateGosub(shared_ptr<label> sub)
|
||||
{
|
||||
this->ret=new label();
|
||||
fn::callStack.push_back(this);
|
||||
output_cpp << "state=" << sub->getID() << ";\nbreak;\n";
|
||||
output_cpp << "case " << ret->getID() << ":\n";
|
||||
shared_ptr<label>r=new label();
|
||||
shared_ptr<fn> self=new fn(r);
|
||||
fn::callStack.push_back(self);
|
||||
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