|
@@ -172,17 +172,27 @@ static bool cSetVar(const char* literal) {
|
|
|
return b;
|
|
|
}
|
|
|
|
|
|
-static bool cCallFunction(const char* literal) {
|
|
|
+static int cCallFunctionArguments() {
|
|
|
int arguments = 0;
|
|
|
while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
arguments++;
|
|
|
if(!cExpression()) {
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
} else if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) {
|
|
|
cUnexpectedToken(tPeekToken());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
+ return arguments;
|
|
|
+}
|
|
|
+
|
|
|
+static bool cCallFunction(const char* literal) {
|
|
|
+ cAddOperation(OP_PUSH_INT);
|
|
|
+ cAddInt(0);
|
|
|
+ int arguments = cCallFunctionArguments();
|
|
|
+ if(arguments == -1) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
int address = fmSearchAddress(&functions, literal, arguments);
|
|
|
if(address == -1) {
|
|
|
cError("unknown function on line %d", line);
|
|
@@ -210,57 +220,30 @@ static bool cLiteral() {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
-static bool cLine();
|
|
|
-
|
|
|
-static bool cFunction() {
|
|
|
- if(varIndex == 1) {
|
|
|
- cError("function inside function on line %d", line);
|
|
|
- return false;
|
|
|
- }
|
|
|
- if(!cConsumeToken(T_LITERAL)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- const char* name = tReadString();
|
|
|
- if(name == NULL) {
|
|
|
- cError("function literal without a function name on line %d", line);
|
|
|
- return false;
|
|
|
- }
|
|
|
- if(!cConsumeToken(T_OPEN_BRACKET)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- varIndex = 1;
|
|
|
- vars[1].entries = 0;
|
|
|
-
|
|
|
+static int cFunctionArguments() {
|
|
|
int arguments = 0;
|
|
|
while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
if(!cConsumeToken(T_LITERAL)) {
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
arguments++;
|
|
|
const char* arg = tReadString();
|
|
|
if(arg == NULL) {
|
|
|
cError("function argument literal without string on line %d", line);
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
cAddVar(arg);
|
|
|
if(cConsumeTokenIf(T_COMMA) && tPeekToken() != T_LITERAL) {
|
|
|
cUnexpectedToken(tPeekToken());
|
|
|
- return false;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
+ return arguments;
|
|
|
+}
|
|
|
|
|
|
- if(!cConsumeToken(T_OPEN_CURVED_BRACKET)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- cAddOperation(OP_GOTO);
|
|
|
- int gotoIndex = cReserveInt();
|
|
|
-
|
|
|
- if(!fmAdd(&functions, name, arguments, code->length)) {
|
|
|
- cError("function registered twice on line %d", line);
|
|
|
- return false;
|
|
|
- }
|
|
|
+static bool cLine();
|
|
|
|
|
|
+static bool cFunctionInnerBody(int arguments) {
|
|
|
cAddOperation(OP_PUSH);
|
|
|
int pushIndex = cReserveInt();
|
|
|
cAddInt(arguments);
|
|
@@ -270,22 +253,61 @@ static bool cFunction() {
|
|
|
if(cConsumeTokenIf(T_END)) {
|
|
|
cError("unexpected end of file: function not closed on line %d", oldLine);
|
|
|
return false;
|
|
|
- }
|
|
|
- if(!cLine()) {
|
|
|
+ } else if(!cLine()) {
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- varIndex = 0;
|
|
|
cAddOperation(OP_POP);
|
|
|
cAddInt(vars[1].entries);
|
|
|
cSetInt(pushIndex, vars[1].entries);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+static bool cFunctionBody(const char* name, int arguments) {
|
|
|
+ if(!cConsumeToken(T_OPEN_CURVED_BRACKET)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ cAddOperation(OP_GOTO);
|
|
|
+ int gotoIndex = cReserveInt();
|
|
|
+
|
|
|
+ if(!fmAdd(&functions, name, arguments, code->length)) {
|
|
|
+ cError("function registered twice on line %d", line);
|
|
|
+ return false;
|
|
|
+ } else if(!cFunctionInnerBody(arguments)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
|
|
|
cAddOperation(OP_RETURN);
|
|
|
cSetInt(gotoIndex, code->length);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+static bool cFunction() {
|
|
|
+ if(varIndex == 1) {
|
|
|
+ cError("function inside function on line %d", line);
|
|
|
+ return false;
|
|
|
+ } else if(!cConsumeToken(T_LITERAL)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ const char* name = tReadString();
|
|
|
+ if(name == NULL) {
|
|
|
+ cError("function literal without a function name on line %d", line);
|
|
|
+ return false;
|
|
|
+ } else if(!cConsumeToken(T_OPEN_BRACKET)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ varIndex = 1;
|
|
|
+ vars[1].entries = 0;
|
|
|
+ int arguments = cFunctionArguments();
|
|
|
+ if(arguments == -1 || !cFunctionBody(name, arguments)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ varIndex = 0;
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
static bool cPrint() {
|
|
|
bool b = cExpression() && cConsumeToken(T_SEMICOLON);
|
|
|
cAddOperation(OP_PRINT);
|