Ver código fonte

function vars have own scope (own storage on the stack)

Kajetan Johannes Hammerle 4 anos atrás
pai
commit
8c544a56ce
5 arquivos alterados com 66 adições e 16 exclusões
  1. 26 13
      Compiler.c
  2. 13 3
      Script.c
  3. 1 0
      Script.h
  4. 18 0
      tests/functions/scope
  5. 8 0
      tests/functions/scope.out

+ 26 - 13
Compiler.c

@@ -16,9 +16,8 @@ static ByteCode* code;
 
 static int16 line = 1;
 
-static StringIntMap vars;
 static int varIndex = 0;
-
+static StringIntMap vars[2];
 static StringIntMap functions;
 
 static void cError(const char* format, ...) {
@@ -29,10 +28,8 @@ static void cError(const char* format, ...) {
 }
 
 static int cAddVar(const char* var) {
-    int index = varIndex;
-    if(simAdd(&vars, var, &index)) {
-        varIndex++;
-    }
+    int index = vars[varIndex].entries;
+    simAdd(vars + varIndex, var, &index);
     return index;
 }
 
@@ -205,6 +202,10 @@ static bool cLiteral() {
 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;
     }
@@ -217,7 +218,7 @@ static bool cFunction() {
         return false;
     }
     cAddOperation(OP_GOTO);
-    int p = cReserveInt();
+    int gotoIndex = cReserveInt();
 
     int functionIndex = code->length;
     if(!simAdd(&functions, name, &functionIndex)) {
@@ -225,6 +226,11 @@ static bool cFunction() {
         return false;
     }
 
+    varIndex = 1;
+    vars[1].entries = 0;
+    cAddOperation(OP_PUSH);
+    int pushIndex = cReserveInt();
+
     int oldLine = line;
     while(!cConsumeTokenIf(T_CLOSE_CURVED_BRACKET)) {
         if(cConsumeTokenIf(T_END)) {
@@ -233,8 +239,14 @@ static bool cFunction() {
         }
         cLine();
     }
+
+    varIndex = 0;
+    cAddOperation(OP_POP);
+    cAddInt(vars[1].entries);
+    cSetInt(pushIndex, vars[1].entries);
+
     cAddOperation(OP_RETURN);
-    cSetInt(p, code->length);
+    cSetInt(gotoIndex, code->length);
     return true;
 }
 
@@ -263,22 +275,23 @@ static bool cLine() {
 }
 
 static void cForEachLine() {
-    varIndex = 0;
     cAddOperation(OP_PUSH);
     int globalVars = cReserveInt();
     while(cLine()) {
     }
     cAddOperation(OP_POP);
-    cSetInt(globalVars, varIndex);
-    cAddInt(varIndex);
+    cSetInt(globalVars, vars[varIndex].entries);
+    cAddInt(vars[varIndex].entries);
 }
 
 static void cAllocAndCompile() {
-    simInit(&vars);
+    simInit(vars);
+    simInit(vars + 1);
     simInit(&functions);
     cForEachLine();
     simDelete(&functions);
-    simDelete(&vars);
+    simDelete(vars + 1);
+    simDelete(vars);
 }
 
 ByteCode* cCompile() {

+ 13 - 3
Script.c

@@ -87,15 +87,24 @@ static void sPushBool(Script* sc, bool value) {
 static void sPushVars(Script* sc) {
     int value = 0;
     if(sReadInt(sc, &value)) {
+        int stackVarIndex = sc->stackVarIndex;
+        sc->stackVarIndex = sc->stackIndex;
         for(int i = 0; i < value; i++) {
             sPushNull(sc);
         }
+        sPushInt(sc, stackVarIndex);
     }
 }
 
 static void sPopVars(Script* sc) {
     int value = 0;
-    if(sReadInt(sc, &value)) {
+    Object o;
+    if(sReadInt(sc, &value) && !sPop(sc, &o)) {
+        if(o.type != OT_INT) {
+            sError(sc, "stack variable index has wrong type");
+            return;
+        }
+        sc->stackVarIndex = o.data.intValue;
         if(sc->stackIndex < value) {
             sError(sc, "stack underflow on line %d", sc->line);
         } else {
@@ -107,14 +116,14 @@ static void sPopVars(Script* sc) {
 static void sSet(Script* sc) {
     int value = 0;
     if(sReadInt(sc, &value)) {
-        sPop(sc, sc->stack + value);
+        sPop(sc, sc->stack + value + sc->stackVarIndex);
     }
 }
 
 static void sGet(Script* sc) {
     int value = 0;
     if(sReadInt(sc, &value)) {
-        sPush(sc, sc->stack + value);
+        sPush(sc, sc->stack + value + sc->stackVarIndex);
     }
 }
 
@@ -247,6 +256,7 @@ Script* sInit(ByteCode* code) {
     sc->code = code;
     sc->readIndex = 0;
     sc->stackIndex = 0;
+    sc->stackVarIndex = 0;
     sc->line = 0;
     return sc;
 }

+ 1 - 0
Script.h

@@ -15,6 +15,7 @@ typedef struct Script {
     int readIndex;
     Object stack[SCRIPT_STACK_SIZE];
     int stackIndex;
+    int stackVarIndex;
     int line;
 } Script;
 

+ 18 - 0
tests/functions/scope

@@ -0,0 +1,18 @@
+a = 2;
+b = 3;
+print a;
+print b;
+
+function test() {
+    print a;
+    print b;
+    a = 4;
+    b = 5;
+    print a;
+    print b;
+}
+
+test();
+
+print a;
+print b;

+ 8 - 0
tests/functions/scope.out

@@ -0,0 +1,8 @@
+2
+3
+null
+null
+4
+5
+2
+3