Kaynağa Gözat

fix a bug of REPL

blueloveTH 3 yıl önce
ebeveyn
işleme
84cdb20687
4 değiştirilmiş dosya ile 23 ekleme ve 13 silme
  1. 1 0
      src/codeobject.h
  2. 7 8
      src/compiler.h
  3. 5 1
      src/error.h
  4. 10 4
      src/main.cpp

+ 1 - 0
src/codeobject.h

@@ -67,6 +67,7 @@ struct CodeObject {
         int prev_line = -1;
         for(int i=0; i<co_code.size(); i++){
             const ByteCode& byte = co_code[i];
+            if(byte.op == OP_NO_OP) continue;
             _Str line = std::to_string(byte.line);
             if(byte.line == prev_line) line = "";
             else{

+ 7 - 8
src/compiler.h

@@ -44,6 +44,8 @@ public:
     std::stack<_Code> codes;
     std::stack<Loop> loops;
 
+    CompileMode mode;
+
     bool isCompilingClass = false;
 
     _Str path = "<?>";
@@ -59,13 +61,10 @@ public:
         return loops.top();
     }
 
-    CompileMode mode() {
-        return getCode()->mode;
-    }
-
     Compiler(VM* vm, const char* source, _Code code){
         this->vm = vm;
         this->codes.push(code);
+        this->mode = code->mode;
         if (!code->co_filename.empty()) path = code->co_filename;
         this->parser = std::make_unique<Parser>(source);
 
@@ -281,7 +280,7 @@ public:
             consumed = true;
         }
         if (repl_throw && peek() == TK("@eof")){
-            throw NeedMoreLines();
+            throw NeedMoreLines(isCompilingClass);
         }
         return consumed;
     }
@@ -579,7 +578,7 @@ __LISTCOMP:
     
     void __compileBlockBody(CompilerAction action) {
         consume(TK(":"));
-        if(!matchNewLines(mode()==SINGLE_MODE)){
+        if(!matchNewLines(mode==SINGLE_MODE)){
             throw SyntaxError(path, parser->previous, "expected a new line after ':'");
         }
         consume(TK("@indent"));
@@ -745,7 +744,7 @@ __LISTCOMP:
             // If last op is not an assignment, pop the result.
             uint8_t lastOp = getCode()->co_code.back().op;
             if( lastOp != OP_STORE_NAME_PTR && lastOp != OP_STORE_PTR){
-                if(mode()==SINGLE_MODE && parser->indents.top() == 0){
+                if(mode==SINGLE_MODE && parser->indents.top() == 0){
                     emitCode(OP_PRINT_EXPR);
                 }
                 emitCode(OP_POP_TOP);
@@ -853,7 +852,7 @@ __LITERAL_EXIT:
         lexToken();
         matchNewLines();
 
-        if(mode() == EVAL_MODE) {
+        if(mode == EVAL_MODE) {
             EXPR_TUPLE();
             consume(TK("@eof"));
             return;

+ 5 - 1
src/error.h

@@ -7,7 +7,11 @@
 
 #include "parser.h"
 
-class NeedMoreLines : public std::exception {};
+class NeedMoreLines : public std::exception {
+public:
+    NeedMoreLines(bool isClassDef) : isClassDef(isClassDef) {}
+    bool isClassDef;
+};
 
 class SyntaxError : public std::exception {
 private:

+ 10 - 4
src/main.cpp

@@ -40,7 +40,8 @@ VM* newVM(){
 void REPL(){
     std::cout << "pocketpy 0.1.0" << std::endl;
 
-    bool need_more_lines = false;
+    int need_more_lines = 0;
+
     std::string buffer;
     VM* vm = newVM();
 
@@ -54,12 +55,16 @@ void REPL(){
             buffer += line;
             buffer += '\n';
             int n = buffer.size();
-            if(n>=2 && buffer[n-1]=='\n' && buffer[n-2]=='\n'){
-                need_more_lines = false;
+            if(n>=need_more_lines){
+                for(int i=buffer.size()-need_more_lines; i<buffer.size(); i++){
+                    if(buffer[i] != '\n') goto __NOT_ENOUGH_LINES;
+                }
+                need_more_lines = 0;
                 line = buffer;
                 mode = EXEC_MODE;       // tmp set to EXEC_MODE
                 buffer.clear();
             }else{
+__NOT_ENOUGH_LINES:
                 continue;
             }
         }else{
@@ -74,9 +79,10 @@ void REPL(){
 #else
         }catch(std::exception& e){
 #endif
-            if(need_more_lines = dynamic_cast<NeedMoreLines*>(&e)){
+            if(dynamic_cast<NeedMoreLines*>(&e)){
                 buffer += line;
                 buffer += '\n';
+                need_more_lines = e.isClassDef ? 3 : 2;
             }else{
                 vm->printFn(e.what());
                 vm->printFn("\n");