diff --git a/README.md b/README.md index 2860c681..a2e07639 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ Please see https://pocketpy.dev for details and try the following resources. + [Live Python Demo](https://pocketpy.dev/static/web/): Python REPL of the latest version + [Live C++ Examples](https://pocketpy.github.io/examples/): Common usage of pkpy in C++ +> We are moving to v2.0 branch, which is a complete refactor of this project in C11. See [Migration Guide](https://pocketpy.dev/migrate/) for more details. + ## Supported Platforms pkpy should work on any platform with a C++17 compiler. diff --git a/docs/cheatsheet.md b/docs/cheatsheet.md deleted file mode 100644 index e52a93eb..00000000 --- a/docs/cheatsheet.md +++ /dev/null @@ -1,333 +0,0 @@ ---- -icon: log -title: 'Cheatsheet' -order: 22 ---- - -## Basics - -Setup pocketpy - -```cpp -#include "pocketpy.h" -using namespace pkpy; -``` - -Create a python virtual machine - -```cpp -VM* vm = new VM(); -``` - -Dispose a python virtual machine - -```cpp -delete vm; -``` - -Execute a source string - -```cpp -vm->exec("print('Hello!')"); -``` - -Evaluate a source string - -```cpp -PyVar obj = vm->eval("123"); -std::cout << py_cast(vm, obj); // 123 -``` - -Compile a source string into a code object - -```cpp -CodeObject_ co = vm->compile("print('Hello!')", "main.py", EXEC_MODE); -``` - -Execute a compiled code object - -```cpp -try{ - vm->_exec(co); // may throw -}catch(Exception& e){ - std::cerr << e.summary() << std::endl; -} -``` - -## Interop with native types - -Create primitive objects - -```cpp -PyVar obj; -obj = py_var(vm, 1); // create a int -obj = py_var(vm, 1.0); // create a float -obj = py_var(vm, "123"); // create a string -obj = py_var(vm, true); // create a bool -``` - -Create a tuple object - -```cpp -// obj = (1, 1.0, '123') -Tuple t(3); -t[0] = py_var(vm, 1); -t[1] = py_var(vm, 1.0); -t[2] = py_var(vm, "123"); -PyVar obj = py_var(vm, std::move(t)); -``` - -Create a list object - -```cpp -// obj = [1, 1.0, '123'] -List t; -t.push_back(py_var(vm, 1)); -t.push_back(py_var(vm, 1.0)); -t.push_back(py_var(vm, "123")); -PyVar obj = py_var(vm, std::move(t)); -``` - -Create a dict object - -```cpp -// obj = {'x': 1, 'y': '123'} -Dict d(vm); -d.set(py_var(vm, "x"), py_var(vm, 1)); -d.set(py_var(vm, "y"), py_var(vm, "123")); -PyVar obj = py_var(vm, std::move(d)); -``` - -Get native types from python objects - -```cpp -PyVar obj; -i64 a = py_cast(vm, obj); -f64 b = py_cast(vm, obj); -Str& c = py_cast(vm, obj); // reference cast -bool d = py_cast(vm, obj); - -Tuple& e = py_cast(vm, obj); // reference cast -List& f = py_cast(vm, obj); // reference cast -Dict& g = py_cast(vm, obj); // reference cast -``` - -Get native types without type checking - -```cpp -// unsafe version 1 (for int object you must use `_py_cast`) -i64 a = _py_cast(vm, obj); -f64 b = _py_cast(vm, obj); -Tuple& c = _py_cast(vm, obj); -// unsafe version 2 (for others, you can also use `PK_OBJ_GET` macro) -Str& a_ = PK_OBJ_GET(Str, obj); -List& b_ = PK_OBJ_GET(List, obj); -Tuple& c_ = PK_OBJ_GET(Tuple, obj); -``` - -## Access python types - -Access built-in python types - -```cpp -PyVar int_t = vm->_t(VM::tp_int); -PyVar float_t = vm->_t(VM::tp_float); -PyVar object_t = vm->_t(VM::tp_object); -PyVar tuple_t = vm->_t(VM::tp_tuple); -PyVar list_t = vm->_t(VM::tp_list); -``` - -Access user registered types - -```cpp -Type voidp_t = vm->_tp_user(); -``` - -Check if an object is a python type - -```cpp -PyVar obj; -bool ok = is_type(obj, VM::tp_int); // check if obj is an int -``` - -Get the type of a python object - -```cpp -PyVar obj = py_var(vm, 1); -PyVar t = vm->_t(obj); // -Type type = vm->_tp(obj); // VM::tp_int -``` - -Convert a type object into a type index - -```cpp -PyVar int_t = vm->_t(VM::tp_int); -Type t = PK_OBJ_GET(Type, int_t); -// t == VM::tp_int -``` - -## Access attributes - -Check an object supports attribute access - -```cpp -PyVar obj; -bool ok = !is_tagged(obj) && obj->is_attr_valid(); -``` - -```python -class MyClass: - def __init__(self, x, y): - self.x = x - self.y = y - - def sum(self): - return self.x + self.y -``` - -Get and set attributes - -```cpp -PyVar obj = vm->exec("MyClass(1, 2)"); -PyVar x = vm->getattr(obj, "x"); // obj.x -vm->setattr(obj, "x", py_var(vm, 3)); // obj.x = 3 -``` - -## Call python functions - -```python -def add(a, b): - return a + b -``` - -Call a function - -```cpp -PyVar f_add = vm->eval("add"); -PyVar ret = vm->call(f_add, py_var(vm, 1), py_var(vm, 2)); -std::cout << py_cast(vm, ret); // 3 -``` - -Call a method - -```cpp -PyVar obj = vm->exec("MyClass(1, 2)"); -PyVar ret = vm->call_method(obj, "sum"); -std::cout << CAST(i64, ret); // 3 -``` - -Cache the name of a function or method to avoid string-based lookup - -```cpp -// cache the name "add" to avoid string-based lookup -const static StrName m_sum("sum"); -PyVar ret = vm->call_method(obj, m_sum); -``` - -## Special operations - -Compare two python objects - -```cpp -PyVar obj1 = py_var(vm, 1); -PyVar obj2 = py_var(vm, 2); -bool ok = vm->py_eq(obj1, obj2); -``` - -Convert a python object to string - -```cpp -PyVar obj = py_var(vm, 123); -std::cout << vm->py_str(obj); // 123 -``` - -Get the string representation of a python object - -```cpp -PyVar obj = py_var(vm, "123"); -std::cout << vm->py_repr(obj); // "'123'" -``` - -Get the JSON representation of a python object - -```cpp -PyVar obj = py_var(vm, 123); -std::cout << vm->py_json(obj); // "123" -``` - -Get the hash value of a python object - -```cpp -PyVar obj = py_var(vm, 1); -i64 h = vm->py_hash(obj); // 1 -``` - -Get the iterator of a python object - -```cpp -PyVar obj = vm->eval("range(3)"); -PyVar iter = vm->py_iter(obj); -``` - -Get the next item of an iterator - -```cpp -PyVar obj = vm->py_next(iter); -if(obj == vm->StopIteration){ - // end of iteration -}else{ - // process obj -} -``` - -Convert a python iterable to a list - -```cpp -PyVar obj = vm->eval("range(3)"); -List list = vm->py_list(obj); -``` - -## Bindings - -Bind a native function - -```cpp -vm->bind(obj, "add(a: int, b: int) -> int", [](VM* vm, ArgsView args){ - int a = py_cast(vm, args[0]); - int b = py_cast(vm, args[1]); - return py_var(vm, a + b); -}); -``` - -Bind a property - -```cpp - // getter and setter of property `x` - vm->bind_property(type, "x: int", - [](VM* vm, ArgsView args){ - Point& self = PK_OBJ_GET(Point, args[0]); - return VAR(self.x); - }, - [](VM* vm, ArgsView args){ - Point& self = PK_OBJ_GET(Point, args[0]); - self.x = py_cast(vm, args[1]); - return vm->None; - }); -``` - -## Modules - -Create a source module - -```cpp -vm->_lazy_modules["test"] = "pi = 3.14"; -// import test -// print(test.pi) # 3.14 -``` - -Create a native module - -```cpp -PyVar mod = vm->new_module("test"); -vm->setattr(mod, "pi", py_var(vm, 3.14)); -``` diff --git a/docs/index.md b/docs/index.md index bcd5984c..0e302189 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,6 +5,12 @@ label: Welcome # Welcome to pocketpy +!!! +We are moving to v2.0 branch, which is a complete refactor of this project in C11. + +See [Migration Guide](migrate.md) for more details. +!!! + pkpy is a lightweight(~15K LOC) Python interpreter for game scripting, built on C++17 with STL. It aims to be an alternative to lua for game scripting, with elegant syntax, powerful features and competitive performance. diff --git a/docs/migrate.md b/docs/migrate.md new file mode 100644 index 00000000..bae74801 --- /dev/null +++ b/docs/migrate.md @@ -0,0 +1,27 @@ +--- +icon: log +title: 'Migration Guide' +order: 22 +--- + +## Overview + +This document describes the changes from v1.x to v2.0. + +## API compatibility + +| name | v1.x | v2.0 | +| --- | --- | --- | +| legacy C++ API (v1.x only) | ✅ | ❌ | +| legacy C API (v1.x only) | ✅ | ❌ | +| C11 API (v2.0 only) | ❌ | ✅ | +| pybind11 API (both) | ✅ | ✅ | + +## Suggestions + +- If you are a C++ user + - Use **pybind11 API** if you want to upgrade to v2.0 in the future + - Use **legacy C++ API** if you want to stay in v1.x +- If you are a C user + - Use **v2.0's C11 API** (will be available soon) + - Use **legacy C API** if you want to stay in v1.x \ No newline at end of file