Kajetan Johannes Hammerle 3 years ago
parent
commit
1716f8bcaf
5 changed files with 87 additions and 3 deletions
  1. 17 0
      Compiler.c
  2. 4 3
      Tokenizer.c
  3. 1 0
      Tokenizer.h
  4. 35 0
      tests/loops/continue
  5. 30 0
      tests/loops/continue.out

+ 17 - 0
Compiler.c

@@ -30,6 +30,7 @@ static int returnState = 0;
 static int breaks[BREAK_BUFFER];
 static int breakIndex = 0;
 static int forWhileStack = 0;
+static int continueAt = 0;
 
 static void cError(const char* format, ...) {
     va_list args;
@@ -580,7 +581,10 @@ static void cWhile() {
     int ifP = cReserveInt();
     int breakStart = breakIndex;
     forWhileStack++;
+    int oldContinue = continueAt;
+    continueAt = start;
     cConsumeBody();
+    continueAt = oldContinue;
     forWhileStack--;
     cAddOperation(OP_GOTO);
     cAddInt(start);
@@ -622,7 +626,10 @@ static void cFor() {
     cSetInt(beginBody, code->length);
     int breakStart = breakIndex;
     forWhileStack++;
+    int oldContinue = continueAt;
+    continueAt = startPerLoop;
     cConsumeBody();
+    continueAt = oldContinue;
     forWhileStack--;
     cAddOperation(OP_GOTO);
     cAddInt(startPerLoop);
@@ -641,6 +648,15 @@ static void cBreak() {
     cConsumeToken(T_SEMICOLON);
 }
 
+static void cContinue() {
+    if(forWhileStack == 0) {
+        cError("continue without for or while on line %d", line);
+    }
+    cAddOperation(OP_GOTO);
+    cAddInt(continueAt);
+    cConsumeToken(T_SEMICOLON);
+}
+
 static void cLine(Token t) {
     cAddOperation(OP_LINE);
     cAddInt16(line);
@@ -652,6 +668,7 @@ static void cLine(Token t) {
         case T_WHILE: cWhile(); break;
         case T_FOR: cFor(); break;
         case T_BREAK: cBreak(); break;
+        case T_CONTINUE: cContinue(); break;
         default: cLineExpression(t); cConsumeToken(T_SEMICOLON);
     }
 }

+ 4 - 3
Tokenizer.c

@@ -22,9 +22,9 @@ typedef struct Literal {
     Token token;
 } Literal;
 
-Literal LITERALS[] = {{"print", T_PRINT},       {"null", T_NULL},     {"true", T_TRUE},  {"false", T_FALSE},
-                      {"function", T_FUNCTION}, {"return", T_RETURN}, {"if", T_IF},      {"else", T_ELSE},
-                      {"while", T_WHILE},       {"for", T_FOR},       {"break", T_BREAK}};
+Literal LITERALS[] = {{"print", T_PRINT},       {"null", T_NULL},     {"true", T_TRUE},   {"false", T_FALSE},
+                      {"function", T_FUNCTION}, {"return", T_RETURN}, {"if", T_IF},       {"else", T_ELSE},
+                      {"while", T_WHILE},       {"for", T_FOR},       {"break", T_BREAK}, {"continue", T_CONTINUE}};
 const int LITERAL_AMOUNT = sizeof(LITERALS) / sizeof(Literal);
 
 static void tError(const char* format, ...) {
@@ -314,6 +314,7 @@ const char* tGetTokenName(Token token) {
         case T_WHILE: return "while";
         case T_FOR: return "for";
         case T_BREAK: return "break";
+        case T_CONTINUE: return "continue";
         case T_FUNCTION: return "function";
         case T_RETURN: return "return";
         case T_COMMA: return ",";

+ 1 - 0
Tokenizer.h

@@ -50,6 +50,7 @@ typedef enum Token {
     T_WHILE,
     T_FOR,
     T_BREAK,
+    T_CONTINUE,
     T_FUNCTION,
     T_RETURN,
     T_COMMA,

+ 35 - 0
tests/loops/continue

@@ -0,0 +1,35 @@
+for(i = 0; i < 10; i++) {
+    if(i == 4) {
+        continue;
+    }
+    print i;
+}
+for(x = 0; x < 3; ++x) {
+    if(x == 1) {
+        continue;
+    }
+    for(y = 0; y < 3; y++) {
+        print x;
+        if(x == 2) {
+            continue;
+        }
+        print y;
+    }
+    i = 0;
+    while(i < 5) {
+        i++;
+        if(i == 3) {
+            continue;
+        }
+        print i;
+    }
+    continue;
+}
+i = 0;
+while(i < 5) {
+    i++;
+    if(i == 3) {
+        continue;
+    }
+    print i;
+}

+ 30 - 0
tests/loops/continue.out

@@ -0,0 +1,30 @@
+0
+1
+2
+3
+5
+6
+7
+8
+9
+0
+0
+0
+1
+0
+2
+1
+2
+4
+5
+2
+2
+2
+1
+2
+4
+5
+1
+2
+4
+5