simplify the workdir process and minor optimizations

This commit is contained in:
lightovernight 2025-07-08 15:23:45 +08:00
parent 47e99c0897
commit 4d1d2a7581
4 changed files with 116 additions and 28 deletions

View File

@ -5,11 +5,13 @@
#include "pocketpy/common/vector.h"
#include "pocketpy/pocketpy.h"
enum C11_STEP_MODE { C11_STEP_IN, C11_STEP_OVER, C11_STEP_OUT, C11_STEP_CONTINUE };
typedef enum { C11_STEP_IN, C11_STEP_OVER, C11_STEP_OUT, C11_STEP_CONTINUE } C11_STEP_MODE;
typedef enum { C11_DEBUGGER_SUCCESS, C11_DEBUGGER_UNKNOW_ERROR, C11_DEBUGGER_FILEPATH_ERROR } C11_DEBUGGER_FAIL_REASON;
void c11_debugger_init(void);
void c11_debugger_set_step_mode(enum C11_STEP_MODE mode);
void c11_debugger_on_trace(py_Frame* frame, enum py_TraceEvent event);
void c11_debugger_set_step_mode(C11_STEP_MODE mode);
C11_DEBUGGER_FAIL_REASON c11_debugger_on_trace(py_Frame* frame, enum py_TraceEvent event);
void c11_debugger_frames(c11_sbuf* buffer);
void c11_debugger_scopes(int frameid, c11_sbuf* buffer);
bool c11_debugger_unfold_var(int var_id, c11_sbuf* buffer);

View File

@ -34,14 +34,18 @@ static struct c11_debugger {
int current_line;
int pause_allowed_depth;
int step_line;
enum C11_STEP_MODE step_mode;
C11_STEP_MODE step_mode;
bool keep_suspend;
c11_vector breakpoints;
c11_vector py_frames;
c11_smallmap_d2index scopes_query_cache;
<<<<<<< HEAD
#define python_vars py_r7()
=======
#define python_vars py_r7()
>>>>>>> 429f2e78 (simplify the workdir process)
} debugger;
@ -65,6 +69,21 @@ inline static py_Ref get_variable(int var_ref) {
return py_list_getitem(python_vars, var_ref);
}
static inline const char* format_filepath(const char* path) {
if (strstr(path, "..")) {
return NULL;
}
if (strstr(path + 1, "./") || strstr(path + 1, ".\\")) {
return NULL;
}
if (path[0] == '.' && (path[1] == '/' || path[1] == '\\')) {
return path + 2;
}
return path;
}
void c11_debugger_init() {
debugger.curr_stack_depth = 0;
debugger.current_line = -1;
@ -75,16 +94,22 @@ void c11_debugger_init() {
init_structures();
}
void c11_debugger_on_trace(py_Frame* frame, enum py_TraceEvent event) {
C11_DEBUGGER_FAIL_REASON c11_debugger_on_trace(py_Frame* frame, enum py_TraceEvent event) {
debugger.current_frame = frame;
debugger.current_event = event;
debugger.current_filename = py_Frame_sourceloc(debugger.current_frame, &debugger.current_line);
const char* source_name = py_Frame_sourceloc(debugger.current_frame, &debugger.current_line);
debugger.current_filename = format_filepath(source_name);
if(debugger.current_filename == NULL) { return C11_DEBUGGER_FILEPATH_ERROR; }
clear_structures();
if(event == TRACE_EVENT_LINE) return;
event == TRACE_EVENT_PUSH ? debugger.curr_stack_depth++ : debugger.curr_stack_depth--;
switch(event) {
case TRACE_EVENT_PUSH: debugger.curr_stack_depth++; break;
case TRACE_EVENT_POP: debugger.curr_stack_depth--; break;
default: break;
}
return C11_DEBUGGER_SUCCESS;
}
void c11_debugger_set_step_mode(enum C11_STEP_MODE mode) {
void c11_debugger_set_step_mode(C11_STEP_MODE mode) {
switch(mode) {
case C11_STEP_IN: debugger.pause_allowed_depth = INT32_MAX; break;
case C11_STEP_OVER:
@ -98,7 +123,10 @@ void c11_debugger_set_step_mode(enum C11_STEP_MODE mode) {
debugger.keep_suspend = false;
}
<<<<<<< HEAD
=======
>>>>>>> 429f2e78 (simplify the workdir process)
int c11_debugger_setbreakpoint(const char* filename, int lineno) {
c11_debugger_breakpoint breakpoint = {.sourcename = c11_strdup(filename), .lineno = lineno};
c11_vector__push(c11_debugger_breakpoint, &debugger.breakpoints, breakpoint);
@ -156,7 +184,10 @@ int c11_debugger_should_pause() {
int c11_debugger_should_keep_pause(void) { return debugger.keep_suspend; }
<<<<<<< HEAD
=======
>>>>>>> 429f2e78 (simplify the workdir process)
inline static c11_sv sv_from_cstr(const char* str) {
c11_sv sv = {.data = str, .size = strlen(str)};
return sv;
@ -164,7 +195,7 @@ inline static c11_sv sv_from_cstr(const char* str) {
const inline static char* get_basename(const char* path) {
const char* last_slash = strrchr(path, '/');
#ifdef _WIN32
#if defined(_WIN32) || defined(_WIN64)
const char* last_backslash = strrchr(path, '\\');
if(!last_slash || (last_backslash && last_backslash > last_slash)) {
last_slash = last_backslash;
@ -254,31 +285,46 @@ bool c11_debugger_unfold_var(int var_id, c11_sbuf* buffer) {
py_Ref base_var_ref = py_pushtmp();
py_newint(base_var_ref, base_index);
// 3. construct DAP JSON
const char* dap_code =
"{'variables': ["
" {"
" 'name': kv[0],"
" 'value': repr(kv[1]),"
" 'variablesReference': (_1 + i) if (isinstance(kv[1], (dict, list, tuple)) or kv[1].__dict__ is not None) else 0,"
" 'type': type(kv[1]).__name__"
" }"
" for i, kv in enumerate(_0)"
"]}";
if(!py_smarteval(dap_code, NULL, kv_list, base_var_ref)) {
py_printexc();
return false;
}
// 3. construct DAP JSON and extend python_vars
py_Ref dap_obj = py_pushtmp();
<<<<<<< HEAD
py_assign(dap_obj, py_retval());
// 4. extend python_vars
if(!py_smartexec("_0.extend([kv[1] for kv in _1])", NULL, python_vars, kv_list)) {
=======
py_newdict(dap_obj); // 先创建字典
const char* dap_code =
"_2['variables'] = []\n"
"var_ref = _1\n"
"for k, v in _0:\n"
" has_children = isinstance(v, (dict, list, tuple)) or v.__dict__ is not None\n"
" _2['variables'].append({\n"
" 'name': k if type(k) == str else str(k),\n"
" 'value': repr(v) if type(v) == str else str(v),\n"
" 'variablesReference': var_ref if has_children else 0,\n"
" 'type': type(v).__name__\n"
" })\n"
" if has_children: var_ref += 1\n";
if(!py_smartexec(dap_code, NULL, kv_list, base_var_ref, dap_obj)) {
>>>>>>> 429f2e78 (simplify the workdir process)
py_printexc();
return false;
}
// 4. extend python_vars
if(!py_smartexec(
"_0.extend([v for k, v in _1 if isinstance(v, (dict, list, tuple)) or v.__dict__ is not None])",
NULL,
python_vars,
kv_list)) {
py_printexc();
return false;
}
// 5. dump & write
if(!py_json_dumps(dap_obj, 0)) {
printf("dap_obj: %s\n", py_tpname(py_typeof(dap_obj)));
py_printexc();
return false;
}
@ -291,4 +337,8 @@ bool c11_debugger_unfold_var(int var_id, c11_sbuf* buffer) {
py_pop(); // kv_list
return true;
}
<<<<<<< HEAD
=======
>>>>>>> 429f2e78 (simplify the workdir process)
#undef python_vars

View File

@ -54,10 +54,14 @@ void c11_dap_handle_initialize(py_Ref arguments, c11_sbuf* buffer) {
c11_sbuf__write_char(buffer, ',');
}
<<<<<<< HEAD
void c11_dap_handle_attach(py_Ref arguments, c11_sbuf* buffer) {
server.isatttach = true;
}
=======
void c11_dap_handle_attach(py_Ref arguments, c11_sbuf* buffer) { server.isatttach = true; }
>>>>>>> 429f2e78 (simplify the workdir process)
void c11_dap_handle_next(py_Ref arguments, c11_sbuf* buffer) {
c11_debugger_set_step_mode(C11_STEP_OVER);
@ -230,9 +234,24 @@ void c11_dap_send_event(const char* event_name, const char* body_json) {
void c11_dap_send_stop_event() {
c11_dap_send_event("stopped",
"{\"reason\":\"breakpoint\",\"threadId\":1,\"allThreadsStopped\":true}");
"{\"threadId\":1,\"allThreadsStopped\":true}");
}
<<<<<<< HEAD
=======
void c11_dap_send_exited_event(int exitCode) {
char body[64];
snprintf(body, sizeof(body), "{\"exitCode\":%d}", exitCode);
c11_dap_send_event("exited", body);
}
void c11_dap_send_fatal_event(const char* message) {
char body[128];
snprintf(body, sizeof(body), "{\"message\":\"%s\"}", message);
c11_dap_send_event("pkpy/fatalError", body);
}
>>>>>>> 429f2e78 (simplify the workdir process)
void c11_dap_send_initialized_event() { c11_dap_send_event("initialized", "{}"); }
int c11_dap_read_content_length(const char* buffer, int* header_length) {
@ -346,7 +365,20 @@ void c11_dap_configure_debugger() {
void c11_dap_tracefunc(py_Frame* frame, enum py_TraceEvent event) {
py_sys_settrace(NULL, false);
c11_debugger_on_trace(frame, event);
C11_DEBUGGER_FAIL_REASON result = c11_debugger_on_trace(frame, event);
if(result != C11_DEBUGGER_SUCCESS) {
const char* message = NULL;
switch(result) {
case C11_DEBUGGER_FILEPATH_ERROR:
message = "Invalid py_file path: '..' forbidden, './' only allowed at start.";
break;
case C11_DEBUGGER_UNKNOW_ERROR:
default: message = "Unknown debugger failure."; break;
}
if(message) { c11_dap_send_fatal_event(message); }
c11_dap_send_exited_event(1);
exit(1);
}
c11_dap_handle_message();
if(!c11_debugger_should_pause()) {
py_sys_settrace(c11_dap_tracefunc, false);

View File

@ -4,7 +4,7 @@
#include <string.h>
#include "pocketpy.h"
#include "pocketpy/debugger/dap.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -90,9 +90,13 @@ int main(int argc, char** argv) {
}
}
} else {
<<<<<<< HEAD
if(profile) py_profiler_begin();
if(debug) py_debugger_waitforattach("127.0.0.1", 6110);
=======
wait_for_debugger("127.0.0.1", 3939);
>>>>>>> 429f2e78 (simplify the workdir process)
char* source = read_file(filename);
if(source) {
if(!py_exec(source, filename, EXEC_MODE, NULL))