mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
impl unpack
This commit is contained in:
parent
c2fa538f44
commit
b5aba376fe
@ -139,9 +139,15 @@ public:
|
|||||||
this->ip = i;
|
this->ip = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PyVarList popNReversed(VM* vm, int n){
|
PyVarList popNValuesReversed(VM* vm, int n){
|
||||||
PyVarList v(n);
|
PyVarList v(n);
|
||||||
for(int i=n-1; i>=0; i--) v[i] = popValue(vm);
|
for(int i=n-1; i>=0; i--) v[i] = popValue(vm);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyVarList __popNReversed(int n){
|
||||||
|
PyVarList v(n);
|
||||||
|
for(int i=n-1; i>=0; i--) v[i] = __pop();
|
||||||
|
return v;
|
||||||
|
}
|
||||||
};
|
};
|
125
src/compiler.h
125
src/compiler.h
@ -26,19 +26,18 @@ struct Loop {
|
|||||||
Loop(bool forLoop, int start) : forLoop(forLoop), start(start) {}
|
Loop(bool forLoop, int start) : forLoop(forLoop), start(start) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ExprCommaSplitArgs(end) \
|
#define ExprCommaSplitArgs(end) \
|
||||||
int ARGC = 0; \
|
int ARGC = 0; \
|
||||||
do { \
|
do { \
|
||||||
matchNewLines(); \
|
matchNewLines(); \
|
||||||
if (peek() == TK(end)) break; \
|
if (peek() == TK(end)) break; \
|
||||||
compileExpression(); \
|
EXPR(); \
|
||||||
ARGC++; \
|
ARGC++; \
|
||||||
matchNewLines(); \
|
matchNewLines(); \
|
||||||
} while (match(TK(","))); \
|
} while (match(TK(","))); \
|
||||||
matchNewLines(); \
|
matchNewLines(); \
|
||||||
consume(TK(end));
|
consume(TK(end));
|
||||||
|
|
||||||
|
|
||||||
class Compiler {
|
class Compiler {
|
||||||
public:
|
public:
|
||||||
std::unique_ptr<Parser> parser;
|
std::unique_ptr<Parser> parser;
|
||||||
@ -104,14 +103,19 @@ public:
|
|||||||
rules[TK("@id")] = { METHOD(exprName), NO_INFIX };
|
rules[TK("@id")] = { METHOD(exprName), NO_INFIX };
|
||||||
rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX };
|
rules[TK("@num")] = { METHOD(exprLiteral), NO_INFIX };
|
||||||
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
|
rules[TK("@str")] = { METHOD(exprLiteral), NO_INFIX };
|
||||||
rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_LOWEST };
|
rules[TK("=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_LOWEST };
|
rules[TK("+=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
rules[TK("-=")] = { nullptr, METHOD(exprAssign), PREC_LOWEST };
|
rules[TK("-=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
rules[TK("*=")] = { nullptr, METHOD(exprAssign), PREC_LOWEST };
|
rules[TK("*=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
rules[TK("/=")] = { nullptr, METHOD(exprAssign), PREC_LOWEST };
|
rules[TK("/=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
rules[TK("//=")] = { nullptr, METHOD(exprAssign), PREC_LOWEST };
|
rules[TK("//=")] = { nullptr, METHOD(exprAssign), PREC_ASSIGNMENT };
|
||||||
|
rules[TK(",")] = { nullptr, METHOD(exprComma), PREC_COMMA };
|
||||||
#undef METHOD
|
#undef METHOD
|
||||||
#undef NO_INFIX
|
#undef NO_INFIX
|
||||||
|
|
||||||
|
#define EXPR() parsePrecedence(PREC_COMMA) // no '=' and ',' just a simple expression
|
||||||
|
#define EXPR_TUPLE() parsePrecedence(PREC_ASSIGNMENT) // no '=', but ',' is allowed
|
||||||
|
#define EXPR_ANY() parsePrecedence(PREC_NONE)
|
||||||
}
|
}
|
||||||
|
|
||||||
void eatString(bool single_quote) {
|
void eatString(bool single_quote) {
|
||||||
@ -297,15 +301,15 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void exprAssign(){
|
void exprAssign() {
|
||||||
_TokenType op = parser->previous.type;
|
_TokenType op = parser->previous.type;
|
||||||
if(op == TK("=")) { // a = (expr)
|
if(op == TK("=")) { // a = (expr)
|
||||||
compileExpressionTuple();
|
EXPR_TUPLE();
|
||||||
emitCode(OP_STORE_PTR);
|
emitCode(OP_STORE_PTR);
|
||||||
}else{ // a += (expr) -> a = a + (expr)
|
}else{ // a += (expr) -> a = a + (expr)
|
||||||
// TODO: optimization is needed for inplace operators
|
// TODO: optimization is needed for inplace operators
|
||||||
emitCode(OP_DUP_TOP);
|
emitCode(OP_DUP_TOP);
|
||||||
compileExpression();
|
EXPR();
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case TK("+="): emitCode(OP_BINARY_OP, 0); break;
|
case TK("+="): emitCode(OP_BINARY_OP, 0); break;
|
||||||
case TK("-="): emitCode(OP_BINARY_OP, 1); break;
|
case TK("-="): emitCode(OP_BINARY_OP, 1); break;
|
||||||
@ -318,6 +322,15 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void exprComma() {
|
||||||
|
int size = 1; // an expr is in the stack now
|
||||||
|
do {
|
||||||
|
EXPR(); // NOTE: "1," will fail, "1,2" will be ok
|
||||||
|
size++;
|
||||||
|
} while(match(TK(",")));
|
||||||
|
emitCode(OP_BUILD_SMART_TUPLE, size);
|
||||||
|
}
|
||||||
|
|
||||||
void exprOr() {
|
void exprOr() {
|
||||||
int patch = emitCode(OP_JUMP_IF_TRUE_OR_POP);
|
int patch = emitCode(OP_JUMP_IF_TRUE_OR_POP);
|
||||||
parsePrecedence(PREC_LOGICAL_OR);
|
parsePrecedence(PREC_LOGICAL_OR);
|
||||||
@ -371,7 +384,7 @@ public:
|
|||||||
|
|
||||||
void exprGrouping() {
|
void exprGrouping() {
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
compileExpressionTuple();
|
EXPR_TUPLE();
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
consume(TK(")"));
|
consume(TK(")"));
|
||||||
}
|
}
|
||||||
@ -386,8 +399,8 @@ public:
|
|||||||
do {
|
do {
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
if (peek() == TK("}")) break;
|
if (peek() == TK("}")) break;
|
||||||
compileExpression();consume(TK(":"));compileExpression();
|
EXPR();consume(TK(":"));EXPR();
|
||||||
emitCode(OP_BUILD_TUPLE, 2);
|
emitCode(OP_BUILD_SMART_TUPLE, 2);
|
||||||
size++;
|
size++;
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
@ -425,17 +438,17 @@ public:
|
|||||||
if(match(TK("]"))){
|
if(match(TK("]"))){
|
||||||
emitCode(OP_LOAD_NONE);
|
emitCode(OP_LOAD_NONE);
|
||||||
}else{
|
}else{
|
||||||
compileExpression();
|
EXPR();
|
||||||
consume(TK("]"));
|
consume(TK("]"));
|
||||||
}
|
}
|
||||||
emitCode(OP_BUILD_SLICE);
|
emitCode(OP_BUILD_SLICE);
|
||||||
}else{
|
}else{
|
||||||
compileExpression();
|
EXPR();
|
||||||
if(match(TK(":"))){
|
if(match(TK(":"))){
|
||||||
if(match(TK("]"))){
|
if(match(TK("]"))){
|
||||||
emitCode(OP_LOAD_NONE);
|
emitCode(OP_LOAD_NONE);
|
||||||
}else{
|
}else{
|
||||||
compileExpression();
|
EXPR();
|
||||||
consume(TK("]"));
|
consume(TK("]"));
|
||||||
}
|
}
|
||||||
emitCode(OP_BUILD_SLICE);
|
emitCode(OP_BUILD_SLICE);
|
||||||
@ -457,23 +470,6 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parsePrecedence(Precedence precedence) {
|
|
||||||
lexToken();
|
|
||||||
GrammarFn prefix = rules[parser->previous.type].prefix;
|
|
||||||
|
|
||||||
if (prefix == nullptr) {
|
|
||||||
throw SyntaxError(path, parser->previous, "expected an expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
(this->*prefix)();
|
|
||||||
while (rules[peek()].precedence >= precedence) {
|
|
||||||
lexToken();
|
|
||||||
_TokenType op = parser->previous.type;
|
|
||||||
GrammarFn infix = rules[op].infix;
|
|
||||||
(this->*infix)();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void keepOpcodeLine(){
|
void keepOpcodeLine(){
|
||||||
int i = getCode()->co_code.size() - 1;
|
int i = getCode()->co_code.size() - 1;
|
||||||
getCode()->co_code[i].line = getCode()->co_code[i-1].line;
|
getCode()->co_code[i].line = getCode()->co_code[i-1].line;
|
||||||
@ -527,29 +523,30 @@ public:
|
|||||||
}
|
}
|
||||||
int index = getCode()->addName(tkmodule.str(), NAME_GLOBAL);
|
int index = getCode()->addName(tkmodule.str(), NAME_GLOBAL);
|
||||||
emitCode(OP_STORE_NAME_PTR, index);
|
emitCode(OP_STORE_NAME_PTR, index);
|
||||||
} while (match(TK(",")) && (matchNewLines(), true));
|
} while (match(TK(",")));
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compiles an expression. An expression will result a value on top of the stack.
|
void parsePrecedence(Precedence precedence) {
|
||||||
void compileExpression() {
|
lexToken();
|
||||||
parsePrecedence(PREC_LOWEST);
|
GrammarFn prefix = rules[parser->previous.type].prefix;
|
||||||
}
|
|
||||||
|
|
||||||
// Compiles an expression. Support tuple syntax.
|
if (prefix == nullptr) {
|
||||||
void compileExpressionTuple() {
|
throw SyntaxError(path, parser->previous, "expected an expression");
|
||||||
int size = 0;
|
}
|
||||||
while (true) {
|
|
||||||
compileExpression();
|
(this->*prefix)();
|
||||||
size++;
|
while (rules[peek()].precedence > precedence) {
|
||||||
if (!match(TK(","))) break;
|
lexToken();
|
||||||
|
_TokenType op = parser->previous.type;
|
||||||
|
GrammarFn infix = rules[op].infix;
|
||||||
|
(this->*infix)();
|
||||||
}
|
}
|
||||||
if(size > 1) emitCode(OP_BUILD_TUPLE, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compileIfStatement() {
|
void compileIfStatement() {
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
compileExpression(); //< Condition.
|
EXPR_TUPLE();
|
||||||
|
|
||||||
int ifpatch = emitCode(OP_POP_JUMP_IF_FALSE);
|
int ifpatch = emitCode(OP_POP_JUMP_IF_FALSE);
|
||||||
compileBlockBody();
|
compileBlockBody();
|
||||||
@ -583,7 +580,7 @@ public:
|
|||||||
|
|
||||||
void compileWhileStatement() {
|
void compileWhileStatement() {
|
||||||
Loop& loop = enterLoop(false);
|
Loop& loop = enterLoop(false);
|
||||||
compileExpression();
|
EXPR_TUPLE();
|
||||||
int patch = emitCode(OP_POP_JUMP_IF_FALSE);
|
int patch = emitCode(OP_POP_JUMP_IF_FALSE);
|
||||||
compileBlockBody();
|
compileBlockBody();
|
||||||
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
||||||
@ -598,7 +595,7 @@ public:
|
|||||||
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
|
codes.size()>1 ? NAME_LOCAL : NAME_GLOBAL
|
||||||
);
|
);
|
||||||
consume(TK("in"));
|
consume(TK("in"));
|
||||||
compileExpressionTuple();
|
EXPR_TUPLE();
|
||||||
emitCode(OP_GET_ITER);
|
emitCode(OP_GET_ITER);
|
||||||
Loop& loop = enterLoop(true);
|
Loop& loop = enterLoop(true);
|
||||||
int patch = emitCode(OP_FOR_ITER);
|
int patch = emitCode(OP_FOR_ITER);
|
||||||
@ -628,7 +625,7 @@ public:
|
|||||||
if(matchEndStatement()){
|
if(matchEndStatement()){
|
||||||
emitCode(OP_LOAD_NONE);
|
emitCode(OP_LOAD_NONE);
|
||||||
}else{
|
}else{
|
||||||
compileExpressionTuple();
|
EXPR_TUPLE();
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
}
|
}
|
||||||
emitCode(OP_RETURN_VALUE);
|
emitCode(OP_RETURN_VALUE);
|
||||||
@ -639,23 +636,23 @@ public:
|
|||||||
} else if (match(TK("for"))) {
|
} else if (match(TK("for"))) {
|
||||||
compileForStatement();
|
compileForStatement();
|
||||||
} else if(match(TK("assert"))){
|
} else if(match(TK("assert"))){
|
||||||
compileExpression();
|
EXPR();
|
||||||
emitCode(OP_ASSERT);
|
emitCode(OP_ASSERT);
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
} else if(match(TK("raise"))){
|
} else if(match(TK("raise"))){
|
||||||
consume(TK("@id")); // dummy exception type
|
consume(TK("@id")); // dummy exception type
|
||||||
emitCode(OP_LOAD_CONST, getCode()->addConst(vm->PyStr(parser->previous.str())));
|
emitCode(OP_LOAD_CONST, getCode()->addConst(vm->PyStr(parser->previous.str())));
|
||||||
consume(TK("("));compileExpression();consume(TK(")"));
|
consume(TK("("));EXPR();consume(TK(")"));
|
||||||
emitCode(OP_RAISE_ERROR);
|
emitCode(OP_RAISE_ERROR);
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
} else if(match(TK("del"))){
|
} else if(match(TK("del"))){
|
||||||
compileExpression();
|
EXPR();
|
||||||
emitCode(OP_DELETE_PTR);
|
emitCode(OP_DELETE_PTR);
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
} else if(match(TK("pass"))){
|
} else if(match(TK("pass"))){
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
} else {
|
} else {
|
||||||
compileExpressionTuple();
|
EXPR_ANY();
|
||||||
consumeEndStatement();
|
consumeEndStatement();
|
||||||
|
|
||||||
// If last op is not an assignment, pop the result.
|
// If last op is not an assignment, pop the result.
|
||||||
|
@ -18,10 +18,8 @@ OPCODE(UNARY_NOT)
|
|||||||
OPCODE(DUP_TOP)
|
OPCODE(DUP_TOP)
|
||||||
|
|
||||||
OPCODE(BUILD_LIST)
|
OPCODE(BUILD_LIST)
|
||||||
OPCODE(BUILD_TUPLE)
|
|
||||||
OPCODE(BUILD_MAP)
|
OPCODE(BUILD_MAP)
|
||||||
OPCODE(BUILD_SLICE)
|
OPCODE(BUILD_SLICE)
|
||||||
OPCODE(UNPACK_SEQUENCE)
|
|
||||||
|
|
||||||
OPCODE(GET_ITER)
|
OPCODE(GET_ITER)
|
||||||
OPCODE(FOR_ITER)
|
OPCODE(FOR_ITER)
|
||||||
@ -49,4 +47,6 @@ OPCODE(STORE_NAME_PTR) // arg for the name_ptr, [expr], directly store to t
|
|||||||
OPCODE(STORE_PTR) // no arg, [ptr, expr] -> *ptr = expr
|
OPCODE(STORE_PTR) // no arg, [ptr, expr] -> *ptr = expr
|
||||||
OPCODE(DELETE_PTR) // no arg, [ptr] -> [] -> delete ptr
|
OPCODE(DELETE_PTR) // no arg, [ptr] -> [] -> delete ptr
|
||||||
|
|
||||||
|
OPCODE(BUILD_SMART_TUPLE) // if all elements are pointers, build a compound pointer, otherwise build a tuple
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -65,7 +65,8 @@ struct Token{
|
|||||||
|
|
||||||
enum Precedence {
|
enum Precedence {
|
||||||
PREC_NONE,
|
PREC_NONE,
|
||||||
PREC_LOWEST,
|
PREC_ASSIGNMENT, // =
|
||||||
|
PREC_COMMA, // ,
|
||||||
PREC_LOGICAL_OR, // or
|
PREC_LOGICAL_OR, // or
|
||||||
PREC_LOGICAL_AND, // and
|
PREC_LOGICAL_AND, // and
|
||||||
PREC_EQUALITY, // == !=
|
PREC_EQUALITY, // == !=
|
||||||
|
@ -49,3 +49,13 @@ struct IndexPointer : BasePointer {
|
|||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
void del(VM* vm, Frame* frame) const;
|
void del(VM* vm, Frame* frame) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CompoundPointer : BasePointer {
|
||||||
|
const std::vector<_Pointer> pointers;
|
||||||
|
CompoundPointer(std::vector<_Pointer> pointers) : pointers(pointers) {}
|
||||||
|
CompoundPointer(std::vector<_Pointer>&& pointers) : pointers(pointers) {}
|
||||||
|
|
||||||
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
|
void del(VM* vm, Frame* frame) const;
|
||||||
|
};
|
66
src/vm.h
66
src/vm.h
@ -163,6 +163,27 @@ public:
|
|||||||
_Pointer p = PyPointer_AS_C(frame->__pop());
|
_Pointer p = PyPointer_AS_C(frame->__pop());
|
||||||
p->del(this, frame.get());
|
p->del(this, frame.get());
|
||||||
} break;
|
} break;
|
||||||
|
case OP_BUILD_SMART_TUPLE:
|
||||||
|
{
|
||||||
|
PyVarList items = frame->__popNReversed(byte.arg);
|
||||||
|
bool done = false;
|
||||||
|
for(auto& item : items){
|
||||||
|
if(!item->isType(_tp_pointer)) {
|
||||||
|
done = true;
|
||||||
|
PyVarList values(items.size());
|
||||||
|
for(int i=0; i<items.size(); i++){
|
||||||
|
values[i] = frame->__deref_pointer(this, items[i]);
|
||||||
|
}
|
||||||
|
frame->push(PyTuple(values));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(done) break;
|
||||||
|
std::vector<_Pointer> pointers(items.size());
|
||||||
|
for(int i=0; i<items.size(); i++)
|
||||||
|
pointers[i] = PyPointer_AS_C(items[i]);
|
||||||
|
frame->push(PyPointer(std::make_shared<CompoundPointer>(pointers)));
|
||||||
|
} break;
|
||||||
case OP_STORE_FUNCTION:
|
case OP_STORE_FUNCTION:
|
||||||
{
|
{
|
||||||
PyVar obj = frame->popValue(this);
|
PyVar obj = frame->popValue(this);
|
||||||
@ -190,16 +211,6 @@ public:
|
|||||||
callstack.pop();
|
callstack.pop();
|
||||||
return ret;
|
return ret;
|
||||||
} break;
|
} break;
|
||||||
case OP_UNPACK_SEQUENCE:
|
|
||||||
{
|
|
||||||
PyVar seq = frame->popValue(this);
|
|
||||||
bool iterable = (seq->isType(_tp_tuple) || seq->isType(_tp_list));
|
|
||||||
if(!iterable) _error("TypeError", "only tuple and list can be unpacked");
|
|
||||||
const PyVarList& objs = std::get<PyVarList>(seq->_native);
|
|
||||||
if(objs.size() > byte.arg) _error("ValueError", "too many values to unpack (expected " + std::to_string(byte.arg) + ")");
|
|
||||||
if(objs.size() < byte.arg) _error("ValueError", "not enough values to unpack (expected " + std::to_string(byte.arg) + ", got " + std::to_string(objs.size()) + ")");
|
|
||||||
for(auto it=objs.rbegin(); it!=objs.rend(); it++) frame->push(*it);
|
|
||||||
} break;
|
|
||||||
case OP_PRINT_EXPR:
|
case OP_PRINT_EXPR:
|
||||||
{
|
{
|
||||||
const PyVar& expr = frame->topValue(this);
|
const PyVar& expr = frame->topValue(this);
|
||||||
@ -254,24 +265,19 @@ public:
|
|||||||
} break;
|
} break;
|
||||||
case OP_BUILD_LIST:
|
case OP_BUILD_LIST:
|
||||||
{
|
{
|
||||||
PyVarList items = frame->popNReversed(this, byte.arg);
|
PyVarList items = frame->popNValuesReversed(this, byte.arg);
|
||||||
frame->push(PyList(items));
|
frame->push(PyList(items));
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_MAP:
|
case OP_BUILD_MAP:
|
||||||
{
|
{
|
||||||
PyVarList items = frame->popNReversed(this, byte.arg);
|
PyVarList items = frame->popNValuesReversed(this, byte.arg);
|
||||||
PyVar obj = call(builtins->attribs["dict"], {PyList(items)});
|
PyVar obj = call(builtins->attribs["dict"], {PyList(items)});
|
||||||
frame->push(obj);
|
frame->push(obj);
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_TUPLE:
|
|
||||||
{
|
|
||||||
PyVarList items = frame->popNReversed(this, byte.arg);
|
|
||||||
frame->push(PyTuple(items));
|
|
||||||
} break;
|
|
||||||
case OP_DUP_TOP: frame->push(frame->topValue(this)); break;
|
case OP_DUP_TOP: frame->push(frame->topValue(this)); break;
|
||||||
case OP_CALL:
|
case OP_CALL:
|
||||||
{
|
{
|
||||||
PyVarList args = frame->popNReversed(this, byte.arg);
|
PyVarList args = frame->popNValuesReversed(this, byte.arg);
|
||||||
PyVar callable = frame->popValue(this);
|
PyVar callable = frame->popValue(this);
|
||||||
frame->push(call(callable, args));
|
frame->push(call(callable, args));
|
||||||
} break;
|
} break;
|
||||||
@ -640,6 +646,30 @@ void IndexPointer::del(VM* vm, Frame* frame) const{
|
|||||||
vm->call(obj, __delitem__, {index});
|
vm->call(obj, __delitem__, {index});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyVar CompoundPointer::get(VM* vm, Frame* frame) const{
|
||||||
|
PyVarList args(pointers.size());
|
||||||
|
for (int i = 0; i < pointers.size(); i++) {
|
||||||
|
args[i] = pointers[i]->get(vm, frame);
|
||||||
|
}
|
||||||
|
return vm->PyTuple(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundPointer::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
|
if(!val->isType(vm->_tp_tuple) && !val->isType(vm->_tp_list)){
|
||||||
|
vm->_error("TypeError", "only tuple or list can be unpacked");
|
||||||
|
}
|
||||||
|
const PyVarList& args = std::get<PyVarList>(val->_native);
|
||||||
|
if(args.size() > pointers.size()) vm->_error("ValueError", "too many values to unpack");
|
||||||
|
if(args.size() < pointers.size()) vm->_error("ValueError", "not enough values to unpack");
|
||||||
|
for (int i = 0; i < pointers.size(); i++) {
|
||||||
|
pointers[i]->set(vm, frame, args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompoundPointer::del(VM* vm, Frame* frame) const{
|
||||||
|
for (auto& ptr : pointers) ptr->del(vm, frame);
|
||||||
|
}
|
||||||
|
|
||||||
/**************** Frame ****************/
|
/**************** Frame ****************/
|
||||||
inline PyVar Frame::__deref_pointer(VM* vm, PyVar v){
|
inline PyVar Frame::__deref_pointer(VM* vm, PyVar v){
|
||||||
if(v->isType(vm->_tp_pointer)) v = vm->PyPointer_AS_C(v)->get(vm, this);
|
if(v->isType(vm->_tp_pointer)) v = vm->PyPointer_AS_C(v)->get(vm, this);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user