blueloveTH 1 год назад
Родитель
Сommit
aaa0d55361
7 измененных файлов с 57 добавлено и 3 удалено
  1. 1 1
      include/pocketpy/lexer.h
  2. 2 0
      include/pocketpy/opcodes.h
  3. 1 0
      include/pocketpy/vm.h
  4. 5 2
      src/ceval.cpp
  5. 6 0
      src/compiler.cpp
  6. 29 0
      src/vm.cpp
  7. 13 0
      tests/95_pdb.py

+ 1 - 1
include/pocketpy/lexer.h

@@ -26,7 +26,7 @@ constexpr const char* kTokens[] = {
     /** KW_BEGIN **/
     /** KW_BEGIN **/
     "class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield",
     "class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield",
     "None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally",
     "None", "in", "is", "and", "or", "not", "True", "False", "global", "try", "except", "finally",
-    "while", "for", "if", "elif", "else", "break", "continue", "return", "assert", "raise"
+    "while", "for", "if", "elif", "else", "break", "continue", "return", "assert", "raise", "breakpoint"
 };
 };
 
 
 using TokenValue = std::variant<std::monostate, i64, f64, Str>;
 using TokenValue = std::variant<std::monostate, i64, f64, Str>;

+ 2 - 0
include/pocketpy/opcodes.h

@@ -165,4 +165,6 @@ OPCODE(INC_FAST)
 OPCODE(DEC_FAST)
 OPCODE(DEC_FAST)
 OPCODE(INC_GLOBAL)
 OPCODE(INC_GLOBAL)
 OPCODE(DEC_GLOBAL)
 OPCODE(DEC_GLOBAL)
+/**************************/
+OPCODE(BREAKPOINT)
 #endif
 #endif

+ 1 - 0
include/pocketpy/vm.h

@@ -154,6 +154,7 @@ public:
     VM(bool enable_os=true);
     VM(bool enable_os=true);
 
 
     void set_main_argv(int argc, char** argv);
     void set_main_argv(int argc, char** argv);
+    void _breakpoint();
 
 
     Frame* top_frame(){
     Frame* top_frame(){
         return &callstack.top();
         return &callstack.top();

+ 5 - 2
src/ceval.cpp

@@ -907,9 +907,12 @@ __NEXT_STEP:;
         if(p == nullptr) vm->NameError(_name);
         if(p == nullptr) vm->NameError(_name);
         *p = VAR(CAST(i64, *p) - 1);
         *p = VAR(CAST(i64, *p) - 1);
     } DISPATCH();
     } DISPATCH();
+    TARGET(BREAKPOINT) {
+        vm->_breakpoint();
+    } DISPATCH();
     /*****************************************/
     /*****************************************/
-        static_assert(OP_DEC_GLOBAL == 136);
-        case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: case 147: case 148: case 149:
+        static_assert(OP_BREAKPOINT == 137);
+        case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: case 147: case 148: case 149:
         case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: case 160: case 161: case 162: case 163: case 164:
         case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: case 160: case 161: case 162: case 163: case 164:
         case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179:
         case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179:
         case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194:
         case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194:

+ 6 - 0
src/compiler.cpp

@@ -873,6 +873,12 @@ __EAT_DOTS_END:
             case TK("@"): compile_decorated(); break;
             case TK("@"): compile_decorated(); break;
             case TK("try"): compile_try_except(); break;
             case TK("try"): compile_try_except(); break;
             case TK("pass"): consume_end_stmt(); break;
             case TK("pass"): consume_end_stmt(); break;
+            case TK("breakpoint"):
+                consume(TK("("));
+                consume(TK(")"));
+                consume_end_stmt();
+                ctx()->emit_(OP_BREAKPOINT, BC_NOARG, kw_line);
+                break;
             /*************************************************/
             /*************************************************/
             case TK("++"):{
             case TK("++"):{
                 consume(TK("@id"));
                 consume(TK("@id"));

+ 29 - 0
src/vm.cpp

@@ -1353,4 +1353,33 @@ PyObject* NativeFunc::call(VM *vm, ArgsView args) const {
     return f(vm, args);
     return f(vm, args);
 }
 }
 
 
+void VM::_breakpoint(){
+    SStream ss;
+    Frame* frame = vm->top_frame();
+    int lineno = frame->co->lines[frame->_next_ip].lineno;
+    auto [_0, _1] = frame->co->src->_get_line(lineno);
+    ss << "> " << frame->co->src->filename << '(' << lineno << ')';
+    if(frame->_callable){
+        ss << PK_OBJ_GET(Function, frame->_callable).decl->code->name << "()";
+    }
+    ss << '\n';
+
+    if(_0 && _1){
+        ss << "-> " << std::string_view(_0, _1-_0) << '\n';
+    }else{
+        ss << "-> <no source code available>\n";
+    }
+
+    vm->stdout_write(ss.str());
+    std::string line;
+    while(true){
+        vm->stdout_write("(Pdb) ");
+        if(!std::getline(std::cin, line)) break;
+        if(line == "h" || line == "help") continue;
+        if(line == "q" || line == "quit") std::exit(0);
+        if(line == "n" || line == "next") break;
+        if(line == "c" || line == "continue") break;
+    }
+}
+
 }   // namespace pkpy
 }   // namespace pkpy

+ 13 - 0
tests/95_pdb.py

@@ -0,0 +1,13 @@
+a = 1
+b = 2
+
+print(a, b)
+
+
+def f(a, b):
+    breakpoint()
+    b = a + b
+    print(a, b)
+    return b
+
+f(1, 2)