diff --git a/src/ceval.h b/src/ceval.h index a6c266c8..e7b91b95 100644 --- a/src/ceval.h +++ b/src/ceval.h @@ -309,11 +309,9 @@ __NEXT_STEP:; } }; 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()); BaseIter* iter = PyIter_AS_C(obj); for(int i=0; ipush(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(); /*****************************************/ // case OP_SETUP_DECORATOR: DISPATCH(); diff --git a/src/compiler.h b/src/compiler.h index 4f214360..9b070200 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -611,6 +611,11 @@ class Compiler { } std::cout << ctx()->_log_s_expr() << std::endl; Expr_ rhs = ctx()->s_expr.popx(); + + if(lhs_p->is_starred() || rhs->is_starred()){ + SyntaxError("can't use starred expression here"); + } + rhs->emit(ctx()); bool ok = lhs_p->emit_store(ctx()); if(!ok) SyntaxError(); diff --git a/src/expr.h b/src/expr.h index da0bc366..bd3cfd92 100644 --- a/src/expr.h +++ b/src/expr.h @@ -153,7 +153,6 @@ struct NameExpr: Expr{ } }; -// *号运算符,作为左值和右值效果不同 struct StarredExpr: Expr{ Expr_ child; StarredExpr(Expr_&& child): child(std::move(child)) {} @@ -411,13 +410,14 @@ struct TupleExpr: SequenceExpr{ } 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); }else{ // starred assignment target must be in a tuple if(items.size() == 1) return false; // starred assignment target must be the last one (differ from CPython) 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); } // do reverse emit