diff --git a/include/pocketpy/lexer.h b/include/pocketpy/lexer.h index ff268454..28edbccc 100644 --- a/include/pocketpy/lexer.h +++ b/include/pocketpy/lexer.h @@ -26,7 +26,7 @@ constexpr const char* kTokens[] = { /** KW_BEGIN **/ "class", "import", "as", "def", "lambda", "pass", "del", "from", "with", "yield", "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; diff --git a/include/pocketpy/opcodes.h b/include/pocketpy/opcodes.h index 269cf094..39fdf75f 100644 --- a/include/pocketpy/opcodes.h +++ b/include/pocketpy/opcodes.h @@ -165,4 +165,6 @@ OPCODE(INC_FAST) OPCODE(DEC_FAST) OPCODE(INC_GLOBAL) OPCODE(DEC_GLOBAL) +/**************************/ +OPCODE(BREAKPOINT) #endif \ No newline at end of file diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 9ba5ee55..6e8403b8 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -154,6 +154,7 @@ public: VM(bool enable_os=true); void set_main_argv(int argc, char** argv); + void _breakpoint(); Frame* top_frame(){ return &callstack.top(); diff --git a/src/ceval.cpp b/src/ceval.cpp index 3f77a70b..2aaa18fa 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -907,9 +907,12 @@ __NEXT_STEP:; if(p == nullptr) vm->NameError(_name); *p = VAR(CAST(i64, *p) - 1); } 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 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: diff --git a/src/compiler.cpp b/src/compiler.cpp index 3b085e05..de52121b 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -873,6 +873,12 @@ __EAT_DOTS_END: case TK("@"): compile_decorated(); break; case TK("try"): compile_try_except(); 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("++"):{ consume(TK("@id")); diff --git a/src/vm.cpp b/src/vm.cpp index b22895a8..8db6cc67 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -1353,4 +1353,33 @@ PyObject* NativeFunc::call(VM *vm, ArgsView args) const { 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 << "-> \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 \ No newline at end of file diff --git a/tests/95_pdb.py b/tests/95_pdb.py new file mode 100644 index 00000000..afb09463 --- /dev/null +++ b/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)