blueloveTH 3 лет назад
Родитель
Сommit
bb651906c3
4 измененных файлов с 58 добавлено и 15 удалено
  1. 15 5
      src/codeobject.h
  2. 34 10
      src/compiler.h
  3. 3 0
      src/opcodes.h
  4. 6 0
      src/vm.h

+ 15 - 5
src/codeobject.h

@@ -55,6 +55,12 @@ struct CodeObject {
         return co_consts.size() - 1;
     }
 
+    void __copyToEnd(int start, int end){
+        auto _start = co_code.begin() + start;
+        auto _end = co_code.begin() + end;
+        co_code.insert(co_code.end(), _start, _end);
+    }
+
     _Str toString(){
         _StrStream ss;
         int prev_line = -1;
@@ -95,7 +101,7 @@ struct CodeObject {
 
 class Frame {
 private:
-    std::stack<PyVar> s_data;
+    std::vector<PyVar> s_data;
     int ip = 0;
 public:
     StlDict* f_globals;
@@ -124,8 +130,8 @@ public:
     }
 
     inline PyVar __pop(){
-        PyVar v = s_data.top();
-        s_data.pop();
+        PyVar v = s_data.back();
+        s_data.pop_back();
         return v;
     }
 
@@ -136,11 +142,15 @@ public:
     }
 
     inline PyVar topValue(VM* vm){
-        return __deref_pointer(vm, s_data.top());
+        return __deref_pointer(vm, s_data.back());
+    }
+
+    inline PyVar topNValue(VM* vm, int n=-1){
+        return __deref_pointer(vm, s_data[s_data.size() + n]);
     }
 
     inline void push(PyVar v){
-        s_data.push(v);
+        s_data.push_back(v);
     }
 
     inline void jumpTo(int i){

+ 34 - 10
src/compiler.h

@@ -11,7 +11,7 @@
 class Compiler;
 
 typedef void (Compiler::*GrammarFn)();
-typedef void (Compiler::*CompilerAction)();
+typedef std::function<void(Compiler*)> CompilerAction;
 
 struct GrammarRule{
     GrammarFn prefix;
@@ -430,8 +430,33 @@ public:
     }
 
     void exprList() {
-        ExprCommaSplitArgs("]");
+        int _patch = emitCode(OP_NO_OP);
+        int _body_start = getCode()->co_code.size();
+        int ARGC = 0;
+        do {
+            matchNewLines();
+            if (peek() == TK("]")) break;
+            EXPR(); ARGC++;
+            matchNewLines();
+            if(ARGC == 1 && match(TK("for"))) goto __LISTCOMP;
+        } while (match(TK(",")));
+        matchNewLines();
+        consume(TK("]"));
         emitCode(OP_BUILD_LIST, ARGC);
+        return;
+
+__LISTCOMP:
+        int _body_end = getCode()->co_code.size();
+        getCode()->co_code[_patch].op = OP_JUMP_ABSOLUTE;
+        getCode()->co_code[_patch].arg = _body_end;
+        emitCode(OP_BUILD_LIST, 0);
+        __compileForLoop([=](Compiler* compiler){
+            // [list, iter]
+            getCode()->__copyToEnd(_body_start, _body_end);
+            // [list, iter, value]
+            emitCode(OP_LIST_APPEND);
+        });
+        consume(TK("]"));
     }
 
     void exprMap() {
@@ -538,7 +563,7 @@ public:
         }
         consume(TK("@indent"));
         while (peek() != TK("@dedent")) {
-            (this->*action)();
+            action(this);
             matchNewLines();
         }
         consume(TK("@dedent"));
@@ -617,7 +642,7 @@ public:
         loops.pop();
     }
 
-    void compileWhileStatement() {
+    void compileWhileLoop() {
         Loop& loop = enterLoop(false);
         EXPR_TUPLE();
         int patch = emitCode(OP_POP_JUMP_IF_FALSE);
@@ -627,12 +652,11 @@ public:
         exitLoop();
     }
 
-    void compileForStatement() {
+    void __compileForLoop(CompilerAction action) {
         int size = 0;
         do {
             consume(TK("@id"));
-            exprName();     // push a name ptr into stack
-            size++;
+            exprName(); size++;
         } while (match(TK(",")));
         if(size > 1) emitCode(OP_BUILD_SMART_TUPLE, size);
         consume(TK("in"));
@@ -640,7 +664,7 @@ public:
         emitCode(OP_GET_ITER);              // [ptr, list] -> iter
         Loop& loop = enterLoop(true);
         int patch = emitCode(OP_FOR_ITER);
-        compileBlockBody();
+        action(this);
         emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
         patchJump(patch);
         exitLoop();
@@ -672,9 +696,9 @@ public:
         } else if (match(TK("if"))) {
             compileIfStatement();
         } else if (match(TK("while"))) {
-            compileWhileStatement();
+            compileWhileLoop();
         } else if (match(TK("for"))) {
-            compileForStatement();
+            __compileForLoop(&Compiler::compileBlockBody);
         } else if(match(TK("assert"))){
             EXPR();
             emitCode(OP_ASSERT);

+ 3 - 0
src/opcodes.h

@@ -1,5 +1,6 @@
 #ifdef OPCODE
 
+OPCODE(NO_OP)
 OPCODE(LOAD_CONST)
 OPCODE(IMPORT_NAME)
 OPCODE(PRINT_EXPR)
@@ -21,6 +22,8 @@ OPCODE(BUILD_LIST)
 OPCODE(BUILD_MAP)
 OPCODE(BUILD_SLICE)
 
+OPCODE(LIST_APPEND)
+
 OPCODE(GET_ITER)
 OPCODE(FOR_ITER)
 

+ 6 - 0
src/vm.h

@@ -162,6 +162,7 @@ public:
 
             switch (byte.op)
             {
+            case OP_NO_OP: break;       // do nothing
             case OP_LOAD_CONST: frame->push(frame->code->co_consts[byte.arg]); break;
             case OP_LOAD_NAME_PTR: {
                 frame->push(PyPointer(frame->code->co_names[byte.arg]));
@@ -220,6 +221,11 @@ public:
             case OP_LOAD_EVAL_FN: {
                 frame->push(builtins->attribs["eval"]);
             } break;
+            case OP_LIST_APPEND: {
+                PyVar obj = frame->popValue(this);
+                PyVar list = frame->topNValue(this, -2);
+                fastCall(list, "append", {list, obj});
+            } break;
             case OP_STORE_FUNCTION:
                 {
                     PyVar obj = frame->popValue(this);