Browse Source

refactored binary operations by using makros

Kajetan Johannes Hammerle 3 years ago
parent
commit
42a02a5dd2
1 changed files with 89 additions and 160 deletions
  1. 89 160
      Script.c

+ 89 - 160
Script.c

@@ -20,7 +20,9 @@ static bool sPrinter(Object* o) {
         case OT_FLOAT: printf("%.2f\n", o->data.floatValue); return false;
         case OT_CONST_STRING: printf("%s\n", o->data.stringValue); return false;
         case OT_NULL: printf("null\n"); return false;
-        case OT_BOOL: printf(o->data.intValue ? "true\n" : "false\n"); return false;
+        case OT_BOOL:
+            printf(o->data.intValue ? "true\n" : "false\n");
+            return false;
         case OT_ARRAY: printf("array\n"); return false;
         default: return true;
     }
@@ -30,7 +32,9 @@ static ObjectPrinter printer = sPrinter;
 
 static bool sRead(Script* sc, void* buffer, int length) {
     if(sc->readIndex + length > sc->code->length) {
-        sError(sc, "cannot read expected %d bytes of data from bytecode on line %d", sc->line);
+        sError(sc,
+               "cannot read expected %d bytes of data from bytecode on line %d",
+               sc->line);
         return true;
     }
     memcpy(buffer, sc->code->code + sc->readIndex, length);
@@ -110,7 +114,9 @@ static void sPushBool(Script* sc, bool value) {
 }
 
 static void sPushReference(Script* sc, int pointer, int index) {
-    Object o = {.type = OT_REFERENCE, .data.reference.pointer = pointer, .data.reference.index = index};
+    Object o = {.type = OT_REFERENCE,
+                .data.reference.pointer = pointer,
+                .data.reference.index = index};
     sPush(sc, &o);
 }
 
@@ -160,16 +166,19 @@ static Object* sDereference(Script* sc, Object* reference) {
     int index = reference->data.reference.index;
     if(pointer == -1) {
         if(index < 0 || index >= sc->stackIndex) {
-            sError(sc, "variable reference index exceeds stack on line %d", sc->line);
+            sError(sc, "variable reference index exceeds stack on line %d",
+                   sc->line);
             return NULL;
         }
         return sc->stack + index;
     } else {
         if(pointer < 0 || pointer >= sc->allocator.capacity) {
-            sError(sc, "array reference pointer is out of range on line %d\n", sc->line);
+            sError(sc, "array reference pointer is out of range on line %d\n",
+                   sc->line);
             return NULL;
         } else if(index < 0 || index >= sc->allocator.data[pointer].length) {
-            sError(sc, "array reference index is out of bounds on line %d\n", sc->line);
+            sError(sc, "array reference index is out of bounds on line %d\n",
+                   sc->line);
             return NULL;
         }
         return sc->allocator.data[pointer].data + index;
@@ -209,7 +218,9 @@ static void sAllocateArray(Script* sc) {
             sError(sc, "negative array length on line %d", sc->line);
             return;
         }
-        Object o = {.type = OT_ARRAY, .data.intValue = aAllocate(&sc->allocator, length.data.intValue)};
+        Object o = {.type = OT_ARRAY,
+                    .data.intValue =
+                        aAllocate(&sc->allocator, length.data.intValue)};
         sPush(sc, &o);
     }
 }
@@ -234,7 +245,8 @@ static void sPreChange(Script* sc, int change) {
         } else if(o->type == OT_FLOAT) {
             o->data.floatValue += change;
         } else {
-            sError(sc, "variable is '%s' not a number on line %d", oGetName(o->type), sc->line);
+            sError(sc, "variable is '%s' not a number on line %d",
+                   oGetName(o->type), sc->line);
             return;
         }
         sPush(sc, o);
@@ -259,7 +271,8 @@ static void sPostChange(Script* sc, int change) {
             sPush(sc, o);
             o->data.floatValue += change;
         } else {
-            sError(sc, "variable is '%s' not a number on line %d", oGetName(o->type), sc->line);
+            sError(sc, "variable is '%s' not a number on line %d",
+                   oGetName(o->type), sc->line);
         }
     }
 }
@@ -282,7 +295,8 @@ static void sPushCodeInt(Script* sc) {
 static void sPushCodeFloat(Script* sc) {
     float value = 0;
     if(sRead(sc, &value, sizeof(float))) {
-        sError(sc, "cannot read a float from the bytecode on line %d", sc->line);
+        sError(sc, "cannot read a float from the bytecode on line %d",
+               sc->line);
         return;
     }
     sPushFloat(sc, value);
@@ -298,134 +312,41 @@ static void sPushCodeString(Script* sc) {
     }
 }
 
-static void sNumberBinary(Script* sc, int (*fInt)(Script*, int, int), float (*fFloat)(float, float)) {
-    Object o[2];
-    if(sPop(sc, o) || sPop(sc, o + 1)) {
-        return;
-    } else if(o[0].type == OT_INT && o[1].type == OT_INT) {
-        sPushInt(sc, fInt(sc, o[0].data.intValue, o[1].data.intValue));
-    } else if(o[0].type == OT_FLOAT && o[1].type == OT_INT) {
-        sPushFloat(sc, fFloat(o[0].data.floatValue, o[1].data.intValue));
-    } else if(o[0].type == OT_INT && o[1].type == OT_FLOAT) {
-        sPushFloat(sc, fFloat(o[0].data.intValue, o[1].data.floatValue));
-    } else if(o[0].type == OT_FLOAT && o[1].type == OT_FLOAT) {
-        sPushFloat(sc, fFloat(o[0].data.floatValue, o[1].data.floatValue));
-    } else {
-        sError(sc, "object is not a number on line %d", sc->line);
-    }
-}
-
-static void sIntBinary(Script* sc, int (*f)(Script*, int, int)) {
-    Object o[2];
-    if(!sPop(sc, o) && !sPop(sc, o + 1) && sCheckType(sc, o, OT_INT) && sCheckType(sc, o + 1, OT_INT)) {
-        sPushInt(sc, f(sc, o[0].data.intValue, o[1].data.intValue));
-    }
-}
-
-static int sIntAdd(Script* sc, int a, int b) {
-    (void)sc;
-    return a + b;
-}
-
-static int sIntSub(Script* sc, int a, int b) {
-    (void)sc;
-    return b - a;
-}
-
-static int sIntMul(Script* sc, int a, int b) {
-    (void)sc;
-    return a * b;
-}
-
-static int sIntDiv(Script* sc, int a, int b) {
-    if(a == 0) {
-        sError(sc, "division by 0 on line %d", sc->line);
-        return b;
-    }
-    return b / a;
-}
-
-static int sMod(Script* sc, int a, int b) {
-    if(a == 0) {
-        sError(sc, "module of 0 on line %d", sc->line);
-        return b;
-    }
-    return b % a;
-}
-
-static int sBitAnd(Script* sc, int a, int b) {
-    (void)sc;
-    return b & a;
-}
-
-static int sBitOr(Script* sc, int a, int b) {
-    (void)sc;
-    return b | a;
-}
-
-static int sBitXor(Script* sc, int a, int b) {
-    (void)sc;
-    return b ^ a;
-}
-
-static int sLeftShift(Script* sc, int a, int b) {
-    (void)sc;
-    return b << a;
-}
-
-static int sRightShift(Script* sc, int a, int b) {
-    (void)sc;
-    return b >> a;
-}
-
-static float sFloatAdd(float a, float b) {
-    return a + b;
-}
-
-static float sFloatSub(float a, float b) {
-    return b - a;
-}
-
-static float sFloatMul(float a, float b) {
-    return a * b;
-}
-
-static float sFloatDiv(float a, float b) {
-    return b / a;
-}
-
-static void sBoolBinary(Script* sc, bool (*fInt)(int, int), bool (*fFloat)(float, float)) {
-    Object o[2];
-    if(sPop(sc, o) || sPop(sc, o + 1)) {
-        return;
-    } else if(o[0].type == OT_INT && o[1].type == OT_INT) {
-        sPushBool(sc, fInt(o[0].data.intValue, o[1].data.intValue));
-    } else if(o[0].type == OT_FLOAT && o[1].type == OT_INT) {
-        sPushBool(sc, fFloat(o[0].data.floatValue, o[1].data.intValue));
-    } else if(o[0].type == OT_INT && o[1].type == OT_FLOAT) {
-        sPushBool(sc, fFloat(o[0].data.intValue, o[1].data.floatValue));
-    } else if(o[0].type == OT_FLOAT && o[1].type == OT_FLOAT) {
-        sPushBool(sc, fFloat(o[0].data.floatValue, o[1].data.floatValue));
-    } else {
-        sError(sc, "object is not a number on line %d", sc->line);
-    }
-}
-
-static bool sIntLess(int a, int b) {
-    return b < a;
-}
-
-static bool sIntGreater(int a, int b) {
-    return b > a;
-}
-
-static bool sFloatLess(float a, float b) {
-    return b < a;
-}
-
-static bool sFloatGreater(float a, float b) {
-    return b > a;
-}
+#define CHECKED_NUMBER_OP(check, op, typeA, typeB)                             \
+    {                                                                          \
+        Object o[2];                                                           \
+        if(sPop(sc, o) || sPop(sc, o + 1)) {                                   \
+            return;                                                            \
+        } else if(o[0].type == OT_INT && o[1].type == OT_INT) {                \
+            check sPush##typeA(sc, o[1].data.intValue op o[0].data.intValue);  \
+        } else if(o[0].type == OT_INT && o[1].type == OT_FLOAT) {              \
+            sPush##typeB(sc, o[1].data.floatValue op o[0].data.intValue);      \
+        } else if(o[0].type == OT_FLOAT && o[1].type == OT_INT) {              \
+            sPush##typeB(sc, o[1].data.intValue op o[0].data.floatValue);      \
+        } else if(o[0].type == OT_FLOAT && o[1].type == OT_FLOAT) {            \
+            sPush##typeB(sc, o[1].data.floatValue op o[0].data.floatValue);    \
+        } else {                                                               \
+            sError(sc, "object is not a number on line %d", sc->line);         \
+        }                                                                      \
+    }
+#define NUMBER_NUMBER_OP(op) CHECKED_NUMBER_OP(, op, Int, Float)
+#define NUMBER_BOOL_OP(op) CHECKED_NUMBER_OP(, op, Bool, Bool)
+#define CHECKED_INT_OP(check, op)                                              \
+    {                                                                          \
+        Object o[2];                                                           \
+        if(!sPop(sc, o) && !sPop(sc, o + 1) && sCheckType(sc, o, OT_INT) &&    \
+           sCheckType(sc, o + 1, OT_INT)) {                                    \
+            check sPushInt(sc, o[1].data.intValue op o[0].data.intValue);      \
+        }                                                                      \
+    }
+#define INT_OP(op) CHECKED_INT_OP(, op)
+#define ZERO_CHECK(op)                                                         \
+    if(o[0].data.intValue == 0) {                                              \
+        sError(sc, op " by 0 on line %d", sc->line);                           \
+        return;                                                                \
+    }
+#define DIVISION CHECKED_NUMBER_OP(ZERO_CHECK("division"), /, Int, Float)
+#define MODULE CHECKED_INT_OP(ZERO_CHECK("module"), %);
 
 static void sInvertSign(Script* sc) {
     Object* o = sPeek(sc);
@@ -477,14 +398,16 @@ static void sBitNot(Script* sc) {
 
 static void sAnd(Script* sc) {
     Object o[2];
-    if(!sPop(sc, o) && !sPop(sc, o + 1) && sCheckType(sc, o, OT_BOOL) && sCheckType(sc, o + 1, OT_BOOL)) {
+    if(!sPop(sc, o) && !sPop(sc, o + 1) && sCheckType(sc, o, OT_BOOL) &&
+       sCheckType(sc, o + 1, OT_BOOL)) {
         sPushBool(sc, o[0].data.intValue && o[1].data.intValue);
     }
 }
 
 static void sOr(Script* sc) {
     Object o[2];
-    if(!sPop(sc, o) && !sPop(sc, o + 1) && sCheckType(sc, o, OT_BOOL) && sCheckType(sc, o + 1, OT_BOOL)) {
+    if(!sPop(sc, o) && !sPop(sc, o + 1) && sCheckType(sc, o, OT_BOOL) &&
+       sCheckType(sc, o + 1, OT_BOOL)) {
         sPushBool(sc, o[0].data.intValue || o[1].data.intValue);
     }
 }
@@ -515,7 +438,8 @@ static void sGoSub(Script* sc) {
     if(sReadInt(sc, &gotoIndex) && sReadInt(sc, &arguments)) {
         int returnStackIndex = sc->stackIndex - arguments - 1;
         if(returnStackIndex < 0 || sc->stack[returnStackIndex].type != OT_INT) {
-            sError(sc, "cannot find return address entry on stack on line %d", sc->line);
+            sError(sc, "cannot find return address entry on stack on line %d",
+                   sc->line);
             return;
         }
         sc->stack[returnStackIndex].data.intValue = sc->readIndex;
@@ -526,7 +450,8 @@ static void sGoSub(Script* sc) {
 static void sIfGoTo(Script* sc) {
     int gotoIndex;
     Object o;
-    if(sReadInt(sc, &gotoIndex) && !sPop(sc, &o) && sCheckType(sc, &o, OT_BOOL) && !o.data.intValue) {
+    if(sReadInt(sc, &gotoIndex) && !sPop(sc, &o) &&
+       sCheckType(sc, &o, OT_BOOL) && !o.data.intValue) {
         sc->readIndex = gotoIndex;
     }
 }
@@ -554,9 +479,7 @@ static void sDuplicate(Script* sc) {
 }
 
 static void sConsumeInstruction(Script* sc) {
-    Operation op = sReadOperation(sc);
-    // printf("Operation: %d\n", op);
-    switch(op) {
+    switch(sReadOperation(sc)) {
         case OP_NOTHING: break;
         case OP_PUSH_INT: sPushCodeInt(sc); break;
         case OP_PUSH_FLOAT: sPushCodeFloat(sc); break;
@@ -572,24 +495,24 @@ static void sConsumeInstruction(Script* sc) {
         case OP_POST_INCREMENT: sPostIncrement(sc); break;
         case OP_PRE_DECREMENT: sPreDecrement(sc); break;
         case OP_POST_DECREMENT: sPostDecrement(sc); break;
-        case OP_ADD: sNumberBinary(sc, sIntAdd, sFloatAdd); break;
-        case OP_SUB: sNumberBinary(sc, sIntSub, sFloatSub); break;
-        case OP_MUL: sNumberBinary(sc, sIntMul, sFloatMul); break;
-        case OP_DIV: sNumberBinary(sc, sIntDiv, sFloatDiv); break;
-        case OP_MOD: sIntBinary(sc, sMod); break;
+        case OP_ADD: NUMBER_NUMBER_OP(+); break;
+        case OP_SUB: NUMBER_NUMBER_OP(-); break;
+        case OP_MUL: NUMBER_NUMBER_OP(*); break;
+        case OP_DIV: DIVISION; break;
+        case OP_MOD: MODULE; break;
         case OP_INVERT_SIGN: sInvertSign(sc); break;
-        case OP_LESS: sBoolBinary(sc, sIntLess, sFloatLess); break;
-        case OP_GREATER: sBoolBinary(sc, sIntGreater, sFloatGreater); break;
+        case OP_LESS: NUMBER_BOOL_OP(<); break;
+        case OP_GREATER: NUMBER_BOOL_OP(>); break;
         case OP_EQUAL: sEqual(sc); break;
         case OP_NOT: sNot(sc); break;
         case OP_AND: sAnd(sc); break;
         case OP_OR: sOr(sc); break;
         case OP_BIT_NOT: sBitNot(sc); break;
-        case OP_BIT_AND: sIntBinary(sc, sBitAnd); break;
-        case OP_BIT_OR: sIntBinary(sc, sBitOr); break;
-        case OP_BIT_XOR: sIntBinary(sc, sBitXor); break;
-        case OP_LEFT_SHIFT: sIntBinary(sc, sLeftShift); break;
-        case OP_RIGHT_SHIFT: sIntBinary(sc, sRightShift); break;
+        case OP_BIT_AND: INT_OP(&); break;
+        case OP_BIT_OR: INT_OP(|); break;
+        case OP_BIT_XOR: INT_OP(^); break;
+        case OP_LEFT_SHIFT: INT_OP(<<); break;
+        case OP_RIGHT_SHIFT: INT_OP(>>); break;
         case OP_PRINT: sPrint(sc); break;
         case OP_LINE: sLine(sc); break;
         case OP_GOTO: sGoTo(sc); break;
@@ -705,7 +628,9 @@ void sPrintCode(Script* sc) {
             case OP_NOTHING: puts("Nothing"); break;
             case OP_PUSH_INT: sPrintInt(sc, "Push Int"); break;
             case OP_PUSH_FLOAT: sPrintFloat(sc, "Push Float"); break;
-            case OP_PUSH_CONST_STRING: sPrintString(sc, "Push Const String"); break;
+            case OP_PUSH_CONST_STRING:
+                sPrintString(sc, "Push Const String");
+                break;
             case OP_PUSH_NULL: puts("Push null"); break;
             case OP_PUSH_TRUE: puts("Push true"); break;
             case OP_PUSH_FALSE: puts("Push false"); break;
@@ -745,8 +670,12 @@ void sPrintCode(Script* sc) {
             case OP_DUPLICATE: puts("Duplicate"); break;
             case OP_ALLOCATE_ARRAY: puts("Allocate Array"); break;
             case OP_ARRAY_LENGTH: puts("Array Length"); break;
-            case OP_REFERENCE_FROM_VAR: sPrintInt(sc, "Reference From Var"); break;
-            case OP_REFERENCE_FROM_ARRAY: sPrintInt(sc, "Reference From Array"); break;
+            case OP_REFERENCE_FROM_VAR:
+                sPrintInt(sc, "Reference From Var");
+                break;
+            case OP_REFERENCE_FROM_ARRAY:
+                sPrintInt(sc, "Reference From Array");
+                break;
             case OP_DEREFERENCE: puts("Dereference"); break;
         }
     }