Browse Source

pre and post decrement

Kajetan Johannes Hammerle 3 years ago
parent
commit
8fad43916c
9 changed files with 106 additions and 1 deletions
  1. 25 0
      Compiler.c
  2. 2 0
      Operation.h
  3. 36 0
      Script.c
  4. 2 1
      Tokenizer.c
  5. 1 0
      Tokenizer.h
  6. 10 0
      tests/loops/while_post_dec
  7. 10 0
      tests/loops/while_post_dec.out
  8. 10 0
      tests/loops/while_pre_dec
  9. 10 0
      tests/loops/while_pre_dec.out

+ 25 - 0
Compiler.c

@@ -177,12 +177,19 @@ static void cPostIncrement(const char* literal) {
     cAddInt(cAddVar(literal));
 }
 
+static void cPostDecrement(const char* literal) {
+    cAddOperation(OP_POST_DECREMENT);
+    cAddInt(cAddVar(literal));
+}
+
 static void cLiteral() {
     const char* literal = cReadString();
     if(cConsumeTokenIf(T_OPEN_BRACKET)) {
         cCallFunction(literal, false);
     } else if(cConsumeTokenIf(T_INCREMENT)) {
         cPostIncrement(literal);
+    } else if(cConsumeTokenIf(T_DECREMENT)) {
+        cPostDecrement(literal);
     } else {
         cGetVar(literal);
     }
@@ -211,12 +218,20 @@ static void cPreIncrement() {
     cAddInt(cAddVar(cReadString()));
 }
 
+static void cPreDecrement() {
+    cConsumeToken(T_LITERAL);
+    cAddOperation(OP_PRE_DECREMENT);
+    cAddInt(cAddVar(cReadString()));
+}
+
 static void cPreUnary() {
     if(cConsumeTokenIf(T_SUB)) {
         cPrimary();
         cAddOperation(OP_INVERT_SIGN);
     } else if(cConsumeTokenIf(T_INCREMENT)) {
         cPreIncrement();
+    } else if(cConsumeTokenIf(T_DECREMENT)) {
+        cPreDecrement();
     } else {
         cPrimary();
     }
@@ -334,6 +349,11 @@ static void cLineLiteral() {
             cConsumeToken(T_SEMICOLON);
             cAddOperation(OP_POP);
             break;
+        case T_DECREMENT:
+            cPostDecrement(literal);
+            cConsumeToken(T_SEMICOLON);
+            cAddOperation(OP_POP);
+            break;
         default: cUnexpectedToken(t);
     }
 }
@@ -493,6 +513,11 @@ static void cLine(Token t) {
             cConsumeToken(T_SEMICOLON);
             cAddOperation(OP_POP);
             break;
+        case T_DECREMENT:
+            cPreDecrement();
+            cConsumeToken(T_SEMICOLON);
+            cAddOperation(OP_POP);
+            break;
         default: cUnexpectedToken(t);
     }
 }

+ 2 - 0
Operation.h

@@ -15,6 +15,8 @@ typedef enum Operation {
     OP_GET,
     OP_PRE_INCREMENT,
     OP_POST_INCREMENT,
+    OP_PRE_DECREMENT,
+    OP_POST_DECREMENT,
     OP_ADD,
     OP_SUB,
     OP_MUL,

+ 36 - 0
Script.c

@@ -180,6 +180,38 @@ static void sPostIncrement(Script* sc) {
     }
 }
 
+static void sPreDecrement(Script* sc) {
+    int value = 0;
+    if(sReadInt(sc, &value)) {
+        Object* o = sc->stack + value + sc->stackVarIndex;
+        if(o->type == OT_INT) {
+            o->data.intValue--;
+        } else if(o->type == OT_FLOAT) {
+            o->data.floatValue--;
+        } else {
+            sError(sc, "variable is not a number on line %d", sc->line);
+            return;
+        }
+        sPush(sc, o);
+    }
+}
+
+static void sPostDecrement(Script* sc) {
+    int value = 0;
+    if(sReadInt(sc, &value)) {
+        Object* o = sc->stack + value + sc->stackVarIndex;
+        if(o->type == OT_INT) {
+            sPush(sc, o);
+            o->data.intValue--;
+        } else if(o->type == OT_FLOAT) {
+            sPush(sc, o);
+            o->data.floatValue--;
+        } else {
+            sError(sc, "variable is not a number on line %d", sc->line);
+        }
+    }
+}
+
 static void sPushCodeInt(Script* sc) {
     int value = 0;
     if(sReadInt(sc, &value)) {
@@ -423,6 +455,8 @@ static void sConsumeInstruction(Script* sc) {
         case OP_GET: sGet(sc); break;
         case OP_PRE_INCREMENT: sPreIncrement(sc); break;
         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;
@@ -526,6 +560,8 @@ void sPrintCode(Script* sc) {
             case OP_GET: sPrintInt(sc, "Get"); break;
             case OP_PRE_INCREMENT: sPrintInt(sc, "Pre Increment"); break;
             case OP_POST_INCREMENT: sPrintInt(sc, "Post Increment"); break;
+            case OP_PRE_DECREMENT: sPrintInt(sc, "Pre Decrement"); break;
+            case OP_POST_DECREMENT: sPrintInt(sc, "Post Decrement"); break;
             case OP_ADD: puts("Add"); break;
             case OP_SUB: puts("Sub"); break;
             case OP_MUL: puts("Mul"); break;

+ 2 - 1
Tokenizer.c

@@ -147,7 +147,7 @@ static bool tParseToken() {
         case ' ': return true;
         case '\n': line++; return true;
         case '+': return tReadIf('+') ? tAddToken(T_INCREMENT) : tAddToken(T_ADD);
-        case '-': return tAddToken(T_SUB);
+        case '-': return tReadIf('-') ? tAddToken(T_DECREMENT) : tAddToken(T_SUB);
         case '*': return tAddToken(T_MUL);
         case '/': return tAddToken(T_DIV);
         case '%': return tAddToken(T_MOD);
@@ -268,6 +268,7 @@ const char* tGetTokenName(Token token) {
         case T_BIT_OR: return "|";
         case T_SET: return "=";
         case T_INCREMENT: return "++";
+        case T_DECREMENT: return "--";
         case T_LITERAL: return "literal";
         case T_PRINT: return "print";
         case T_IF: return "if";

+ 1 - 0
Tokenizer.h

@@ -28,6 +28,7 @@ typedef enum Token {
     T_BIT_OR,
     T_SET,
     T_INCREMENT,
+    T_DECREMENT,
     T_LITERAL,
     T_PRINT,
     T_IF,

+ 10 - 0
tests/loops/while_post_dec

@@ -0,0 +1,10 @@
+a = 5;
+while(a > 0) {
+    print a--;
+}
+
+a = 5;
+while(a > 0) {
+    print a;
+    a--;
+}

+ 10 - 0
tests/loops/while_post_dec.out

@@ -0,0 +1,10 @@
+5
+4
+3
+2
+1
+5
+4
+3
+2
+1

+ 10 - 0
tests/loops/while_pre_dec

@@ -0,0 +1,10 @@
+a = 5;
+while(a > 0) {
+    print --a;
+}
+
+a = 5;
+while(a > 0) {
+    print a;
+    --a;
+}

+ 10 - 0
tests/loops/while_pre_dec.out

@@ -0,0 +1,10 @@
+4
+3
+2
+1
+0
+5
+4
+3
+2
+1