|
@@ -130,13 +130,48 @@ static const char* cReadString() {
|
|
return literal;
|
|
return literal;
|
|
}
|
|
}
|
|
|
|
|
|
-static void cGetVar() {
|
|
|
|
|
|
+static void cGetVar(const char* var) {
|
|
cAddOperation(OP_GET);
|
|
cAddOperation(OP_GET);
|
|
- cAddInt(cAddVar(cReadString()));
|
|
|
|
|
|
+ cAddInt(cAddVar(var));
|
|
}
|
|
}
|
|
|
|
|
|
static void cExpression();
|
|
static void cExpression();
|
|
|
|
|
|
|
|
+static int cCallFunctionArguments() {
|
|
|
|
+ int arguments = 0;
|
|
|
|
+ while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
|
+ arguments++;
|
|
|
|
+ cExpression();
|
|
|
|
+ if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) {
|
|
|
|
+ cUnexpectedToken(tPeekToken());
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return arguments;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cCallFunction(const char* literal) {
|
|
|
|
+ cAddOperation(OP_PUSH_INT);
|
|
|
|
+ cAddInt(0);
|
|
|
|
+ int arguments = cCallFunctionArguments();
|
|
|
|
+ int address = fmSearchAddress(&functions, literal, arguments);
|
|
|
|
+ cAddOperation(OP_GOSUB);
|
|
|
|
+ if(address == -1) {
|
|
|
|
+ fmEnqueue(&functions, literal, arguments, line, cReserveInt());
|
|
|
|
+ } else {
|
|
|
|
+ cAddInt(address);
|
|
|
|
+ }
|
|
|
|
+ cAddInt(arguments);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void cLiteral() {
|
|
|
|
+ const char* literal = cReadString();
|
|
|
|
+ if(cConsumeTokenIf(T_OPEN_BRACKET)) {
|
|
|
|
+ cCallFunction(literal);
|
|
|
|
+ } else {
|
|
|
|
+ cGetVar(literal);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
static void cPrimary() {
|
|
static void cPrimary() {
|
|
Token t = cReadTokenAndLine();
|
|
Token t = cReadTokenAndLine();
|
|
switch(t) {
|
|
switch(t) {
|
|
@@ -149,7 +184,7 @@ static void cPrimary() {
|
|
cExpression();
|
|
cExpression();
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
cConsumeToken(T_CLOSE_BRACKET);
|
|
break;
|
|
break;
|
|
- case T_LITERAL: cGetVar(); break;
|
|
|
|
|
|
+ case T_LITERAL: cLiteral(); break;
|
|
default: cUnexpectedToken(t); break;
|
|
default: cUnexpectedToken(t); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -181,39 +216,15 @@ static void cSetVar(const char* literal) {
|
|
cAddInt(cAddVar(literal));
|
|
cAddInt(cAddVar(literal));
|
|
}
|
|
}
|
|
|
|
|
|
-static int cCallFunctionArguments() {
|
|
|
|
- int arguments = 0;
|
|
|
|
- while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
|
|
|
|
- arguments++;
|
|
|
|
- cExpression();
|
|
|
|
- if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) {
|
|
|
|
- cUnexpectedToken(tPeekToken());
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- return arguments;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void cCallFunction(const char* literal) {
|
|
|
|
- cAddOperation(OP_PUSH_INT);
|
|
|
|
- cAddInt(0);
|
|
|
|
- int arguments = cCallFunctionArguments();
|
|
|
|
- int address = fmSearchAddress(&functions, literal, arguments);
|
|
|
|
- cAddOperation(OP_GOSUB);
|
|
|
|
- if(address == -1) {
|
|
|
|
- fmEnqueue(&functions, literal, arguments, line, cReserveInt());
|
|
|
|
- } else {
|
|
|
|
- cAddInt(address);
|
|
|
|
- }
|
|
|
|
- cAddInt(arguments);
|
|
|
|
- cConsumeToken(T_SEMICOLON);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-static void cLiteral() {
|
|
|
|
|
|
+static void cLineLiteral() {
|
|
const char* literal = cReadString();
|
|
const char* literal = cReadString();
|
|
Token t = cReadTokenAndLine();
|
|
Token t = cReadTokenAndLine();
|
|
switch(t) {
|
|
switch(t) {
|
|
case T_SET: cSetVar(literal); break;
|
|
case T_SET: cSetVar(literal); break;
|
|
- case T_OPEN_BRACKET: cCallFunction(literal); break;
|
|
|
|
|
|
+ case T_OPEN_BRACKET:
|
|
|
|
+ cCallFunction(literal);
|
|
|
|
+ cConsumeToken(T_SEMICOLON);
|
|
|
|
+ break;
|
|
default: cUnexpectedToken(t);
|
|
default: cUnexpectedToken(t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -282,6 +293,9 @@ static void cReturn() {
|
|
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) {
|
|
|
|
+ cExpression();
|
|
|
|
+ cAddOperation(OP_SET_RETURN);
|
|
}
|
|
}
|
|
cAddOperation(OP_POP);
|
|
cAddOperation(OP_POP);
|
|
returns[returnIndex++] = cReserveInt(vars);
|
|
returns[returnIndex++] = cReserveInt(vars);
|
|
@@ -300,7 +314,7 @@ static void cLine(Token t) {
|
|
cAddInt16(line);
|
|
cAddInt16(line);
|
|
switch(t) {
|
|
switch(t) {
|
|
case T_PRINT: cPrint(); break;
|
|
case T_PRINT: cPrint(); break;
|
|
- case T_LITERAL: cLiteral(); break;
|
|
|
|
|
|
+ case T_LITERAL: cLineLiteral(); break;
|
|
case T_FUNCTION: cFunction(); break;
|
|
case T_FUNCTION: cFunction(); break;
|
|
case T_RETURN: cReturn(); break;
|
|
case T_RETURN: cReturn(); break;
|
|
default: cUnexpectedToken(t);
|
|
default: cUnexpectedToken(t);
|