blueloveTH 2 tahun lalu
induk
melakukan
449fb9a2f8
7 mengubah file dengan 290 tambahan dan 160 penghapusan
  1. 74 37
      src/ceval.h
  2. 2 2
      src/codeobject.h
  3. 31 39
      src/compiler.h
  4. 162 48
      src/expr.h
  5. 5 28
      src/frame.h
  6. 16 1
      src/opcodes.h
  7. 0 5
      src/ref.h

+ 74 - 37
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])));
+        case OP_ROT_TWO: ::std::swap(frame->top(), frame->top_1()); continue;
+        case OP_BUILD_TUPLE: {
+            Args items = frame->pop_n_values_reversed(this, byte.arg);
+            frame->push(VAR(std::move(items)));
         } continue;
         } continue;
+        /*****************************************/
         case OP_LOAD_NAME: {
         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());
+            // 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;
         } 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));
+        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;
         } 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();
+        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;
         } continue;
-        case OP_DELETE_REF: 
-            PyRef_AS_C(frame->top())->del(this, frame);
-            frame->_pop();
-            continue;
-        case OP_BUILD_TUPLE: {
-            Args items = frame->pop_n_values_reversed(this, byte.arg);
-            frame->push(VAR(std::move(items)));
+        case OP_DELETE_SUBSCR: {
+            PyObject* b = frame->popx();
+            PyObject* a = frame->popx();
+            fast_call(__delitem__, Args{a, b});
         } continue;
         } 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))));

+ 2 - 2
src/codeobject.h

@@ -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;

+ 31 - 39
src/compiler.h

@@ -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"));

+ 162 - 48
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 {
-        return EXPR_NO_REF;
-    }
+    virtual std::vector<const Expr*> children() const { return {}; }
+    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){
-        if(scope == NAME_LOCAL && co->global_names.count(name)) scope = NAME_GLOBAL;
-        auto p = std::make_pair(name, scope);
+    int add_name(StrName name){
         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 {
-        return EXPR_NAME_REF;
+    bool emit_del(CodeEmitContext* ctx) override {
+        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 {
-        return EXPR_STARRED_REF;
+    bool emit_store(CodeEmitContext* ctx) override {
+        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 {
-        return EXPR_TUPLE_REF;
+    bool emit_store(CodeEmitContext* ctx) override {
+        // ...
+        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 {
-        return EXPR_INDEX_REF;
+    bool emit_del(CodeEmitContext* ctx) override {
+        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 {
-        return EXPR_ATTR_REF;
+    void emit(CodeEmitContext* ctx) override{
+        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 {

+ 5 - 28
src/frame.h

@@ -53,34 +53,20 @@ struct Frame {
     //     return ss.str();
     //     return ss.str();
     // }
     // }
 
 
-    PyObject* pop(){
+    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
-        PyObject* v = _data.back();
         _data.pop_back();
         _data.pop_back();
-        return v;
     }
     }
 
 
-    void _pop(){
+    PyObject* popx(){
 #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
+        PyObject* ret = _data.back();
         _data.pop_back();
         _data.pop_back();
-    }
-
-    void try_deref(VM*, PyObject*&);
-
-    PyObject* pop_value(VM* vm){
-        PyObject* value = pop();
-        try_deref(vm, value);
-        return value;
-    }
-
-    PyObject* top_value(VM* vm){
-        PyObject* value = top();
-        try_deref(vm, value);
-        return value;
+        return ret;
     }
     }
 
 
     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;
     }
     }
 
 

+ 16 - 1
src/opcodes.h

@@ -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

+ 0 - 5
src/ref.h

@@ -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 {