Browse Source

type casts between float and int

Kajetan Johannes Hammerle 3 years ago
parent
commit
328a5b8a34
8 changed files with 69 additions and 6 deletions
  1. 21 0
      Compiler.c
  2. 14 0
      tests/cast
  3. 8 0
      tests/cast.out
  4. 1 1
      tests/pre/list_test
  5. 4 4
      tests/pre/list_test.out
  6. 2 0
      utils/ByteCodePrinter.c
  7. 3 1
      vm/Operation.h
  8. 16 0
      vm/Script.c

+ 21 - 0
Compiler.c

@@ -442,6 +442,27 @@ static DataType cInvertSign(DataType dt) {
 }
 
 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();
+        } 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();
+        }
+    }
+    tReset(marker);
     if(cConsumeTokenIf(T_INCREMENT)) {
         return cPreChange(cPreUnary(), 1, "++");
     } else if(cConsumeTokenIf(T_DECREMENT)) {

+ 14 - 0
tests/cast

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

+ 8 - 0
tests/cast.out

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

+ 1 - 1
tests/pre/list_test

@@ -6,7 +6,7 @@ void main() {
 
     for(int i = 0; i < 5; i++) {
         listAdd(intList, i * 50 + 3);
-        listAdd(floatList, 3.0);
+        listAdd(floatList, (float)i * 3.0);
     }
     
     for(int i = 0; i < listGetLength(intList); i++) {

+ 4 - 4
tests/pre/list_test.out

@@ -3,8 +3,8 @@
 103
 153
 203
+0.00
 3.00
-3.00
-3.00
-3.00
-3.00
+6.00
+9.00
+12.00

+ 2 - 0
utils/ByteCodePrinter.c

@@ -180,6 +180,8 @@ static void btConsumeOperation() {
         PRINT_OP_BYTE(OP_PUSH_PRE_INT_CHANGE);
         PRINT_OP_BYTE(OP_PUSH_POST_INT_CHANGE);
         PRINT_OP_BYTE(OP_INT_CHANGE);
+        PRINT_OP(OP_INT_TO_FLOAT);
+        PRINT_OP(OP_FLOAT_TO_INT);
         case OP_LINE: sPrintLine(); break;
     }
 }

+ 3 - 1
vm/Operation.h

@@ -55,7 +55,9 @@ typedef enum Operation {
     OP_STORE_POINTER,
     OP_PUSH_PRE_INT_CHANGE,
     OP_PUSH_POST_INT_CHANGE,
-    OP_INT_CHANGE
+    OP_INT_CHANGE,
+    OP_FLOAT_TO_INT,
+    OP_INT_TO_FLOAT
 } Operation;
 
 #endif

+ 16 - 0
vm/Script.c

@@ -462,6 +462,20 @@ static void sIntChange(Script* sc) {
     }
 }
 
+static void sIntToFloat(Script* sc) {
+    int i = 0;
+    if(sPopInt(sc, &i)) {
+        sPushFloat(sc, i);
+    }
+}
+
+static void sFloatToInt(Script* sc) {
+    float f = 0;
+    if(sPopFloat(sc, &f)) {
+        sPushInt(sc, f);
+    }
+}
+
 #define CASE_NUMBER_OP(name, op)                                               \
     case OP_##name##_INT: NUMBER_OP(int, Int, op); break;                      \
     case OP_##name##_FLOAT:                                                    \
@@ -531,6 +545,8 @@ static void sConsumeInstruction(Script* sc) {
         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;
     }
 }