mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 12:30:19 +00:00
up
This commit is contained in:
parent
b88cd66046
commit
449fb9a2f8
113
src/ceval.h
113
src/ceval.h
@ -26,49 +26,86 @@ inline PyObject* VM::run_frame(Frame* frame){
|
|||||||
Function& f = CAST(Function&, frame->top()); // reference
|
Function& f = CAST(Function&, frame->top()); // reference
|
||||||
f._closure = frame->_locals;
|
f._closure = frame->_locals;
|
||||||
} continue;
|
} continue;
|
||||||
case OP_LOAD_NAME_REF: {
|
|
||||||
frame->push(PyRef(NameRef(frame->co->names[byte.arg])));
|
|
||||||
} continue;
|
|
||||||
case OP_LOAD_NAME: {
|
|
||||||
frame->push(NameRef(frame->co->names[byte.arg]).get(this, frame));
|
|
||||||
} continue;
|
|
||||||
case OP_STORE_NAME: {
|
|
||||||
auto& p = frame->co->names[byte.arg];
|
|
||||||
NameRef(p).set(this, frame, frame->pop());
|
|
||||||
} continue;
|
|
||||||
case OP_BUILD_ATTR_REF: case OP_BUILD_ATTR: {
|
|
||||||
auto& attr = frame->co->names[byte.arg];
|
|
||||||
PyObject* obj = frame->pop_value(this);
|
|
||||||
AttrRef ref = AttrRef(obj, NameRef(attr));
|
|
||||||
if(byte.op == OP_BUILD_ATTR) frame->push(ref.get(this, frame));
|
|
||||||
else frame->push(PyRef(ref));
|
|
||||||
} continue;
|
|
||||||
case OP_BUILD_INDEX: {
|
|
||||||
PyObject* index = frame->pop_value(this);
|
|
||||||
auto ref = IndexRef(frame->pop_value(this), index);
|
|
||||||
if(byte.arg > 0) frame->push(ref.get(this, frame));
|
|
||||||
else frame->push(PyRef(ref));
|
|
||||||
} continue;
|
|
||||||
case OP_FAST_INDEX: case OP_FAST_INDEX_REF: {
|
|
||||||
auto& a = frame->co->names[byte.arg & 0xFFFF];
|
|
||||||
auto& x = frame->co->names[(byte.arg >> 16) & 0xFFFF];
|
|
||||||
auto ref = IndexRef(NameRef(a).get(this, frame), NameRef(x).get(this, frame));
|
|
||||||
if(byte.op == OP_FAST_INDEX) frame->push(ref.get(this, frame));
|
|
||||||
else frame->push(PyRef(ref));
|
|
||||||
} continue;
|
|
||||||
case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue;
|
case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue;
|
||||||
case OP_STORE_REF: {
|
|
||||||
PyRef_AS_C(frame->top_1())->set(this, frame, frame->top_value(this));
|
|
||||||
frame->_pop(); frame->_pop();
|
|
||||||
} continue;
|
|
||||||
case OP_DELETE_REF:
|
|
||||||
PyRef_AS_C(frame->top())->del(this, frame);
|
|
||||||
frame->_pop();
|
|
||||||
continue;
|
|
||||||
case OP_BUILD_TUPLE: {
|
case OP_BUILD_TUPLE: {
|
||||||
Args items = frame->pop_n_values_reversed(this, byte.arg);
|
Args items = frame->pop_n_values_reversed(this, byte.arg);
|
||||||
frame->push(VAR(std::move(items)));
|
frame->push(VAR(std::move(items)));
|
||||||
} continue;
|
} continue;
|
||||||
|
/*****************************************/
|
||||||
|
case OP_LOAD_NAME: {
|
||||||
|
// TODO: use name resolution linked list to optimize this
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
PyObject* val;
|
||||||
|
val = frame->f_locals().try_get(name);
|
||||||
|
if(val != nullptr) { frame->push(val); continue; }
|
||||||
|
val = frame->f_closure_try_get(name);
|
||||||
|
if(val != nullptr) { frame->push(val); continue; }
|
||||||
|
val = frame->f_globals().try_get(name);
|
||||||
|
if(val != nullptr) { frame->push(val); continue; }
|
||||||
|
val = vm->builtins->attr().try_get(name);
|
||||||
|
if(val != nullptr) { frame->push(val); continue; }
|
||||||
|
vm->NameError(name);
|
||||||
|
} continue;
|
||||||
|
case OP_LOAD_ATTR: {
|
||||||
|
PyObject* a = frame->top();
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
frame->top() = getattr(a, name);
|
||||||
|
} continue;
|
||||||
|
case OP_LOAD_SUBSCR: {
|
||||||
|
PyObject* b = frame->popx();
|
||||||
|
PyObject* a = frame->top();
|
||||||
|
frame->top() = fast_call(__getitem__, Args{a, b});
|
||||||
|
} continue;
|
||||||
|
case OP_STORE_LOCAL: {
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
frame->f_locals().set(name, frame->popx());
|
||||||
|
} continue;
|
||||||
|
case OP_STORE_GLOBAL: {
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
frame->f_globals().set(name, frame->popx());
|
||||||
|
} continue;
|
||||||
|
case OP_STORE_ATTR: {
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
PyObject* a = frame->popx();
|
||||||
|
PyObject* val = frame->popx();
|
||||||
|
setattr(a, name, val);
|
||||||
|
} continue;
|
||||||
|
case OP_STORE_SUBSCR: {
|
||||||
|
Args args(3);
|
||||||
|
args[1] = frame->popx(); // b
|
||||||
|
args[0] = frame->popx(); // a
|
||||||
|
args[2] = frame->popx(); // val
|
||||||
|
fast_call(__setitem__, std::move(args));
|
||||||
|
} continue;
|
||||||
|
case OP_DELETE_LOCAL: {
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
if(frame->f_locals().contains(name)){
|
||||||
|
frame->f_locals().erase(name);
|
||||||
|
}else{
|
||||||
|
NameError(name);
|
||||||
|
}
|
||||||
|
} continue;
|
||||||
|
case OP_DELETE_GLOBAL: {
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
if(frame->f_globals().contains(name)){
|
||||||
|
frame->f_globals().erase(name);
|
||||||
|
}else{
|
||||||
|
NameError(name);
|
||||||
|
}
|
||||||
|
} continue;
|
||||||
|
case OP_DELETE_ATTR: {
|
||||||
|
PyObject* a = frame->popx();
|
||||||
|
StrName name = frame->co->names[byte.arg];
|
||||||
|
if(!a->is_attr_valid()) TypeError("cannot delete attribute");
|
||||||
|
if(!a->attr().contains(name)) AttributeError(a, name);
|
||||||
|
a->attr().erase(name);
|
||||||
|
} continue;
|
||||||
|
case OP_DELETE_SUBSCR: {
|
||||||
|
PyObject* b = frame->popx();
|
||||||
|
PyObject* a = frame->popx();
|
||||||
|
fast_call(__delitem__, Args{a, b});
|
||||||
|
} continue;
|
||||||
|
/*****************************************/
|
||||||
case OP_BUILD_TUPLE_REF: {
|
case OP_BUILD_TUPLE_REF: {
|
||||||
Args items = frame->pop_n_reversed(byte.arg);
|
Args items = frame->pop_n_reversed(byte.arg);
|
||||||
frame->push(PyRef(TupleRef(std::move(items))));
|
frame->push(PyRef(TupleRef(std::move(items))));
|
||||||
|
@ -25,7 +25,7 @@ inline const char* OP_NAMES[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Bytecode{
|
struct Bytecode{
|
||||||
uint8_t op;
|
uint16_t op;
|
||||||
uint16_t block;
|
uint16_t block;
|
||||||
int arg;
|
int arg;
|
||||||
int line;
|
int line;
|
||||||
@ -61,7 +61,7 @@ struct CodeObject {
|
|||||||
|
|
||||||
std::vector<Bytecode> codes;
|
std::vector<Bytecode> codes;
|
||||||
List consts;
|
List consts;
|
||||||
std::vector<std::pair<StrName, NameScope>> names;
|
std::vector<StrName> names;
|
||||||
std::set<StrName> global_names;
|
std::set<StrName> global_names;
|
||||||
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
||||||
std::map<StrName, int> labels;
|
std::map<StrName, int> labels;
|
||||||
|
@ -173,7 +173,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
std::unique_ptr<T> expr_prev_line(Args&&... args) {
|
std::unique_ptr<T> make_expr(Args&&... args) {
|
||||||
std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...);
|
std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...);
|
||||||
expr->line = prev().line;
|
expr->line = prev().line;
|
||||||
return expr;
|
return expr;
|
||||||
@ -183,17 +183,17 @@ private:
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprLiteral(){
|
void exprLiteral(){
|
||||||
ctx()->s_expr.push(expr_prev_line<LiteralExpr>(prev().value));
|
ctx()->s_expr.push(make_expr<LiteralExpr>(prev().value));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprFString(){
|
void exprFString(){
|
||||||
ctx()->s_expr.push(expr_prev_line<FStringExpr>(std::get<Str>(prev().value)));
|
ctx()->s_expr.push(make_expr<FStringExpr>(std::get<Str>(prev().value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprLambda(){
|
void exprLambda(){
|
||||||
auto e = expr_prev_line<LambdaExpr>();
|
auto e = make_expr<LambdaExpr>();
|
||||||
e->func.name = "<lambda>";
|
e->func.name = "<lambda>";
|
||||||
e->scope = name_scope();
|
e->scope = name_scope();
|
||||||
if(!match(TK(":"))){
|
if(!match(TK(":"))){
|
||||||
@ -260,7 +260,7 @@ private:
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprTuple(){
|
void exprTuple(){
|
||||||
auto e = expr_prev_line<TupleExpr>();
|
auto e = make_expr<TupleExpr>();
|
||||||
do {
|
do {
|
||||||
EXPR(); // NOTE: "1," will fail, "1,2" will be ok
|
EXPR(); // NOTE: "1," will fail, "1,2" will be ok
|
||||||
e->items.push_back(ctx()->s_expr.popx());
|
e->items.push_back(ctx()->s_expr.popx());
|
||||||
@ -270,7 +270,7 @@ private:
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprOr(){
|
void exprOr(){
|
||||||
auto e = expr_prev_line<OrExpr>();
|
auto e = make_expr<OrExpr>();
|
||||||
e->lhs = ctx()->s_expr.popx();
|
e->lhs = ctx()->s_expr.popx();
|
||||||
parse_expression(PREC_LOGICAL_OR + 1);
|
parse_expression(PREC_LOGICAL_OR + 1);
|
||||||
e->rhs = ctx()->s_expr.popx();
|
e->rhs = ctx()->s_expr.popx();
|
||||||
@ -279,7 +279,7 @@ private:
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprAnd(){
|
void exprAnd(){
|
||||||
auto e = expr_prev_line<AndExpr>();
|
auto e = make_expr<AndExpr>();
|
||||||
e->lhs = ctx()->s_expr.popx();
|
e->lhs = ctx()->s_expr.popx();
|
||||||
parse_expression(PREC_LOGICAL_AND + 1);
|
parse_expression(PREC_LOGICAL_AND + 1);
|
||||||
e->rhs = ctx()->s_expr.popx();
|
e->rhs = ctx()->s_expr.popx();
|
||||||
@ -288,7 +288,7 @@ private:
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprTernary(){
|
void exprTernary(){
|
||||||
auto e = expr_prev_line<TernaryExpr>();
|
auto e = make_expr<TernaryExpr>();
|
||||||
e->cond = ctx()->s_expr.popx();
|
e->cond = ctx()->s_expr.popx();
|
||||||
EXPR(); // if true
|
EXPR(); // if true
|
||||||
e->true_expr = ctx()->s_expr.popx();
|
e->true_expr = ctx()->s_expr.popx();
|
||||||
@ -300,7 +300,7 @@ private:
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprBinaryOp(){
|
void exprBinaryOp(){
|
||||||
auto e = expr_prev_line<BinaryExpr>();
|
auto e = make_expr<BinaryExpr>();
|
||||||
e->op = prev().type;
|
e->op = prev().type;
|
||||||
e->lhs = ctx()->s_expr.popx();
|
e->lhs = ctx()->s_expr.popx();
|
||||||
parse_expression(rules[e->op].precedence + 1);
|
parse_expression(rules[e->op].precedence + 1);
|
||||||
@ -311,7 +311,7 @@ private:
|
|||||||
// PASS
|
// PASS
|
||||||
void exprNot() {
|
void exprNot() {
|
||||||
parse_expression(PREC_LOGICAL_NOT + 1);
|
parse_expression(PREC_LOGICAL_NOT + 1);
|
||||||
ctx()->s_expr.push(expr_prev_line<NotExpr>(ctx()->s_expr.popx()));
|
ctx()->s_expr.push(make_expr<NotExpr>(ctx()->s_expr.popx()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
@ -320,10 +320,10 @@ private:
|
|||||||
parse_expression(PREC_UNARY + 1);
|
parse_expression(PREC_UNARY + 1);
|
||||||
switch(op){
|
switch(op){
|
||||||
case TK("-"):
|
case TK("-"):
|
||||||
ctx()->s_expr.push(expr_prev_line<NegatedExpr>(ctx()->s_expr.popx()));
|
ctx()->s_expr.push(make_expr<NegatedExpr>(ctx()->s_expr.popx()));
|
||||||
break;
|
break;
|
||||||
case TK("*"):
|
case TK("*"):
|
||||||
ctx()->s_expr.push(expr_prev_line<StarredExpr>(ctx()->s_expr.popx()));
|
ctx()->s_expr.push(make_expr<StarredExpr>(ctx()->s_expr.popx()));
|
||||||
break;
|
break;
|
||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
}
|
}
|
||||||
@ -375,7 +375,7 @@ private:
|
|||||||
match_newlines(mode()==REPL_MODE);
|
match_newlines(mode()==REPL_MODE);
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
consume(TK("]"));
|
consume(TK("]"));
|
||||||
auto e = expr_prev_line<ListExpr>(std::move(items));
|
auto e = make_expr<ListExpr>(std::move(items));
|
||||||
e->line = line; // override line
|
e->line = line; // override line
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
}
|
}
|
||||||
@ -392,7 +392,7 @@ private:
|
|||||||
if(parsing_dict){
|
if(parsing_dict){
|
||||||
consume(TK(":"));
|
consume(TK(":"));
|
||||||
EXPR();
|
EXPR();
|
||||||
auto dict_item = expr_prev_line<DictItemExpr>();
|
auto dict_item = make_expr<DictItemExpr>();
|
||||||
dict_item->key = ctx()->s_expr.popx();
|
dict_item->key = ctx()->s_expr.popx();
|
||||||
dict_item->value = ctx()->s_expr.popx();
|
dict_item->value = ctx()->s_expr.popx();
|
||||||
items.push_back(std::move(dict_item));
|
items.push_back(std::move(dict_item));
|
||||||
@ -410,17 +410,17 @@ private:
|
|||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
consume(TK("}"));
|
consume(TK("}"));
|
||||||
if(items.size()==0 || parsing_dict){
|
if(items.size()==0 || parsing_dict){
|
||||||
auto e = expr_prev_line<DictExpr>(std::move(items));
|
auto e = make_expr<DictExpr>(std::move(items));
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
}else{
|
}else{
|
||||||
auto e = expr_prev_line<SetExpr>(std::move(items));
|
auto e = make_expr<SetExpr>(std::move(items));
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprCall() {
|
void exprCall() {
|
||||||
auto e = expr_prev_line<CallExpr>();
|
auto e = make_expr<CallExpr>();
|
||||||
e->callable = ctx()->s_expr.popx();
|
e->callable = ctx()->s_expr.popx();
|
||||||
do {
|
do {
|
||||||
match_newlines(mode()==REPL_MODE);
|
match_newlines(mode()==REPL_MODE);
|
||||||
@ -434,38 +434,32 @@ private:
|
|||||||
} else{
|
} else{
|
||||||
if(!e->kwargs.empty()) SyntaxError("positional argument follows keyword argument");
|
if(!e->kwargs.empty()) SyntaxError("positional argument follows keyword argument");
|
||||||
EXPR();
|
EXPR();
|
||||||
// if(co()->codes.back().op == OP_UNARY_STAR) need_unpack = true;
|
|
||||||
e->args.push_back(ctx()->s_expr.popx());
|
e->args.push_back(ctx()->s_expr.popx());
|
||||||
}
|
}
|
||||||
match_newlines(mode()==REPL_MODE);
|
match_newlines(mode()==REPL_MODE);
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
consume(TK(")"));
|
consume(TK(")"));
|
||||||
|
if(e->args.size() > 32767) SyntaxError("too many positional arguments");
|
||||||
|
if(e->kwargs.size() > 32767) SyntaxError("too many keyword arguments");
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
// if(ARGC > 32767) SyntaxError("too many positional arguments");
|
|
||||||
// if(KWARGC > 32767) SyntaxError("too many keyword arguments");
|
|
||||||
// if(KWARGC > 0){
|
|
||||||
// emit(need_unpack ? OP_CALL_KWARGS_UNPACK : OP_CALL_KWARGS, (KWARGC << 16) | ARGC);
|
|
||||||
// }else{
|
|
||||||
// emit(need_unpack ? OP_CALL_UNPACK : OP_CALL, ARGC);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprName(){
|
void exprName(){
|
||||||
ctx()->s_expr.push(expr_prev_line<NameExpr>(prev().str(), name_scope()));
|
ctx()->s_expr.push(make_expr<NameExpr>(prev().str(), name_scope()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprAttrib() {
|
void exprAttrib() {
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
ctx()->s_expr.push(
|
ctx()->s_expr.push(
|
||||||
expr_prev_line<AttribExpr>(ctx()->s_expr.popx(), prev().str())
|
make_expr<AttribExpr>(ctx()->s_expr.popx(), prev().str())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprSubscr() {
|
void exprSubscr() {
|
||||||
auto e = expr_prev_line<SubscrExpr>();
|
auto e = make_expr<SubscrExpr>();
|
||||||
std::vector<Expr_> items;
|
std::vector<Expr_> items;
|
||||||
do {
|
do {
|
||||||
EXPR_TUPLE();
|
EXPR_TUPLE();
|
||||||
@ -477,7 +471,7 @@ private:
|
|||||||
e->b = std::move(items[0]);
|
e->b = std::move(items[0]);
|
||||||
break;
|
break;
|
||||||
case 2: case 3: {
|
case 2: case 3: {
|
||||||
auto slice = expr_prev_line<SliceExpr>();
|
auto slice = make_expr<SliceExpr>();
|
||||||
slice->start = std::move(items[0]);
|
slice->start = std::move(items[0]);
|
||||||
slice->stop = std::move(items[1]);
|
slice->stop = std::move(items[1]);
|
||||||
if(items.size()==3){
|
if(items.size()==3){
|
||||||
@ -492,7 +486,7 @@ private:
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprLiteral0() {
|
void exprLiteral0() {
|
||||||
ctx()->s_expr.push(expr_prev_line<Literal0Expr>(prev().type));
|
ctx()->s_expr.push(make_expr<Literal0Expr>(prev().type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_block_body() {
|
void compile_block_body() {
|
||||||
@ -708,15 +702,6 @@ private:
|
|||||||
ctx()->emit(OP_ASSERT, BC_NOARG, kw_line);
|
ctx()->emit(OP_ASSERT, BC_NOARG, kw_line);
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
break;
|
break;
|
||||||
case TK("del"):
|
|
||||||
EXPR_TUPLE();
|
|
||||||
Expr_ e = ctx()->s_expr.popx();
|
|
||||||
switch(e->ref_type()){
|
|
||||||
case EXPR_NAME_REF:
|
|
||||||
}
|
|
||||||
ctx()->emit(OP_DELETE_REF, BC_NOARG, kw_line);
|
|
||||||
consume_end_stmt();
|
|
||||||
break;
|
|
||||||
case TK("global"):
|
case TK("global"):
|
||||||
do {
|
do {
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
@ -735,6 +720,13 @@ private:
|
|||||||
ctx()->emit(OP_RAISE, dummy_t, kw_line);
|
ctx()->emit(OP_RAISE, dummy_t, kw_line);
|
||||||
consume_end_stmt();
|
consume_end_stmt();
|
||||||
} break;
|
} break;
|
||||||
|
case TK("del"): {
|
||||||
|
EXPR_TUPLE();
|
||||||
|
Expr_ e = ctx()->s_expr.popx();
|
||||||
|
bool ok = e->emit_del(ctx());
|
||||||
|
if(!ok) SyntaxError();
|
||||||
|
consume_end_stmt();
|
||||||
|
} break;
|
||||||
case TK("with"): {
|
case TK("with"): {
|
||||||
EXPR(true);
|
EXPR(true);
|
||||||
consume(TK("as"));
|
consume(TK("as"));
|
||||||
|
210
src/expr.h
210
src/expr.h
@ -11,25 +11,20 @@ namespace pkpy{
|
|||||||
|
|
||||||
struct CodeEmitContext;
|
struct CodeEmitContext;
|
||||||
|
|
||||||
enum ExprRefType{
|
|
||||||
EXPR_NO_REF,
|
|
||||||
EXPR_NAME_REF,
|
|
||||||
EXPR_ATTR_REF,
|
|
||||||
EXPR_INDEX_REF,
|
|
||||||
EXPR_STARRED_REF,
|
|
||||||
EXPR_TUPLE_REF
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Expr{
|
struct Expr{
|
||||||
int line = 0;
|
int line = 0;
|
||||||
virtual ~Expr() = default;
|
virtual ~Expr() = default;
|
||||||
virtual void emit(CodeEmitContext* ctx) = 0;
|
virtual void emit(CodeEmitContext* ctx) = 0;
|
||||||
virtual Str str() const = 0;
|
virtual Str str() const = 0;
|
||||||
virtual std::vector<const Expr*> children() = 0;
|
|
||||||
|
|
||||||
virtual ExprRefType ref_type() const {
|
virtual std::vector<const Expr*> children() const { return {}; }
|
||||||
return EXPR_NO_REF;
|
virtual bool is_starred() const { return false; }
|
||||||
}
|
|
||||||
|
// for OP_DELETE_XXX
|
||||||
|
virtual bool emit_del(CodeEmitContext* ctx) { return false; }
|
||||||
|
|
||||||
|
// for OP_STORE_XXX
|
||||||
|
virtual bool emit_store(CodeEmitContext* ctx) { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CodeEmitContext{
|
struct CodeEmitContext{
|
||||||
@ -67,13 +62,12 @@ struct CodeEmitContext{
|
|||||||
void emit_expr(){
|
void emit_expr(){
|
||||||
if(s_expr.size() != 1) UNREACHABLE();
|
if(s_expr.size() != 1) UNREACHABLE();
|
||||||
Expr_ expr = s_expr.popx();
|
Expr_ expr = s_expr.popx();
|
||||||
// emit
|
expr->emit(this);
|
||||||
// ...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int emit(Opcode opcode, int arg, int line) {
|
int emit(Opcode opcode, int arg, int line) {
|
||||||
co->codes.push_back(
|
co->codes.push_back(
|
||||||
Bytecode{(uint8_t)opcode, (uint16_t)curr_block_i, arg, line}
|
Bytecode{(uint16_t)opcode, (uint16_t)curr_block_i, arg, line}
|
||||||
);
|
);
|
||||||
int i = co->codes.size() - 1;
|
int i = co->codes.size() - 1;
|
||||||
if(line==BC_KEEPLINE && i>=1) co->codes[i].line = co->codes[i-1].line;
|
if(line==BC_KEEPLINE && i>=1) co->codes[i].line = co->codes[i-1].line;
|
||||||
@ -91,13 +85,11 @@ struct CodeEmitContext{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int add_name(StrName name, NameScope scope){
|
int add_name(StrName name){
|
||||||
if(scope == NAME_LOCAL && co->global_names.count(name)) scope = NAME_GLOBAL;
|
|
||||||
auto p = std::make_pair(name, scope);
|
|
||||||
for(int i=0; i<co->names.size(); i++){
|
for(int i=0; i<co->names.size(); i++){
|
||||||
if(co->names[i] == p) return i;
|
if(co->names[i] == name) return i;
|
||||||
}
|
}
|
||||||
co->names.push_back(p);
|
co->names.push_back(name);
|
||||||
return co->names.size() - 1;
|
return co->names.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,7 +99,7 @@ struct CodeEmitContext{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct NameExpr: Expr{
|
struct NameExpr: Expr{
|
||||||
Str name;
|
Str name;
|
||||||
NameScope scope;
|
NameScope scope;
|
||||||
@ -117,59 +109,99 @@ struct NameExpr: Expr{
|
|||||||
Str str() const override { return "$" + name; }
|
Str str() const override { return "$" + name; }
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
int index = ctx->add_name(name, scope);
|
int index = ctx->add_name(name);
|
||||||
ctx->emit(OP_LOAD_NAME, index, line);
|
ctx->emit(OP_LOAD_NAME, index, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprRefType ref_type() const override {
|
bool emit_del(CodeEmitContext* ctx) override {
|
||||||
return EXPR_NAME_REF;
|
int index = ctx->add_name(name);
|
||||||
|
switch(scope){
|
||||||
|
case NAME_LOCAL:
|
||||||
|
ctx->emit(OP_DELETE_LOCAL, index, line);
|
||||||
|
break;
|
||||||
|
case NAME_GLOBAL:
|
||||||
|
ctx->emit(OP_DELETE_GLOBAL, index, line);
|
||||||
|
break;
|
||||||
|
default: UNREACHABLE(); break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emit_store(CodeEmitContext* ctx) override {
|
||||||
|
int index = ctx->add_name(name);
|
||||||
|
switch(scope){
|
||||||
|
case NAME_LOCAL:
|
||||||
|
ctx->emit(OP_STORE_LOCAL, index, line);
|
||||||
|
break;
|
||||||
|
case NAME_GLOBAL:
|
||||||
|
ctx->emit(OP_STORE_GLOBAL, index, line);
|
||||||
|
break;
|
||||||
|
default: UNREACHABLE(); break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// *号运算符,作为左值和右值效果不同
|
||||||
struct StarredExpr: Expr{
|
struct StarredExpr: Expr{
|
||||||
Expr_ child;
|
Expr_ child;
|
||||||
StarredExpr(Expr_&& child): child(std::move(child)) {}
|
StarredExpr(Expr_&& child): child(std::move(child)) {}
|
||||||
Str str() const override { return "*"; }
|
Str str() const override { return "*"; }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override { return {child.get()}; }
|
||||||
|
|
||||||
|
bool is_starred() const override { return true; }
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
child->emit(ctx);
|
child->emit(ctx);
|
||||||
ctx->emit(OP_UNARY_STAR, (int)false, line);
|
// as a rvalue, we should do unpack here
|
||||||
|
//ctx->emit(OP_UNARY_STAR, (int)false, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprRefType ref_type() const override {
|
bool emit_store(CodeEmitContext* ctx) override {
|
||||||
return EXPR_STARRED_REF;
|
child->emit(ctx);
|
||||||
|
// as a lvalue, we should do pack here
|
||||||
|
//ctx->emit(OP_UNARY_STAR, (int)true, line);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct NegatedExpr: Expr{
|
struct NegatedExpr: Expr{
|
||||||
Expr_ child;
|
Expr_ child;
|
||||||
NegatedExpr(Expr_&& child): child(std::move(child)) {}
|
NegatedExpr(Expr_&& child): child(std::move(child)) {}
|
||||||
Str str() const override { return "-"; }
|
Str str() const override { return "-"; }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override { return {child.get()}; }
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
child->emit(ctx);
|
child->emit(ctx);
|
||||||
ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
|
ctx->emit(OP_UNARY_NEGATIVE, BC_NOARG, line);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct NotExpr: Expr{
|
struct NotExpr: Expr{
|
||||||
Expr_ child;
|
Expr_ child;
|
||||||
NotExpr(Expr_&& child): child(std::move(child)) {}
|
NotExpr(Expr_&& child): child(std::move(child)) {}
|
||||||
Str str() const override { return "not"; }
|
Str str() const override { return "not"; }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override { return {child.get()}; }
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
child->emit(ctx);
|
child->emit(ctx);
|
||||||
ctx->emit(OP_UNARY_NOT, BC_NOARG, line);
|
ctx->emit(OP_UNARY_NOT, BC_NOARG, line);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct AndExpr: Expr{
|
struct AndExpr: Expr{
|
||||||
Expr_ lhs;
|
Expr_ lhs;
|
||||||
Expr_ rhs;
|
Expr_ rhs;
|
||||||
Str str() const override { return "and"; }
|
Str str() const override { return "and"; }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override { return {lhs.get(), rhs.get()}; }
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
lhs->emit(ctx);
|
lhs->emit(ctx);
|
||||||
int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
|
int patch = ctx->emit(OP_JUMP_IF_FALSE_OR_POP, BC_NOARG, line);
|
||||||
@ -178,11 +210,14 @@ struct AndExpr: Expr{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct OrExpr: Expr{
|
struct OrExpr: Expr{
|
||||||
Expr_ lhs;
|
Expr_ lhs;
|
||||||
Expr_ rhs;
|
Expr_ rhs;
|
||||||
Str str() const override { return "or"; }
|
Str str() const override { return "or"; }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override { return {lhs.get(), rhs.get()}; }
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
lhs->emit(ctx);
|
lhs->emit(ctx);
|
||||||
int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
|
int patch = ctx->emit(OP_JUMP_IF_TRUE_OR_POP, BC_NOARG, line);
|
||||||
@ -249,12 +284,18 @@ struct LiteralExpr: Expr{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct SliceExpr: Expr{
|
struct SliceExpr: Expr{
|
||||||
Expr_ start;
|
Expr_ start;
|
||||||
Expr_ stop;
|
Expr_ stop;
|
||||||
Expr_ step;
|
Expr_ step;
|
||||||
Str str() const override { return "slice()"; }
|
Str str() const override { return "slice()"; }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override {
|
||||||
|
// may contain nullptr
|
||||||
|
return {start.get(), stop.get(), step.get()};
|
||||||
|
}
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
if(start){
|
if(start){
|
||||||
start->emit(ctx);
|
start->emit(ctx);
|
||||||
@ -278,11 +319,30 @@ struct SliceExpr: Expr{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct DictItemExpr: Expr{
|
||||||
|
Expr_ key;
|
||||||
|
Expr_ value;
|
||||||
|
Str str() const override { return "k:v"; }
|
||||||
|
std::vector<const Expr*> children() const override { return {key.get(), value.get()}; }
|
||||||
|
|
||||||
|
void emit(CodeEmitContext* ctx) override {
|
||||||
|
key->emit(ctx);
|
||||||
|
value->emit(ctx);
|
||||||
|
ctx->emit(OP_BUILD_TUPLE, 2, line);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct SequenceExpr: Expr{
|
struct SequenceExpr: Expr{
|
||||||
std::vector<Expr_> items;
|
std::vector<Expr_> items;
|
||||||
SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {}
|
SequenceExpr(std::vector<Expr_>&& items): items(std::move(items)) {}
|
||||||
virtual Opcode opcode() const = 0;
|
virtual Opcode opcode() const = 0;
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override {
|
||||||
|
std::vector<const Expr*> ret;
|
||||||
|
for(auto& item: items) ret.push_back(item.get());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
for(auto& item: items) item->emit(ctx);
|
for(auto& item: items) item->emit(ctx);
|
||||||
ctx->emit(opcode(), items.size(), line);
|
ctx->emit(opcode(), items.size(), line);
|
||||||
@ -308,8 +368,9 @@ struct TupleExpr: SequenceExpr{
|
|||||||
Str str() const override { return "tuple()"; }
|
Str str() const override { return "tuple()"; }
|
||||||
Opcode opcode() const override { return OP_BUILD_TUPLE; }
|
Opcode opcode() const override { return OP_BUILD_TUPLE; }
|
||||||
|
|
||||||
ExprRefType ref_type() const override {
|
bool emit_store(CodeEmitContext* ctx) override {
|
||||||
return EXPR_TUPLE_REF;
|
// ...
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -318,14 +379,6 @@ struct CompExpr: Expr{
|
|||||||
Expr_ vars; // loop vars
|
Expr_ vars; // loop vars
|
||||||
Expr_ iter; // loop iter
|
Expr_ iter; // loop iter
|
||||||
Expr_ cond; // optional if condition
|
Expr_ cond; // optional if condition
|
||||||
virtual void emit_expr() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// a:b
|
|
||||||
struct DictItemExpr: Expr{
|
|
||||||
Expr_ key;
|
|
||||||
Expr_ value;
|
|
||||||
Str str() const override { return "k:v"; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ListCompExpr: CompExpr{
|
struct ListCompExpr: CompExpr{
|
||||||
@ -345,7 +398,9 @@ struct LambdaExpr: Expr{
|
|||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
VM* vm = ctx->vm;
|
VM* vm = ctx->vm;
|
||||||
ctx->emit(OP_LOAD_FUNCTION, ctx->add_const(VAR(func)), line);
|
ctx->emit(OP_LOAD_FUNCTION, ctx->add_const(VAR(func)), line);
|
||||||
if(scope == NAME_LOCAL) ctx->emit(OP_SETUP_CLOSURE, BC_NOARG, BC_KEEPLINE);
|
if(scope == NAME_LOCAL){
|
||||||
|
ctx->emit(OP_SETUP_CLOSURE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -393,11 +448,21 @@ struct SubscrExpr: Expr{
|
|||||||
void emit(CodeEmitContext* ctx) override{
|
void emit(CodeEmitContext* ctx) override{
|
||||||
a->emit(ctx);
|
a->emit(ctx);
|
||||||
b->emit(ctx);
|
b->emit(ctx);
|
||||||
ctx->emit(OP_BUILD_INDEX, BC_NOARG, line);
|
ctx->emit(OP_LOAD_SUBSCR, BC_NOARG, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprRefType ref_type() const override {
|
bool emit_del(CodeEmitContext* ctx) override {
|
||||||
return EXPR_INDEX_REF;
|
a->emit(ctx);
|
||||||
|
b->emit(ctx);
|
||||||
|
ctx->emit(OP_DELETE_SUBSCR, BC_NOARG, line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emit_store(CodeEmitContext* ctx) override {
|
||||||
|
a->emit(ctx);
|
||||||
|
b->emit(ctx);
|
||||||
|
ctx->emit(OP_STORE_SUBSCR, BC_NOARG, line);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -408,16 +473,56 @@ struct AttribExpr: Expr{
|
|||||||
AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {}
|
AttribExpr(Expr_ a, Str&& b): a(std::move(a)), b(std::move(b)) {}
|
||||||
Str str() const override { return "a.b"; }
|
Str str() const override { return "a.b"; }
|
||||||
|
|
||||||
ExprRefType ref_type() const override {
|
void emit(CodeEmitContext* ctx) override{
|
||||||
return EXPR_ATTR_REF;
|
a->emit(ctx);
|
||||||
|
int index = ctx->add_name(b);
|
||||||
|
ctx->emit(OP_LOAD_ATTR, index, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emit_del(CodeEmitContext* ctx) override {
|
||||||
|
a->emit(ctx);
|
||||||
|
int index = ctx->add_name(b);
|
||||||
|
ctx->emit(OP_DELETE_ATTR, index, line);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool emit_store(CodeEmitContext* ctx) override {
|
||||||
|
a->emit(ctx);
|
||||||
|
int index = ctx->add_name(b);
|
||||||
|
ctx->emit(OP_STORE_ATTR, index, line);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct CallExpr: Expr{
|
struct CallExpr: Expr{
|
||||||
Expr_ callable;
|
Expr_ callable;
|
||||||
std::vector<Expr_> args;
|
std::vector<Expr_> args;
|
||||||
std::vector<std::pair<Str, Expr_>> kwargs;
|
std::vector<std::pair<Str, Expr_>> kwargs;
|
||||||
Str str() const override { return "()"; }
|
Str str() const override { return "call(...)"; }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override {
|
||||||
|
std::vector<const Expr*> ret;
|
||||||
|
for(auto& item: args) ret.push_back(item.get());
|
||||||
|
// ...ignore kwargs for simplicity
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool need_unpack() const {
|
||||||
|
for(auto& item: args) if(item->is_starred()) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void emit(CodeEmitContext* ctx) override {
|
||||||
|
callable->emit(ctx);
|
||||||
|
int KWARGC = (int)kwargs.size();
|
||||||
|
int ARGC = (int)args.size();
|
||||||
|
if(KWARGC > 0){
|
||||||
|
ctx->emit(need_unpack() ? OP_CALL_KWARGS_UNPACK : OP_CALL_KWARGS, (KWARGC<<16)|ARGC, line);
|
||||||
|
}else{
|
||||||
|
ctx->emit(need_unpack() ? OP_CALL_UNPACK : OP_CALL, ARGC, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BinaryExpr: Expr{
|
struct BinaryExpr: Expr{
|
||||||
@ -426,6 +531,10 @@ struct BinaryExpr: Expr{
|
|||||||
Expr_ rhs;
|
Expr_ rhs;
|
||||||
Str str() const override { return TK_STR(op); }
|
Str str() const override { return TK_STR(op); }
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override {
|
||||||
|
return {lhs.get(), rhs.get()};
|
||||||
|
}
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
lhs->emit(ctx);
|
lhs->emit(ctx);
|
||||||
rhs->emit(ctx);
|
rhs->emit(ctx);
|
||||||
@ -459,13 +568,18 @@ struct BinaryExpr: Expr{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// PASS
|
||||||
struct TernaryExpr: Expr{
|
struct TernaryExpr: Expr{
|
||||||
Expr_ cond;
|
Expr_ cond;
|
||||||
Expr_ true_expr;
|
Expr_ true_expr;
|
||||||
Expr_ false_expr;
|
Expr_ false_expr;
|
||||||
|
|
||||||
Str str() const override {
|
Str str() const override {
|
||||||
return "cond ? true_expr : false_expr";
|
return "cond ? t : f";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const Expr*> children() const override {
|
||||||
|
return {cond.get(), true_expr.get(), false_expr.get()};
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
|
41
src/frame.h
41
src/frame.h
@ -53,34 +53,20 @@ struct Frame {
|
|||||||
// return ss.str();
|
// return ss.str();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
PyObject* pop(){
|
void pop(){
|
||||||
#if DEBUG_EXTRA_CHECK
|
|
||||||
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
|
||||||
#endif
|
|
||||||
PyObject* v = _data.back();
|
|
||||||
_data.pop_back();
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _pop(){
|
|
||||||
#if DEBUG_EXTRA_CHECK
|
#if DEBUG_EXTRA_CHECK
|
||||||
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
||||||
#endif
|
#endif
|
||||||
_data.pop_back();
|
_data.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void try_deref(VM*, PyObject*&);
|
PyObject* popx(){
|
||||||
|
#if DEBUG_EXTRA_CHECK
|
||||||
PyObject* pop_value(VM* vm){
|
if(_data.empty()) throw std::runtime_error("_data.empty() is true");
|
||||||
PyObject* value = pop();
|
#endif
|
||||||
try_deref(vm, value);
|
PyObject* ret = _data.back();
|
||||||
return value;
|
_data.pop_back();
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
PyObject* top_value(VM* vm){
|
|
||||||
PyObject* value = top();
|
|
||||||
try_deref(vm, value);
|
|
||||||
return value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject*& top(){
|
PyObject*& top(){
|
||||||
@ -141,18 +127,9 @@ struct Frame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Args pop_n_values_reversed(VM* vm, int n){
|
|
||||||
Args v(n);
|
|
||||||
for(int i=n-1; i>=0; i--){
|
|
||||||
v[i] = pop();
|
|
||||||
try_deref(vm, v[i]);
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
Args pop_n_reversed(int n){
|
Args pop_n_reversed(int n){
|
||||||
Args v(n);
|
Args v(n);
|
||||||
for(int i=n-1; i>=0; i--) v[i] = pop();
|
for(int i=n-1; i>=0; i--) v[i] = popx();
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,6 @@ OPCODE(BUILD_ATTR_REF)
|
|||||||
OPCODE(STORE_NAME)
|
OPCODE(STORE_NAME)
|
||||||
OPCODE(STORE_FUNCTION)
|
OPCODE(STORE_FUNCTION)
|
||||||
OPCODE(STORE_REF)
|
OPCODE(STORE_REF)
|
||||||
OPCODE(DELETE_REF)
|
|
||||||
|
|
||||||
OPCODE(TRY_BLOCK_ENTER)
|
OPCODE(TRY_BLOCK_ENTER)
|
||||||
OPCODE(TRY_BLOCK_EXIT)
|
OPCODE(TRY_BLOCK_EXIT)
|
||||||
@ -89,4 +88,20 @@ OPCODE(BEGIN_CLASS)
|
|||||||
OPCODE(END_CLASS)
|
OPCODE(END_CLASS)
|
||||||
OPCODE(STORE_CLASS_ATTR)
|
OPCODE(STORE_CLASS_ATTR)
|
||||||
|
|
||||||
|
/**************************/
|
||||||
|
OPCODE(LOAD_NAME)
|
||||||
|
OPCODE(LOAD_ATTR)
|
||||||
|
OPCODE(LOAD_SUBSCR)
|
||||||
|
|
||||||
|
OPCODE(STORE_LOCAL)
|
||||||
|
OPCODE(STORE_GLOBAL)
|
||||||
|
OPCODE(STORE_ATTR)
|
||||||
|
OPCODE(STORE_SUBSCR)
|
||||||
|
|
||||||
|
OPCODE(DELETE_LOCAL)
|
||||||
|
OPCODE(DELETE_GLOBAL)
|
||||||
|
OPCODE(DELETE_ATTR)
|
||||||
|
OPCODE(DELETE_SUBSCR)
|
||||||
|
/**************************/
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -83,11 +83,6 @@ struct AttrRef : BaseRef {
|
|||||||
vm->setattr(obj, attr.name(), std::move(val));
|
vm->setattr(obj, attr.name(), std::move(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
void del(VM* vm, Frame* frame) const{
|
|
||||||
if(!obj->is_attr_valid()) vm->TypeError("cannot delete attribute");
|
|
||||||
if(!obj->attr().contains(attr.name())) vm->AttributeError(obj, attr.name());
|
|
||||||
obj->attr().erase(attr.name());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IndexRef : BaseRef {
|
struct IndexRef : BaseRef {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user