Ver Fonte

add unpack builder

blueloveTH há 2 anos atrás
pai
commit
754808412b
6 ficheiros alterados com 60 adições e 10 exclusões
  1. 13 5
      src/compiler.h
  2. 2 1
      src/expr.h
  3. 10 1
      tests/05_list.py
  4. 10 1
      tests/06_tuple.py
  5. 15 1
      tests/07_dict.py
  6. 10 1
      tests/08_set.py

+ 13 - 5
src/compiler.h

@@ -343,13 +343,21 @@ class Compiler {
             match_newlines_repl();
             if (curr().type == TK("}")) break;
             EXPR();
-            if(curr().type == TK(":")) parsing_dict = true;
+            int star_level = ctx()->s_expr.top()->star_level();
+            if(star_level==2 || curr().type == TK(":")){
+                parsing_dict = true;
+            }
             if(parsing_dict){
-                consume(TK(":"));
-                EXPR();
                 auto dict_item = make_expr<DictItemExpr>();
-                dict_item->key = ctx()->s_expr.popx();
-                dict_item->value = ctx()->s_expr.popx();
+                if(star_level == 2){
+                    dict_item->key = nullptr;
+                    dict_item->value = ctx()->s_expr.popx();
+                }else{
+                    consume(TK(":"));
+                    EXPR();
+                    dict_item->key = ctx()->s_expr.popx();
+                    dict_item->value = ctx()->s_expr.popx();
+                }
                 items.push_back(std::move(dict_item));
             }else{
                 items.push_back(ctx()->s_expr.popx());

+ 2 - 1
src/expr.h

@@ -366,7 +366,7 @@ struct SliceExpr: Expr{
 };
 
 struct DictItemExpr: Expr{
-    Expr_ key;
+    Expr_ key;      // maybe nullptr if it is **kwargs
     Expr_ value;
     std::string str() const override { return "DictItem()"; }
 
@@ -374,6 +374,7 @@ struct DictItemExpr: Expr{
 
     void emit(CodeEmitContext* ctx) override {
         if(is_starred()){
+            PK_ASSERT(key == nullptr);
             value->emit(ctx);
         }else{
             value->emit(ctx);

+ 10 - 1
tests/05_list.py

@@ -74,4 +74,13 @@ assert a == [8, 2, 4, 2, 9]
 
 b = [(1, 2), (3, 3), (5, 1)]
 b.sort(key=lambda x:x[1])
-assert b == [(5, 1), (1, 2), (3,3)]
+assert b == [(5, 1), (1, 2), (3,3)]
+
+# unpack expression
+a = [1, 2, 3]
+b = [*a, 4, 5]
+assert b == [1, 2, 3, 4, 5]
+
+a = []
+b = [*a, 1, 2, 3, *a, *a]
+assert b == [1, 2, 3]

+ 10 - 1
tests/06_tuple.py

@@ -5,4 +5,13 @@ assert b == 2
 a,b = b,a
 assert a == 2
 assert b == 1
-assert len(tup) == 6
+assert len(tup) == 6
+
+# unpack expression
+a = 1, 2, 3
+b = *a, 4, 5
+assert b == (1, 2, 3, 4, 5)
+
+a = tuple([])
+b = *a, 1, 2, 3, *a, *a
+assert b == (1, 2, 3)

+ 15 - 1
tests/07_dict.py

@@ -52,4 +52,18 @@ assert a == {1: 2, 3: 4}
 assert a.pop(1) == 2
 assert a == {3: 4}
 assert a.pop(3) == 4
-assert a == {}
+assert a == {}
+
+# unpack expression
+a = {1:2, 3:4}
+b = {**a, 5:6, **a}
+assert b == {1: 2, 3: 4, 5: 6}
+
+a = {}
+b = {**a, 1:2, 3:4}
+assert b == {1: 2, 3: 4}
+
+a = {1:2, 3:4, 7:8}
+b = {**a, 1:5, 3:6}
+c = {**a, **b}
+assert c == {1: 5, 3: 6, 7: 8}

+ 10 - 1
tests/08_set.py

@@ -76,4 +76,13 @@ assert type({}) is dict
 assert {1,2}.issubset({1,2,3})
 assert {1,2,3}.issuperset({1,2})
 assert {1,2,3}.isdisjoint({4,5,6})
-assert not {1,2,3}.isdisjoint({2,3,4})
+assert not {1,2,3}.isdisjoint({2,3,4})
+
+# unpack expression
+a = {1, 2, 3}
+b = {*a, 4, 5, *a, *a}
+assert b == {1, 2, 3, 4, 5}
+
+a = set()
+b = {*a, 1, 2, 3, *a, *a}
+assert b == {1, 2, 3}