فهرست منبع

long as new data type

Kajetan Johannes Hammerle 3 سال پیش
والد
کامیت
bef52ef67d
66فایلهای تغییر یافته به همراه510 افزوده شده و 154 حذف شده
  1. 96 45
      Compiler.c
  2. 11 0
      DataType.c
  3. 7 4
      DataType.h
  4. 5 0
      Test.c
  5. 6 0
      tests/bits/and
  6. 2 0
      tests/bits/and.out
  7. 2 0
      tests/bits/invert
  8. 2 0
      tests/bits/invert.out
  9. 6 0
      tests/bits/or
  10. 2 0
      tests/bits/or.out
  11. 10 0
      tests/bits/shift
  12. 2 0
      tests/bits/shift.out
  13. 6 0
      tests/bits/xor
  14. 2 0
      tests/bits/xor.out
  15. 1 0
      tests/calc/add
  16. 1 0
      tests/calc/add.out
  17. 1 0
      tests/calc/div
  18. 1 0
      tests/calc/div.out
  19. 1 0
      tests/calc/mod
  20. 1 0
      tests/calc/mod.out
  21. 1 0
      tests/calc/mul
  22. 1 0
      tests/calc/mul.out
  23. 1 0
      tests/calc/sub
  24. 1 0
      tests/calc/sub.out
  25. 14 0
      tests/cast/cast_float_long
  26. 0 0
      tests/cast/cast_float_long.out
  27. 0 0
      tests/cast/cast_int_float
  28. 8 0
      tests/cast/cast_int_float.out
  29. 11 0
      tests/cast/cast_int_long
  30. 6 0
      tests/cast/cast_int_long.out
  31. 11 0
      tests/loops/while_post_dec
  32. 10 0
      tests/loops/while_post_dec.out
  33. 11 0
      tests/loops/while_post_inc
  34. 10 0
      tests/loops/while_post_inc.out
  35. 11 0
      tests/loops/while_pre_dec
  36. 10 0
      tests/loops/while_pre_dec.out
  37. 11 0
      tests/loops/while_pre_inc
  38. 10 0
      tests/loops/while_pre_inc.out
  39. 3 0
      tests/struct_ref/alloc
  40. 1 0
      tests/struct_ref/alloc.out
  41. 0 0
      tests/struct_ref/bool_reference
  42. 0 0
      tests/struct_ref/bool_reference.out
  43. 0 0
      tests/struct_ref/float_reference
  44. 0 0
      tests/struct_ref/float_reference.out
  45. 0 0
      tests/struct_ref/int_reference
  46. 0 0
      tests/struct_ref/int_reference.out
  47. 16 0
      tests/struct_ref/long_reference
  48. 4 0
      tests/struct_ref/long_reference.out
  49. 0 0
      tests/struct_ref/nested
  50. 0 0
      tests/struct_ref/nested.out
  51. 0 0
      tests/struct_ref/pass_struct
  52. 0 0
      tests/struct_ref/pass_struct.out
  53. 0 0
      tests/struct_ref/struct_access
  54. 0 0
      tests/struct_ref/struct_access.out
  55. 3 0
      tests/system/time
  56. 0 0
      tests/system/time.out
  57. 12 0
      tests/types/types
  58. 3 0
      tests/types/types.out
  59. 3 0
      tokenizer/Token.c
  60. 2 0
      tokenizer/Token.h
  61. 20 1
      tokenizer/Tokenizer.c
  62. 1 0
      tokenizer/Tokenizer.h
  63. 36 10
      utils/ByteCodePrinter.c
  64. 34 26
      vm/Operation.h
  65. 78 68
      vm/Script.c
  66. 2 0
      vm/Script.h

+ 96 - 45
Compiler.c

@@ -17,6 +17,7 @@
 
 #define DT_OPERATION(op)                                                       \
     case DT_INT: cAddOperation(OP_##op##_INT); break;                          \
+    case DT_LONG: cAddOperation(OP_##op##_LONG); break;                        \
     case DT_BOOL: cAddOperation(OP_##op##_BOOL); break;                        \
     case DT_FLOAT: cAddOperation(OP_##op##_FLOAT); break;
 
@@ -47,31 +48,38 @@ static int continueAt = 0;
 
 typedef struct {
     Operation intOp;
+    Operation longOp;
     Operation floatOp;
     Operation boolOp;
     Operation pointerOp;
     const char* name;
 } TypedOp;
 
-#define TYPE_OP(NAME, INT, FLOAT, BOOL, POINTER, text)                         \
-    static const TypedOp TYPED_##NAME = {OP_##INT, OP_##FLOAT, OP_##BOOL,      \
-                                         OP_##POINTER, text};
-TYPE_OP(MUL, MUL_INT, MUL_FLOAT, NOTHING, NOTHING, "*")
-TYPE_OP(DIV, DIV_INT, DIV_FLOAT, NOTHING, NOTHING, "/")
-TYPE_OP(MOD, MOD_INT, NOTHING, NOTHING, NOTHING, "%")
-TYPE_OP(ADD, ADD_INT, ADD_FLOAT, NOTHING, NOTHING, "+")
-TYPE_OP(SUB, SUB_INT, SUB_FLOAT, NOTHING, NOTHING, "-")
-TYPE_OP(LESS, LESS_INT, LESS_FLOAT, NOTHING, NOTHING, "<")
-TYPE_OP(LESS_EQUAL, GREATER_INT, GREATER_FLOAT, NOTHING, NOTHING, "<=")
-TYPE_OP(GREATER, GREATER_INT, GREATER_FLOAT, NOTHING, NOTHING, ">")
-TYPE_OP(GREATER_EQUAL, LESS_INT, LESS_FLOAT, NOTHING, NOTHING, ">=")
-TYPE_OP(EQUAL, EQUAL_INT, EQUAL_FLOAT, EQUAL_BOOL, EQUAL_POINTER, "==")
-TYPE_OP(NOT_EQUAL, EQUAL_INT, EQUAL_FLOAT, EQUAL_BOOL, EQUAL_POINTER, "!=")
-TYPE_OP(BIT_OR, BIT_OR, NOTHING, NOTHING, NOTHING, "|")
-TYPE_OP(BIT_XOR, BIT_XOR, NOTHING, NOTHING, NOTHING, "^")
-TYPE_OP(BIT_AND, BIT_AND, NOTHING, NOTHING, NOTHING, "&")
-TYPE_OP(LEFT_SHIFT, LEFT_SHIFT, NOTHING, NOTHING, NOTHING, "<<")
-TYPE_OP(RIGHT_SHIFT, RIGHT_SHIFT, NOTHING, NOTHING, NOTHING, ">>")
+#define TYPE_OP(NAME, INT, LONG, FLOAT, BOOL, POINTER, text)                   \
+    static const TypedOp TYPED_##NAME = {OP_##INT,  OP_##LONG,    OP_##FLOAT,  \
+                                         OP_##BOOL, OP_##POINTER, text};
+TYPE_OP(MUL, MUL_INT, MUL_LONG, MUL_FLOAT, NOTHING, NOTHING, "*")
+TYPE_OP(DIV, DIV_INT, DIV_LONG, DIV_FLOAT, NOTHING, NOTHING, "/")
+TYPE_OP(MOD, MOD_INT, MOD_LONG, NOTHING, NOTHING, NOTHING, "%")
+TYPE_OP(ADD, ADD_INT, ADD_LONG, ADD_FLOAT, NOTHING, NOTHING, "+")
+TYPE_OP(SUB, SUB_INT, SUB_LONG, SUB_FLOAT, NOTHING, NOTHING, "-")
+TYPE_OP(LESS, LESS_INT, LESS_LONG, LESS_FLOAT, NOTHING, NOTHING, "<")
+TYPE_OP(LESS_EQUAL, GREATER_INT, GREATER_LONG, GREATER_FLOAT, NOTHING, NOTHING,
+        "<=")
+TYPE_OP(GREATER, GREATER_INT, GREATER_LONG, GREATER_FLOAT, NOTHING, NOTHING,
+        ">")
+TYPE_OP(GREATER_EQUAL, LESS_INT, LESS_LONG, LESS_FLOAT, NOTHING, NOTHING, ">=")
+TYPE_OP(EQUAL, EQUAL_INT, EQUAL_LONG, EQUAL_FLOAT, EQUAL_BOOL, EQUAL_POINTER,
+        "==")
+TYPE_OP(NOT_EQUAL, EQUAL_INT, EQUAL_LONG, EQUAL_FLOAT, EQUAL_BOOL,
+        EQUAL_POINTER, "!=")
+TYPE_OP(BIT_OR, BIT_OR_INT, BIT_OR_LONG, NOTHING, NOTHING, NOTHING, "|")
+TYPE_OP(BIT_XOR, BIT_XOR_INT, BIT_XOR_LONG, NOTHING, NOTHING, NOTHING, "^")
+TYPE_OP(BIT_AND, BIT_AND_INT, BIT_AND_LONG, NOTHING, NOTHING, NOTHING, "&")
+TYPE_OP(LEFT_SHIFT, LEFT_SHIFT_INT, LEFT_SHIFT_LONG, NOTHING, NOTHING, NOTHING,
+        "<<")
+TYPE_OP(RIGHT_SHIFT, RIGHT_SHIFT_INT, RIGHT_SHIFT_LONG, NOTHING, NOTHING,
+        NOTHING, ">>")
 
 static void cError(const char* format, ...) {
     va_list args;
@@ -122,6 +130,10 @@ static void cAddInt(int i) {
     bcAddBytes(code, &i, sizeof(int));
 }
 
+static void cAddLong(long l) {
+    bcAddBytes(code, &l, sizeof(long));
+}
+
 static void cAddIntOperation(Operation token, int i) {
     cAddOperation(token);
     cAddInt(i);
@@ -165,6 +177,15 @@ static void cConstantInt() {
     cAddIntOperation(OP_PUSH_INT, value);
 }
 
+static void cConstantLong() {
+    long value;
+    if(!tReadLong(&value)) {
+        cError("long token without an long");
+    }
+    cAddOperation(OP_PUSH_LONG);
+    cAddLong(value);
+}
+
 static void cConstantFloat() {
     float value;
     if(!tReadFloat(&value)) {
@@ -203,6 +224,7 @@ static DataType cExtendType(DataType dt) {
 static DataType cReadType(Token t) {
     switch(t) {
         case T_INT: return cExtendType(dtInt());
+        case T_LONG: return cExtendType(dtLong());
         case T_BOOL: return cExtendType(dtBool());
         case T_FLOAT: return cExtendType(dtFloat());
         case T_LITERAL:
@@ -340,6 +362,7 @@ static DataType cPrimary() {
     Token t = cReadTokenAndLine();
     switch(t) {
         case T_CONST_INT: cConstantInt(); return dtInt();
+        case T_CONST_LONG: cConstantLong(); return dtLong();
         case T_CONST_FLOAT: cConstantFloat(); return dtFloat();
         case T_TRUE: cAddOperation(OP_PUSH_TRUE); return dtBool();
         case T_FALSE: cAddOperation(OP_PUSH_FALSE); return dtBool();
@@ -363,14 +386,24 @@ static void cExpectType(DataType actual, DataType wanted, const char* name) {
     }
 }
 
-static void cPostChange(DataType* dt, int change, const char* name) {
-    cRemoveReference(dt, name);
-    cExpectType(*dt, dtInt(), name);
+static void cChangeType(DataType* dt, Operation op, Operation pushOp,
+                        int change) {
     if(onLine) {
-        cAddByteOperation(OP_INT_CHANGE, change);
+        cAddByteOperation(op, change);
         *dt = dtVoid();
     } else {
-        cAddByteOperation(OP_PUSH_POST_INT_CHANGE, change);
+        cAddByteOperation(pushOp, change);
+    }
+}
+
+static void cPostChange(DataType* dt, int change, const char* name) {
+    cRemoveReference(dt, name);
+    if(dtCompare(*dt, dtInt())) {
+        cChangeType(dt, OP_CHANGE_INT, OP_PUSH_POST_CHANGE_INT, change);
+    } else if(dtCompare(*dt, dtLong())) {
+        cChangeType(dt, OP_CHANGE_LONG, OP_PUSH_POST_CHANGE_LONG, change);
+    } else {
+        cError("%s needs an int or long not %s", name, cGetName(*dt));
     }
 }
 
@@ -421,18 +454,21 @@ static DataType cAccess() {
 
 static DataType cPreChange(DataType dt, int change, const char* name) {
     cRemoveReference(&dt, name);
-    cExpectType(dt, dtInt(), name);
-    if(onLine) {
-        cAddByteOperation(OP_INT_CHANGE, change);
-        return dtVoid();
+    if(dtCompare(dt, dtInt())) {
+        cChangeType(&dt, OP_CHANGE_INT, OP_PUSH_PRE_CHANGE_INT, change);
+    } else if(dtCompare(dt, dtLong())) {
+        cChangeType(&dt, OP_CHANGE_LONG, OP_PUSH_PRE_CHANGE_LONG, change);
+    } else {
+        cError("%s needs an int or long not %s", name, cGetName(dt));
     }
-    cAddByteOperation(OP_PUSH_PRE_INT_CHANGE, change);
     return dt;
 }
 
 static DataType cInvertSign(DataType dt) {
     if(dtIsInt(dt)) {
         cAddOperation(OP_INVERT_SIGN_INT);
+    } else if(dtIsLong(dt)) {
+        cAddOperation(OP_INVERT_SIGN_LONG);
     } else if(dtIsFloat(dt)) {
         cAddOperation(OP_INVERT_SIGN_FLOAT);
     } else {
@@ -441,25 +477,30 @@ static DataType cInvertSign(DataType dt) {
     return dt;
 }
 
+static DataType cCast(DataType in, DataType a, Operation aOp, DataType b,
+                      Operation bOp, DataType out) {
+    if(dtCompare(in, a)) {
+        cAddOperation(aOp);
+    } else if(dtCompare(in, b)) {
+        cAddOperation(bOp);
+    } else {
+        cError("cannot cast %s to %s", cGetName(in), cGetName(out));
+    }
+    return out;
+}
+
 static DataType cPreUnary() {
     int marker = tGetMarker();
     if(cConsumeTokenIf(T_OPEN_BRACKET)) {
         if(cConsumeTokenIf(T_FLOAT) && cConsumeTokenIf(T_CLOSE_BRACKET)) {
-            DataType dt = cUnpack(cPreUnary());
-            if(dtCompare(dt, dtInt())) {
-                cAddOperation(OP_INT_TO_FLOAT);
-            } else {
-                cError("cannot cast %s to float", cGetName(dt));
-            }
-            return dtFloat();
+            return cCast(cUnpack(cPreUnary()), dtInt(), OP_INT_TO_FLOAT,
+                         dtLong(), OP_LONG_TO_FLOAT, dtFloat());
         } else if(cConsumeTokenIf(T_INT) && cConsumeTokenIf(T_CLOSE_BRACKET)) {
-            DataType dt = cUnpack(cPreUnary());
-            if(dtCompare(dt, dtFloat())) {
-                cAddOperation(OP_FLOAT_TO_INT);
-            } else {
-                cError("cannot cast %s to int", cGetName(dt));
-            }
-            return dtInt();
+            return cCast(cUnpack(cPreUnary()), dtFloat(), OP_FLOAT_TO_INT,
+                         dtLong(), OP_LONG_TO_INT, dtInt());
+        } else if(cConsumeTokenIf(T_LONG) && cConsumeTokenIf(T_CLOSE_BRACKET)) {
+            return cCast(cUnpack(cPreUnary()), dtInt(), OP_INT_TO_LONG,
+                         dtFloat(), OP_FLOAT_TO_LONG, dtLong());
         }
     }
     tReset(marker);
@@ -476,8 +517,13 @@ static DataType cPreUnary() {
         return dt;
     } else if(cConsumeTokenIf(T_BIT_NOT)) {
         DataType dt = cPreUnary();
-        cExpectType(dt, dtInt(), "!");
-        cAddOperation(OP_BIT_NOT);
+        if(dtCompare(dt, dtInt())) {
+            cAddOperation(OP_BIT_NOT_INT);
+        } else if(dtCompare(dt, dtLong())) {
+            cAddOperation(OP_BIT_NOT_LONG);
+        } else {
+            cError("~ needs an int or long not %s", cGetName(dt));
+        }
         return dt;
     } else if(cConsumeTokenIf(T_BIT_AND)) {
         DataType dt = cPreUnary();
@@ -506,6 +552,8 @@ static void cAddTypeOperation(DataType* a, Parser bf, const TypedOp* op) {
         cInvalidOperation(*a, b, op->name);
     } else if(dtIsInt(*a) && op->intOp != OP_NOTHING) {
         cAddOperation(op->intOp);
+    } else if(dtIsLong(*a) && op->longOp != OP_NOTHING) {
+        cAddOperation(op->longOp);
     } else if(dtIsFloat(*a) && op->floatOp != OP_NOTHING) {
         cAddOperation(op->floatOp);
     } else if(dtIsBool(*a) && op->boolOp != OP_NOTHING) {
@@ -681,6 +729,8 @@ static void cReturn() {
         cError("wrong return type, should be %s", cGetName(returnType));
     } else if(dtIsInt(dt)) {
         cAddReturn(OP_RETURN_INT);
+    } else if(dtIsLong(dt)) {
+        cAddReturn(OP_RETURN_LONG);
     } else if(dtIsBool(dt)) {
         cAddReturn(OP_RETURN_BOOL);
     } else if(dtIsFloat(dt)) {
@@ -826,6 +876,7 @@ static void cLineExpression() {
     }
     switch(t) {
         case T_INT: cDeclare(dtInt()); break;
+        case T_LONG: cDeclare(dtLong()); break;
         case T_BOOL: cDeclare(dtBool()); break;
         case T_FLOAT: cDeclare(dtFloat()); break;
         case T_DELETE: cDelete(); break;

+ 11 - 0
DataType.c

@@ -25,6 +25,7 @@ const char* dtGetName(Structs* sts, DataType dt) {
     typeNameIndex = 0;
     switch(dt.type) {
         case DT_INT: dtAppend("int"); break;
+        case DT_LONG: dtAppend("long"); break;
         case DT_FLOAT: dtAppend("float"); break;
         case DT_BOOL: dtAppend("bool"); break;
         case DT_STRUCT: dtAppend(sts->data[dt.structId].name); break;
@@ -43,6 +44,7 @@ int dtGetSize(DataType dt, Structs* sts) {
     }
     switch(dt.type) {
         case DT_INT: return sizeof(int);
+        case DT_LONG: return sizeof(long);
         case DT_FLOAT: return sizeof(float);
         case DT_BOOL: return sizeof(bool);
         case DT_STRUCT:
@@ -63,6 +65,11 @@ DataType dtInt() {
     return dt;
 }
 
+DataType dtLong() {
+    DataType dt = {DT_LONG, 0, 0};
+    return dt;
+}
+
 DataType dtFloat() {
     DataType dt = {DT_FLOAT, 0, 0};
     return dt;
@@ -105,6 +112,10 @@ bool dtIsInt(DataType dt) {
     return dtCompare(dt, dtInt());
 }
 
+bool dtIsLong(DataType dt) {
+    return dtCompare(dt, dtLong());
+}
+
 bool dtIsFloat(DataType dt) {
     return dtCompare(dt, dtFloat());
 }

+ 7 - 4
DataType.h

@@ -4,10 +4,11 @@
 #include <stdbool.h>
 
 #define DT_INT 0
-#define DT_FLOAT 1
-#define DT_BOOL 2
-#define DT_VOID 3
-#define DT_STRUCT 4
+#define DT_LONG 1
+#define DT_FLOAT 2
+#define DT_BOOL 3
+#define DT_VOID 4
+#define DT_STRUCT 5
 
 typedef struct {
     unsigned int type : 4;
@@ -41,6 +42,7 @@ typedef struct {
 int dtGetSize(DataType dt, Structs* sts);
 
 DataType dtInt();
+DataType dtLong();
 DataType dtFloat();
 DataType dtBool();
 DataType dtVoid();
@@ -54,6 +56,7 @@ bool dtRemoveVariable(DataType* dt);
 
 bool dtCompare(DataType a, DataType b);
 bool dtIsInt(DataType dt);
+bool dtIsLong(DataType dt);
 bool dtIsFloat(DataType dt);
 bool dtIsBool(DataType dt);
 bool dtIsVoid(DataType dt);

+ 5 - 0
Test.c

@@ -36,6 +36,10 @@ static void tsIntPrinter(int i) {
     tsPrintToBuffer("%d\n", i);
 }
 
+static void tsLongPrinter(long l) {
+    tsPrintToBuffer("%ld\n", l);
+}
+
 static void tsFloatPrinter(float f) {
     tsPrintToBuffer("%.2f\n", f);
 }
@@ -152,6 +156,7 @@ static void tsScanDirectory() {
 
 void tsStart(const char* path) {
     sSetIntPrinter(tsIntPrinter);
+    sSetLongPrinter(tsLongPrinter);
     sSetFloatPrinter(tsFloatPrinter);
     sSetBoolPrinter(tsBoolPrinter);
     sSetPointerPrinter(tsPointerPrinter);

+ 6 - 0
tests/bits/and

@@ -4,4 +4,10 @@ void main() {
     print a;
     a &= 9;
     print a;
+    
+    long b = 7L;
+    b = b & 15L;
+    print b;
+    b &= 9L;
+    print b;
 }

+ 2 - 0
tests/bits/and.out

@@ -1,2 +1,4 @@
 7
 1
+7
+1

+ 2 - 0
tests/bits/invert

@@ -1,4 +1,6 @@
 void main() {
     print ~0;
     print ~~~(~7);
+    print ~0L;
+    print ~~~(~7L);
 }

+ 2 - 0
tests/bits/invert.out

@@ -1,2 +1,4 @@
 -1
 7
+-1
+7

+ 6 - 0
tests/bits/or

@@ -4,4 +4,10 @@ void main() {
     print a;
     a |= 5;
     print a;
+    
+    long b = 0L;
+    b = b | 2L;
+    print b;
+    b |= 5L;
+    print b;
 }

+ 2 - 0
tests/bits/or.out

@@ -1,2 +1,4 @@
 2
 7
+2
+7

+ 10 - 0
tests/bits/shift

@@ -8,4 +8,14 @@ void main() {
     a = a >> 2;
     a >>= 3;
     print a;
+    
+    long b = 1L;
+    b = b << 2L;
+    b <<= 3L;
+    print b;
+
+    b = 100L;
+    b = b >> 2L;
+    b >>= 3L;
+    print b;
 }

+ 2 - 0
tests/bits/shift.out

@@ -1,2 +1,4 @@
 32
 3
+32
+3

+ 6 - 0
tests/bits/xor

@@ -4,4 +4,10 @@ void main() {
     print a;
     a ^= 7;
     print a;
+    
+    long b = 0L;
+    b = b ^ 2L;
+    print b;
+    b ^= 7L;
+    print b;
 }

+ 2 - 0
tests/bits/xor.out

@@ -1,2 +1,4 @@
 2
 5
+2
+5

+ 1 - 0
tests/calc/add

@@ -7,4 +7,5 @@ void main() {
     print 4.0 + 1.0;
     print 1.0 + -2.0;
     print 6 + -7 + 8 + -9;
+    print 2L + 3L;
 }

+ 1 - 0
tests/calc/add.out

@@ -6,3 +6,4 @@
 5.00
 -1.00
 -2
+5

+ 1 - 0
tests/calc/div

@@ -11,4 +11,5 @@ void main() {
     print 1.0 / 2.0;
     print 20 * 2 / 3 / 5;
     print 20.0 * 2.0 / 3.0 / 5.0;
+    print 7L / 3L;
 }

+ 1 - 0
tests/calc/div.out

@@ -10,3 +10,4 @@
 0.50
 2
 2.67
+2

+ 1 - 0
tests/calc/mod

@@ -4,4 +4,5 @@ void main() {
     print 5 % 5;
     print 7 % 5;
     print 9 % 5;
+    print 9L % 5L;
 }

+ 1 - 0
tests/calc/mod.out

@@ -3,3 +3,4 @@
 0
 2
 4
+4

+ 1 - 0
tests/calc/mul

@@ -7,4 +7,5 @@ void main() {
     print ((3.0 + 2.0) * (5.0 + 1.0));
     print ((3.0 + 2.0) * (5.0 + 1.0));
     print -3 * -5;
+    print -3L * -5L;
 }

+ 1 - 0
tests/calc/mul.out

@@ -6,3 +6,4 @@
 30.00
 30.00
 15
+15

+ 1 - 0
tests/calc/sub

@@ -3,4 +3,5 @@ void main() {
     print 2 - 5 + 3 - 6;
     print 2 - (5 + 3) - 6;
     print -(7 - 8);
+    print -(7L - 8L);
 }

+ 1 - 0
tests/calc/sub.out

@@ -2,3 +2,4 @@
 -6
 -12
 1
+1

+ 14 - 0
tests/cast/cast_float_long

@@ -0,0 +1,14 @@
+void main() {
+    long l = 3L;
+    print (float)l;
+    print (long)(float)l;
+    print (float)(long)(float)l;
+    
+    float f = 4.2;
+    print (long)f;
+    print (float)(long)f;
+    print (long)(float)(long)f;
+    
+    print (float)6 / 5.0;
+    print 6L / (long)5.0;
+}

+ 0 - 0
tests/cast.out → tests/cast/cast_float_long.out


+ 0 - 0
tests/cast → tests/cast/cast_int_float


+ 8 - 0
tests/cast/cast_int_float.out

@@ -0,0 +1,8 @@
+3.00
+3
+3.00
+4
+4.00
+4
+1.20
+1

+ 11 - 0
tests/cast/cast_int_long

@@ -0,0 +1,11 @@
+void main() {
+    long l = 3L;
+    print (int)l;
+    print (long)(int)l;
+    print (int)(long)(int)l;
+    
+    int i = 4;
+    print (long)i;
+    print (int)(long)i;
+    print (long)(int)(long)i;
+}

+ 6 - 0
tests/cast/cast_int_long.out

@@ -0,0 +1,6 @@
+3
+3
+3
+4
+4
+4

+ 11 - 0
tests/loops/while_post_dec

@@ -9,4 +9,15 @@ void main() {
         print a;
         a--;
     }
+    
+    long b = 5L;
+    while(b > 0L) {
+        print b--;
+    }
+
+    b = 5L;
+    while(b > 0L) {
+        print b;
+        b--;
+    }
 }

+ 10 - 0
tests/loops/while_post_dec.out

@@ -8,3 +8,13 @@
 3
 2
 1
+5
+4
+3
+2
+1
+5
+4
+3
+2
+1

+ 11 - 0
tests/loops/while_post_inc

@@ -9,4 +9,15 @@ void main() {
         print a;
         a++;
     }
+    
+    long b = 0L;
+    while(b < 5L) {
+        print b++;
+    }
+
+    b = 0L;
+    while(b < 5L) {
+        print b;
+        b++;
+    }
 }

+ 10 - 0
tests/loops/while_post_inc.out

@@ -8,3 +8,13 @@
 2
 3
 4
+0
+1
+2
+3
+4
+0
+1
+2
+3
+4

+ 11 - 0
tests/loops/while_pre_dec

@@ -9,4 +9,15 @@ void main() {
         print a;
         --a;
     }
+    
+    long b = 5L;
+    while(b > 0L) {
+        print --b;
+    }
+
+    b = 5L;
+    while(b > 0L) {
+        print b;
+        --b;
+    }
 }

+ 10 - 0
tests/loops/while_pre_dec.out

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

+ 11 - 0
tests/loops/while_pre_inc

@@ -9,4 +9,15 @@ void main() {
         print a;
         ++a;
     }
+    
+    long b = 0L;
+    while(b < 5L) {
+        print ++b;
+    }
+
+    b = 0L;
+    while(b < 5L) {
+        print b;
+        ++b;
+    }
 }

+ 10 - 0
tests/loops/while_pre_inc.out

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

+ 3 - 0
tests/struct/alloc → tests/struct_ref/alloc

@@ -1,6 +1,7 @@
 struct A {
     float f;
     int i;
+    long l;
     bool b;
 };
 
@@ -8,8 +9,10 @@ void main() {
     A a;
     a.f = 5.0;
     a.i = 7;
+    a.l = 8L;
     a.b = true;
     print a.f;
     print a.i;
+    print a.l;
     print a.b;
 }

+ 1 - 0
tests/struct/alloc.out → tests/struct_ref/alloc.out

@@ -1,3 +1,4 @@
 5.00
 7
+8
 true

+ 0 - 0
tests/struct/bool_reference → tests/struct_ref/bool_reference


+ 0 - 0
tests/struct/bool_reference.out → tests/struct_ref/bool_reference.out


+ 0 - 0
tests/struct/float_reference → tests/struct_ref/float_reference


+ 0 - 0
tests/struct/float_reference.out → tests/struct_ref/float_reference.out


+ 0 - 0
tests/struct/int_reference → tests/struct_ref/int_reference


+ 0 - 0
tests/struct/int_reference.out → tests/struct_ref/int_reference.out


+ 16 - 0
tests/struct_ref/long_reference

@@ -0,0 +1,16 @@
+void test(long* t) {
+    *t = 8L;
+    *t += 1L;
+}
+
+void main() {
+    long a = 5L;
+    long* b = &a;
+    a = 6L;
+    print a;
+    print *(b);
+    test(&a);
+    test(b);
+    print a;
+    print *b;
+}

+ 4 - 0
tests/struct_ref/long_reference.out

@@ -0,0 +1,4 @@
+6
+6
+9
+9

+ 0 - 0
tests/struct/nested → tests/struct_ref/nested


+ 0 - 0
tests/struct/nested.out → tests/struct_ref/nested.out


+ 0 - 0
tests/struct/pass_struct → tests/struct_ref/pass_struct


+ 0 - 0
tests/struct/pass_struct.out → tests/struct_ref/pass_struct.out


+ 0 - 0
tests/struct/struct_access → tests/struct_ref/struct_access


+ 0 - 0
tests/struct/struct_access.out → tests/struct_ref/struct_access.out


+ 3 - 0
tests/system/time

@@ -0,0 +1,3 @@
+void main() {
+    
+}

+ 0 - 0
tests/system/time.out


+ 12 - 0
tests/types/types

@@ -6,6 +6,10 @@ int intFunction() {
     return 1;
 }
 
+long longFunction() {
+    return 3L;
+}
+
 bool boolFunction() {
     return true;
 }
@@ -18,6 +22,10 @@ int* intFunction(int* i) {
     return i;
 }
 
+long* longFunction(long* l) {
+    return l;
+}
+
 bool* boolFunction(bool* b) {
     return b;
 }
@@ -33,16 +41,20 @@ A* structFunction(A* a) {
 void main() {
     int i = intFunction();
     print i;
+    long l = longFunction();
+    print l;
     bool b = boolFunction();
     print b;
     float f = floatFunction();
     print f;
     
     print *intFunction(&i);
+    print *longFunction(&l);
     print *boolFunction(&b);
     print *floatFunction(&f);
     
     print intFunction(&i)[0];
+    print longFunction(&l)[0];
     print boolFunction(&b)[0];
     print floatFunction(&f)[0];
     

+ 3 - 0
tests/types/types.out

@@ -1,10 +1,13 @@
 1
+3
 true
 2.00
 1
+3
 true
 2.00
 1
+3
 true
 2.00
 53453

+ 3 - 0
tokenizer/Token.c

@@ -7,9 +7,11 @@ const char* tGetName(Token token) {
     switch(token) {
         case T_VOID: return "void";
         case T_INT: return "int";
+        case T_LONG: return "long";
         case T_BOOL: return "bool";
         case T_FLOAT: return "float";
         case T_CONST_INT: return "const int";
+        case T_CONST_LONG: return "const long";
         case T_CONST_FLOAT: return "const float";
         case T_TEXT: return "text";
         case T_NULL: return "null";
@@ -94,6 +96,7 @@ Token tFromName(const char* name) {
     MATCH_TOKEN("break", T_BREAK);
     MATCH_TOKEN("continue", T_CONTINUE);
     MATCH_TOKEN("int", T_INT);
+    MATCH_TOKEN("long", T_LONG);
     MATCH_TOKEN("void", T_VOID);
     MATCH_TOKEN("bool", T_BOOL);
     MATCH_TOKEN("float", T_FLOAT);

+ 2 - 0
tokenizer/Token.h

@@ -4,9 +4,11 @@
 typedef enum {
     T_VOID,
     T_INT,
+    T_LONG,
     T_BOOL,
     T_FLOAT,
     T_CONST_INT,
+    T_CONST_LONG,
     T_CONST_FLOAT,
     T_TEXT,
     T_NULL,

+ 20 - 1
tokenizer/Tokenizer.c

@@ -87,7 +87,19 @@ static void tParseNumber(int c) {
         buffer[index++] = fRead();
     }
     buffer[index] = '\0';
-    if(point) {
+    if(fPeek() == 'L' || fPeek() == 'l') {
+        fRead();
+        if(point) {
+            tError("invalid mix of long and float", line);
+        }
+        char* end = NULL;
+        long l = strtol(buffer, &end, 10);
+        if(end[0] != '\0' || l > INT_MAX) {
+            tError("invalid long on line %d", line);
+        }
+        tAddToken(T_CONST_LONG);
+        tAdd(&l, sizeof(long));
+    } else if(point) {
         char* end = NULL;
         float f = strtof(buffer, &end);
         if(end[0] != '\0') {
@@ -285,6 +297,13 @@ bool tReadInt(int* i) {
     return false;
 }
 
+bool tReadLong(long* l) {
+    if(tReadTokens(l, sizeof(long))) {
+        return true;
+    }
+    return false;
+}
+
 bool tReadInt16(int16* i) {
     if(tReadTokens(i, sizeof(int16))) {
         return true;

+ 1 - 0
tokenizer/Tokenizer.h

@@ -15,6 +15,7 @@ void tResetReader();
 Token tPeekToken();
 Token tReadToken();
 bool tReadInt(int* i);
+bool tReadLong(long* l);
 bool tReadInt16(int16* i);
 bool tReadFloat(float* f);
 const char* tReadString();

+ 36 - 10
utils/ByteCodePrinter.c

@@ -51,6 +51,12 @@ static void btAddInt() {
     btAdd(" %10d |", value);
 }
 
+static void btAddLong() {
+    long value = 0;
+    btRead(&value, sizeof(long));
+    btAdd(" %10d |", value);
+}
+
 static void btAddByte() {
     char value = 0;
     btRead(&value, sizeof(char));
@@ -89,6 +95,14 @@ static void btPrintInt(const char* op) {
     puts(buffer);
 }
 
+static void btPrintLong(const char* op) {
+    btFillBase();
+    btAddOperation(op);
+    btAddLong();
+    btAddFiller();
+    puts(buffer);
+}
+
 static void btPrintByte(const char* op) {
     btFillBase();
     btAddOperation(op);
@@ -121,7 +135,9 @@ static void btPrintFloat(const char* op) {
 #define PRINT_OP_BYTE(op) PRINT_OP_BASE(op, Byte)
 #define PRINT_OP_INT(op) PRINT_OP_BASE(op, Int)
 #define PRINT_OP_INT2(op) PRINT_OP_BASE(op, Int2)
-#define PRINT_NUMBER_OP(op) PRINT_OP(OP_##op##_INT) PRINT_OP(OP_##op##_FLOAT)
+#define PRINT_OP_LONG(op) PRINT_OP_BASE(op, Long)
+#define PRINT_INTEGRAL_OP(op) PRINT_OP(OP_##op##_INT) PRINT_OP(OP_##op##_LONG)
+#define PRINT_NUMBER_OP(op) PRINT_INTEGRAL_OP(op) PRINT_OP(OP_##op##_FLOAT)
 #define PRINT_TYPES(TYPE)                                                      \
     PRINT_OP(OP_STORE_##TYPE);                                                 \
     PRINT_OP(OP_LOAD_##TYPE);                                                  \
@@ -132,9 +148,11 @@ static void btConsumeOperation() {
     Operation op = code->code[readIndex++];
     switch(op) {
         PRINT_TYPES(INT);
+        PRINT_TYPES(LONG);
         PRINT_TYPES(BOOL);
         PRINT_TYPES(FLOAT);
         PRINT_OP(OP_NOTHING);
+        PRINT_OP_LONG(OP_PUSH_LONG);
         PRINT_OP_INT(OP_PUSH_INT);
         PRINT_OP_BASE(OP_PUSH_FLOAT, Float);
         PRINT_OP(OP_PUSH_TRUE);
@@ -144,18 +162,19 @@ static void btConsumeOperation() {
         PRINT_NUMBER_OP(MUL);
         PRINT_NUMBER_OP(DIV);
         PRINT_OP(OP_MOD_INT);
+        PRINT_OP(OP_MOD_LONG);
         PRINT_NUMBER_OP(INVERT_SIGN);
         PRINT_NUMBER_OP(LESS);
         PRINT_NUMBER_OP(GREATER);
         PRINT_OP(OP_NOT);
         PRINT_OP(OP_AND);
         PRINT_OP(OP_OR);
-        PRINT_OP(OP_BIT_NOT);
-        PRINT_OP(OP_BIT_AND);
-        PRINT_OP(OP_BIT_OR);
-        PRINT_OP(OP_BIT_XOR);
-        PRINT_OP(OP_LEFT_SHIFT);
-        PRINT_OP(OP_RIGHT_SHIFT);
+        PRINT_INTEGRAL_OP(BIT_NOT);
+        PRINT_INTEGRAL_OP(BIT_AND);
+        PRINT_INTEGRAL_OP(BIT_OR);
+        PRINT_INTEGRAL_OP(BIT_XOR);
+        PRINT_INTEGRAL_OP(LEFT_SHIFT);
+        PRINT_INTEGRAL_OP(RIGHT_SHIFT);
         PRINT_NUMBER_OP(PRINT);
         PRINT_OP(OP_PRINT_BOOL);
         PRINT_OP(OP_PRINT_POINTER);
@@ -177,11 +196,18 @@ static void btConsumeOperation() {
         PRINT_OP_INT(OP_LOAD);
         PRINT_OP(OP_STORE_POINTER);
         PRINT_OP(OP_EQUAL_POINTER);
-        PRINT_OP_BYTE(OP_PUSH_PRE_INT_CHANGE);
-        PRINT_OP_BYTE(OP_PUSH_POST_INT_CHANGE);
-        PRINT_OP_BYTE(OP_INT_CHANGE);
+        PRINT_OP_BYTE(OP_PUSH_PRE_CHANGE_INT);
+        PRINT_OP_BYTE(OP_PUSH_POST_CHANGE_INT);
+        PRINT_OP_BYTE(OP_CHANGE_INT);
+        PRINT_OP_BYTE(OP_PUSH_PRE_CHANGE_LONG);
+        PRINT_OP_BYTE(OP_PUSH_POST_CHANGE_LONG);
+        PRINT_OP_BYTE(OP_CHANGE_LONG);
         PRINT_OP(OP_INT_TO_FLOAT);
         PRINT_OP(OP_FLOAT_TO_INT);
+        PRINT_OP(OP_INT_TO_LONG);
+        PRINT_OP(OP_LONG_TO_INT);
+        PRINT_OP(OP_FLOAT_TO_LONG);
+        PRINT_OP(OP_LONG_TO_FLOAT);
         case OP_LINE: sPrintLine(); break;
     }
 }

+ 34 - 26
vm/Operation.h

@@ -1,36 +1,40 @@
 #ifndef OPERATION_H
 #define OPERATION_H
 
-#define NUMBER_OPERATION(name) OP_##name##_INT, OP_##name##_FLOAT
-#define TYPE_OPERATION(name)                                                   \
-    OP_##name##_INT, OP_##name##_FLOAT, OP_##name##_BOOL
+#define OP_INTEGRAL(TYPE) OP_##TYPE##_INT, OP_##TYPE##_LONG
+#define OP_NUMBER(TYPE) OP_INTEGRAL(TYPE), OP_##TYPE##_FLOAT
+#define OP_TYPE(TYPE) OP_NUMBER(TYPE), OP_##TYPE##_BOOL
+#define OP_CHANGE_NUMBER(TYPE)                                                 \
+    OP_PUSH_PRE_##TYPE##_CHANGE, OP_PUSH_POST_##TYPE##_CHANGE,                 \
+        OP_##TYPE##_CHANGE
 
 typedef enum Operation {
     OP_NOTHING,
-    NUMBER_OPERATION(PUSH),
+    OP_NUMBER(PUSH),
     OP_PUSH_TRUE,
     OP_PUSH_FALSE,
-    NUMBER_OPERATION(ADD),
-    NUMBER_OPERATION(SUB),
-    NUMBER_OPERATION(MUL),
-    NUMBER_OPERATION(DIV),
+    OP_NUMBER(ADD),
+    OP_NUMBER(SUB),
+    OP_NUMBER(MUL),
+    OP_NUMBER(DIV),
     OP_MOD_INT,
-    NUMBER_OPERATION(INVERT_SIGN),
-    NUMBER_OPERATION(LESS),
-    NUMBER_OPERATION(GREATER),
-    NUMBER_OPERATION(EQUAL),
+    OP_MOD_LONG,
+    OP_NUMBER(INVERT_SIGN),
+    OP_NUMBER(LESS),
+    OP_NUMBER(GREATER),
+    OP_NUMBER(EQUAL),
     OP_EQUAL_BOOL,
     OP_EQUAL_POINTER,
     OP_NOT,
     OP_AND,
     OP_OR,
-    OP_BIT_NOT,
-    OP_BIT_AND,
-    OP_BIT_OR,
-    OP_BIT_XOR,
-    OP_LEFT_SHIFT,
-    OP_RIGHT_SHIFT,
-    TYPE_OPERATION(PRINT),
+    OP_INTEGRAL(BIT_NOT),
+    OP_INTEGRAL(BIT_AND),
+    OP_INTEGRAL(BIT_OR),
+    OP_INTEGRAL(BIT_XOR),
+    OP_INTEGRAL(LEFT_SHIFT),
+    OP_INTEGRAL(RIGHT_SHIFT),
+    OP_TYPE(PRINT),
     OP_PRINT_POINTER,
     OP_LINE,
     OP_GOTO,
@@ -39,12 +43,12 @@ typedef enum Operation {
     OP_PEEK_TRUE_GOTO,
     OP_GOSUB,
     OP_RETURN,
-    TYPE_OPERATION(RETURN),
+    OP_TYPE(RETURN),
     OP_RETURN_POINTER,
     OP_RESERVE,
     OP_LOAD,
-    TYPE_OPERATION(LOAD),
-    TYPE_OPERATION(STORE),
+    OP_TYPE(LOAD),
+    OP_TYPE(STORE),
     OP_DEREFERENCE_VAR,
     OP_REFERENCE,
     OP_DUPLICATE_REFERENCE,
@@ -53,11 +57,15 @@ typedef enum Operation {
     OP_DELETE,
     OP_LENGTH,
     OP_STORE_POINTER,
-    OP_PUSH_PRE_INT_CHANGE,
-    OP_PUSH_POST_INT_CHANGE,
-    OP_INT_CHANGE,
+    OP_INTEGRAL(PUSH_PRE_CHANGE),
+    OP_INTEGRAL(PUSH_POST_CHANGE),
+    OP_INTEGRAL(CHANGE),
     OP_FLOAT_TO_INT,
-    OP_INT_TO_FLOAT
+    OP_INT_TO_FLOAT,
+    OP_INT_TO_LONG,
+    OP_LONG_TO_INT,
+    OP_FLOAT_TO_LONG,
+    OP_LONG_TO_FLOAT,
 } Operation;
 
 #endif

+ 78 - 68
vm/Script.c

@@ -18,6 +18,10 @@ static void sIntPrinter(int i) {
     printf("%d\n", i);
 }
 
+static void sLongPrinter(long l) {
+    printf("%ld\n", l);
+}
+
 static void sFloatPrinter(float f) {
     printf("%.2f\n", f);
 }
@@ -31,6 +35,7 @@ static void sPointerPrinter(Pointer* b) {
 }
 
 static IntPrinter intPrinter = sIntPrinter;
+static LongPrinter longPrinter = sLongPrinter;
 static FloatPrinter floatPrinter = sFloatPrinter;
 static BoolPrinter boolPrinter = sBoolPrinter;
 static PointerPrinter pointerPrinter = sPointerPrinter;
@@ -124,6 +129,7 @@ static bool sPeek(Script* sc, void* data, int length) {
 #define ZERO_CHECK(name)                                                       \
     if(values[0] == 0) {                                                       \
         sError(sc, name " by 0");                                              \
+        return;                                                                \
     }
 
 #define OP_BASE(type, Type, RType, op, check)                                  \
@@ -145,6 +151,7 @@ static bool sPeek(Script* sc, void* data, int length) {
     CHECKED_NUMBER_OP(type, Type, %, ZERO_CHECK("module"));
 
 READ_POP_PUSH(int, Int)
+READ_POP_PUSH(long, Long)
 READ_POP_PUSH(float, Float)
 POP_PUSH(bool, Bool)
 
@@ -216,13 +223,20 @@ static void sNot(Script* sc) {
     }
 }
 
-static void sBitNot(Script* sc) {
+static void sBitNotInt(Script* sc) {
     int value = 0;
     if(sPopInt(sc, &value)) {
         sPushInt(sc, ~value);
     }
 }
 
+static void sBitNotLong(Script* sc) {
+    long value = 0;
+    if(sPopLong(sc, &value)) {
+        sPushLong(sc, ~value);
+    }
+}
+
 static void sLine(Script* sc) {
     sRead(sc, &sc->line, 2);
 }
@@ -418,71 +432,49 @@ static void sEqualPointer(Script* sc) {
     }
 }
 
-static void sPushPreIntChange(Script* sc) {
-    char c = 0;
-    Pointer p;
-    if(sRead(sc, &c, sizeof(char)) && sPopPointer(sc, &p)) {
-        void* data = sCheckAddress(sc, &p, sizeof(int));
-        if(data != NULL) {
-            int current = 0;
-            memcpy(&current, data, sizeof(int));
-            current += c;
-            sPushInt(sc, current);
-            memcpy(data, &current, sizeof(int));
-        }
-    }
-}
-
-static void sPushPostIntChange(Script* sc) {
-    char c = 0;
-    Pointer p;
-    if(sRead(sc, &c, sizeof(char)) && sPopPointer(sc, &p)) {
-        void* data = sCheckAddress(sc, &p, sizeof(int));
-        if(data != NULL) {
-            int current = 0;
-            memcpy(&current, data, sizeof(int));
-            sPushInt(sc, current);
-            current += c;
-            memcpy(data, &current, sizeof(int));
-        }
-    }
-}
-
-static void sIntChange(Script* sc) {
-    char c = 0;
-    Pointer p;
-    if(sRead(sc, &c, sizeof(char)) && sPopPointer(sc, &p)) {
-        void* data = sCheckAddress(sc, &p, sizeof(int));
-        if(data != NULL) {
-            int current = 0;
-            memcpy(&current, data, sizeof(int));
-            current += c;
-            memcpy(data, &current, sizeof(int));
-        }
-    }
-}
-
-static void sIntToFloat(Script* sc) {
-    int i = 0;
-    if(sPopInt(sc, &i)) {
-        sPushFloat(sc, i);
+#define CHANGE_OP(type, op)                                                    \
+    {                                                                          \
+        char c = 0;                                                            \
+        Pointer p;                                                             \
+        if(sRead(sc, &c, sizeof(char)) && sPopPointer(sc, &p)) {               \
+            void* data = sCheckAddress(sc, &p, sizeof(type));                  \
+            if(data != NULL) {                                                 \
+                type current;                                                  \
+                memcpy(&current, data, sizeof(type));                          \
+                op                                                             \
+            }                                                                  \
+        }                                                                      \
     }
-}
-
-static void sFloatToInt(Script* sc) {
-    float f = 0;
-    if(sPopFloat(sc, &f)) {
-        sPushInt(sc, f);
+#define PUSH_PRE_CHANGE(Type, type)                                            \
+    CHANGE_OP(type, current += c; sPush##Type(sc, current);                    \
+              memcpy(data, &current, sizeof(type));)
+#define PUSH_POST_CHANGE(Type, type)                                           \
+    CHANGE_OP(type, sPush##Type(sc, current); current += c;                    \
+              memcpy(data, &current, sizeof(type));)
+#define CHANGE(type)                                                           \
+    CHANGE_OP(type, current += c; memcpy(data, &current, sizeof(type));)
+#define CAST(From, from, To)                                                   \
+    {                                                                          \
+        from value;                                                            \
+        if(sPop##From(sc, &value)) {                                           \
+            sPush##To(sc, value);                                              \
+        }                                                                      \
     }
-}
-
+#define CASE_CHANGE(TYPE, Type, type)                                          \
+    case OP_PUSH_PRE_CHANGE_##TYPE: PUSH_PRE_CHANGE(Type, type); break;        \
+    case OP_PUSH_POST_CHANGE_##TYPE: PUSH_POST_CHANGE(Type, type); break;      \
+    case OP_CHANGE_##TYPE:                                                     \
+        CHANGE(type);                                                          \
+        break;
 #define CASE_NUMBER_OP(name, op)                                               \
     case OP_##name##_INT: NUMBER_OP(int, Int, op); break;                      \
+    case OP_##name##_LONG: NUMBER_OP(long, Long, op); break;                   \
     case OP_##name##_FLOAT:                                                    \
         NUMBER_OP(float, Float, op);                                           \
         break;
 #define CASE_BOOL_OP(name, op)                                                 \
     case OP_##name##_INT: BOOL_OP(int, Int, op); break;                        \
+    case OP_##name##_LONG: BOOL_OP(long, Long, op); break;                     \
     case OP_##name##_FLOAT:                                                    \
         BOOL_OP(float, Float, op);                                             \
         break;
@@ -501,27 +493,40 @@ static void sConsumeInstruction(Script* sc) {
         CASE_BOOL_OP(LESS, <);
         CASE_BOOL_OP(GREATER, >);
         CASE_TYPE(INT, Int, int);
+        CASE_TYPE(LONG, Long, long);
         CASE_TYPE(BOOL, Bool, bool);
         CASE_TYPE(FLOAT, Float, float);
+        CASE_CHANGE(INT, Int, int);
+        CASE_CHANGE(LONG, Long, long);
         case OP_NOTHING: break;
         case OP_PUSH_INT: PUSH_CONSTANT(int, Int); break;
+        case OP_PUSH_LONG: PUSH_CONSTANT(long, Long); break;
         case OP_PUSH_FLOAT: PUSH_CONSTANT(float, Float); break;
         case OP_PUSH_TRUE: sPushBool(sc, true); break;
         case OP_PUSH_FALSE: sPushBool(sc, false); break;
         case OP_DIV_INT: DIVISION(int, Int); break;
+        case OP_DIV_LONG: DIVISION(long, Long); break;
         case OP_DIV_FLOAT: DIVISION(float, Float); break;
         case OP_MOD_INT: MODULE(int, Int); break;
+        case OP_MOD_LONG: MODULE(long, Long); break;
         case OP_INVERT_SIGN_INT: INVERT_SIGN(int, Int); break;
+        case OP_INVERT_SIGN_LONG: INVERT_SIGN(long, Long); break;
         case OP_INVERT_SIGN_FLOAT: INVERT_SIGN(float, Float); break;
         case OP_NOT: sNot(sc); break;
         case OP_AND: BOOL_OP(bool, Bool, &&); break;
         case OP_OR: BOOL_OP(bool, Bool, ||); break;
-        case OP_BIT_NOT: sBitNot(sc); break;
-        case OP_BIT_AND: NUMBER_OP(int, Int, &); break;
-        case OP_BIT_OR: NUMBER_OP(int, Int, |); break;
-        case OP_BIT_XOR: NUMBER_OP(int, Int, ^); break;
-        case OP_LEFT_SHIFT: NUMBER_OP(int, Int, <<); break;
-        case OP_RIGHT_SHIFT: NUMBER_OP(int, Int, >>); break;
+        case OP_BIT_NOT_INT: sBitNotInt(sc); break;
+        case OP_BIT_AND_INT: NUMBER_OP(int, Int, &); break;
+        case OP_BIT_OR_INT: NUMBER_OP(int, Int, |); break;
+        case OP_BIT_XOR_INT: NUMBER_OP(int, Int, ^); break;
+        case OP_LEFT_SHIFT_INT: NUMBER_OP(int, Int, <<); break;
+        case OP_RIGHT_SHIFT_INT: NUMBER_OP(int, Int, >>); break;
+        case OP_BIT_NOT_LONG: sBitNotLong(sc); break;
+        case OP_BIT_AND_LONG: NUMBER_OP(long, Long, &); break;
+        case OP_BIT_OR_LONG: NUMBER_OP(long, Long, |); break;
+        case OP_BIT_XOR_LONG: NUMBER_OP(long, Long, ^); break;
+        case OP_LEFT_SHIFT_LONG: NUMBER_OP(long, Long, <<); break;
+        case OP_RIGHT_SHIFT_LONG: NUMBER_OP(long, Long, >>); break;
         case OP_LINE: sLine(sc); break;
         case OP_GOTO: sGoTo(sc); break;
         case OP_IF_GOTO: sIfGoTo(sc); break;
@@ -542,11 +547,12 @@ static void sConsumeInstruction(Script* sc) {
         case OP_STORE_POINTER: sStore(sc, sizeof(Pointer)); break;
         case OP_PRINT_POINTER: sPrintPointer(sc); break;
         case OP_EQUAL_POINTER: sEqualPointer(sc); break;
-        case OP_PUSH_PRE_INT_CHANGE: sPushPreIntChange(sc); break;
-        case OP_PUSH_POST_INT_CHANGE: sPushPostIntChange(sc); break;
-        case OP_INT_CHANGE: sIntChange(sc); break;
-        case OP_INT_TO_FLOAT: sIntToFloat(sc); break;
-        case OP_FLOAT_TO_INT: sFloatToInt(sc); break;
+        case OP_INT_TO_FLOAT: CAST(Int, int, Float); break;
+        case OP_FLOAT_TO_INT: CAST(Float, float, Int); break;
+        case OP_INT_TO_LONG: CAST(Int, int, Long); break;
+        case OP_LONG_TO_INT: CAST(Long, long, Int); break;
+        case OP_FLOAT_TO_LONG: CAST(Float, float, Long); break;
+        case OP_LONG_TO_FLOAT: CAST(Long, long, Float); break;
     }
 }
 
@@ -588,6 +594,10 @@ void sSetIntPrinter(IntPrinter p) {
     intPrinter = p;
 }
 
+void sSetLongPrinter(LongPrinter p) {
+    longPrinter = p;
+}
+
 void sSetFloatPrinter(FloatPrinter p) {
     floatPrinter = p;
 }

+ 2 - 0
vm/Script.h

@@ -27,6 +27,8 @@ void sRun(Script* sc);
 
 typedef void (*IntPrinter)(int);
 void sSetIntPrinter(IntPrinter p);
+typedef void (*LongPrinter)(long);
+void sSetLongPrinter(LongPrinter p);
 typedef void (*FloatPrinter)(float);
 void sSetFloatPrinter(FloatPrinter p);
 typedef void (*BoolPrinter)(bool);