blueloveTH 2 лет назад
Родитель
Сommit
cf5fadd3b0
4 измененных файлов с 61 добавлено и 52 удалено
  1. 31 26
      src/ceval.h
  2. 15 7
      src/compiler.h
  3. 4 0
      src/expr.h
  4. 11 19
      src/opcodes.h

+ 31 - 26
src/ceval.h

@@ -238,6 +238,7 @@ __NEXT_STEP:;
         frame->push(std::move(ret));
     } DISPATCH();
     case OP_RETURN_VALUE: return frame->popx();
+    case OP_YIELD_VALUE: return _py_op_yield;
     /*****************************************/
     case OP_LIST_APPEND: {
         PyObject* obj = frame->popx();
@@ -352,35 +353,39 @@ __NEXT_STEP:;
         cls->attr().set(name, obj);
     } DISPATCH();
     /*****************************************/
-    /*****************************************/
-    /*****************************************/
-    // case OP_SETUP_DECORATOR: DISPATCH();
-
-    // case OP_ASSERT: {
-    //     PyObject* _msg = frame->pop_value(this);
-    //     Str msg = CAST(Str, asStr(_msg));
-    //     PyObject* expr = frame->pop_value(this);
-    //     if(asBool(expr) != True) _error("AssertionError", msg);
-    // } DISPATCH();
-    // case OP_EXCEPTION_MATCH: {
-    //     const auto& e = CAST(Exception&, frame->top());
-    //     StrName name = frame->co->names[byte.arg].first;
-    //     frame->push(VAR(e.match_type(name)));
-    // } DISPATCH();
-    // case OP_RAISE: {
-    //     PyObject* obj = frame->pop_value(this);
-    //     Str msg = obj == None ? "" : CAST(Str, asStr(obj));
-    //     StrName type = frame->co->names[byte.arg].first;
-    //     _error(type, msg);
-    // } DISPATCH();
-    // case OP_RE_RAISE: _raise(); DISPATCH();
-    // case OP_YIELD_VALUE: return _py_op_yield;
     // // TODO: using "goto" inside with block may cause __exit__ not called
     // case OP_WITH_ENTER: call(frame->pop_value(this), __enter__, no_arg()); DISPATCH();
     // case OP_WITH_EXIT: call(frame->pop_value(this), __exit__, no_arg()); DISPATCH();
-    // case OP_TRY_BLOCK_ENTER: frame->on_try_block_enter(); DISPATCH();
-    // case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); DISPATCH();
-    default: throw std::runtime_error(Str("opcode ") + OP_NAMES[byte.op] + " is not implemented");
+    /*****************************************/
+    case OP_TRY_BLOCK_ENTER: frame->on_try_block_enter(); DISPATCH();
+    case OP_TRY_BLOCK_EXIT: frame->on_try_block_exit(); DISPATCH();
+    /*****************************************/
+    case OP_ASSERT: {
+        PyObject* obj = frame->top();
+        Str msg;
+        if(is_type(obj, tp_tuple)){
+            auto& t = CAST(Tuple&, obj);
+            if(t.size() != 2) ValueError("assert tuple must have 2 elements");
+            obj = t[0];
+            msg = CAST(Str&, asStr(t[1]));
+        }
+        bool ok = asBool(obj);
+        frame->pop();
+        if(!ok) _error("AssertionError", msg);
+    } DISPATCH();
+    case OP_EXCEPTION_MATCH: {
+        const auto& e = CAST(Exception&, frame->top());
+        StrName name = frame->co->names[byte.arg];
+        frame->push(VAR(e.match_type(name)));
+    } DISPATCH();
+    case OP_RAISE: {
+        PyObject* obj = frame->popx();
+        Str msg = obj == None ? "" : CAST(Str, asStr(obj));
+        StrName type = frame->co->names[byte.arg];
+        _error(type, msg);
+    } DISPATCH();
+    case OP_RE_RAISE: _raise(); DISPATCH();
+    default: throw std::runtime_error(OP_NAMES[byte.op] + std::string(" is not implemented"));
     }
     UNREACHABLE();
 }

+ 15 - 7
src/compiler.h

@@ -578,13 +578,14 @@ class Compiler {
     }
 
     void compile_decorated(){
-        EXPR(false);
-        // TODO: support multiple decorator
-        // use a while loop to consume '@'
-        if(!match_newlines_repl()) SyntaxError();
-        ctx()->emit(OP_SETUP_DECORATOR, BC_NOARG, prev().line);
+        std::vector<Expr_> decorators;
+        do{
+            EXPR();
+            decorators.push_back(ctx()->s_expr.popx());
+            if(!match_newlines_repl()) SyntaxError();
+        }while(match(TK("@")));
         consume(TK("def"));
-        compile_function();
+        compile_function(decorators);
     }
 
     bool try_compile_assignment(){
@@ -593,6 +594,7 @@ class Compiler {
         switch (curr().type) {
             case TK("+="): case TK("-="): case TK("*="): case TK("/="): case TK("//="): case TK("%="):
             case TK("<<="): case TK(">>="): case TK("&="): case TK("|="): case TK("^="): {
+                if(ctx()->is_compiling_class) SyntaxError();
                 inplace = true;
                 advance();
                 auto e = make_expr<BinaryExpr>();
@@ -802,7 +804,7 @@ class Compiler {
         } while (match(TK(",")));
     }
 
-    void compile_function(){
+    void compile_function(const std::vector<Expr_>& decorators={}){
         // TODO: bug, if there are multiple decorators, will cause error
         FuncDecl_ decl = make_sp<FuncDecl>();
         StrName obj_name;
@@ -825,6 +827,12 @@ class Compiler {
         compile_block_body();
         pop_context();
         ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_func_decl(decl), prev().line);
+        // add decorators
+        for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){
+            (*it)->emit(ctx());
+            ctx()->emit(OP_ROT_TWO, BC_NOARG, (*it)->line);
+            ctx()->emit(OP_CALL, 1, (*it)->line);
+        }
         if(!ctx()->is_compiling_class){
             if(obj_name.empty()){
                 auto e = make_expr<NameExpr>(decl->name, name_scope());

+ 4 - 0
src/expr.h

@@ -140,6 +140,10 @@ struct NameExpr: Expr{
 
     bool emit_store(CodeEmitContext* ctx) override {
         int index = ctx->add_name(name);
+        if(ctx->is_compiling_class){
+            ctx->emit(OP_STORE_CLASS_ATTR, index, line);
+            return true;
+        }
         switch(scope){
             case NAME_LOCAL:
                 ctx->emit(OP_STORE_LOCAL, index, line);

+ 11 - 19
src/opcodes.h

@@ -1,23 +1,5 @@
 #ifdef OPCODE
 
-/**************************/
-OPCODE(WITH_ENTER)
-OPCODE(WITH_EXIT)
-
-OPCODE(ASSERT)
-OPCODE(EXCEPTION_MATCH)
-OPCODE(RAISE)
-OPCODE(RE_RAISE)
-
-OPCODE(STORE_FUNCTION)
-
-OPCODE(TRY_BLOCK_ENTER)
-OPCODE(TRY_BLOCK_EXIT)
-
-OPCODE(YIELD_VALUE)
-
-OPCODE(SETUP_DECORATOR)
-
 /**************************/
 OPCODE(NO_OP)
 /**************************/
@@ -74,6 +56,7 @@ OPCODE(CALL_UNPACK)
 OPCODE(CALL_KWARGS)
 OPCODE(CALL_KWARGS_UNPACK)
 OPCODE(RETURN_VALUE)
+OPCODE(YIELD_VALUE)
 /**************************/
 OPCODE(LIST_APPEND)
 OPCODE(DICT_ADD)
@@ -92,9 +75,18 @@ OPCODE(IMPORT_STAR)
 OPCODE(UNPACK_SEQUENCE)
 OPCODE(UNPACK_EX)
 /**************************/
-// TODO: examine this
 OPCODE(BEGIN_CLASS)
 OPCODE(END_CLASS)
 OPCODE(STORE_CLASS_ATTR)
 /**************************/
+OPCODE(WITH_ENTER)
+OPCODE(WITH_EXIT)
+/**************************/
+OPCODE(TRY_BLOCK_ENTER)
+OPCODE(TRY_BLOCK_EXIT)
+OPCODE(ASSERT)
+OPCODE(EXCEPTION_MATCH)
+OPCODE(RAISE)
+OPCODE(RE_RAISE)
+/**************************/
 #endif