Browse Source

unary minus

Kajetan Johannes Hammerle 3 years ago
parent
commit
dad5b76b5a
9 changed files with 35 additions and 4 deletions
  1. 13 4
      Compiler.c
  2. 1 0
      Operation.h
  3. 15 0
      Script.c
  4. 1 0
      tests/calc/add
  5. 1 0
      tests/calc/add.out
  6. 1 0
      tests/calc/mul
  7. 1 0
      tests/calc/mul.out
  8. 1 0
      tests/calc/sub
  9. 1 0
      tests/calc/sub.out

+ 13 - 4
Compiler.c

@@ -198,17 +198,26 @@ static void cPrimary() {
     }
 }
 
-static void cMul() {
+static void cPreUnary() {
+    if(cConsumeTokenIf(T_SUB)) {
+        cPrimary();
+        cAddOperation(OP_INVERT_SIGN);
+        return;
+    }
     cPrimary();
+}
+
+static void cMul() {
+    cPreUnary();
     while(true) {
         if(cConsumeTokenIf(T_MUL)) {
-            cPrimary();
+            cPreUnary();
             cAddOperation(OP_MUL);
         } else if(cConsumeTokenIf(T_DIV)) {
-            cPrimary();
+            cPreUnary();
             cAddOperation(OP_DIV);
         } else if(cConsumeTokenIf(T_MOD)) {
-            cPrimary();
+            cPreUnary();
             cAddOperation(OP_MOD);
         } else {
             break;

+ 1 - 0
Operation.h

@@ -18,6 +18,7 @@ typedef enum Operation {
     OP_MUL,
     OP_DIV,
     OP_MOD,
+    OP_INVERT_SIGN,
     OP_LESS,
     OP_GREATER,
     OP_EQUAL,

+ 15 - 0
Script.c

@@ -257,6 +257,19 @@ static bool sFloatGreater(float a, float b) {
     return b > a;
 }
 
+static void sInvertSign(Script* sc) {
+    Object* o = sPeek(sc);
+    if(o == NULL) {
+        return;
+    } else if(o->type == OT_INT) {
+        o->data.intValue = -o->data.intValue;
+    } else if(o->type == OT_FLOAT) {
+        o->data.floatValue = -o->data.floatValue;
+    } else {
+        sError(sc, "object is not a number on line %d", sc->line);
+    }
+}
+
 static void sEqual(Script* sc) {
     Object o[2];
     if(sPop(sc, o) || sPop(sc, o + 1)) {
@@ -381,6 +394,7 @@ static void sConsumeInstruction(Script* sc) {
         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_INVERT_SIGN: sInvertSign(sc); break;
         case OP_LESS: sBoolBinary(sc, sIntLess, sFloatLess); break;
         case OP_GREATER: sBoolBinary(sc, sIntGreater, sFloatGreater); break;
         case OP_EQUAL: sEqual(sc); break;
@@ -481,6 +495,7 @@ void sPrintCode(Script* sc) {
             case OP_MUL: puts("Mul"); break;
             case OP_DIV: puts("Div"); break;
             case OP_MOD: puts("Mod"); break;
+            case OP_INVERT_SIGN: puts("Invert Sign"); break;
             case OP_LESS: puts("Less"); break;
             case OP_GREATER: puts("Greater"); break;
             case OP_EQUAL: puts("Equal"); break;

+ 1 - 0
tests/calc/add

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

+ 1 - 0
tests/calc/add.out

@@ -5,3 +5,4 @@
 9.00
 5.00
 3.00
+-2

+ 1 - 0
tests/calc/multiply → tests/calc/mul

@@ -5,3 +5,4 @@ print (3 + 4) * 5;
 print ((3 + 2) * (5 + 1));
 print ((3 + 2.0) * (5 + 1));
 print ((3 + 2) * (5 + 1.0));
+print -3 * -5;

+ 1 - 0
tests/calc/multiply.out → tests/calc/mul.out

@@ -5,3 +5,4 @@
 30
 30.00
 30.00
+15

+ 1 - 0
tests/calc/sub

@@ -1,3 +1,4 @@
 print 0 - 5;
 print 2 - 5 + 3 - 6;
 print 2 - (5 + 3) - 6;
+print -(7 - 8);

+ 1 - 0
tests/calc/sub.out

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