blueloveTH 2 лет назад
Родитель
Сommit
f0069e109a
3 измененных файлов с 21 добавлено и 8 удалено
  1. 14 6
      src/ceval.h
  2. 5 0
      src/compiler.h
  3. 2 2
      src/expr.h

+ 14 - 6
src/ceval.h

@@ -309,11 +309,9 @@ __NEXT_STEP:;
         }
         }
     }; DISPATCH();
     }; DISPATCH();
     /*****************************************/
     /*****************************************/
-    case OP_UNPACK_SEQUENCE: {
-        // asIter or iter->next may run bytecode
-        // accidential gc may happen
-        // lock the gc via RAII
-        auto _lock = heap.gc_scope_lock();
+    case OP_UNPACK_SEQUENCE: case OP_UNPACK_EX: {
+        // asIter or iter->next may run bytecode, accidential gc may happen
+        auto _lock = heap.gc_scope_lock();  // lock the gc via RAII!!
         PyObject* obj = asIter(frame->popx());
         PyObject* obj = asIter(frame->popx());
         BaseIter* iter = PyIter_AS_C(obj);
         BaseIter* iter = PyIter_AS_C(obj);
         for(int i=0; i<byte.arg; i++){
         for(int i=0; i<byte.arg; i++){
@@ -321,7 +319,17 @@ __NEXT_STEP:;
             if(item == nullptr) ValueError("not enough values to unpack");
             if(item == nullptr) ValueError("not enough values to unpack");
             frame->push(item);
             frame->push(item);
         }
         }
-        if(iter->next() != nullptr) ValueError("too many values to unpack");
+        if(byte.op == OP_UNPACK_EX){
+            List extras;
+            while(true){
+                PyObject* item = iter->next();
+                if(item == nullptr) break;
+                extras.push_back(item);
+            }
+            frame->push(VAR(extras));
+        }else{
+            if(iter->next() != nullptr) ValueError("too many values to unpack");
+        }
     }; DISPATCH();
     }; DISPATCH();
     /*****************************************/
     /*****************************************/
     // case OP_SETUP_DECORATOR: DISPATCH();
     // case OP_SETUP_DECORATOR: DISPATCH();

+ 5 - 0
src/compiler.h

@@ -611,6 +611,11 @@ class Compiler {
         }
         }
         std::cout << ctx()->_log_s_expr() << std::endl;
         std::cout << ctx()->_log_s_expr() << std::endl;
         Expr_ rhs = ctx()->s_expr.popx();
         Expr_ rhs = ctx()->s_expr.popx();
+
+        if(lhs_p->is_starred() || rhs->is_starred()){
+            SyntaxError("can't use starred expression here");
+        }
+
         rhs->emit(ctx());
         rhs->emit(ctx());
         bool ok = lhs_p->emit_store(ctx());
         bool ok = lhs_p->emit_store(ctx());
         if(!ok) SyntaxError();
         if(!ok) SyntaxError();

+ 2 - 2
src/expr.h

@@ -153,7 +153,6 @@ struct NameExpr: Expr{
     }
     }
 };
 };
 
 
-// *号运算符,作为左值和右值效果不同
 struct StarredExpr: Expr{
 struct StarredExpr: Expr{
     Expr_ child;
     Expr_ child;
     StarredExpr(Expr_&& child): child(std::move(child)) {}
     StarredExpr(Expr_&& child): child(std::move(child)) {}
@@ -411,13 +410,14 @@ struct TupleExpr: SequenceExpr{
         }
         }
 
 
         if(starred_i == -1){
         if(starred_i == -1){
-            // Unpacks TOS into count individual values, which are put onto the stack right-to-left.
             ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line);
             ctx->emit(OP_UNPACK_SEQUENCE, items.size(), line);
         }else{
         }else{
             // starred assignment target must be in a tuple
             // starred assignment target must be in a tuple
             if(items.size() == 1) return false;
             if(items.size() == 1) return false;
             // starred assignment target must be the last one (differ from CPython)
             // starred assignment target must be the last one (differ from CPython)
             if(starred_i != items.size()-1) return false;
             if(starred_i != items.size()-1) return false;
+            // a,*b = [1,2,3]
+            // stack is [1,2,3] -> [1,[2,3]]
             ctx->emit(OP_UNPACK_EX, items.size()-1, line);
             ctx->emit(OP_UNPACK_EX, items.size()-1, line);
         }
         }
         // do reverse emit
         // do reverse emit