Kajetan Johannes Hammerle 3 роки тому
батько
коміт
4fff6ffc88
5 змінених файлів з 81 додано та 20 видалено
  1. 39 17
      Compiler.c
  2. 4 3
      Tokenizer.c
  3. 1 0
      Tokenizer.h
  4. 9 0
      tests/loops/for
  5. 28 0
      tests/loops/for.out

+ 39 - 17
Compiler.c

@@ -330,7 +330,6 @@ static void cExpression() {
 
 static void cSetVar(const char* literal) {
     cExpression();
-    cConsumeToken(T_SEMICOLON);
     cAddOperation(OP_SET);
     cAddInt(cAddVar(literal));
 }
@@ -340,18 +339,13 @@ static void cLineLiteral() {
     Token t = cReadTokenAndLine();
     switch(t) {
         case T_SET: cSetVar(literal); break;
-        case T_OPEN_BRACKET:
-            cCallFunction(literal, true);
-            cConsumeToken(T_SEMICOLON);
-            break;
+        case T_OPEN_BRACKET: cCallFunction(literal, true); break;
         case T_INCREMENT:
             cPostIncrement(literal);
-            cConsumeToken(T_SEMICOLON);
             cAddOperation(OP_POP);
             break;
         case T_DECREMENT:
             cPostDecrement(literal);
-            cConsumeToken(T_SEMICOLON);
             cAddOperation(OP_POP);
             break;
         default: cUnexpectedToken(t);
@@ -498,30 +492,58 @@ static void cWhile() {
     cSetInt(ifP, code->length);
 }
 
-static void cLine(Token t) {
-    cAddOperation(OP_LINE);
-    cAddInt16(line);
+static void cLineExpression(Token t) {
     switch(t) {
-        case T_PRINT: cPrint(); break;
         case T_LITERAL: cLineLiteral(); break;
-        case T_FUNCTION: cFunction(); break;
-        case T_RETURN: cReturn(); break;
-        case T_IF: cIf(); break;
-        case T_WHILE: cWhile(); break;
         case T_INCREMENT:
             cPreIncrement();
-            cConsumeToken(T_SEMICOLON);
             cAddOperation(OP_POP);
             break;
         case T_DECREMENT:
             cPreDecrement();
-            cConsumeToken(T_SEMICOLON);
             cAddOperation(OP_POP);
             break;
         default: cUnexpectedToken(t);
     }
 }
 
+static void cFor() {
+    cConsumeToken(T_OPEN_BRACKET);
+    cLineExpression(cReadTokenAndLine());
+    cConsumeToken(T_SEMICOLON);
+    int startCheck = code->length;
+    cExpression();
+    cConsumeToken(T_SEMICOLON);
+    cAddOperation(OP_IF_GOTO);
+    int end = cReserveInt();
+    cAddOperation(OP_GOTO);
+    int beginBody = cReserveInt();
+    int startPerLoop = code->length;
+    cLineExpression(cReadTokenAndLine());
+    cAddOperation(OP_GOTO);
+    cAddInt(startCheck);
+    cConsumeToken(T_CLOSE_BRACKET);
+    cSetInt(beginBody, code->length);
+    cConsumeBody();
+    cAddOperation(OP_GOTO);
+    cAddInt(startPerLoop);
+    cSetInt(end, code->length);
+}
+
+static void cLine(Token t) {
+    cAddOperation(OP_LINE);
+    cAddInt16(line);
+    switch(t) {
+        case T_PRINT: cPrint(); break;
+        case T_FUNCTION: cFunction(); break;
+        case T_RETURN: cReturn(); break;
+        case T_IF: cIf(); break;
+        case T_WHILE: cWhile(); break;
+        case T_FOR: cFor(); break;
+        default: cLineExpression(t); cConsumeToken(T_SEMICOLON);
+    }
+}
+
 static void cForEachLine() {
     Token t = cReadTokenAndLine();
     while(t != T_END) {

+ 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}};
+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}};
 const int LITERAL_AMOUNT = sizeof(LITERALS) / sizeof(Literal);
 
 static void tError(const char* format, ...) {
@@ -274,6 +274,7 @@ const char* tGetTokenName(Token token) {
         case T_IF: return "if";
         case T_ELSE: return "else";
         case T_WHILE: return "while";
+        case T_FOR: return "for";
         case T_FUNCTION: return "function";
         case T_RETURN: return "return";
         case T_COMMA: return ",";

+ 1 - 0
Tokenizer.h

@@ -34,6 +34,7 @@ typedef enum Token {
     T_IF,
     T_ELSE,
     T_WHILE,
+    T_FOR,
     T_FUNCTION,
     T_RETURN,
     T_COMMA,

+ 9 - 0
tests/loops/for

@@ -0,0 +1,9 @@
+for(i = 0; i < 10; i++) {
+    print i;
+}
+for(x = 0; x < 3; ++x) {
+    for(y = 0; y < 3; y++) {
+        print x;
+        print y;
+    }
+}

+ 28 - 0
tests/loops/for.out

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