Kajetan Johannes Hammerle 4 anos atrás
pai
commit
3a58c4a19c
2 arquivos alterados com 70 adições e 63 exclusões
  1. 63 41
      Compiler.c
  2. 7 22
      Script.c

+ 63 - 41
Compiler.c

@@ -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);

+ 7 - 22
Script.c

@@ -48,22 +48,6 @@ static bool sReadInt(Script* sc, int* i) {
     return !sRead(sc, i, sizeof(int));
 }
 
-static bool sShiftPush(Script* sc, Object* o, int shift) {
-    if(sc->stackIndex >= SCRIPT_STACK_SIZE) {
-        sError(sc, "stack overflow on line %d", sc->line);
-        return false;
-    } else if(sc->stackIndex < shift) {
-        sError(sc, "stack shift underflow overflow on line %d", sc->line);
-        return false;
-    }
-    for(int i = sc->stackIndex; i > sc->stackIndex - shift; i--) {
-        sc->stack[i] = sc->stack[i - 1];
-    }
-    sc->stack[sc->stackIndex - shift] = *o;
-    sc->stackIndex++;
-    return true;
-}
-
 static bool sPush(Script* sc, Object* o) {
     if(sc->stackIndex >= SCRIPT_STACK_SIZE) {
         sError(sc, "stack overflow on line %d", sc->line);
@@ -87,11 +71,6 @@ static bool sPushInt(Script* sc, int value) {
     return sPush(sc, &o);
 }
 
-static bool sShiftPushInt(Script* sc, int value, int shift) {
-    Object o = {.type = OT_INT, .data.intValue = value};
-    return sShiftPush(sc, &o, shift);
-}
-
 static void sPushFloat(Script* sc, float value) {
     Object o = {.type = OT_FLOAT, .data.floatValue = value};
     sPush(sc, &o);
@@ -233,7 +212,13 @@ static void sGoTo(Script* sc) {
 static void sGoSub(Script* sc) {
     int gotoIndex;
     int arguments;
-    if(sReadInt(sc, &gotoIndex) && sReadInt(sc, &arguments) && sShiftPushInt(sc, sc->readIndex, arguments)) {
+    if(sReadInt(sc, &gotoIndex) && sReadInt(sc, &arguments)) {
+        int returnStackIndex = sc->stackIndex - arguments - 1;
+        if(returnStackIndex < 0 || sc->stack[returnStackIndex].type != OT_INT) {
+            sError(sc, "cannot find return address entry on stack on line %d", sc->line);
+            return;
+        }
+        sc->stack[returnStackIndex].data.intValue = sc->readIndex;
         sc->readIndex = gotoIndex;
     }
 }