Bladeren bron

While loop

Kajetan Johannes Hammerle 6 dagen geleden
bovenliggende
commit
f4bb7d82de
5 gewijzigde bestanden met toevoegingen van 102 en 7 verwijderingen
  1. 36 7
      src/Compiler.c
  2. 3 0
      src/Tokenizer.c
  3. 1 0
      src/Tokenizer.h
  4. 36 0
      test/While.basic
  5. 26 0
      test/While.basic_result

+ 36 - 7
src/Compiler.c

@@ -401,6 +401,17 @@ static void compileSetVariable(Context* c, const char* name, bool forceGlobal) {
     codePushInstructionI32(c, SET_VARIABLE, addVariable(c, name, forceGlobal));
 }
 
+static void rewriteLoopJumps(
+    Context* c, const BreakContinue* w, i32 end, i32 con) {
+    while(c->loopJumps != w) {
+        BreakContinue* next = c->loopJumps->next;
+        codeRewriteI32(
+            c, c->loopJumps->address, c->loopJumps->stop ? end : con);
+        memoryFree(c->loopJumps);
+        c->loopJumps = next;
+    }
+}
+
 static void compileFor(Context* c) {
     c->inLoop++;
     Token t = consumeToken(c, TT_LITERAL);
@@ -431,14 +442,30 @@ static void compileFor(Context* c) {
     i32 endStart = (i32)codeGetWritePosition(c);
     codeRewriteI32(c, end, endStart);
 
-    while(c->loopJumps != currentJumps) {
-        BreakContinue* next = c->loopJumps->next;
-        codeRewriteI32(
-            c, c->loopJumps->address,
-            c->loopJumps->stop ? endStart : continueStart);
-        memoryFree(c->loopJumps);
-        c->loopJumps = next;
+    rewriteLoopJumps(c, currentJumps, endStart, continueStart);
+    c->inLoop--;
+}
+
+static void compileWhile(Context* c) {
+    c->inLoop++;
+    size_t checkStart = codeGetWritePosition(c);
+    compileExpression(c);
+    consumeNewline(c);
+    size_t end = codePushInstructionI32(c, JUMP_ON_0, 0);
+
+    BreakContinue* currentJumps = c->loopJumps;
+    while(!peekToken(c, TT_END)) {
+        compileLine(c, tokenizerNext(c->tokenizer));
     }
+    consumeToken(c, TT_END);
+    consumeNewline(c);
+
+    i32 continueStart = (i32)codeGetWritePosition(c);
+    codePushInstructionI32(c, JUMP, (i32)checkStart);
+    i32 endStart = (i32)codeGetWritePosition(c);
+    codeRewriteI32(c, end, endStart);
+
+    rewriteLoopJumps(c, currentJumps, endStart, continueStart);
     c->inLoop--;
 }
 
@@ -579,6 +606,8 @@ static void compileLine(Context* c, Token token) {
         consumeNewline(c);
     } else if(token.type == TT_FOR) {
         compileFor(c);
+    } else if(token.type == TT_WHILE) {
+        compileWhile(c);
     } else if(token.type == TT_FUNCTION) {
         compileFunction(c);
     } else if(token.type == TT_RETURN) {

+ 3 - 0
src/Tokenizer.c

@@ -79,6 +79,8 @@ static const char* tokenizerAddLiteral(TState* t, const char* s) {
         tAddToken(t, TT_FOR);
     } else if(strcmp(buffer, "to") == 0) {
         tAddToken(t, TT_TO);
+    } else if(strcmp(buffer, "while") == 0) {
+        tAddToken(t, TT_WHILE);
     } else if(strcmp(buffer, "break") == 0) {
         tAddToken(t, TT_BREAK);
     } else if(strcmp(buffer, "continue") == 0) {
@@ -305,6 +307,7 @@ void tokenizerPrintToken(const Token* token, char* buffer, size_t n) {
         TOKEN_PRINTER(TT_RETURN, "Return");
         TOKEN_PRINTER(TT_FOR, "For");
         TOKEN_PRINTER(TT_TO, "To");
+        TOKEN_PRINTER(TT_WHILE, "While");
         TOKEN_PRINTER(TT_BREAK, "Break");
         TOKEN_PRINTER(TT_CONTINUE, "Continue");
         TOKEN_PRINTER(TT_OPEN_ROUND_BRACKET, "(");

+ 1 - 0
src/Tokenizer.h

@@ -30,6 +30,7 @@ typedef enum : u8 {
     TT_RETURN,
     TT_FOR,
     TT_TO,
+    TT_WHILE,
     TT_BREAK,
     TT_CONTINUE,
     TT_OPEN_ROUND_BRACKET,

+ 36 - 0
test/While.basic

@@ -0,0 +1,36 @@
+i = 0
+while i <= 5
+    print(i)
+    i = i + 1
+end
+
+x = 0
+while x <= 2
+    y = 0
+    while y <= 3
+        print(x, " ", y)
+        y = y + 1
+    end
+    x = x + 1
+end
+
+x = 0
+while x <= 10
+    y = 0
+    while y <= 5
+        if y == 1
+            y = y + 1
+            continue
+        end
+        if y == 3
+            y = y + 1
+            continue
+        end
+        print(x, " ", y)
+        y = y + 1
+    end
+    if x == 1
+        break
+    end
+    x = x + 1
+end

+ 26 - 0
test/While.basic_result

@@ -0,0 +1,26 @@
+0
+1
+2
+3
+4
+5
+0 0
+0 1
+0 2
+0 3
+1 0
+1 1
+1 2
+1 3
+2 0
+2 1
+2 2
+2 3
+0 0
+0 2
+0 4
+0 5
+1 0
+1 2
+1 4
+1 5