Browse Source

WIP making everything strictly typed

Kajetan Johannes Hammerle 3 years ago
parent
commit
d25325f62a
100 changed files with 319 additions and 293 deletions
  1. 259 156
      Compiler.c
  2. 1 0
      Compiler.h
  3. 21 0
      DataType.c
  4. 9 0
      DataType.h
  5. 17 2
      Test.c
  6. 2 1
      meson.build
  7. 0 0
      old_tests/arrays/alloc
  8. 0 0
      old_tests/arrays/alloc.out
  9. 0 0
      old_tests/arrays/and
  10. 0 0
      old_tests/arrays/and.out
  11. 0 0
      old_tests/arrays/dec
  12. 0 0
      old_tests/arrays/dec.out
  13. 0 0
      old_tests/arrays/inc
  14. 0 0
      old_tests/arrays/inc.out
  15. 0 0
      old_tests/arrays/or
  16. 0 0
      old_tests/arrays/or.out
  17. 0 0
      old_tests/arrays/setop
  18. 0 0
      old_tests/arrays/setop.out
  19. 0 0
      old_tests/arrays/shift
  20. 0 0
      old_tests/arrays/shift.out
  21. 0 0
      old_tests/arrays/xor
  22. 0 0
      old_tests/arrays/xor.out
  23. 0 0
      old_tests/bits/and
  24. 0 0
      old_tests/bits/and.out
  25. 0 0
      old_tests/bits/invert
  26. 0 0
      old_tests/bits/invert.out
  27. 0 0
      old_tests/bits/or
  28. 0 0
      old_tests/bits/or.out
  29. 0 0
      old_tests/bits/shift
  30. 0 0
      old_tests/bits/shift.out
  31. 0 0
      old_tests/bits/xor
  32. 0 0
      old_tests/bits/xor.out
  33. 0 0
      old_tests/functions/arguments
  34. 0 0
      old_tests/functions/arguments.out
  35. 0 0
      old_tests/functions/forward
  36. 0 0
      old_tests/functions/forward.out
  37. 0 0
      old_tests/functions/function
  38. 0 0
      old_tests/functions/function.out
  39. 0 0
      old_tests/functions/function2
  40. 0 0
      old_tests/functions/function2.out
  41. 0 0
      old_tests/functions/overloading
  42. 0 0
      old_tests/functions/overloading.out
  43. 0 0
      old_tests/functions/recursion
  44. 0 0
      old_tests/functions/recursion.out
  45. 0 0
      old_tests/functions/return
  46. 0 0
      old_tests/functions/return.out
  47. 0 0
      old_tests/functions/return_value
  48. 0 0
      old_tests/functions/return_value.out
  49. 0 0
      old_tests/functions/scope
  50. 0 0
      old_tests/functions/scope.out
  51. 0 0
      old_tests/if/and
  52. 0 0
      old_tests/if/and.out
  53. 0 0
      old_tests/if/else
  54. 0 0
      old_tests/if/else.out
  55. 0 0
      old_tests/if/elseif
  56. 0 0
      old_tests/if/elseif.out
  57. 0 0
      old_tests/if/if
  58. 0 0
      old_tests/if/if.out
  59. 0 0
      old_tests/if/invert
  60. 0 0
      old_tests/if/invert.out
  61. 0 0
      old_tests/if/or
  62. 0 0
      old_tests/if/or.out
  63. 0 0
      old_tests/loops/break
  64. 0 0
      old_tests/loops/break.out
  65. 0 0
      old_tests/loops/continue
  66. 0 0
      old_tests/loops/continue.out
  67. 0 0
      old_tests/loops/for
  68. 0 0
      old_tests/loops/for.out
  69. 0 0
      old_tests/loops/while
  70. 0 0
      old_tests/loops/while.out
  71. 0 0
      old_tests/loops/while_post_dec
  72. 0 0
      old_tests/loops/while_post_dec.out
  73. 0 0
      old_tests/loops/while_post_inc
  74. 0 0
      old_tests/loops/while_post_inc.out
  75. 0 0
      old_tests/loops/while_pre_dec
  76. 0 0
      old_tests/loops/while_pre_dec.out
  77. 0 0
      old_tests/loops/while_pre_inc
  78. 0 0
      old_tests/loops/while_pre_inc.out
  79. 0 0
      old_tests/mix
  80. 0 0
      old_tests/mix.out
  81. 0 0
      old_tests/strings/const_string
  82. 0 0
      old_tests/strings/const_string.out
  83. 0 0
      old_tests/types/null
  84. 0 0
      old_tests/types/null.out
  85. 2 2
      tests/calc/add
  86. 1 1
      tests/calc/add.out
  87. 5 5
      tests/calc/div
  88. 2 2
      tests/calc/mul
  89. 0 11
      tests/comparison/equal
  90. 0 11
      tests/comparison/equal.out
  91. 0 10
      tests/comparison/greater
  92. 0 10
      tests/comparison/greater.out
  93. 0 10
      tests/comparison/greater_equal
  94. 0 10
      tests/comparison/greater_equal.out
  95. 0 10
      tests/comparison/less
  96. 0 10
      tests/comparison/less.out
  97. 0 10
      tests/comparison/less_equal
  98. 0 10
      tests/comparison/less_equal.out
  99. 0 11
      tests/comparison/not_equal
  100. 0 11
      tests/comparison/not_equal.out

+ 259 - 156
Compiler.c

@@ -4,14 +4,15 @@
 #include <string.h>
 
 #include "Compiler.h"
+#include "DataType.h"
 #include "tokenizer/Tokenizer.h"
 #include "utils/FunctionMap.h"
-#include "utils/StringIntMap.h"
+#include "utils/Variables.h"
 #include "vm/Operation.h"
 
 #define ERROR_LENGTH 256
-#define RETURN_BUFFER 16
-#define BREAK_BUFFER 32
+//#define RETURN_BUFFER 16
+//#define BREAK_BUFFER 32
 
 static jmp_buf errorJump;
 static char error[ERROR_LENGTH] = {'\0'};
@@ -20,18 +21,41 @@ static ByteCode* code;
 
 static int16 line = 1;
 
-static int varIndex = 0;
-static StringIntMap vars[2];
-static FunctionMap functions;
+static Variables vars;
+// static FunctionMap functions;
 
-static int returns[RETURN_BUFFER];
+/*static int returns[RETURN_BUFFER];
 static int returnIndex = 0;
 static int returnState = 0;
 
 static int breaks[BREAK_BUFFER];
 static int breakIndex = 0;
 static int forWhileStack = 0;
-static int continueAt = 0;
+static int continueAt = 0;*/
+
+typedef struct {
+    Operation intOp;
+    Operation floatOp;
+    Operation boolOp;
+    const char* name;
+} TypedOp;
+
+static const TypedOp TYPED_MUL = {OP_MUL_INT, OP_MUL_FLOAT, OP_NOTHING, "*"};
+static const TypedOp TYPED_DIV = {OP_DIV_INT, OP_DIV_FLOAT, OP_NOTHING, "/"};
+static const TypedOp TYPED_MOD = {OP_MOD_INT, OP_NOTHING, OP_NOTHING, "%"};
+static const TypedOp TYPED_ADD = {OP_ADD_INT, OP_ADD_FLOAT, OP_NOTHING, "+"};
+static const TypedOp TYPED_SUB = {OP_SUB_INT, OP_SUB_FLOAT, OP_NOTHING, "-"};
+static const TypedOp TYPED_LESS = {OP_LESS_INT, OP_LESS_FLOAT, OP_NOTHING, "<"};
+static const TypedOp TYPED_LESS_EQUAL = {OP_GREATER_INT, OP_GREATER_FLOAT,
+                                         OP_NOTHING, "<="};
+static const TypedOp TYPED_GREATER = {OP_GREATER_INT, OP_GREATER_FLOAT,
+                                      OP_NOTHING, ">"};
+static const TypedOp TYPED_GREATER_EQUAL = {OP_LESS_INT, OP_LESS_FLOAT,
+                                            OP_NOTHING, ">="};
+static const TypedOp TYPED_EQUAL = {OP_EQUAL_INT, OP_EQUAL_FLOAT, OP_EQUAL_BOOL,
+                                    "=="};
+static const TypedOp TYPED_NOT_EQUAL = {OP_EQUAL_INT, OP_EQUAL_FLOAT,
+                                        OP_EQUAL_BOOL, "!="};
 
 static void cError(const char* format, ...) {
     va_list args;
@@ -41,11 +65,23 @@ static void cError(const char* format, ...) {
     longjmp(errorJump, 0);
 }
 
-static int cAddVar(const char* var) {
+static void cInvalidOperation(DataType a, DataType b, const char* op) {
+    cError("invalid operation: %s %s %s", dtGetName(a), op, dtGetName(b));
+}
+
+static void cNotDeclared(const char* name) {
+    cError("variable %s has not been declared", name);
+}
+
+static void cNotInitialized(const char* name) {
+    cError("variable %s has not been initialized", name);
+}
+
+/*static int cAddVar(const char* var) {
     int index = vars[varIndex].entries;
     simAdd(vars + varIndex, var, &index);
     return index;
-}
+}*/
 
 static void cUnexpectedToken(Token t) {
     cError("unexpected token on line %d: %s", line, tGetName(t));
@@ -56,13 +92,13 @@ static void cAddOperation(Operation token) {
     bcAddBytes(code, &c, 1);
 }
 
-static int cReserveInt() {
+/*static int cReserveInt() {
     return bcReserveBytes(code, sizeof(int));
 }
 
 static void cSetInt(int p, int i) {
     bcSetBytes(code, p, &i, sizeof(int));
-}
+}*/
 
 static void cAddInt(int i) {
     bcAddBytes(code, &i, sizeof(int));
@@ -72,11 +108,7 @@ static void cAddInt16(int16 i) {
     bcAddBytes(code, &i, sizeof(int16));
 }
 
-static void cAddFloat(float f) {
-    bcAddBytes(code, &f, sizeof(float));
-}
-
-static int cAddPush(int offset) {
+/*static int cAddPush(int offset) {
     cAddOperation(OP_PUSH_VARS);
     int p = cReserveInt();
     cAddInt(offset);
@@ -87,7 +119,7 @@ static void cAddPop(int p, int vars) {
     cAddOperation(OP_POP_VARS);
     cAddInt(vars);
     cSetInt(p, vars);
-}
+}*/
 
 static Token cReadTokenAndLine() {
     Token t = tReadToken();
@@ -128,10 +160,10 @@ static void cConstantFloat() {
         cError("float token without a float on line %d", line);
     }
     cAddOperation(OP_PUSH_FLOAT);
-    cAddFloat(value);
+    bcAddBytes(code, &value, sizeof(float));
 }
 
-static void cConstantString() {
+/*static void cConstantString() {
     int length;
     const char* s = tReadString(&length);
     if(s == NULL) {
@@ -140,7 +172,7 @@ static void cConstantString() {
     cAddOperation(OP_PUSH_CONST_STRING);
     cAddInt(length);
     bcAddBytes(code, s, length);
-}
+}*/
 
 static const char* cReadString() {
     int length;
@@ -151,9 +183,9 @@ static const char* cReadString() {
     return literal;
 }
 
-static void cExpression();
+static DataType cExpression();
 
-static int cCallFunctionArguments() {
+/*static int cCallFunctionArguments() {
     int arguments = 0;
     while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
         arguments++;
@@ -187,28 +219,36 @@ static void cCallFunction(const char* literal, bool noReturn) {
             cAddOperation(OP_POP);
         }
     }
-}
+}*/
 
-static void cAddReference(const char* var) {
-    if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
-        cExpression();
-        cAddOperation(OP_REFERENCE_FROM_ARRAY);
-        cAddInt(cAddVar(var));
-        cConsumeToken(T_CLOSE_SQUARE_BRACKET);
-    } else {
-        cAddOperation(OP_REFERENCE_FROM_VAR);
-        cAddInt(cAddVar(var));
-    }
+static void cAddReference(int address) {
+    // if(cConsumeTokenIf(T_OPEN_SQUARE_BRACKET)) {
+    //    cExpression();
+    //    cAddOperation(OP_REFERENCE_FROM_ARRAY);
+    //    cAddInt(cAddVar(var));
+    //    cConsumeToken(T_CLOSE_SQUARE_BRACKET);
+    //} else {
+    cAddOperation(OP_REFERENCE_FROM_VAR);
+    cAddInt(address);
+    //}
 }
 
-static void cLiteral() {
+static DataType cLiteral() {
     const char* literal = cReadString();
-    if(cConsumeTokenIf(T_OPEN_BRACKET)) {
+    /*if(cConsumeTokenIf(T_OPEN_BRACKET)) {
         cCallFunction(literal, false);
         return;
-    }
-    cAddReference(literal);
-    if(cConsumeTokenIf(T_INCREMENT)) {
+    }*/
+    Variable* v = vSearch(&vars, literal);
+    if(v == NULL) {
+        cNotDeclared(literal);
+    } else if(!v->initialized) {
+        cNotInitialized(literal);
+    }
+    cAddReference(v->address);
+    cAddOperation(OP_DEREFERENCE_INT);
+    return v->type;
+    /*if(cConsumeTokenIf(T_INCREMENT)) {
         cAddOperation(OP_POST_INCREMENT);
     } else if(cConsumeTokenIf(T_DECREMENT)) {
         cAddOperation(OP_POST_DECREMENT);
@@ -222,46 +262,54 @@ static void cLiteral() {
         }
     } else {
         cAddOperation(OP_DEREFERENCE);
-    }
+    }*/
 }
 
-static void cArray() {
+/*static void cArray() {
     cConsumeToken(T_OPEN_SQUARE_BRACKET);
     cExpression();
     cConsumeToken(T_CLOSE_SQUARE_BRACKET);
     cAddOperation(OP_ALLOCATE_ARRAY);
+}*/
+
+static DataType cBracketPrimary() {
+    DataType result = cExpression();
+    cConsumeToken(T_CLOSE_BRACKET);
+    return result;
 }
 
-static void cPrimary() {
+static DataType cPrimary() {
     Token t = cReadTokenAndLine();
     switch(t) {
-        case T_INT: cConstantInt(); break;
-        case T_FLOAT: cConstantFloat(); break;
-        case T_TEXT: cConstantString(); break;
-        case T_NULL: cAddOperation(OP_PUSH_NULL); break;
-        case T_TRUE: cAddOperation(OP_PUSH_TRUE); break;
-        case T_FALSE: cAddOperation(OP_PUSH_FALSE); break;
-        case T_OPEN_BRACKET:
-            cExpression();
-            cConsumeToken(T_CLOSE_BRACKET);
-            break;
-        case T_LITERAL: cLiteral(); break;
-        case T_ARRAY: cArray(); break;
-        default: cUnexpectedToken(t); break;
+        case T_CONST_INT: cConstantInt(); return DT_INT;
+        case T_FLOAT: cConstantFloat(); return DT_FLOAT;
+        // case T_TEXT: cConstantString(); break;
+        // case T_NULL: cAddOperation(OP_PUSH_NULL); break;
+        case T_TRUE: cAddOperation(OP_PUSH_TRUE); return DT_BOOL;
+        case T_FALSE: cAddOperation(OP_PUSH_FALSE); return DT_BOOL;
+        case T_OPEN_BRACKET: return cBracketPrimary();
+        case T_LITERAL: return cLiteral();
+        // case T_ARRAY: cArray(); break;
+        default: cUnexpectedToken(t); return DT_VOID;
     }
 }
 
-static void cPreChange(Operation op) {
+/*static void cPreChange(Operation op) {
     cConsumeToken(T_LITERAL);
     cAddReference(cReadString());
     cAddOperation(op);
-}
+}*/
 
-static void cPreUnary() {
+static DataType cPreUnary() {
     if(cConsumeTokenIf(T_SUB)) {
-        cPrimary();
-        cAddOperation(OP_INVERT_SIGN);
-    } else if(cConsumeTokenIf(T_INCREMENT)) {
+        DataType result = cPrimary();
+        switch(result) {
+            case DT_INT: cAddOperation(OP_INVERT_SIGN_INT); break;
+            case DT_FLOAT: cAddOperation(OP_INVERT_SIGN_FLOAT); break;
+            default: cError("cannot invert sign of %s", dtGetName(result));
+        }
+        return result;
+    } /*else if(cConsumeTokenIf(T_INCREMENT)) {
         cPreChange(OP_PRE_INCREMENT);
     } else if(cConsumeTokenIf(T_DECREMENT)) {
         cPreChange(OP_PRE_DECREMENT);
@@ -278,47 +326,56 @@ static void cPreUnary() {
     } else if(cConsumeTokenIf(T_BIT_NOT)) {
         cPrimary();
         cAddOperation(OP_BIT_NOT);
+    } else {*/
+    return cPrimary();
+    //}
+}
+
+static void cAddTypeOperation(DataType a, DataType b, const TypedOp* op) {
+    if(a == DT_INT && b == DT_INT && op->intOp != OP_NOTHING) {
+        cAddOperation(op->intOp);
+    } else if(a == DT_FLOAT && b == DT_FLOAT && op->floatOp != OP_NOTHING) {
+        cAddOperation(op->floatOp);
+    } else if(a == DT_BOOL && b == DT_BOOL && op->boolOp != OP_NOTHING) {
+        cAddOperation(op->boolOp);
     } else {
-        cPrimary();
+        cInvalidOperation(a, b, op->name);
     }
 }
 
-static void cMul() {
-    cPreUnary();
+static DataType cMul() {
+    DataType a = cPreUnary();
     while(true) {
         if(cConsumeTokenIf(T_MUL)) {
-            cPreUnary();
-            cAddOperation(OP_MUL);
+            cAddTypeOperation(a, cPreUnary(), &TYPED_MUL);
         } else if(cConsumeTokenIf(T_DIV)) {
-            cPreUnary();
-            cAddOperation(OP_DIV);
+            cAddTypeOperation(a, cPreUnary(), &TYPED_DIV);
         } else if(cConsumeTokenIf(T_MOD)) {
-            cPreUnary();
-            cAddOperation(OP_MOD);
+            cAddTypeOperation(a, cPreUnary(), &TYPED_MOD);
         } else {
             break;
         }
     }
+    return a;
 }
 
-static void cAdd() {
-    cMul();
+static DataType cAdd() {
+    DataType a = cMul();
     while(true) {
         if(cConsumeTokenIf(T_ADD)) {
-            cMul();
-            cAddOperation(OP_ADD);
+            cAddTypeOperation(a, cMul(), &TYPED_ADD);
         } else if(cConsumeTokenIf(T_SUB)) {
-            cMul();
-            cAddOperation(OP_SUB);
+            cAddTypeOperation(a, cMul(), &TYPED_SUB);
         } else {
             break;
         }
     }
+    return a;
 }
 
-static void cShift() {
-    cAdd();
-    while(true) {
+static DataType cShift() {
+    return cAdd();
+    /*while(true) {
         if(cConsumeTokenIf(T_LEFT_SHIFT)) {
             cAdd();
             cAddOperation(OP_LEFT_SHIFT);
@@ -328,87 +385,89 @@ static void cShift() {
         } else {
             break;
         }
-    }
+    }*/
 }
 
-static void cComparison() {
-    cShift();
+static DataType cComparison() {
+    DataType a = cShift();
     while(true) {
         if(cConsumeTokenIf(T_LESS)) {
-            cShift();
-            cAddOperation(OP_LESS);
+            cAddTypeOperation(a, cShift(), &TYPED_LESS);
+            a = DT_BOOL;
         } else if(cConsumeTokenIf(T_LESS_EQUAL)) {
-            cShift();
-            cAddOperation(OP_GREATER);
+            cAddTypeOperation(a, cShift(), &TYPED_LESS_EQUAL);
             cAddOperation(OP_NOT);
+            a = DT_BOOL;
         } else if(cConsumeTokenIf(T_GREATER)) {
-            cShift();
-            cAddOperation(OP_GREATER);
+            cAddTypeOperation(a, cShift(), &TYPED_GREATER);
+            a = DT_BOOL;
         } else if(cConsumeTokenIf(T_GREATER_EQUAL)) {
-            cShift();
-            cAddOperation(OP_LESS);
+            cAddTypeOperation(a, cShift(), &TYPED_GREATER_EQUAL);
             cAddOperation(OP_NOT);
+            a = DT_BOOL;
         } else {
             break;
         }
     }
+    return a;
 }
 
-static void cEqual() {
-    cComparison();
+static DataType cEqual() {
+    DataType a = cComparison();
     while(true) {
         if(cConsumeTokenIf(T_EQUAL)) {
-            cComparison();
-            cAddOperation(OP_EQUAL);
+            cAddTypeOperation(a, cComparison(), &TYPED_EQUAL);
+            a = DT_BOOL;
         } else if(cConsumeTokenIf(T_NOT_EQUAL)) {
-            cComparison();
-            cAddOperation(OP_EQUAL);
+            cAddTypeOperation(a, cComparison(), &TYPED_NOT_EQUAL);
             cAddOperation(OP_NOT);
+            a = DT_BOOL;
         } else {
             break;
         }
     }
+    return a;
 }
 
-static void cBitAnd() {
-    cEqual();
-    while(cConsumeTokenIf(T_BIT_AND)) {
+static DataType cBitAnd() {
+    return cEqual();
+    /*while(cConsumeTokenIf(T_BIT_AND)) {
         cEqual();
         cAddOperation(OP_BIT_AND);
-    }
+    }*/
 }
 
-static void cBitXor() {
-    cBitAnd();
-    while(cConsumeTokenIf(T_BIT_XOR)) {
+static DataType cBitXor() {
+    return cBitAnd();
+    /*while(cConsumeTokenIf(T_BIT_XOR)) {
         cBitAnd();
         cAddOperation(OP_BIT_XOR);
-    }
+    }*/
 }
 
-static void cBitOr() {
-    cBitXor();
-    while(cConsumeTokenIf(T_BIT_OR)) {
+static DataType cBitOr() {
+    return cBitXor();
+    /*while(cConsumeTokenIf(T_BIT_OR)) {
         cBitXor();
         cAddOperation(OP_BIT_OR);
-    }
+    }*/
 }
 
-static void cAnd() {
-    cBitOr();
-    while(cConsumeTokenIf(T_AND)) {
+static DataType cAnd() {
+    return cBitOr();
+    /*while(cConsumeTokenIf(T_AND)) {
         cAddOperation(OP_DUPLICATE);
         cAddOperation(OP_IF_GOTO);
         int p = cReserveInt();
         cBitOr();
         cAddOperation(OP_AND);
         cSetInt(p, code->length);
-    }
+    }*/
 }
 
-static void cOr() {
-    cAnd();
-    while(cConsumeTokenIf(T_OR)) {
+static DataType cOr() {
+    return cAnd();
+    /*while(cConsumeTokenIf(T_OR)) {
         cAddOperation(OP_DUPLICATE);
         cAddOperation(OP_NOT);
         cAddOperation(OP_IF_GOTO);
@@ -416,29 +475,44 @@ static void cOr() {
         cAnd();
         cAddOperation(OP_OR);
         cSetInt(p, code->length);
-    }
+    }*/
 }
 
-static void cExpression() {
-    cOr();
+static DataType cExpression() {
+    return cOr();
 }
 
-static void cOperationSet(Operation op) {
+/*static void cOperationSet(Operation op) {
     cAddOperation(OP_DUPLICATE);
     cAddOperation(OP_DEREFERENCE);
     cExpression();
     cAddOperation(op);
     cAddOperation(OP_SET);
-}
+}*/
 
 static void cLineLiteral() {
     const char* literal = cReadString();
-    if(cConsumeTokenIf(T_OPEN_BRACKET)) {
+    /*if(cConsumeTokenIf(T_OPEN_BRACKET)) {
         cCallFunction(literal, true);
         return;
+    }*/
+    Variable* v = vSearch(&vars, literal);
+    if(v == NULL) {
+        cNotDeclared(literal);
+    }
+    cAddReference(v->address);
+    cConsumeToken(T_SET);
+    DataType dt = cExpression();
+    if(v->type != dt) {
+        cInvalidOperation(v->type, dt, "=");
+    }
+    if(dt == DT_INT) {
+        cAddOperation(OP_SET_INT);
+    } else {
+        cError("%s cannot be set", dtGetName(dt));
     }
-    cAddReference(literal);
-    Token t = cReadTokenAndLine();
+    v->initialized = true;
+    /*Token t = cReadTokenAndLine();
     switch(t) {
         case T_SET:
             cExpression();
@@ -463,10 +537,10 @@ static void cLineLiteral() {
             cAddOperation(OP_POP);
             break;
         default: cUnexpectedToken(t);
-    }
+    }*/
 }
 
-static int cFunctionArguments() {
+/*static int cFunctionArguments() {
     int arguments = 0;
     while(!cConsumeTokenIf(T_CLOSE_BRACKET)) {
         cConsumeToken(T_LITERAL);
@@ -565,15 +639,20 @@ static void cReturn() {
         cAddReturn();
         cConsumeToken(T_SEMICOLON);
     }
-}
+}*/
 
 static void cPrint() {
-    cExpression();
+    DataType dt = cExpression();
+    switch(dt) {
+        case DT_INT: cAddOperation(OP_PRINT_INT); break;
+        case DT_FLOAT: cAddOperation(OP_PRINT_FLOAT); break;
+        case DT_BOOL: cAddOperation(OP_PRINT_BOOL); break;
+        default: cError("cannot print data type %s", dtGetName(dt));
+    }
     cConsumeToken(T_SEMICOLON);
-    cAddOperation(OP_PRINT);
 }
 
-static void cIf() {
+/*static void cIf() {
     cConsumeToken(T_OPEN_BRACKET);
     cExpression();
     cConsumeToken(T_CLOSE_BRACKET);
@@ -620,24 +699,46 @@ static void cWhile() {
     cAddInt(start);
     cSetInt(ifP, code->length);
     cConsumeBreaks(breakStart, code->length);
+}*/
+
+static void cInt() {
+    cConsumeToken(T_LITERAL);
+    const char* var = cReadString();
+    Variable* v = vSearch(&vars, var);
+    if(v != NULL) {
+        cError("%s has already been declared", var);
+    }
+    v = vAdd(&vars, var, DT_INT);
+    if(tPeekToken() == T_SEMICOLON) {
+        return;
+    }
+    cConsumeToken(T_SET);
+    cAddReference(v->address);
+    DataType dt = cExpression();
+    if(dt != DT_INT) {
+        cInvalidOperation(DT_INT, dt, "=");
+    }
+    cAddOperation(OP_SET_INT);
+    v->initialized = true;
 }
 
 static void cLineExpression(Token t) {
     switch(t) {
         case T_LITERAL: cLineLiteral(); break;
-        case T_INCREMENT:
+        case T_INT: cInt(); break;
+        /*case T_INCREMENT:
             cPreChange(OP_PRE_INCREMENT);
             cAddOperation(OP_POP);
             break;
         case T_DECREMENT:
             cPreChange(OP_PRE_DECREMENT);
             cAddOperation(OP_POP);
-            break;
+            break;*/
         default: cUnexpectedToken(t);
     }
 }
 
-static void cFor() {
+/*static void cFor() {
     cConsumeToken(T_OPEN_BRACKET);
     cLineExpression(cReadTokenAndLine());
     cConsumeToken(T_SEMICOLON);
@@ -685,20 +786,20 @@ static void cContinue() {
     cAddOperation(OP_GOTO);
     cAddInt(continueAt);
     cConsumeToken(T_SEMICOLON);
-}
+}*/
 
 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;
-        case T_BREAK: cBreak(); break;
-        case T_CONTINUE: cContinue(); 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;
+        // case T_BREAK: cBreak(); break;
+        // case T_CONTINUE: cContinue(); break;
         default: cLineExpression(t); cConsumeToken(T_SEMICOLON);
     }
 }
@@ -711,7 +812,7 @@ static void cForEachLine() {
     }
 }
 
-static void cLinkQueuedFunctions() {
+/*static void cLinkQueuedFunctions() {
     for(int i = 0; i < functions.queueEntries; i++) {
         Function* f = fmSearch(&functions, functions.queue[i].name,
                                functions.queue[i].arguments);
@@ -726,26 +827,24 @@ static void cLinkQueuedFunctions() {
             code->code[functions.queue[i].reserved + sizeof(int) * 2] = OP_POP;
         }
     }
-}
+}*/
 
 static void cAllocAndCompile() {
-    varIndex = 0;
-    returnIndex = 0;
-    returnState = 0;
-    forWhileStack = 0;
-    breakIndex = 0;
-    simInit(vars);
-    simInit(vars + 1);
-    fmInit(&functions);
+    // varIndex = 0;
+    // returnIndex = 0;
+    // returnState = 0;
+    // forWhileStack = 0;
+    // breakIndex = 0;
+    vInit(&vars);
+    // fmInit(&functions);
     if(!setjmp(errorJump)) {
-        int p = cAddPush(0);
+        // int p = cAddPush(0);
         cForEachLine();
-        cAddPop(p, vars[varIndex].entries);
-        cLinkQueuedFunctions();
+        // cAddPop(p, vars[varIndex].entries);
+        // cLinkQueuedFunctions();
     }
-    fmDelete(&functions);
-    simDelete(vars + 1);
-    simDelete(vars);
+    // fmDelete(&functions);
+    vDelete(&vars);
 }
 
 ByteCode* cCompile() {
@@ -761,4 +860,8 @@ ByteCode* cCompile() {
 
 const char* cGetError() {
     return error;
+}
+
+int cGetLine() {
+    return line;
 }

+ 1 - 0
Compiler.h

@@ -5,5 +5,6 @@
 
 ByteCode* cCompile();
 const char* cGetError();
+int cGetLine();
 
 #endif

+ 21 - 0
DataType.c

@@ -0,0 +1,21 @@
+#include <stdbool.h>
+
+#include "DataType.h"
+
+const char* dtGetName(DataType dt) {
+    switch(dt) {
+        case DT_INT: return "int";
+        case DT_FLOAT: return "float";
+        case DT_BOOL: return "bool";
+        default: return "unknown";
+    }
+}
+
+int dtGetSize(DataType dt) {
+    switch(dt) {
+        case DT_INT: return sizeof(int);
+        case DT_FLOAT: return sizeof(float);
+        case DT_BOOL: return sizeof(bool);
+        default: return 0;
+    }
+}

+ 9 - 0
DataType.h

@@ -0,0 +1,9 @@
+#ifndef DATATYPE_H
+#define DATATYPE_H
+
+typedef enum { DT_INT, DT_FLOAT, DT_BOOL, DT_VOID } DataType;
+
+const char* dtGetName(DataType dt);
+int dtGetSize(DataType dt);
+
+#endif

+ 17 - 2
Test.c

@@ -32,7 +32,7 @@ static void tsPrintToBuffer(const char* format, ...) {
     va_end(args);
 }
 
-static bool tsPrinter(Object* o) {
+/*static bool tsPrinter(Object* o) {
     if(testBufferIndex >= TEST_BUFFER_LENGTH) {
         return true;
     }
@@ -51,6 +51,18 @@ static bool tsPrinter(Object* o) {
         case OT_ARRAY: tsPrintToBuffer("array\n"); return false;
         default: return true;
     }
+}*/
+
+static void tsIntPrinter(int i) {
+    tsPrintToBuffer("%d\n", i);
+}
+
+static void tsFloatPrinter(float f) {
+    tsPrintToBuffer("%.2f\n", f);
+}
+
+static void tsBoolPrinter(bool b) {
+    tsPrintToBuffer(b ? "true\n" : "false\n");
 }
 
 static void tsAppend(const char* s) {
@@ -120,6 +132,7 @@ static void tsCheckFile() {
     if(bc == NULL) {
         puts(path);
         puts(cGetError());
+        printf("line: %d\n", cGetLine());
         return;
     }
     Script* sc = sInit(bc);
@@ -155,7 +168,9 @@ static void tsScanDirectory() {
 }
 
 void tsStart(const char* path) {
-    sSetPrinter(tsPrinter);
+    sSetIntPrinter(tsIntPrinter);
+    sSetFloatPrinter(tsFloatPrinter);
+    sSetBoolPrinter(tsBoolPrinter);
     doneTests = 0;
     allTests = 0;
     tsAppend(path);

+ 2 - 1
meson.build

@@ -6,10 +6,11 @@ src = [
     'tokenizer/Token.c', 
     'tokenizer/File.c', 
     'utils/Utils.c', 
-    'utils/StringIntMap.c',
+    'utils/Variables.c',
     'utils/FunctionMap.c',
     'utils/ByteCodePrinter.c',
     'Compiler.c', 
+    'DataType.c', 
     'Test.c', 
     'vm/ByteCode.c',
     'vm/Script.c', 

+ 0 - 0
tests/arrays/alloc → old_tests/arrays/alloc


+ 0 - 0
tests/arrays/alloc.out → old_tests/arrays/alloc.out


+ 0 - 0
tests/arrays/and → old_tests/arrays/and


+ 0 - 0
tests/arrays/and.out → old_tests/arrays/and.out


+ 0 - 0
tests/arrays/dec → old_tests/arrays/dec


+ 0 - 0
tests/arrays/dec.out → old_tests/arrays/dec.out


+ 0 - 0
tests/arrays/inc → old_tests/arrays/inc


+ 0 - 0
tests/arrays/inc.out → old_tests/arrays/inc.out


+ 0 - 0
tests/arrays/or → old_tests/arrays/or


+ 0 - 0
tests/arrays/or.out → old_tests/arrays/or.out


+ 0 - 0
tests/arrays/setop → old_tests/arrays/setop


+ 0 - 0
tests/arrays/setop.out → old_tests/arrays/setop.out


+ 0 - 0
tests/arrays/shift → old_tests/arrays/shift


+ 0 - 0
tests/arrays/shift.out → old_tests/arrays/shift.out


+ 0 - 0
tests/arrays/xor → old_tests/arrays/xor


+ 0 - 0
tests/arrays/xor.out → old_tests/arrays/xor.out


+ 0 - 0
tests/bits/and → old_tests/bits/and


+ 0 - 0
tests/bits/and.out → old_tests/bits/and.out


+ 0 - 0
tests/bits/invert → old_tests/bits/invert


+ 0 - 0
tests/bits/invert.out → old_tests/bits/invert.out


+ 0 - 0
tests/bits/or → old_tests/bits/or


+ 0 - 0
tests/bits/or.out → old_tests/bits/or.out


+ 0 - 0
tests/bits/shift → old_tests/bits/shift


+ 0 - 0
tests/bits/shift.out → old_tests/bits/shift.out


+ 0 - 0
tests/bits/xor → old_tests/bits/xor


+ 0 - 0
tests/bits/xor.out → old_tests/bits/xor.out


+ 0 - 0
tests/functions/arguments → old_tests/functions/arguments


+ 0 - 0
tests/functions/arguments.out → old_tests/functions/arguments.out


+ 0 - 0
tests/functions/forward → old_tests/functions/forward


+ 0 - 0
tests/functions/forward.out → old_tests/functions/forward.out


+ 0 - 0
tests/functions/function → old_tests/functions/function


+ 0 - 0
tests/functions/function.out → old_tests/functions/function.out


+ 0 - 0
tests/functions/function2 → old_tests/functions/function2


+ 0 - 0
tests/functions/function2.out → old_tests/functions/function2.out


+ 0 - 0
tests/functions/overloading → old_tests/functions/overloading


+ 0 - 0
tests/functions/overloading.out → old_tests/functions/overloading.out


+ 0 - 0
tests/functions/recursion → old_tests/functions/recursion


+ 0 - 0
tests/functions/recursion.out → old_tests/functions/recursion.out


+ 0 - 0
tests/functions/return → old_tests/functions/return


+ 0 - 0
tests/functions/return.out → old_tests/functions/return.out


+ 0 - 0
tests/functions/return_value → old_tests/functions/return_value


+ 0 - 0
tests/functions/return_value.out → old_tests/functions/return_value.out


+ 0 - 0
tests/functions/scope → old_tests/functions/scope


+ 0 - 0
tests/functions/scope.out → old_tests/functions/scope.out


+ 0 - 0
tests/if/and → old_tests/if/and


+ 0 - 0
tests/if/and.out → old_tests/if/and.out


+ 0 - 0
tests/if/else → old_tests/if/else


+ 0 - 0
tests/if/else.out → old_tests/if/else.out


+ 0 - 0
tests/if/elseif → old_tests/if/elseif


+ 0 - 0
tests/if/elseif.out → old_tests/if/elseif.out


+ 0 - 0
tests/if/if → old_tests/if/if


+ 0 - 0
tests/if/if.out → old_tests/if/if.out


+ 0 - 0
tests/if/invert → old_tests/if/invert


+ 0 - 0
tests/if/invert.out → old_tests/if/invert.out


+ 0 - 0
tests/if/or → old_tests/if/or


+ 0 - 0
tests/if/or.out → old_tests/if/or.out


+ 0 - 0
tests/loops/break → old_tests/loops/break


+ 0 - 0
tests/loops/break.out → old_tests/loops/break.out


+ 0 - 0
tests/loops/continue → old_tests/loops/continue


+ 0 - 0
tests/loops/continue.out → old_tests/loops/continue.out


+ 0 - 0
tests/loops/for → old_tests/loops/for


+ 0 - 0
tests/loops/for.out → old_tests/loops/for.out


+ 0 - 0
tests/loops/while → old_tests/loops/while


+ 0 - 0
tests/loops/while.out → old_tests/loops/while.out


+ 0 - 0
tests/loops/while_post_dec → old_tests/loops/while_post_dec


+ 0 - 0
tests/loops/while_post_dec.out → old_tests/loops/while_post_dec.out


+ 0 - 0
tests/loops/while_post_inc → old_tests/loops/while_post_inc


+ 0 - 0
tests/loops/while_post_inc.out → old_tests/loops/while_post_inc.out


+ 0 - 0
tests/loops/while_pre_dec → old_tests/loops/while_pre_dec


+ 0 - 0
tests/loops/while_pre_dec.out → old_tests/loops/while_pre_dec.out


+ 0 - 0
tests/loops/while_pre_inc → old_tests/loops/while_pre_inc


+ 0 - 0
tests/loops/while_pre_inc.out → old_tests/loops/while_pre_inc.out


+ 0 - 0
tests/mix → old_tests/mix


+ 0 - 0
tests/mix.out → old_tests/mix.out


+ 0 - 0
tests/strings/const_string → old_tests/strings/const_string


+ 0 - 0
tests/strings/const_string.out → old_tests/strings/const_string.out


+ 0 - 0
tests/types/null → old_tests/types/null


+ 0 - 0
tests/types/null.out → old_tests/types/null.out


+ 2 - 2
tests/calc/add

@@ -3,6 +3,6 @@ print 2 + 3;
 print 3 + 4 + 5;
 print 6 + 7 + 8 + 9;
 print 3.5 + 5.5;
-print 4.0 + 1;
-print 1 + 2.0;
+print 4.0 + 1.0;
+print 1.0 + -2.0;
 print 6 + -7 + 8 + -9;

+ 1 - 1
tests/calc/add.out

@@ -4,5 +4,5 @@
 30
 9.00
 5.00
-3.00
+-1.00
 -2

+ 5 - 5
tests/calc/div

@@ -1,12 +1,12 @@
 print 1 / 2;
 print 7 / 3;
-print 7 / 3.0;
-print 7.0 / 3;
+print 7.0 / 3.0;
+print 7.0 / 3.0;
 print 7.0 / 3.0;
 print 3 / 4 + 5;
 print 6 + 7 / 8 + 9;
 print 3.5 / 5.5;
-print 4.0 / 1;
-print 1 / 2.0;
+print 4.0 / 1.0;
+print 1.0 / 2.0;
 print 20 * 2 / 3 / 5;
-print 20.0 * 2 / 3 / 5;
+print 20.0 * 2.0 / 3.0 / 5.0;

+ 2 - 2
tests/calc/mul

@@ -3,6 +3,6 @@ print 3 + 4 * 5;
 print 6 + 7 * 8 + 9;
 print (3 + 4) * 5;
 print ((3 + 2) * (5 + 1));
-print ((3 + 2.0) * (5 + 1));
-print ((3 + 2) * (5 + 1.0));
+print ((3.0 + 2.0) * (5.0 + 1.0));
+print ((3.0 + 2.0) * (5.0 + 1.0));
 print -3 * -5;

+ 0 - 11
tests/comparison/equal

@@ -8,18 +8,7 @@ print 4.0 == 5.0;
 print 5.0 == 5.0;
 print 6.0 == 5.0;
 print 10.0 == 5.0;
-print 0.0 == 5;
-print 4.0 == 5;
-print 5.0 == 5;
-print 6.0 == 5;
-print 10.0 == 5;
-print 0 == 5.0;
-print 4 == 5.0;
-print 5 == 5.0;
-print 6 == 5.0;
-print 10 == 5.0;
 print false == false;
 print true == false;
 print false == true;
 print true == true;
-print null == null;

+ 0 - 11
tests/comparison/equal.out

@@ -8,18 +8,7 @@ false
 true
 false
 false
-false
-false
 true
 false
 false
-false
-false
-true
-false
-false
-true
-false
-false
-true
 true

+ 0 - 10
tests/comparison/greater

@@ -8,13 +8,3 @@ print 4.0 > 5.0;
 print 5.0 > 5.0;
 print 6.0 > 5.0;
 print 10.0 > 5.0;
-print 0.0 > 5;
-print 4.0 > 5;
-print 5.0 > 5;
-print 6.0 > 5;
-print 10.0 > 5;
-print 0 > 5.0;
-print 4 > 5.0;
-print 5 > 5.0;
-print 6 > 5.0;
-print 10 > 5.0;

+ 0 - 10
tests/comparison/greater.out

@@ -8,13 +8,3 @@ false
 false
 true
 true
-false
-false
-false
-true
-true
-false
-false
-false
-true
-true

+ 0 - 10
tests/comparison/greater_equal

@@ -8,13 +8,3 @@ print 4.0 >= 5.0;
 print 5.0 >= 5.0;
 print 6.0 >= 5.0;
 print 10.0 >= 5.0;
-print 0.0 >= 5;
-print 4.0 >= 5;
-print 5.0 >= 5;
-print 6.0 >= 5;
-print 10.0 >= 5;
-print 0 >= 5.0;
-print 4 >= 5.0;
-print 5 >= 5.0;
-print 6 >= 5.0;
-print 10 >= 5.0;

+ 0 - 10
tests/comparison/greater_equal.out

@@ -8,13 +8,3 @@ false
 true
 true
 true
-false
-false
-true
-true
-true
-false
-false
-true
-true
-true

+ 0 - 10
tests/comparison/less

@@ -8,13 +8,3 @@ print 4.0 < 5.0;
 print 5.0 < 5.0;
 print 6.0 < 5.0;
 print 10.0 < 5.0;
-print 0.0 < 5;
-print 4.0 < 5;
-print 5.0 < 5;
-print 6.0 < 5;
-print 10.0 < 5;
-print 0 < 5.0;
-print 4 < 5.0;
-print 5 < 5.0;
-print 6 < 5.0;
-print 10 < 5.0;

+ 0 - 10
tests/comparison/less.out

@@ -8,13 +8,3 @@ true
 false
 false
 false
-true
-true
-false
-false
-false
-true
-true
-false
-false
-false

+ 0 - 10
tests/comparison/less_equal

@@ -8,13 +8,3 @@ print 4.0 <= 5.0;
 print 5.0 <= 5.0;
 print 6.0 <= 5.0;
 print 10.0 <= 5.0;
-print 0.0 <= 5;
-print 4.0 <= 5;
-print 5.0 <= 5;
-print 6.0 <= 5;
-print 10.0 <= 5;
-print 0 <= 5.0;
-print 4 <= 5.0;
-print 5 <= 5.0;
-print 6 <= 5.0;
-print 10 <= 5.0;

+ 0 - 10
tests/comparison/less_equal.out

@@ -8,13 +8,3 @@ true
 true
 false
 false
-true
-true
-true
-false
-false
-true
-true
-true
-false
-false

+ 0 - 11
tests/comparison/not_equal

@@ -8,18 +8,7 @@ print 4.0 != 5.0;
 print 5.0 != 5.0;
 print 6.0 != 5.0;
 print 10.0 != 5.0;
-print 0.0 != 5;
-print 4.0 != 5;
-print 5.0 != 5;
-print 6.0 != 5;
-print 10.0 != 5;
-print 0 != 5.0;
-print 4 != 5.0;
-print 5 != 5.0;
-print 6 != 5.0;
-print 10 != 5.0;
 print false != false;
 print true != false;
 print false != true;
 print true != true;
-print null != null;

+ 0 - 11
tests/comparison/not_equal.out

@@ -8,18 +8,7 @@ true
 false
 true
 true
-true
-true
 false
 true
 true
-true
-true
-false
-true
-true
-false
-true
-true
-false
 false

Some files were not shown because too many files changed in this diff