Ver Fonte

+=, -=, *=, /= and %=, errors for modules of 0 or division by 0

Kajetan Johannes Hammerle há 4 anos atrás
pai
commit
adda79319f
6 ficheiros alterados com 82 adições e 14 exclusões
  1. 13 0
      Compiler.c
  2. 20 9
      Script.c
  3. 10 5
      Tokenizer.c
  4. 5 0
      Tokenizer.h
  5. 29 0
      tests/vars/setop
  6. 5 0
      tests/vars/setop.out

+ 13 - 0
Compiler.c

@@ -334,11 +334,24 @@ static void cSetVar(const char* literal) {
     cAddInt(cAddVar(literal));
 }
 
+static void cOperationSetVar(const char* literal, Operation op) {
+    cGetVar(literal);
+    cExpression();
+    cAddOperation(op);
+    cAddOperation(OP_SET);
+    cAddInt(cAddVar(literal));
+}
+
 static void cLineLiteral() {
     const char* literal = cReadString();
     Token t = cReadTokenAndLine();
     switch(t) {
         case T_SET: cSetVar(literal); break;
+        case T_ADD_SET: cOperationSetVar(literal, OP_ADD); break;
+        case T_SUB_SET: cOperationSetVar(literal, OP_SUB); break;
+        case T_MUL_SET: cOperationSetVar(literal, OP_MUL); break;
+        case T_DIV_SET: cOperationSetVar(literal, OP_DIV); break;
+        case T_MOD_SET: cOperationSetVar(literal, OP_MOD); break;
         case T_OPEN_BRACKET: cCallFunction(literal, true); break;
         case T_INCREMENT:
             cPostIncrement(literal);

+ 20 - 9
Script.c

@@ -228,12 +228,12 @@ static void sPushCodeFloat(Script* sc) {
     sPushFloat(sc, value);
 }
 
-static void sNumberBinary(Script* sc, int (*fInt)(int, int), float (*fFloat)(float, float)) {
+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(o[0].data.intValue, o[1].data.intValue));
+        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) {
@@ -245,30 +245,41 @@ static void sNumberBinary(Script* sc, int (*fInt)(int, int), float (*fFloat)(flo
     }
 }
 
-static void sIntBinary(Script* sc, int (*f)(int, int)) {
+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(o[0].data.intValue, o[1].data.intValue));
+        sPushInt(sc, f(sc, o[0].data.intValue, o[1].data.intValue));
     }
 }
 
-static int sIntAdd(int a, int b) {
+static int sIntAdd(Script* sc, int a, int b) {
+    (void)sc;
     return a + b;
 }
 
-static int sIntSub(int a, int b) {
+static int sIntSub(Script* sc, int a, int b) {
+    (void)sc;
     return b - a;
 }
 
-static int sIntMul(int a, int b) {
+static int sIntMul(Script* sc, int a, int b) {
+    (void)sc;
     return a * b;
 }
 
-static int sIntDiv(int a, int 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(int a, int b) {
+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;
 }
 

+ 10 - 5
Tokenizer.c

@@ -146,11 +146,11 @@ static bool tParseToken() {
     switch(c) {
         case ' ': return true;
         case '\n': line++; return true;
-        case '+': return tReadIf('+') ? tAddToken(T_INCREMENT) : tAddToken(T_ADD);
-        case '-': return tReadIf('-') ? tAddToken(T_DECREMENT) : tAddToken(T_SUB);
-        case '*': return tAddToken(T_MUL);
-        case '/': return tAddToken(T_DIV);
-        case '%': return tAddToken(T_MOD);
+        case '+': return tReadIf('+') ? tAddToken(T_INCREMENT) : tReadIf('=') ? tAddToken(T_ADD_SET) : tAddToken(T_ADD);
+        case '-': return tReadIf('-') ? tAddToken(T_DECREMENT) : tReadIf('=') ? tAddToken(T_SUB_SET) : tAddToken(T_SUB);
+        case '*': return tReadIf('=') ? tAddToken(T_MUL_SET) : tAddToken(T_MUL);
+        case '/': return tReadIf('=') ? tAddToken(T_DIV_SET) : tAddToken(T_DIV);
+        case '%': return tReadIf('=') ? tAddToken(T_MOD_SET) : tAddToken(T_MOD);
         case '<': return tReadIf('=') ? tAddToken(T_LESS_EQUAL) : tAddToken(T_LESS);
         case '>': return tReadIf('=') ? tAddToken(T_GREATER_EQUAL) : tAddToken(T_GREATER);
         case '=': return tReadIf('=') ? tAddToken(T_EQUAL) : tAddToken(T_SET);
@@ -267,6 +267,11 @@ const char* tGetTokenName(Token token) {
         case T_BIT_AND: return "&";
         case T_BIT_OR: return "|";
         case T_SET: return "=";
+        case T_ADD_SET: return "+=";
+        case T_SUB_SET: return "-=";
+        case T_MUL_SET: return "*=";
+        case T_DIV_SET: return "/=";
+        case T_MOD_SET: return "%=";
         case T_INCREMENT: return "++";
         case T_DECREMENT: return "--";
         case T_LITERAL: return "literal";

+ 5 - 0
Tokenizer.h

@@ -27,6 +27,11 @@ typedef enum Token {
     T_BIT_AND,
     T_BIT_OR,
     T_SET,
+    T_ADD_SET,
+    T_SUB_SET,
+    T_MUL_SET,
+    T_DIV_SET,
+    T_MOD_SET,
     T_INCREMENT,
     T_DECREMENT,
     T_LITERAL,

+ 29 - 0
tests/vars/setop

@@ -0,0 +1,29 @@
+a = 5;
+a += 5;
+a += 10;
+a += 20;
+print a;
+
+a = 5;
+a -= 5;
+a -= -10;
+a -= 20;
+print a;
+
+a = 5;
+a *= 2;
+a *= 3;
+a *= 4;
+print a;
+
+a = 100;
+a /= 2;
+a /= 3;
+a /= 4;
+print a;
+
+a = 100;
+a %= 120;
+a %= 90;
+a %= 3;
+print a;

+ 5 - 0
tests/vars/setop.out

@@ -0,0 +1,5 @@
+40
+-10
+120
+4
+1