|
@@ -24,6 +24,7 @@ static FunctionMap functions;
|
|
|
|
|
|
static int returns[RETURN_BUFFER];
|
|
static int returns[RETURN_BUFFER];
|
|
static int returnIndex = 0;
|
|
static int returnIndex = 0;
|
|
|
|
+static int returnState = 0;
|
|
|
|
|
|
static void cError(const char* format, ...) {
|
|
static void cError(const char* format, ...) {
|
|
va_list args;
|
|
va_list args;
|
|
@@ -69,14 +70,14 @@ static void cAddFloat(float f) {
|
|
}
|
|
}
|
|
|
|
|
|
static int cAddPush(int offset) {
|
|
static int cAddPush(int offset) {
|
|
- cAddOperation(OP_PUSH);
|
|
|
|
|
|
+ cAddOperation(OP_PUSH_VARS);
|
|
int p = cReserveInt();
|
|
int p = cReserveInt();
|
|
cAddInt(offset);
|
|
cAddInt(offset);
|
|
return p;
|
|
return p;
|
|
}
|
|
}
|
|
|
|
|
|
static void cAddPop(int p, int vars) {
|
|
static void cAddPop(int p, int vars) {
|
|
- cAddOperation(OP_POP);
|
|
|
|
|
|
+ cAddOperation(OP_POP_VARS);
|
|
cAddInt(vars);
|
|
cAddInt(vars);
|
|
cSetInt(p, vars);
|
|
cSetInt(p, vars);
|
|
}
|
|
}
|
|
@@ -149,24 +150,29 @@ static int cCallFunctionArguments() {
|
|
return arguments;
|
|
return arguments;
|
|
}
|
|
}
|
|
|
|
|
|
-static void cCallFunction(const char* literal) {
|
|
|
|
|
|
+static void cCallFunction(const char* literal, bool noReturn) {
|
|
cAddOperation(OP_PUSH_INT);
|
|
cAddOperation(OP_PUSH_INT);
|
|
cAddInt(0);
|
|
cAddInt(0);
|
|
int arguments = cCallFunctionArguments();
|
|
int arguments = cCallFunctionArguments();
|
|
- int address = fmSearchAddress(&functions, literal, arguments);
|
|
|
|
|
|
+ Function* f = fmSearch(&functions, literal, arguments);
|
|
cAddOperation(OP_GOSUB);
|
|
cAddOperation(OP_GOSUB);
|
|
- if(address == -1) {
|
|
|
|
- fmEnqueue(&functions, literal, arguments, line, cReserveInt());
|
|
|
|
|
|
+ if(f == NULL) {
|
|
|
|
+ fmEnqueue(&functions, literal, arguments, line, cReserveInt(), noReturn);
|
|
|
|
+ cAddInt(arguments);
|
|
|
|
+ cAddOperation(OP_NOTHING);
|
|
} else {
|
|
} else {
|
|
- cAddInt(address);
|
|
|
|
|
|
+ cAddInt(f->address);
|
|
|
|
+ cAddInt(arguments);
|
|
|
|
+ if(f->returns && noReturn) {
|
|
|
|
+ cAddOperation(OP_POP);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
- cAddInt(arguments);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void cLiteral() {
|
|
static void cLiteral() {
|
|
const char* literal = cReadString();
|
|
const char* literal = cReadString();
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
- cCallFunction(literal);
|
|
|
|
|
|
+ cCallFunction(literal, false);
|
|
} else {
|
|
} else {
|
|
cGetVar(literal);
|
|
cGetVar(literal);
|
|
}
|
|
}
|
|
@@ -222,7 +228,7 @@ static void cLineLiteral() {
|
|
switch(t) {
|
|
switch(t) {
|
|
case T_SET: cSetVar(literal); break;
|
|
case T_SET: cSetVar(literal); break;
|
|
case T_OPEN_BRACKET:
|
|
case T_OPEN_BRACKET:
|
|
- cCallFunction(literal);
|
|
|
|
|
|
+ cCallFunction(literal, true);
|
|
cConsumeToken(T_SEMICOLON);
|
|
cConsumeToken(T_SEMICOLON);
|
|
break;
|
|
break;
|
|
default: cUnexpectedToken(t);
|
|
default: cUnexpectedToken(t);
|
|
@@ -266,10 +272,12 @@ static void cFunctionBody(const char* name, int arguments) {
|
|
cAddOperation(OP_GOTO);
|
|
cAddOperation(OP_GOTO);
|
|
int gotoIndex = cReserveInt();
|
|
int gotoIndex = cReserveInt();
|
|
|
|
|
|
- if(!fmAdd(&functions, name, arguments, code->length)) {
|
|
|
|
|
|
+ int address = code->length;
|
|
|
|
+ returnState = 0;
|
|
|
|
+ cFunctionInnerBody(arguments);
|
|
|
|
+ if(!fmAdd(&functions, name, arguments, address, returnState == 2)) {
|
|
cError("function registered twice on line %d", line);
|
|
cError("function registered twice on line %d", line);
|
|
}
|
|
}
|
|
- cFunctionInnerBody(arguments);
|
|
|
|
|
|
|
|
cAddOperation(OP_RETURN);
|
|
cAddOperation(OP_RETURN);
|
|
cSetInt(gotoIndex, code->length);
|
|
cSetInt(gotoIndex, code->length);
|
|
@@ -288,19 +296,34 @@ static void cFunction() {
|
|
varIndex = 0;
|
|
varIndex = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void cAddReturn() {
|
|
|
|
+ cAddOperation(OP_POP_VARS);
|
|
|
|
+ returns[returnIndex++] = cReserveInt(vars);
|
|
|
|
+ cAddOperation(OP_RETURN);
|
|
|
|
+}
|
|
|
|
+
|
|
static void cReturn() {
|
|
static void cReturn() {
|
|
if(varIndex == 0) {
|
|
if(varIndex == 0) {
|
|
cError("return without a function on line %d", line);
|
|
cError("return without a function on line %d", line);
|
|
} else if(returnIndex >= RETURN_BUFFER) {
|
|
} else if(returnIndex >= RETURN_BUFFER) {
|
|
cError("too much returns in function around line %d", line);
|
|
cError("too much returns in function around line %d", line);
|
|
- } else if(tPeekToken() != T_SEMICOLON) {
|
|
|
|
|
|
+ }
|
|
|
|
+ if(cConsumeTokenIf(T_SEMICOLON)) {
|
|
|
|
+ if(returnState == 2) {
|
|
|
|
+ cError("mixed return type on line %d", line);
|
|
|
|
+ }
|
|
|
|
+ returnState = 1;
|
|
|
|
+ cAddReturn();
|
|
|
|
+ } else {
|
|
|
|
+ if(returnState == 1) {
|
|
|
|
+ cError("mixed return type on line %d", line);
|
|
|
|
+ }
|
|
|
|
+ returnState = 2;
|
|
cExpression();
|
|
cExpression();
|
|
cAddOperation(OP_SET_RETURN);
|
|
cAddOperation(OP_SET_RETURN);
|
|
|
|
+ cAddReturn();
|
|
|
|
+ cConsumeToken(T_SEMICOLON);
|
|
}
|
|
}
|
|
- cAddOperation(OP_POP);
|
|
|
|
- returns[returnIndex++] = cReserveInt(vars);
|
|
|
|
- cAddOperation(OP_RETURN);
|
|
|
|
- cConsumeToken(T_SEMICOLON);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
static void cPrint() {
|
|
static void cPrint() {
|
|
@@ -331,11 +354,14 @@ static void cForEachLine() {
|
|
|
|
|
|
static void cLinkQueuedFunctions() {
|
|
static void cLinkQueuedFunctions() {
|
|
for(int i = 0; i < functions.queueEntries; i++) {
|
|
for(int i = 0; i < functions.queueEntries; i++) {
|
|
- int address = fmSearchAddress(&functions, functions.queue[i].name, functions.queue[i].arguments);
|
|
|
|
- if(address == -1) {
|
|
|
|
|
|
+ Function* f = fmSearch(&functions, functions.queue[i].name, functions.queue[i].arguments);
|
|
|
|
+ if(f == NULL) {
|
|
cError("unknown function on line %d", functions.queue[i].line);
|
|
cError("unknown function on line %d", functions.queue[i].line);
|
|
}
|
|
}
|
|
- cSetInt(functions.queue[i].reserved, address);
|
|
|
|
|
|
+ cSetInt(functions.queue[i].reserved, f->address);
|
|
|
|
+ if(functions.queue[i].noReturn && f->returns) {
|
|
|
|
+ code->code[functions.queue[i].reserved + sizeof(int) * 2] = OP_POP;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|