mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
impl starred unpack
This commit is contained in:
parent
5e15d526a0
commit
256f9af147
@ -35,7 +35,7 @@ Please see https://pocketpy.dev for details or try [Live Demo](https://bluelovet
|
|||||||
| Dict | `{'a': 1, 'b': 2}` | YES |
|
| Dict | `{'a': 1, 'b': 2}` | YES |
|
||||||
| F-String | `f'value is {x}'` | YES |
|
| F-String | `f'value is {x}'` | YES |
|
||||||
| Unpacking | `a, b = 1, 2` | YES |
|
| Unpacking | `a, b = 1, 2` | YES |
|
||||||
| Star Unpacking | `a, *b = [1, 2, 3]` | NO |
|
| Star Unpacking | `a, *b = [1, 2, 3]` | YES |
|
||||||
| Exception | `raise/try..catch` | YES |
|
| Exception | `raise/try..catch` | YES |
|
||||||
| Dynamic Code | `eval()/exec()` | YES |
|
| Dynamic Code | `eval()/exec()` | YES |
|
||||||
| Reflection | `hasattr()/getattr()/setattr()` | YES |
|
| Reflection | `hasattr()/getattr()/setattr()` | YES |
|
||||||
|
21
src/ceval.h
21
src/ceval.h
@ -44,8 +44,8 @@ PyVar VM::run_frame(Frame* frame){
|
|||||||
case OP_BUILD_INDEX: {
|
case OP_BUILD_INDEX: {
|
||||||
PyVar index = frame->pop_value(this);
|
PyVar index = frame->pop_value(this);
|
||||||
auto ref = IndexRef(frame->pop_value(this), index);
|
auto ref = IndexRef(frame->pop_value(this), index);
|
||||||
if(byte.arg == 0) frame->push(PyRef(ref));
|
if(byte.arg > 0) frame->push(ref.get(this, frame));
|
||||||
else frame->push(ref.get(this, frame));
|
else frame->push(PyRef(ref));
|
||||||
} continue;
|
} continue;
|
||||||
case OP_FAST_INDEX: case OP_FAST_INDEX_REF: {
|
case OP_FAST_INDEX: case OP_FAST_INDEX_REF: {
|
||||||
auto& a = frame->co->names[byte.arg & 0xFFFF];
|
auto& a = frame->co->names[byte.arg & 0xFFFF];
|
||||||
@ -65,18 +65,13 @@ PyVar VM::run_frame(Frame* frame){
|
|||||||
PyRef_AS_C(frame->top())->del(this, frame);
|
PyRef_AS_C(frame->top())->del(this, frame);
|
||||||
frame->_pop();
|
frame->_pop();
|
||||||
continue;
|
continue;
|
||||||
case OP_BUILD_SMART_TUPLE: {
|
case OP_BUILD_TUPLE: {
|
||||||
pkpy::Args items = frame->pop_n_reversed(byte.arg);
|
pkpy::Args items = frame->pop_n_reversed(byte.arg);
|
||||||
bool done = false;
|
frame->push(PyTuple(std::move(items)));
|
||||||
for(int i=0; i<items.size(); i++){
|
} continue;
|
||||||
if(!is_type(items[i], tp_ref)) {
|
case OP_BUILD_TUPLE_REF: {
|
||||||
done = true;
|
pkpy::Args items = frame->pop_n_reversed(byte.arg);
|
||||||
for(int j=i; j<items.size(); j++) frame->try_deref(this, items[j]);
|
frame->push(PyRef(TupleRef(std::move(items))));
|
||||||
frame->push(PyTuple(std::move(items)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!done) frame->push(PyRef(TupleRef(std::move(items))));
|
|
||||||
} continue;
|
} continue;
|
||||||
case OP_BUILD_STRING: {
|
case OP_BUILD_STRING: {
|
||||||
pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg);
|
pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg);
|
||||||
|
@ -436,7 +436,7 @@ private:
|
|||||||
EXPR(); // NOTE: "1," will fail, "1,2" will be ok
|
EXPR(); // NOTE: "1," will fail, "1,2" will be ok
|
||||||
size++;
|
size++;
|
||||||
} while(match(TK(",")));
|
} while(match(TK(",")));
|
||||||
emit(OP_BUILD_SMART_TUPLE, size);
|
emit(co()->_rvalue ? OP_BUILD_TUPLE : OP_BUILD_TUPLE_REF, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void exprOr() {
|
void exprOr() {
|
||||||
@ -813,7 +813,7 @@ __LISTCOMP:
|
|||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
_exprName(true); size++;
|
_exprName(true); size++;
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
if(size > 1) emit(OP_BUILD_SMART_TUPLE, size);
|
if(size > 1) emit(OP_BUILD_TUPLE_REF, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_for_loop() {
|
void compile_for_loop() {
|
||||||
|
@ -24,7 +24,8 @@ OPCODE(BUILD_MAP)
|
|||||||
OPCODE(BUILD_SET)
|
OPCODE(BUILD_SET)
|
||||||
OPCODE(BUILD_SLICE)
|
OPCODE(BUILD_SLICE)
|
||||||
OPCODE(BUILD_CLASS)
|
OPCODE(BUILD_CLASS)
|
||||||
OPCODE(BUILD_SMART_TUPLE)
|
OPCODE(BUILD_TUPLE)
|
||||||
|
OPCODE(BUILD_TUPLE_REF)
|
||||||
OPCODE(BUILD_STRING)
|
OPCODE(BUILD_STRING)
|
||||||
|
|
||||||
OPCODE(LIST_APPEND)
|
OPCODE(LIST_APPEND)
|
||||||
|
34
src/vm.h
34
src/vm.h
@ -859,21 +859,27 @@ PyVar TupleRef::get(VM* vm, Frame* frame) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
|
void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
#define TUPLE_REF_SET() \
|
val = vm->asIter(val);
|
||||||
if(args.size() > objs.size()) vm->ValueError("too many values to unpack"); \
|
pkpy::shared_ptr<BaseIter> iter = vm->PyIter_AS_C(val);
|
||||||
if(args.size() < objs.size()) vm->ValueError("not enough values to unpack"); \
|
for(int i=0; i<objs.size(); i++){
|
||||||
for (int i = 0; i < objs.size(); i++) vm->PyRef_AS_C(objs[i])->set(vm, frame, args[i]);
|
PyVarOrNull x;
|
||||||
|
if(is_type(objs[i], vm->tp_star_wrapper)){
|
||||||
if(is_type(val, vm->tp_tuple)){
|
auto& star = vm->PyStarWrapper_AS_C(objs[i]);
|
||||||
const pkpy::Tuple& args = OBJ_GET(pkpy::Tuple, val);
|
if(star.rvalue) vm->ValueError("can't use starred expression here");
|
||||||
TUPLE_REF_SET()
|
if(i != objs.size()-1) vm->ValueError("* can only be used at the end");
|
||||||
}else if(is_type(val, vm->tp_list)){
|
auto ref = vm->PyRef_AS_C(star.obj);
|
||||||
const pkpy::List& args = OBJ_GET(pkpy::List, val);
|
pkpy::List list;
|
||||||
TUPLE_REF_SET()
|
while((x = iter->next()) != nullptr) list.push_back(x);
|
||||||
}else{
|
ref->set(vm, frame, vm->PyList(std::move(list)));
|
||||||
vm->TypeError("only tuple or list can be unpacked");
|
return;
|
||||||
|
}else{
|
||||||
|
x = iter->next();
|
||||||
|
if(x == nullptr) vm->ValueError("not enough values to unpack");
|
||||||
|
vm->PyRef_AS_C(objs[i])->set(vm, frame, x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#undef TUPLE_REF_SET
|
PyVarOrNull x = iter->next();
|
||||||
|
if(x != nullptr) vm->ValueError("too many values to unpack");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TupleRef::del(VM* vm, Frame* frame) const{
|
void TupleRef::del(VM* vm, Frame* frame) const{
|
||||||
|
@ -18,4 +18,18 @@ def f(a, b, *args, c=16):
|
|||||||
assert f(1, 2, 3, 4) == 26
|
assert f(1, 2, 3, 4) == 26
|
||||||
assert f(1, 2, 3, 4, c=32) == 42
|
assert f(1, 2, 3, 4, c=32) == 42
|
||||||
|
|
||||||
assert f(*a, c=-26) == 0
|
assert f(*a, c=-26) == 0
|
||||||
|
|
||||||
|
|
||||||
|
a, b = 1, 2
|
||||||
|
a, b = b, a
|
||||||
|
assert a == 2
|
||||||
|
assert b == 1
|
||||||
|
|
||||||
|
a, *b = 1, 2, 3, 4
|
||||||
|
assert a == 1
|
||||||
|
assert b == [2, 3, 4]
|
||||||
|
|
||||||
|
a, *b = [1]
|
||||||
|
assert a == 1
|
||||||
|
assert b == []
|
Loading…
x
Reference in New Issue
Block a user