Quellcode durchsuchen

add %= &= |= ^=

blueloveTH vor 3 Jahren
Ursprung
Commit
a72e413034
6 geänderte Dateien mit 61 neuen und 9 gelöschten Zeilen
  1. 23 6
      src/compiler.h
  2. 2 2
      src/main.cpp
  3. 1 0
      src/opcodes.h
  4. 1 1
      src/parser.h
  5. 7 0
      src/vm.h
  6. 27 0
      tests/_assign.py

+ 23 - 6
src/compiler.h

@@ -95,6 +95,10 @@ public:
         rules[TK("*=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
         rules[TK("/=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
         rules[TK("//=")] =      { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
+        rules[TK("%=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
+        rules[TK("&=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
+        rules[TK("|=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
+        rules[TK("^=")] =       { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
         rules[TK(",")] =        { nullptr,               METHOD(exprComma),          PREC_COMMA };
         rules[TK("<<")] =       { nullptr,               METHOD(exprBinaryOp),       PREC_BITWISE_SHIFT };
         rules[TK(">>")] =       { nullptr,               METHOD(exprBinaryOp),       PREC_BITWISE_SHIFT };
@@ -199,10 +203,10 @@ public:
                 case ')': parser->setNextToken(TK(")")); return;
                 case '[': parser->setNextToken(TK("[")); return;
                 case ']': parser->setNextToken(TK("]")); return;
-                case '%': parser->setNextToken(TK("%")); return;
-                case '&': parser->setNextToken(TK("&")); return;
-                case '|': parser->setNextToken(TK("|")); return;
-                case '^': parser->setNextToken(TK("^")); return;
+                case '%': parser->setNextTwoCharToken('=', TK("%"), TK("%=")); return;
+                case '&': parser->setNextTwoCharToken('=', TK("&"), TK("&=")); return;
+                case '|': parser->setNextTwoCharToken('=', TK("|"), TK("|=")); return;
+                case '^': parser->setNextTwoCharToken('=', TK("^"), TK("^=")); return;
                 case '?': parser->setNextToken(TK("?")); return;
                 case '.': {
                     if(parser->matchChar('.')) {
@@ -405,6 +409,11 @@ public:
                 case TK("*="):      emitCode(OP_BINARY_OP, 2);  break;
                 case TK("/="):      emitCode(OP_BINARY_OP, 3);  break;
                 case TK("//="):     emitCode(OP_BINARY_OP, 4);  break;
+                
+                case TK("%="):      emitCode(OP_BINARY_OP, 5);  break;
+                case TK("&="):      emitCode(OP_BITWISE_OP, 2);  break;
+                case TK("|="):      emitCode(OP_BITWISE_OP, 3);  break;
+                case TK("^="):      emitCode(OP_BITWISE_OP, 4);  break;
                 default: UNREACHABLE();
             }
             emitCode(OP_STORE_REF);
@@ -549,17 +558,25 @@ __LISTCOMP:
     }
 
     void exprMap() {
+        bool parsing_dict = false;
         int size = 0;
         do {
             matchNewLines(mode()==SINGLE_MODE);
             if (peek() == TK("}")) break;
-            EXPR();consume(TK(":"));EXPR();
+            EXPR();
+            if(peek() == TK(":")) parsing_dict = true;
+            if(parsing_dict){
+                consume(TK(":"));
+                EXPR();
+            }
             size++;
             matchNewLines(mode()==SINGLE_MODE);
         } while (match(TK(",")));
         matchNewLines();
         consume(TK("}"));
-        emitCode(OP_BUILD_MAP, size);
+
+        if(parsing_dict) emitCode(OP_BUILD_MAP, size);
+        else emitCode(OP_BUILD_SET, size);
     }
 
     void exprCall() {

+ 2 - 2
src/main.cpp

@@ -3,8 +3,8 @@
 
 #include "pocketpy.h"
 
-#define PK_DEBUG_TIME
-//#define PK_DEBUG_THREADED
+//#define PK_DEBUG_TIME
+#define PK_DEBUG_THREADED
 
 struct Timer{
     const char* title;

+ 1 - 0
src/opcodes.h

@@ -22,6 +22,7 @@ OPCODE(DUP_TOP)
 
 OPCODE(BUILD_LIST)
 OPCODE(BUILD_MAP)
+OPCODE(BUILD_SET)
 OPCODE(BUILD_SLICE)
 
 OPCODE(LIST_APPEND)

+ 1 - 1
src/parser.h

@@ -10,7 +10,7 @@ constexpr const char* __TOKENS[] = {
     "+", "-", "*", "/", "//", "**", "=", ">", "<", "...", "->",
     "<<", ">>", "&", "|", "^", "?",
     "==", "!=", ">=", "<=",
-    "+=", "-=", "*=", "/=", "//=",
+    "+=", "-=", "*=", "/=", "//=", "%=", "&=", "|=", "^=",
     /** KW_BEGIN **/
     "class", "import", "as", "def", "lambda", "pass", "del", "from", "with",
     "None", "in", "is", "and", "or", "not", "True", "False", "global",

+ 7 - 0
src/vm.h

@@ -249,6 +249,13 @@ protected:
                     }
                     frame->push(obj);
                 } break;
+            case OP_BUILD_SET:
+                {
+                    pkpy::ArgList items = frame->popNValuesReversed(this, byte.arg);
+                    PyVar list = PyList(items.toList());
+                    PyVar obj = call(builtins->attribs["set"], pkpy::oneArg(list));
+                    frame->push(obj);
+                } break;
             case OP_DUP_TOP: frame->push(frame->topValue(this)); break;
             case OP_CALL:
                 {

+ 27 - 0
tests/_assign.py

@@ -0,0 +1,27 @@
+a = 0
+
+a += 2
+assert a == 2
+
+a -= 1
+assert a == 1
+
+a *= 2
+assert a == 2
+
+a //= 2
+assert a == 1
+
+a |= 0xff
+assert a == 0xff
+
+a &= 0x0f
+assert a == 0x0f
+
+a = 8
+
+a %= 3
+assert a == 2
+
+a ^= 0xf0
+assert a == 242