mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
Merge branch 'pocketpy:main' into gsoc-2025-debugger
This commit is contained in:
commit
8dd9f5f0d2
@ -32,6 +32,8 @@ Please see https://pocketpy.dev for details and try the following resources.
|
|||||||
+ [Live Python Demo](https://pocketpy.dev/static/web/): Run Python code in your browser
|
+ [Live Python Demo](https://pocketpy.dev/static/web/): Run Python code in your browser
|
||||||
+ [Live C Examples](https://pocketpy.github.io/examples/): Explore C-APIs in your browser
|
+ [Live C Examples](https://pocketpy.github.io/examples/): Explore C-APIs in your browser
|
||||||
+ [Godot Extension](https://github.com/pocketpy/godot-pocketpy): Use pocketpy in Godot Engine
|
+ [Godot Extension](https://github.com/pocketpy/godot-pocketpy): Use pocketpy in Godot Engine
|
||||||
|
+ [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=pocketpy.pocketpy): Debug and profile pocketpy scripts in VSCode
|
||||||
|
+ [Flutter Plugin](https://pub.dev/packages/pocketpy): Use pocketpy in Flutter apps
|
||||||
|
|
||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
|
|
||||||
|
@ -1,24 +1,88 @@
|
|||||||
---
|
---
|
||||||
icon: dot
|
icon: dot
|
||||||
title: Debugging
|
title: Debugging
|
||||||
|
order: 80
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Install VSCode Extension
|
||||||
|
|
||||||
|
To debug a pocketpy program, you need to install our VSCode extension first:
|
||||||
|
|
||||||
|
https://marketplace.visualstudio.com/items?itemName=pocketpy.pocketpy
|
||||||
|
|
||||||
!!!
|
!!!
|
||||||
This feature is not available in `v2.0` yet.
|
The VSCode extension requires pocketpy version >= `2.1.1`
|
||||||
!!!
|
!!!
|
||||||
|
|
||||||
You can invoke `breakpoint()` in your python code to start a PDB-like session.
|
## Create a `launch.json` file
|
||||||
|
|
||||||
The following commands are supported:
|
Navigate to the Debug view in VSCode, and click on "create a launch.json file" link.
|
||||||
|
In the dropdown menu, select "pocketpy".
|
||||||
|
|
||||||
+ `h, help`: show this help message
|

|
||||||
+ `q, quit`: exit the debugger
|
|
||||||
+ `n, next`: execute next line
|
Then a default `launch.json` file will be created in the `.vscode` folder
|
||||||
+ `s, step`: step into
|
with a sample pocketpy debug configuration.
|
||||||
+ `w, where`: show current stack frame
|
|
||||||
+ `c, continue`: continue execution
|
## How does it work?
|
||||||
+ `a, args`: show local variables
|
|
||||||
+ `l, list`: show lines around current line
|
pocketpy provides a C-API `py_debugger_waitforattach`,
|
||||||
+ `ll, longlist`: show all lines
|
which starts a debug server and waits for the VSCode extension to attach.
|
||||||
+ `p, print <expr>`: evaluate expression
|
When the debugger is attached, the program will continue to run.
|
||||||
+ `!, execute statement`: execute statement
|
|
||||||
|
+ If you are using pocketpy's standalone executable `main.exe`, you can pass `--debug` flag to it. This will automatically call `py_debugger_waitforattach("localhost", 6110)` before running your program.
|
||||||
|
+ If you are embedding pocketpy as a library, you need to call `py_debugger_waitforattach` manually in your C/C++ code.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
+ `type`: must be `pocketpy`
|
||||||
|
+ `request`: can be `attach` or `launch`
|
||||||
|
+ `name`: the name of this configuration
|
||||||
|
+ `port`: the port number of the debug server, must match the one in `py_debugger_waitforattach`
|
||||||
|
+ `host`: the host of the debug server, must match the one in `py_debugger_waitforattach`
|
||||||
|
+ `sourceFolder`: the root folder of your python source code, default to `${workspaceFolder}`. However,
|
||||||
|
sometimes you may run your program from a subfolder, in this case you need to set `sourceFolder` to the correct path. If this is not set correctly, breakpoints will not be hit.
|
||||||
|
+ `program`: (for launch mode only) the path to the executable file which calls `py_debugger_waitforattach`, e.g. the pocketpy standalone executable `main.exe`.
|
||||||
|
+ `args`: (for launch mode only) the arguments to pass to the executable file, e.g. `--debug` and the script path if you are using `main.exe`.
|
||||||
|
+ `cwd`: (for launch mode only) the working directory to launch the executable file, default to `${workspaceFolder}`.
|
||||||
|
|
||||||
|
### For attach mode
|
||||||
|
|
||||||
|
In this mode, you need to start your pocketpy program manually which must call `py_debugger_waitforattach` first.
|
||||||
|
After the program starts, you can let VSCode attach to the debug server.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "pocketpy",
|
||||||
|
"request": "attach",
|
||||||
|
"name": "Attach to pocketpy program",
|
||||||
|
"port": 6110,
|
||||||
|
"host": "localhost",
|
||||||
|
"sourceFolder": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### For launch mode
|
||||||
|
|
||||||
|
In this mode, VSCode will start your program with the specified `program`, `args` and `cwd`.
|
||||||
|
After the program starts, VSCode attempts to attach to the debug server automatically.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "pocketpy",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch pocketpy program",
|
||||||
|
"port": 6110,
|
||||||
|
"host": "localhost",
|
||||||
|
"sourceFolder": "${workspaceFolder}",
|
||||||
|
"program": "${workspaceFolder}/pocketpy/main.exe",
|
||||||
|
"args": [
|
||||||
|
"--debug"
|
||||||
|
],
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Showcase
|
||||||
|
|
||||||
|

|
||||||
|
29
docs/features/profiling.md
Normal file
29
docs/features/profiling.md
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
icon: dot
|
||||||
|
title: Profiling
|
||||||
|
order: 79
|
||||||
|
---
|
||||||
|
|
||||||
|
To profile your pocketpy program, you can run `main.exe` with `--profile` flag.
|
||||||
|
|
||||||
|
For example, to profile `test/test_math.py`, run
|
||||||
|
|
||||||
|
```
|
||||||
|
main.exe --profile test/test_math.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This will output a JSON report file named `profile_report.json` in the current directory,
|
||||||
|
which records the time spent for each line. To visualize the report, please install our VSCode extension.
|
||||||
|
|
||||||
|
https://marketplace.visualstudio.com/items?itemName=pocketpy.pocketpy
|
||||||
|
|
||||||
|
!!!
|
||||||
|
The VSCode extension requires pocketpy version >= `2.1.1`
|
||||||
|
!!!
|
||||||
|
|
||||||
|
With pocketpy VSCode extension, press `F1` and type `pocketpy: Load Line Profiler Report`,
|
||||||
|
select **1. the `profile_report.json` file; 2. the source root of the program**. Then you will see a nice visualization of the profiling result.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Press `ESC` to exit the report view.
|
@ -13,6 +13,7 @@ Developers are able to write Python bindings via C-API or pybind11 compatible in
|
|||||||
+ [Live Python Demo](https://pocketpy.dev/static/web/): Run Python code in your browser
|
+ [Live Python Demo](https://pocketpy.dev/static/web/): Run Python code in your browser
|
||||||
+ [Live C Examples](https://pocketpy.github.io/examples/): Explore C-APIs in your browser
|
+ [Live C Examples](https://pocketpy.github.io/examples/): Explore C-APIs in your browser
|
||||||
+ [Godot Extension](https://github.com/pocketpy/godot-pocketpy): Use pocketpy in Godot Engine
|
+ [Godot Extension](https://github.com/pocketpy/godot-pocketpy): Use pocketpy in Godot Engine
|
||||||
|
+ [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=pocketpy.pocketpy): Debug and profile pocketpy scripts in VSCode
|
||||||
+ [Flutter Plugin](https://pub.dev/packages/pocketpy): Use pocketpy in Flutter apps
|
+ [Flutter Plugin](https://pub.dev/packages/pocketpy): Use pocketpy in Flutter apps
|
||||||
|
|
||||||
## What it looks like
|
## What it looks like
|
||||||
|
@ -3,7 +3,7 @@ output: .retype
|
|||||||
url: https://pocketpy.dev
|
url: https://pocketpy.dev
|
||||||
branding:
|
branding:
|
||||||
title: pocketpy
|
title: pocketpy
|
||||||
label: v2.1.0
|
label: v2.1.1
|
||||||
logo: "./static/logo.png"
|
logo: "./static/logo.png"
|
||||||
favicon: "./static/logo.png"
|
favicon: "./static/logo.png"
|
||||||
meta:
|
meta:
|
||||||
|
BIN
docs/static/debugger/debugger_demo.png
vendored
Normal file
BIN
docs/static/debugger/debugger_demo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 582 KiB |
BIN
docs/static/debugger/launch_json.png
vendored
Normal file
BIN
docs/static/debugger/launch_json.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 263 KiB |
BIN
docs/static/profiler_demo.png
vendored
Normal file
BIN
docs/static/profiler_demo.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 518 KiB |
@ -23,11 +23,10 @@
|
|||||||
#define V int
|
#define V int
|
||||||
#define NAME c11_smallmap_v2d
|
#define NAME c11_smallmap_v2d
|
||||||
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
||||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
#define equal(a, b) c11__sveq((a), (b))
|
||||||
#include "pocketpy/xmacros/smallmap.h"
|
#include "pocketpy/xmacros/smallmap.h"
|
||||||
#undef SMALLMAP_T__HEADER
|
#undef SMALLMAP_T__HEADER
|
||||||
|
|
||||||
|
|
||||||
#define SMALLMAP_T__HEADER
|
#define SMALLMAP_T__HEADER
|
||||||
#define K void*
|
#define K void*
|
||||||
#define V py_i64
|
#define V py_i64
|
||||||
|
@ -5,7 +5,20 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define HASH_KEY(__k) ((uintptr_t)(__k) >> 3U)
|
// https://jfdube.wordpress.com/2011/10/12/hashing-strings-and-pointers-avoiding-common-pitfalls/
|
||||||
|
uintptr_t ThomasWangInt32Hash(void* Ptr) {
|
||||||
|
// Here we think only the lower 32 bits are useful
|
||||||
|
uint32_t Value = (uint32_t)(uintptr_t)Ptr;
|
||||||
|
Value = ~Value + (Value << 15);
|
||||||
|
Value = Value ^ (Value >> 12);
|
||||||
|
Value = Value + (Value << 2);
|
||||||
|
Value = Value ^ (Value >> 4);
|
||||||
|
Value = Value * 2057;
|
||||||
|
Value = Value ^ (Value >> 16);
|
||||||
|
return Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define HASH_KEY(__k) ThomasWangInt32Hash(__k)
|
||||||
|
|
||||||
#define HASH_PROBE_0(__k, ok, i) \
|
#define HASH_PROBE_0(__k, ok, i) \
|
||||||
ok = false; \
|
ok = false; \
|
||||||
|
@ -136,16 +136,17 @@ static void Dict__set_index(Dict* self, uint32_t index, uint32_t value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dict__probe won't raise exception for string keys
|
||||||
static bool Dict__probe(Dict* self,
|
static bool Dict__probe(Dict* self,
|
||||||
py_TValue* key,
|
py_TValue* key,
|
||||||
uint64_t* p_hash,
|
uint64_t* p_hash,
|
||||||
uint32_t* p_idx,
|
uint32_t* p_idx,
|
||||||
DictEntry** p_entry) {
|
DictEntry** p_entry) {
|
||||||
|
if(py_isstr(key)) {
|
||||||
|
*p_hash = c11_sv__hash(py_tosv(key));
|
||||||
|
} else {
|
||||||
py_i64 h_user;
|
py_i64 h_user;
|
||||||
if(!py_hash(key, &h_user)) return false;
|
if(!py_hash(key, &h_user)) return false;
|
||||||
if(py_isstr(key)) {
|
|
||||||
*p_hash = (uint64_t)h_user;
|
|
||||||
} else {
|
|
||||||
*p_hash = Dict__hash_2nd((uint64_t)h_user);
|
*p_hash = Dict__hash_2nd((uint64_t)h_user);
|
||||||
}
|
}
|
||||||
uint32_t mask = self->capacity - 1;
|
uint32_t mask = self->capacity - 1;
|
||||||
@ -155,6 +156,15 @@ static bool Dict__probe(Dict* self,
|
|||||||
if(idx2 == self->null_index_value) break;
|
if(idx2 == self->null_index_value) break;
|
||||||
DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
|
DictEntry* entry = c11__at(DictEntry, &self->entries, idx2);
|
||||||
if(entry->hash == (*p_hash)) {
|
if(entry->hash == (*p_hash)) {
|
||||||
|
if(py_isstr(&entry->key) && py_isstr(key)) {
|
||||||
|
c11_sv lhs = py_tosv(&entry->key);
|
||||||
|
c11_sv rhs = py_tosv(key);
|
||||||
|
if(c11__sveq(lhs, rhs)) {
|
||||||
|
*p_idx = idx;
|
||||||
|
*p_entry = entry;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
int res = py_equal(&entry->key, key);
|
int res = py_equal(&entry->key, key);
|
||||||
if(res == 1) {
|
if(res == 1) {
|
||||||
*p_idx = idx;
|
*p_idx = idx;
|
||||||
@ -163,6 +173,7 @@ static bool Dict__probe(Dict* self,
|
|||||||
}
|
}
|
||||||
if(res == -1) return false; // error
|
if(res == -1) return false; // error
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// try next index
|
// try next index
|
||||||
idx = Dict__step(idx);
|
idx = Dict__step(idx);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user