mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
Squashed commit of the following:
commit 7e52f767ca130a49abb90ec922d74d2f5e9be078 Author: blueloveTH <blueloveTH@foxmail.com> Date: Sat Jun 1 12:49:46 2024 +0800 some optimize commit 3e2ad5b1fbad4367c80ea1325d1aa379282c10c4 Author: blueloveTH <blueloveTH@foxmail.com> Date: Sat Jun 1 12:29:53 2024 +0800 some fix commit bc0e530c72896a23cb6616ff4197ac36913389a4 Author: blueloveTH <blueloveTH@foxmail.com> Date: Sat Jun 1 00:00:47 2024 +0800 some fix commit f17ddcf8299c5d6803085cd3263181f44284f31b Author: blueloveTH <blueloveTH@foxmail.com> Date: Fri May 31 23:56:15 2024 +0800 some fix commit cc63926c8bb89df2d99d8c92c2e18bd5a0180a2c Author: blueloveTH <blueloveTH@foxmail.com> Date: Fri May 31 23:44:09 2024 +0800 some fix commit 3d3fb042651579cbdbcf3255398276ebb7b81e58 Author: blueloveTH <blueloveth@foxmail.com> Date: Fri May 31 17:28:13 2024 +0800 deprecate `PK_OBJ_MARK` commit 3df5f1cf128f157fb3a7aac2ceeeb47c55f5bb3b Author: blueloveTH <blueloveth@foxmail.com> Date: Fri May 31 17:18:34 2024 +0800 init
This commit is contained in:
parent
17de5b3024
commit
1e365ca72c
310
.github/workflows/main.yml
vendored
310
.github/workflows/main.yml
vendored
@ -1,157 +1,157 @@
|
|||||||
name: build
|
# name: build
|
||||||
on:
|
# on:
|
||||||
push:
|
# push:
|
||||||
paths-ignore:
|
# paths-ignore:
|
||||||
- 'docs/**'
|
# - 'docs/**'
|
||||||
- 'web/**'
|
# - 'web/**'
|
||||||
- '**.md'
|
# - '**.md'
|
||||||
pull_request:
|
# pull_request:
|
||||||
paths-ignore:
|
# paths-ignore:
|
||||||
- 'docs/**'
|
# - 'docs/**'
|
||||||
- 'web/**'
|
# - 'web/**'
|
||||||
- '**.md'
|
# - '**.md'
|
||||||
jobs:
|
# jobs:
|
||||||
build_win32_amalgamated:
|
# build_win32_amalgamated:
|
||||||
runs-on: windows-latest
|
# runs-on: windows-latest
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
- uses: ilammy/msvc-dev-cmd@v1
|
# - uses: ilammy/msvc-dev-cmd@v1
|
||||||
- name: Compile
|
# - name: Compile
|
||||||
shell: powershell
|
# shell: powershell
|
||||||
run: |
|
# run: |
|
||||||
python amalgamate.py
|
# python amalgamate.py
|
||||||
cd amalgamated
|
# cd amalgamated
|
||||||
cl.exe /std:c++17 /EHsc /utf-8 /Ox /I. /DPK_ENABLE_OS=1 main.cpp /link /out:pkpy.exe
|
# cl.exe /std:c++17 /EHsc /utf-8 /Ox /I. /DPK_ENABLE_OS=1 main.cpp /link /out:pkpy.exe
|
||||||
- uses: actions/upload-artifact@v3
|
# - uses: actions/upload-artifact@v3
|
||||||
with:
|
# with:
|
||||||
path: amalgamated/pkpy.exe
|
# path: amalgamated/pkpy.exe
|
||||||
build_win32:
|
# build_win32:
|
||||||
runs-on: windows-latest
|
# runs-on: windows-latest
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
- uses: ilammy/msvc-dev-cmd@v1
|
# - uses: ilammy/msvc-dev-cmd@v1
|
||||||
- name: Compile
|
# - name: Compile
|
||||||
shell: bash
|
# shell: bash
|
||||||
run: |
|
# run: |
|
||||||
mkdir -p output/windows/x86_64
|
# mkdir -p output/windows/x86_64
|
||||||
python cmake_build.py
|
# python cmake_build.py
|
||||||
cp main.exe output/windows/x86_64
|
# cp main.exe output/windows/x86_64
|
||||||
cp pocketpy.dll output/windows/x86_64
|
# cp pocketpy.dll output/windows/x86_64
|
||||||
- uses: actions/upload-artifact@v3
|
# - uses: actions/upload-artifact@v3
|
||||||
with:
|
# with:
|
||||||
path: output
|
# path: output
|
||||||
- name: Unit Test
|
# - name: Unit Test
|
||||||
run: python scripts/run_tests.py
|
# run: python scripts/run_tests.py
|
||||||
- name: Benchmark
|
# - name: Benchmark
|
||||||
run: python scripts/run_tests.py benchmark
|
# run: python scripts/run_tests.py benchmark
|
||||||
build_linux:
|
# build_linux:
|
||||||
runs-on: ubuntu-20.04
|
# runs-on: ubuntu-20.04
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
- name: Setup Clang
|
# - name: Setup Clang
|
||||||
uses: egor-tensin/setup-clang@v1
|
# uses: egor-tensin/setup-clang@v1
|
||||||
with:
|
# with:
|
||||||
version: 15
|
# version: 15
|
||||||
platform: x64
|
# platform: x64
|
||||||
- name: Install libc++
|
# - name: Install libc++
|
||||||
run: sudo apt-get install -y libc++-15-dev libc++1-15 libc++abi-15-dev libc++abi1-15 libclang-rt-15-dev
|
# run: sudo apt-get install -y libc++-15-dev libc++1-15 libc++abi-15-dev libc++abi1-15 libclang-rt-15-dev
|
||||||
- name: Unit Test with Coverage
|
# - name: Unit Test with Coverage
|
||||||
run: bash run_tests.sh
|
# run: bash run_tests.sh
|
||||||
- name: Upload coverage reports to Codecov
|
# - name: Upload coverage reports to Codecov
|
||||||
uses: codecov/codecov-action@v4
|
# uses: codecov/codecov-action@v4
|
||||||
with:
|
# with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
# token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
directory: .coverage
|
# directory: .coverage
|
||||||
if: github.ref == 'refs/heads/main'
|
# if: github.ref == 'refs/heads/main'
|
||||||
- name: Compile
|
# - name: Compile
|
||||||
run: |
|
# run: |
|
||||||
mkdir -p output/linux/x86_64
|
# mkdir -p output/linux/x86_64
|
||||||
python cmake_build.py
|
# python cmake_build.py
|
||||||
cp main output/linux/x86_64
|
# cp main output/linux/x86_64
|
||||||
cp libpocketpy.so output/linux/x86_64
|
# cp libpocketpy.so output/linux/x86_64
|
||||||
env:
|
# env:
|
||||||
CXX: clang++
|
# CXX: clang++
|
||||||
CC: clang
|
# CC: clang
|
||||||
- uses: actions/upload-artifact@v3
|
# - uses: actions/upload-artifact@v3
|
||||||
with:
|
# with:
|
||||||
path: output
|
# path: output
|
||||||
- name: Benchmark
|
# - name: Benchmark
|
||||||
run: python scripts/run_tests.py benchmark
|
# run: python scripts/run_tests.py benchmark
|
||||||
- name: C Binding Test
|
# - name: C Binding Test
|
||||||
run: bash run_c_binding_test.sh
|
# run: bash run_c_binding_test.sh
|
||||||
build_linux_x86:
|
# build_linux_x86:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
- name: Setup Alpine Linux for aarch64
|
# - name: Setup Alpine Linux for aarch64
|
||||||
uses: jirutka/setup-alpine@v1
|
# uses: jirutka/setup-alpine@v1
|
||||||
with:
|
# with:
|
||||||
arch: x86
|
# arch: x86
|
||||||
packages: gcc g++ make cmake libc-dev linux-headers python3
|
# packages: gcc g++ make cmake libc-dev linux-headers python3
|
||||||
- name: Build and Test
|
# - name: Build and Test
|
||||||
run: |
|
# run: |
|
||||||
uname -m
|
# uname -m
|
||||||
python cmake_build.py
|
# python cmake_build.py
|
||||||
python scripts/run_tests.py
|
# python scripts/run_tests.py
|
||||||
python scripts/run_tests.py benchmark
|
# python scripts/run_tests.py benchmark
|
||||||
shell: alpine.sh --root {0}
|
# shell: alpine.sh --root {0}
|
||||||
build_darwin:
|
# build_darwin:
|
||||||
runs-on: macos-latest
|
# runs-on: macos-latest
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
- name: Compile and Test
|
# - name: Compile and Test
|
||||||
run: |
|
# run: |
|
||||||
python cmake_build.py
|
# python cmake_build.py
|
||||||
python scripts/run_tests.py
|
# python scripts/run_tests.py
|
||||||
- name: Benchmark
|
# - name: Benchmark
|
||||||
run: python scripts/run_tests.py benchmark
|
# run: python scripts/run_tests.py benchmark
|
||||||
- run: |
|
# - run: |
|
||||||
python amalgamate.py
|
# python amalgamate.py
|
||||||
cd plugins/macos/pocketpy
|
# cd plugins/macos/pocketpy
|
||||||
mkdir -p output/macos
|
# mkdir -p output/macos
|
||||||
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
|
# xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
|
||||||
cp -r build/Release/pocketpy.bundle output/macos
|
# cp -r build/Release/pocketpy.bundle output/macos
|
||||||
- uses: actions/upload-artifact@v3
|
# - uses: actions/upload-artifact@v3
|
||||||
with:
|
# with:
|
||||||
path: plugins/macos/pocketpy/output
|
# path: plugins/macos/pocketpy/output
|
||||||
build_android:
|
# build_android:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
- uses: nttld/setup-ndk@v1
|
# - uses: nttld/setup-ndk@v1
|
||||||
id: setup-ndk
|
# id: setup-ndk
|
||||||
with:
|
# with:
|
||||||
ndk-version: r23
|
# ndk-version: r23
|
||||||
local-cache: false
|
# local-cache: false
|
||||||
add-to-path: false
|
# add-to-path: false
|
||||||
- name: Compile Shared Library
|
# - name: Compile Shared Library
|
||||||
run: |
|
# run: |
|
||||||
bash build_android.sh arm64-v8a
|
# bash build_android.sh arm64-v8a
|
||||||
bash build_android.sh armeabi-v7a
|
# bash build_android.sh armeabi-v7a
|
||||||
bash build_android.sh x86_64
|
# bash build_android.sh x86_64
|
||||||
|
|
||||||
mkdir -p output/android/arm64-v8a
|
# mkdir -p output/android/arm64-v8a
|
||||||
mkdir -p output/android/armeabi-v7a
|
# mkdir -p output/android/armeabi-v7a
|
||||||
mkdir -p output/android/x86_64
|
# mkdir -p output/android/x86_64
|
||||||
|
|
||||||
cp build/android/arm64-v8a/libpocketpy.so output/android/arm64-v8a
|
# cp build/android/arm64-v8a/libpocketpy.so output/android/arm64-v8a
|
||||||
cp build/android/armeabi-v7a/libpocketpy.so output/android/armeabi-v7a
|
# cp build/android/armeabi-v7a/libpocketpy.so output/android/armeabi-v7a
|
||||||
cp build/android/x86_64/libpocketpy.so output/android/x86_64
|
# cp build/android/x86_64/libpocketpy.so output/android/x86_64
|
||||||
env:
|
# env:
|
||||||
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
# ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
|
||||||
- uses: actions/upload-artifact@v3
|
# - uses: actions/upload-artifact@v3
|
||||||
with:
|
# with:
|
||||||
path: output
|
# path: output
|
||||||
build_ios:
|
# build_ios:
|
||||||
runs-on: macos-latest
|
# runs-on: macos-latest
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
- name: Compile Frameworks
|
# - name: Compile Frameworks
|
||||||
run: |
|
# run: |
|
||||||
git clone https://github.com/leetal/ios-cmake --depth 1 ~/ios-cmake
|
# git clone https://github.com/leetal/ios-cmake --depth 1 ~/ios-cmake
|
||||||
bash build_ios.sh
|
# bash build_ios.sh
|
||||||
mkdir -p output/ios
|
# mkdir -p output/ios
|
||||||
cp -r build/pocketpy.xcframework output/ios/pocketpy.xcframework
|
# cp -r build/pocketpy.xcframework output/ios/pocketpy.xcframework
|
||||||
- uses: actions/upload-artifact@v3
|
# - uses: actions/upload-artifact@v3
|
||||||
with:
|
# with:
|
||||||
path: output
|
# path: output
|
||||||
|
78
.github/workflows/website.yml
vendored
78
.github/workflows/website.yml
vendored
@ -1,42 +1,42 @@
|
|||||||
name: website
|
# name: website
|
||||||
|
|
||||||
on:
|
# on:
|
||||||
push:
|
# push:
|
||||||
branches: [ main ]
|
# branches: [ main ]
|
||||||
pull_request:
|
# pull_request:
|
||||||
branches: [ main ]
|
# branches: [ main ]
|
||||||
|
|
||||||
permissions:
|
# permissions:
|
||||||
contents: write
|
# contents: write
|
||||||
|
|
||||||
jobs:
|
# jobs:
|
||||||
deploy:
|
# deploy:
|
||||||
runs-on: ubuntu-latest
|
# runs-on: ubuntu-latest
|
||||||
steps:
|
# steps:
|
||||||
- uses: actions/checkout@v4
|
# - uses: actions/checkout@v4
|
||||||
###################################################
|
# ###################################################
|
||||||
- uses: actions/setup-node@v3.1.1
|
# - uses: actions/setup-node@v3.1.1
|
||||||
- name: Retype build
|
# - name: Retype build
|
||||||
run: |
|
# run: |
|
||||||
python scripts/build_references.py
|
# python scripts/build_references.py
|
||||||
cd docs
|
# cd docs
|
||||||
npm install retypeapp --global
|
# npm install retypeapp --global
|
||||||
retype build
|
# retype build
|
||||||
###################################################
|
# ###################################################
|
||||||
- name: Setup emsdk
|
# - name: Setup emsdk
|
||||||
uses: mymindstorm/setup-emsdk@v12
|
# uses: mymindstorm/setup-emsdk@v12
|
||||||
with:
|
# with:
|
||||||
version: 3.1.25
|
# version: 3.1.25
|
||||||
actions-cache-folder: 'emsdk-cache'
|
# actions-cache-folder: 'emsdk-cache'
|
||||||
- name: Compile
|
# - name: Compile
|
||||||
run: |
|
# run: |
|
||||||
bash build_web.sh
|
# bash build_web.sh
|
||||||
mv web docs/.retype/static
|
# mv web docs/.retype/static
|
||||||
###################################################
|
# ###################################################
|
||||||
- uses: crazy-max/ghaction-github-pages@v3
|
# - uses: crazy-max/ghaction-github-pages@v3
|
||||||
with:
|
# with:
|
||||||
target_branch: gh-pages
|
# target_branch: gh-pages
|
||||||
build_dir: docs/.retype
|
# build_dir: docs/.retype
|
||||||
env:
|
# env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
if: github.ref == 'refs/heads/main'
|
# if: github.ref == 'refs/heads/main'
|
||||||
|
@ -90,7 +90,7 @@ static PyVar convert_cjson_to_python_object(const cJSON * const item, VM* vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_cjson(VM* vm){
|
void add_module_cjson(VM* vm){
|
||||||
PyVar mod = vm->new_module("cjson");
|
PyObject* mod = vm->new_module("cjson");
|
||||||
|
|
||||||
vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args){
|
vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args){
|
||||||
std::string_view sv;
|
std::string_view sv;
|
||||||
|
@ -38,8 +38,8 @@ struct PyLuaObject{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PyLuaTable: PyLuaObject{
|
struct PyLuaTable: PyLuaObject{
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
Type t = PK_OBJ_GET(Type, type);
|
Type t = type->as<Type>();
|
||||||
PyTypeInfo* ti = &vm->_all_types[t];
|
PyTypeInfo* ti = &vm->_all_types[t];
|
||||||
ti->subclass_enabled = false;
|
ti->subclass_enabled = false;
|
||||||
ti->m__getattr__ = [](VM* vm, PyVar obj, StrName name){
|
ti->m__getattr__ = [](VM* vm, PyVar obj, StrName name){
|
||||||
@ -195,7 +195,7 @@ static PyVar lua_popx_multi_to_python(VM* vm, int count){
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct PyLuaFunction: PyLuaObject{
|
struct PyLuaFunction: PyLuaObject{
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_func(type, __call__, -1, [](VM* vm, ArgsView args){
|
vm->bind_func(type, __call__, -1, [](VM* vm, ArgsView args){
|
||||||
if(args.size() < 1) vm->TypeError("__call__ takes at least 1 argument");
|
if(args.size() < 1) vm->TypeError("__call__ takes at least 1 argument");
|
||||||
const PyLuaFunction& self = _CAST(PyLuaFunction&, args[0]);
|
const PyLuaFunction& self = _CAST(PyLuaFunction&, args[0]);
|
||||||
@ -320,7 +320,7 @@ PyVar lua_popx_to_python(VM* vm) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void initialize_lua_bridge(VM* vm, lua_State* newL){
|
void initialize_lua_bridge(VM* vm, lua_State* newL){
|
||||||
PyVar mod = vm->new_module("lua");
|
PyObject* mod = vm->new_module("lua");
|
||||||
|
|
||||||
if(_L != nullptr){
|
if(_L != nullptr){
|
||||||
throw std::runtime_error("lua bridge already initialized");
|
throw std::runtime_error("lua bridge already initialized");
|
||||||
|
@ -46,14 +46,14 @@ struct Point{
|
|||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
// do bindings here
|
// do bindings here
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
VM* vm = new VM();
|
VM* vm = new VM();
|
||||||
PyVar mod = vm->new_module("test");
|
PyObject* mod = vm->new_module("test");
|
||||||
Point::register_class(vm, mod);
|
Point::register_class(vm, mod);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ struct Point{
|
|||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
VM* vm = new VM();
|
VM* vm = new VM();
|
||||||
PyVar mod = vm->new_module("test");
|
PyObject* mod = vm->new_module("test");
|
||||||
vm->register_user_class<Point>(mod, "Point",
|
vm->register_user_class<Point>(mod, "Point",
|
||||||
[](VM* vm, PyVar mod, PyVar type){
|
[](VM* vm, PyVar mod, PyVar type){
|
||||||
// do bindings here
|
// do bindings here
|
||||||
@ -84,14 +84,14 @@ This is achieved by an overloaded version of `vm->register_user_class<>`. For ex
|
|||||||
struct Point{
|
struct Point{
|
||||||
int x, y;
|
int x, y;
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
// do bindings here (if you like the intrusive way)
|
// do bindings here (if you like the intrusive way)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
VM* vm = new VM();
|
VM* vm = new VM();
|
||||||
PyVar mod = vm->new_module("test");
|
PyObject* mod = vm->new_module("test");
|
||||||
vm->register_user_class<Point>(mod, "Point");
|
vm->register_user_class<Point>(mod, "Point");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ You can create a `test` module and use `vm->register_user_class<>` to bind the c
|
|||||||
```cpp
|
```cpp
|
||||||
int main(){
|
int main(){
|
||||||
VM* vm = new VM();
|
VM* vm = new VM();
|
||||||
PyVar mod = vm->new_module("test");
|
PyObject* mod = vm->new_module("test");
|
||||||
vm->register_user_class<Point>(mod, "Point",
|
vm->register_user_class<Point>(mod, "Point",
|
||||||
[](VM* vm, PyVar mod, PyVar type){
|
[](VM* vm, PyVar mod, PyVar type){
|
||||||
// wrap field x
|
// wrap field x
|
||||||
@ -165,11 +165,11 @@ struct Container{
|
|||||||
|
|
||||||
void _gc_mark(VM* vm) const{
|
void _gc_mark(VM* vm) const{
|
||||||
// mark a
|
// mark a
|
||||||
if(a) PK_OBJ_MARK(a);
|
vm->obj_gc_mark(a);
|
||||||
|
|
||||||
// mark elements in b
|
// mark elements in b
|
||||||
for(PyVar obj : b){
|
for(PyVar obj : b){
|
||||||
if(obj) PK_OBJ_MARK(obj);
|
vm->obj_gc_mark(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,6 +328,6 @@ vm->_lazy_modules["test"] = "pi = 3.14";
|
|||||||
Create a native module
|
Create a native module
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
PyVar mod = vm->new_module("test");
|
PyObject* mod = vm->new_module("test");
|
||||||
vm->setattr(mod, "pi", py_var(vm, 3.14));
|
vm->setattr(mod, "pi", py_var(vm, 3.14));
|
||||||
```
|
```
|
||||||
|
@ -30,7 +30,7 @@ Native modules are always compiled and executed when the VM is created.
|
|||||||
To creata a native module, use `vm->new_module(Str name)`.
|
To creata a native module, use `vm->new_module(Str name)`.
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
PyVar mod = vm->new_module("test");
|
PyObject* mod = vm->new_module("test");
|
||||||
mod->attr().set("pi", py_var(vm, 3.14));
|
mod->attr().set("pi", py_var(vm, 3.14));
|
||||||
|
|
||||||
vm->bind(mod, "add(a: int, b: int)",
|
vm->bind(mod, "add(a: int, b: int)",
|
||||||
|
@ -63,31 +63,31 @@ inline PyVar __proxy_wrapper(VM* vm, ArgsView args){
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ret, typename... Params>
|
template<typename Ret, typename... Params>
|
||||||
PyVar VM::bind(PyVar obj, const char* sig, Ret(*func)(Params...), BindType bt){
|
PyObject* VM::bind(PyObject* obj, const char* sig, Ret(*func)(Params...), BindType bt){
|
||||||
NativeProxyFuncCBase* proxy = new NativeProxyFuncC<Ret, Params...>(func);
|
NativeProxyFuncCBase* proxy = new NativeProxyFuncC<Ret, Params...>(func);
|
||||||
return vm->bind(obj, sig, __proxy_wrapper, proxy, bt);
|
return vm->bind(obj, sig, __proxy_wrapper, proxy, bt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ret, typename T, typename... Params>
|
template<typename Ret, typename T, typename... Params>
|
||||||
PyVar VM::bind(PyVar obj, const char* sig, Ret(T::*func)(Params...), BindType bt){
|
PyObject* VM::bind(PyObject* obj, const char* sig, Ret(T::*func)(Params...), BindType bt){
|
||||||
NativeProxyFuncCBase* proxy = new NativeProxyMethodC<Ret, T, Params...>(func);
|
NativeProxyFuncCBase* proxy = new NativeProxyMethodC<Ret, T, Params...>(func);
|
||||||
return vm->bind(obj, sig, __proxy_wrapper, proxy, bt);
|
return vm->bind(obj, sig, __proxy_wrapper, proxy, bt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ret, typename... Params>
|
template<typename Ret, typename... Params>
|
||||||
PyVar VM::bind(PyVar obj, const char* sig, const char* docstring, Ret(*func)(Params...), BindType bt){
|
PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Ret(*func)(Params...), BindType bt){
|
||||||
NativeProxyFuncCBase* proxy = new NativeProxyFuncC<Ret, Params...>(func);
|
NativeProxyFuncCBase* proxy = new NativeProxyFuncC<Ret, Params...>(func);
|
||||||
return vm->bind(obj, sig, docstring, __proxy_wrapper, proxy, bt);
|
return vm->bind(obj, sig, docstring, __proxy_wrapper, proxy, bt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ret, typename T, typename... Params>
|
template<typename Ret, typename T, typename... Params>
|
||||||
PyVar VM::bind(PyVar obj, const char* sig, const char* docstring, Ret(T::*func)(Params...), BindType bt){
|
PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, Ret(T::*func)(Params...), BindType bt){
|
||||||
NativeProxyFuncCBase* proxy = new NativeProxyMethodC<Ret, T, Params...>(func);
|
NativeProxyFuncCBase* proxy = new NativeProxyMethodC<Ret, T, Params...>(func);
|
||||||
return vm->bind(obj, sig, docstring, __proxy_wrapper, proxy, bt);
|
return vm->bind(obj, sig, docstring, __proxy_wrapper, proxy, bt);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename F, bool ReadOnly>
|
template<typename T, typename F, bool ReadOnly>
|
||||||
PyVar VM::bind_field(PyVar obj, const char* name, F T::*field){
|
PyObject* VM::bind_field(PyObject* obj, const char* name, F T::*field){
|
||||||
static_assert(!std::is_reference_v<F>);
|
static_assert(!std::is_reference_v<F>);
|
||||||
PK_ASSERT(is_type(obj, tp_type));
|
PK_ASSERT(is_type(obj, tp_type));
|
||||||
std::string_view name_sv(name); int pos = name_sv.find(':');
|
std::string_view name_sv(name); int pos = name_sv.find(':');
|
||||||
@ -108,7 +108,7 @@ PyVar VM::bind_field(PyVar obj, const char* name, F T::*field){
|
|||||||
};
|
};
|
||||||
_1 = new_object<NativeFunc>(tp_native_func, fset, 2, field);
|
_1 = new_object<NativeFunc>(tp_native_func, fset, 2, field);
|
||||||
}
|
}
|
||||||
PyVar prop = VAR(Property(_0, _1));
|
PyObject* prop = heap.gcnew<Property>(tp_property, _0, _1);
|
||||||
obj->attr().set(StrName(name_sv), prop);
|
obj->attr().set(StrName(name_sv), prop);
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ PyVar VM::bind_field(PyVar obj, const char* name, F T::*field){
|
|||||||
vm->bind_func(type, "sizeof", 1, [](VM* vm, ArgsView args){ \
|
vm->bind_func(type, "sizeof", 1, [](VM* vm, ArgsView args){ \
|
||||||
return VAR(sizeof(wT)); \
|
return VAR(sizeof(wT)); \
|
||||||
}); \
|
}); \
|
||||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
vm->bind__eq__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||||
wT& self = _CAST(wT&, _0); \
|
wT& self = _CAST(wT&, _0); \
|
||||||
if(!vm->isinstance(_1, vm->_tp_user<wT>())) return vm->NotImplemented; \
|
if(!vm->isinstance(_1, vm->_tp_user<wT>())) return vm->NotImplemented; \
|
||||||
wT& other = _CAST(wT&, _1); \
|
wT& other = _CAST(wT&, _1); \
|
||||||
@ -188,13 +188,13 @@ PyVar VM::bind_field(PyVar obj, const char* name, F T::*field){
|
|||||||
}); \
|
}); \
|
||||||
|
|
||||||
#define PY_POINTER_SETGETITEM(T) \
|
#define PY_POINTER_SETGETITEM(T) \
|
||||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
vm->bind__getitem__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||||
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, _0); \
|
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, _0); \
|
||||||
i64 i = CAST(i64, _1); \
|
i64 i = CAST(i64, _1); \
|
||||||
T* tgt = reinterpret_cast<T*>(self.ptr); \
|
T* tgt = reinterpret_cast<T*>(self.ptr); \
|
||||||
return VAR(tgt[i]); \
|
return VAR(tgt[i]); \
|
||||||
}); \
|
}); \
|
||||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1, PyVar _2){ \
|
vm->bind__setitem__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1, PyVar _2){ \
|
||||||
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, _0); \
|
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, _0); \
|
||||||
i64 i = CAST(i64, _1); \
|
i64 i = CAST(i64, _1); \
|
||||||
T* tgt = reinterpret_cast<T*>(self.ptr); \
|
T* tgt = reinterpret_cast<T*>(self.ptr); \
|
||||||
|
@ -32,14 +32,14 @@ struct VoidP{
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define POINTER_VAR(Tp, NAME) \
|
#define POINTER_VAR(Tp, NAME) \
|
||||||
inline PyVar py_var(VM* vm, Tp val){ \
|
inline PyVar py_var(VM* vm, Tp val){ \
|
||||||
const static std::pair<StrName, StrName> P("c", NAME); \
|
const static std::pair<StrName, StrName> P("c", NAME); \
|
||||||
PyVar type = vm->_modules[P.first]->attr(P.second); \
|
PyVar type = vm->_modules[P.first]->attr(P.second); \
|
||||||
return vm->new_object<VoidP>(PK_OBJ_GET(Type, type), val); \
|
return vm->new_object<VoidP>(type->as<Type>(), val); \
|
||||||
}
|
}
|
||||||
|
|
||||||
POINTER_VAR(char*, "char_p")
|
POINTER_VAR(char*, "char_p")
|
||||||
@ -84,7 +84,7 @@ struct Struct{
|
|||||||
Struct(const Struct& other): Struct(other.p, other.size){}
|
Struct(const Struct& other): Struct(other.p, other.size){}
|
||||||
~Struct(){ if(p!=_inlined) free(p); }
|
~Struct(){ if(p!=_inlined) free(p); }
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert(py_sizeof<Struct> <= 64);
|
static_assert(py_sizeof<Struct> <= 64);
|
||||||
|
@ -145,11 +145,11 @@ struct NativeFunc {
|
|||||||
|
|
||||||
struct Function{
|
struct Function{
|
||||||
FuncDecl_ decl;
|
FuncDecl_ decl;
|
||||||
PyVar _module; // weak ref
|
PyObject* _module; // weak ref
|
||||||
PyVar _class; // weak ref
|
PyObject* _class; // weak ref
|
||||||
NameDict_ _closure;
|
NameDict_ _closure;
|
||||||
|
|
||||||
explicit Function(FuncDecl_ decl, PyVar _module, PyVar _class, NameDict_ _closure):
|
explicit Function(FuncDecl_ decl, PyObject* _module, PyObject* _class, NameDict_ _closure):
|
||||||
decl(decl), _module(_module), _class(_class), _closure(_closure) {}
|
decl(decl), _module(_module), _class(_class), _closure(_closure) {}
|
||||||
|
|
||||||
void _gc_mark(VM*) const;
|
void _gc_mark(VM*) const;
|
||||||
|
@ -89,7 +89,6 @@ using f64 = double; // always 64-bit
|
|||||||
|
|
||||||
static_assert(sizeof(i64) == 8);
|
static_assert(sizeof(i64) == 8);
|
||||||
|
|
||||||
struct Dummy { }; // for special objects: True, False, None, Ellipsis, etc.
|
|
||||||
struct DummyInstance { };
|
struct DummyInstance { };
|
||||||
struct DummyModule { };
|
struct DummyModule { };
|
||||||
struct NoReturn { };
|
struct NoReturn { };
|
||||||
@ -104,9 +103,9 @@ struct Type {
|
|||||||
constexpr operator int() const { return index; }
|
constexpr operator int() const { return index; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; })
|
#define PK_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return x; })
|
||||||
#define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) { return VAR(x); })
|
#define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return VAR(x); })
|
||||||
#define PK_ACTION(x) ([](VM* vm, ArgsView args) { x; return vm->None; })
|
#define PK_ACTION(x) ([](VM* vm, ArgsView args) -> PyVar { x; return vm->None; })
|
||||||
|
|
||||||
#define PK_REGION(name) 1
|
#define PK_REGION(name) 1
|
||||||
|
|
||||||
@ -190,6 +189,9 @@ struct PyVar final{
|
|||||||
// uninitialized
|
// uninitialized
|
||||||
PyVar() = default;
|
PyVar() = default;
|
||||||
|
|
||||||
|
// implict conversion
|
||||||
|
PyVar(PyObject* p);
|
||||||
|
|
||||||
/* We must initialize all members to allow == operator to work correctly */
|
/* We must initialize all members to allow == operator to work correctly */
|
||||||
// constexpr initialized
|
// constexpr initialized
|
||||||
constexpr PyVar(const const_sso_var&, Type type, int value): type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
|
constexpr PyVar(const const_sso_var&, Type type, int value): type(type), is_ptr(false), flags(0), _0(value), _1(0) {}
|
||||||
|
@ -69,12 +69,12 @@ struct Exception {
|
|||||||
int _ip_on_error;
|
int _ip_on_error;
|
||||||
void* _code_on_error;
|
void* _code_on_error;
|
||||||
|
|
||||||
PyVar _self; // weak reference
|
PyObject* _self; // weak reference
|
||||||
|
|
||||||
stack<ExceptionLine> stacktrace;
|
stack<ExceptionLine> stacktrace;
|
||||||
Exception(StrName type): type(type), is_re(true), _ip_on_error(-1), _code_on_error(nullptr), _self(nullptr) {}
|
Exception(StrName type): type(type), is_re(true), _ip_on_error(-1), _code_on_error(nullptr), _self(nullptr) {}
|
||||||
|
|
||||||
PyVar self() const{
|
PyObject* self() const{
|
||||||
PK_ASSERT(_self != nullptr);
|
PK_ASSERT(_self != nullptr);
|
||||||
return _self;
|
return _self;
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ struct CodeEmitContext{
|
|||||||
bool is_compiling_class = false;
|
bool is_compiling_class = false;
|
||||||
|
|
||||||
std::map<PyVar, int> _co_consts_nonstring_dedup_map;
|
std::map<PyVar, int> _co_consts_nonstring_dedup_map;
|
||||||
std::map<std::string, int, std::less<>> _co_consts_string_dedup_map;
|
std::map<std::string_view, int> _co_consts_string_dedup_map;
|
||||||
|
|
||||||
int get_loop() const;
|
int get_loop() const;
|
||||||
CodeBlock* enter_block(CodeBlockType type);
|
CodeBlock* enter_block(CodeBlockType type);
|
||||||
|
@ -29,6 +29,8 @@ struct FastLocals{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ValueStack {
|
struct ValueStack {
|
||||||
|
PK_ALWAYS_PASS_BY_POINTER(ValueStack)
|
||||||
|
|
||||||
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() == true`.
|
// We allocate extra PK_VM_STACK_SIZE/128 places to keep `_sp` valid when `is_overflow() == true`.
|
||||||
PyVar _begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE/128];
|
PyVar _begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE/128];
|
||||||
PyVar* _sp;
|
PyVar* _sp;
|
||||||
@ -65,14 +67,6 @@ struct ValueStack {
|
|||||||
new(_sp) PyVar(std::forward<Args>(args)...);
|
new(_sp) PyVar(std::forward<Args>(args)...);
|
||||||
++_sp;
|
++_sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar operator[](int i) const { return _begin[i]; }
|
|
||||||
PyVar& operator[](int i) { return _begin[i]; }
|
|
||||||
|
|
||||||
ValueStack(const ValueStack&) = delete;
|
|
||||||
ValueStack(ValueStack&&) = delete;
|
|
||||||
ValueStack& operator=(const ValueStack&) = delete;
|
|
||||||
ValueStack& operator=(ValueStack&&) = delete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct UnwindTarget{
|
struct UnwindTarget{
|
||||||
@ -91,27 +85,27 @@ struct Frame {
|
|||||||
PyVar* _sp_base;
|
PyVar* _sp_base;
|
||||||
|
|
||||||
const CodeObject* co;
|
const CodeObject* co;
|
||||||
PyVar _module;
|
PyObject* _module;
|
||||||
PyVar _callable; // a function object or nullptr (global scope)
|
PyObject* _callable; // a function object or nullptr (global scope)
|
||||||
FastLocals _locals;
|
FastLocals _locals;
|
||||||
|
|
||||||
// This list will be freed in __pop_frame
|
// This list will be freed in __pop_frame
|
||||||
UnwindTarget* _uw_list;
|
UnwindTarget* _uw_list;
|
||||||
|
|
||||||
NameDict& f_globals() { return _module->attr(); }
|
NameDict& f_globals() { return _module->attr(); }
|
||||||
PyVar f_closure_try_get(StrName name);
|
PyVar* f_closure_try_get(StrName name);
|
||||||
int ip() const { return _ip - co->codes.data(); }
|
int ip() const { return _ip - co->codes.data(); }
|
||||||
|
|
||||||
// function scope
|
// function scope
|
||||||
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, PyVar* _locals_base)
|
Frame(PyVar* p0, const CodeObject* co, PyObject* _module, PyObject* _callable, PyVar* _locals_base)
|
||||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base), _uw_list(nullptr) { }
|
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(co, _locals_base), _uw_list(nullptr) { }
|
||||||
|
|
||||||
// exec/eval
|
// exec/eval
|
||||||
Frame(PyVar* p0, const CodeObject* co, PyVar _module, PyVar _callable, FastLocals _locals)
|
Frame(PyVar* p0, const CodeObject* co, PyObject* _module, PyObject* _callable, FastLocals _locals)
|
||||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals), _uw_list(nullptr) { }
|
: _ip(co->codes.data()-1), _sp_base(p0), co(co), _module(_module), _callable(_callable), _locals(_locals), _uw_list(nullptr) { }
|
||||||
|
|
||||||
// global scope
|
// global scope
|
||||||
Frame(PyVar* p0, const CodeObject_& co, PyVar _module)
|
Frame(PyVar* p0, const CodeObject_& co, PyObject* _module)
|
||||||
: _ip(co->codes.data()-1), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0), _uw_list(nullptr) { }
|
: _ip(co->codes.data()-1), _sp_base(p0), co(co.get()), _module(_module), _callable(nullptr), _locals(co.get(), p0), _uw_list(nullptr) { }
|
||||||
|
|
||||||
PyVar* actual_sp_base() const { return _locals.a; }
|
PyVar* actual_sp_base() const { return _locals.a; }
|
||||||
|
@ -39,7 +39,7 @@ struct ManagedHeap{
|
|||||||
/********************/
|
/********************/
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
PyVar gcnew(Type type, Args&&... args){
|
PyObject* gcnew(Type type, Args&&... args){
|
||||||
using __T = std::decay_t<T>;
|
using __T = std::decay_t<T>;
|
||||||
static_assert(!is_sso_v<__T>, "gcnew cannot be used with SSO types");
|
static_assert(!is_sso_v<__T>, "gcnew cannot be used with SSO types");
|
||||||
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
|
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
|
||||||
@ -47,17 +47,17 @@ struct ManagedHeap{
|
|||||||
p->placement_new<__T>(std::forward<Args>(args)...);
|
p->placement_new<__T>(std::forward<Args>(args)...);
|
||||||
gen.push_back(p);
|
gen.push_back(p);
|
||||||
gc_counter++;
|
gc_counter++;
|
||||||
return PyVar(type, p);
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
PyVar _new(Type type, Args&&... args){
|
PyObject* _new(Type type, Args&&... args){
|
||||||
using __T = std::decay_t<T>;
|
using __T = std::decay_t<T>;
|
||||||
static_assert(!is_sso_v<__T>);
|
static_assert(!is_sso_v<__T>);
|
||||||
PyObject* p = new(pool128_alloc(py_sizeof<__T>)) PyObject(type);
|
PyObject* p = new(pool128_alloc(py_sizeof<__T>)) PyObject(type);
|
||||||
p->placement_new<__T>(std::forward<Args>(args)...);
|
p->placement_new<__T>(std::forward<Args>(args)...);
|
||||||
_no_gc.push_back(p);
|
_no_gc.push_back(p);
|
||||||
return PyVar(type, p);
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _delete(PyObject*);
|
void _delete(PyObject*);
|
||||||
|
@ -11,7 +11,7 @@ struct RangeIter{ // step > 0
|
|||||||
i64 current;
|
i64 current;
|
||||||
RangeIter(Range r) : r(r), current(r.start) {}
|
RangeIter(Range r) : r(r), current(r.start) {}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RangeIterR{ // step < 0
|
struct RangeIterR{ // step < 0
|
||||||
@ -19,7 +19,7 @@ struct RangeIterR{ // step < 0
|
|||||||
i64 current;
|
i64 current;
|
||||||
RangeIterR(Range r) : r(r), current(r.start) {}
|
RangeIterR(Range r) : r(r), current(r.start) {}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArrayIter{
|
struct ArrayIter{
|
||||||
@ -31,15 +31,15 @@ struct ArrayIter{
|
|||||||
: ref(ref), end(end), current(begin) {}
|
: ref(ref), end(end), current(begin) {}
|
||||||
|
|
||||||
void _gc_mark(VM* vm) const{ vm->__obj_gc_mark(ref); }
|
void _gc_mark(VM* vm) const{ vm->__obj_gc_mark(ref); }
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringIter{
|
struct StringIter{
|
||||||
PyVar ref;
|
PyVar ref;
|
||||||
int i; // byte index
|
int i; // byte index
|
||||||
StringIter(PyVar ref) : ref(ref), i(0) {}
|
StringIter(PyVar ref) : ref(ref), i(0) {}
|
||||||
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
|
void _gc_mark(VM* vm) const{ vm->obj_gc_mark(ref); }
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Generator{
|
struct Generator{
|
||||||
@ -58,7 +58,7 @@ struct Generator{
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar next(VM* vm);
|
PyVar next(VM* vm);
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
|
|
||||||
~Generator(){
|
~Generator(){
|
||||||
if(lf){
|
if(lf){
|
||||||
@ -74,8 +74,8 @@ struct DictItemsIter{
|
|||||||
DictItemsIter(PyVar ref) : ref(ref) {
|
DictItemsIter(PyVar ref) : ref(ref) {
|
||||||
i = PK_OBJ_GET(Dict, ref)._head_idx;
|
i = PK_OBJ_GET(Dict, ref)._head_idx;
|
||||||
}
|
}
|
||||||
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
|
void _gc_mark(VM* vm) const{ vm->obj_gc_mark(ref); }
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pkpy
|
} // namespace pkpy
|
@ -7,7 +7,7 @@ namespace pkpy{
|
|||||||
inline bool isclose(float a, float b){ return std::fabs(a - b) < 1e-4; }
|
inline bool isclose(float a, float b){ return std::fabs(a - b) < 1e-4; }
|
||||||
|
|
||||||
struct Vec2{
|
struct Vec2{
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
|
|
||||||
float x, y;
|
float x, y;
|
||||||
Vec2() : x(0.0f), y(0.0f) {}
|
Vec2() : x(0.0f), y(0.0f) {}
|
||||||
@ -31,7 +31,7 @@ struct Vec2{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Vec3{
|
struct Vec3{
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
|
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
Vec3() : x(0.0f), y(0.0f), z(0.0f) {}
|
Vec3() : x(0.0f), y(0.0f), z(0.0f) {}
|
||||||
@ -54,7 +54,7 @@ struct Vec3{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Vec4{
|
struct Vec4{
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
|
|
||||||
float x, y, z, w;
|
float x, y, z, w;
|
||||||
Vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
|
Vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
|
||||||
@ -78,7 +78,7 @@ struct Vec4{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Mat3x3{
|
struct Mat3x3{
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
|
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
@ -16,6 +16,11 @@ constexpr T default_invalid_value(){
|
|||||||
#define PK_SMALL_NAME_DICT_CAPACITY 6
|
#define PK_SMALL_NAME_DICT_CAPACITY 6
|
||||||
#define PK_SMALL_NAME_DICT_LOOP(B) for(int i=0; i<PK_SMALL_NAME_DICT_CAPACITY; i++) { B }
|
#define PK_SMALL_NAME_DICT_LOOP(B) for(int i=0; i<PK_SMALL_NAME_DICT_CAPACITY; i++) { B }
|
||||||
|
|
||||||
|
struct A{
|
||||||
|
uint16_t k;
|
||||||
|
PyVar v;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename V>
|
template<typename V>
|
||||||
struct SmallNameDict{
|
struct SmallNameDict{
|
||||||
using K = StrName;
|
using K = StrName;
|
||||||
|
@ -180,8 +180,8 @@ template <typename, typename=void> struct has_gc_marker : std::false_type {};
|
|||||||
template <typename T> struct has_gc_marker<T, std::void_t<decltype(&T::_gc_mark)>> : std::true_type {};
|
template <typename T> struct has_gc_marker<T, std::void_t<decltype(&T::_gc_mark)>> : std::true_type {};
|
||||||
|
|
||||||
struct MappingProxy{
|
struct MappingProxy{
|
||||||
PyVar obj;
|
PyObject* obj;
|
||||||
MappingProxy(PyVar obj) : obj(obj) {}
|
MappingProxy(PyObject* obj) : obj(obj) {}
|
||||||
NameDict& attr() { return obj->attr(); }
|
NameDict& attr() { return obj->attr(); }
|
||||||
void _gc_mark(VM*) const;
|
void _gc_mark(VM*) const;
|
||||||
};
|
};
|
||||||
@ -202,8 +202,10 @@ obj_get_t<T> PyVar::obj_get(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PK_OBJ_GET(T, obj) (obj).obj_get<T>()
|
#define PK_OBJ_GET(T, obj) ((obj).obj_get<T>())
|
||||||
#define PK_OBJ_MARK(obj) if((obj).is_ptr) vm->__obj_gc_mark((obj).get());
|
|
||||||
|
// deprecated
|
||||||
|
#define PK_OBJ_MARK(obj) vm->obj_gc_mark(obj)
|
||||||
|
|
||||||
#define VAR(x) py_var(vm, x)
|
#define VAR(x) py_var(vm, x)
|
||||||
#define CAST(T, x) py_cast<T>(vm, x)
|
#define CAST(T, x) py_cast<T>(vm, x)
|
||||||
@ -213,13 +215,6 @@ obj_get_t<T> PyVar::obj_get(){
|
|||||||
#define CAST_DEFAULT(T, x, default_value) (x != vm->None) ? py_cast<T>(vm, x) : (default_value)
|
#define CAST_DEFAULT(T, x, default_value) (x != vm->None) ? py_cast<T>(vm, x) : (default_value)
|
||||||
|
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
inline bool try_cast_int(PyVar obj, i64* val) noexcept {
|
|
||||||
if(is_int(obj)){
|
|
||||||
*val = obj.as<i64>();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PY_NULL nullptr
|
#define PY_NULL nullptr
|
||||||
extern PyVar const PY_OP_CALL;
|
extern PyVar const PY_OP_CALL;
|
||||||
|
@ -119,9 +119,8 @@ struct StrName {
|
|||||||
return sv() > other.sv();
|
return sv() > other.sv();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_valid(int index);
|
|
||||||
static StrName get(std::string_view s);
|
static StrName get(std::string_view s);
|
||||||
static std::map<std::string, uint16_t, std::less<>>& _interned();
|
static std::map<std::string_view, uint16_t>& _interned();
|
||||||
static std::map<uint16_t, std::string>& _r_interned();
|
static std::map<uint16_t, std::string>& _r_interned();
|
||||||
static uint32_t _pesudo_random_index;
|
static uint32_t _pesudo_random_index;
|
||||||
};
|
};
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
namespace pkpy {
|
namespace pkpy {
|
||||||
|
|
||||||
struct List: pod_vector<PyVar, 4>{
|
struct List: pod_vector<PyVar>{
|
||||||
using pod_vector<PyVar, 4>::pod_vector;
|
using pod_vector<PyVar>::pod_vector;
|
||||||
void _gc_mark(VM*) const;
|
void _gc_mark(VM*) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5,10 +5,11 @@
|
|||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
template<typename T, int Growth=2>
|
template<typename T>
|
||||||
struct pod_vector{
|
struct pod_vector{
|
||||||
static constexpr int SizeT = sizeof(T);
|
static constexpr int SizeT = sizeof(T);
|
||||||
static constexpr int N = 128 / SizeT;
|
static constexpr int N = 128 / SizeT;
|
||||||
|
static constexpr int Growth = 2;
|
||||||
|
|
||||||
// static_assert(128 % SizeT == 0);
|
// static_assert(128 % SizeT == 0);
|
||||||
static_assert(is_pod_v<T>);
|
static_assert(is_pod_v<T>);
|
||||||
|
@ -27,7 +27,7 @@ namespace pkpy{
|
|||||||
#define STACK_VIEW(n) (s_data.view(n))
|
#define STACK_VIEW(n) (s_data.view(n))
|
||||||
|
|
||||||
typedef PyVar (*BinaryFuncC)(VM*, PyVar, PyVar);
|
typedef PyVar (*BinaryFuncC)(VM*, PyVar, PyVar);
|
||||||
typedef void (*RegisterFunc)(VM*, PyVar, PyVar);
|
typedef void (*RegisterFunc)(VM*, PyObject*, PyObject*);
|
||||||
|
|
||||||
#if PK_ENABLE_PROFILER
|
#if PK_ENABLE_PROFILER
|
||||||
struct NextBreakpoint{
|
struct NextBreakpoint{
|
||||||
@ -64,14 +64,14 @@ struct PyTypeInfo{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
PyVar obj; // never be garbage collected
|
PyObject* obj; // never be garbage collected
|
||||||
Type base;
|
Type base;
|
||||||
PyVar mod; // never be garbage collected
|
PyObject* mod; // never be garbage collected
|
||||||
StrName name;
|
StrName name;
|
||||||
bool subclass_enabled;
|
bool subclass_enabled;
|
||||||
Vt vt;
|
Vt vt;
|
||||||
|
|
||||||
PyTypeInfo(PyVar obj, Type base, PyVar mod, StrName name, bool subclass_enabled, Vt vt={}):
|
PyTypeInfo(PyObject* obj, Type base, PyObject* mod, StrName name, bool subclass_enabled, Vt vt={}):
|
||||||
obj(obj), base(base), mod(mod), name(name), subclass_enabled(subclass_enabled), vt(vt) {}
|
obj(obj), base(base), mod(mod), name(name), subclass_enabled(subclass_enabled), vt(vt) {}
|
||||||
|
|
||||||
std::vector<StrName> annotated_fields = {};
|
std::vector<StrName> annotated_fields = {};
|
||||||
@ -165,12 +165,13 @@ public:
|
|||||||
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
|
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
|
||||||
|
|
||||||
struct{
|
struct{
|
||||||
PyVar error;
|
PyObject* error;
|
||||||
stack_no_copy<ArgsView> s_view;
|
stack_no_copy<ArgsView> s_view;
|
||||||
} __c;
|
} __c;
|
||||||
|
|
||||||
PyVar StopIteration; // a special Exception class
|
PyVar StopIteration; // a special Exception class
|
||||||
PyVar builtins, _main;
|
PyObject* builtins;
|
||||||
|
PyObject* _main;
|
||||||
|
|
||||||
// typeid -> Type
|
// typeid -> Type
|
||||||
std::map<const std::type_index, Type> _cxx_typeid_map;
|
std::map<const std::type_index, Type> _cxx_typeid_map;
|
||||||
@ -178,8 +179,8 @@ public:
|
|||||||
std::set<PyVar> _repr_recursion_set;
|
std::set<PyVar> _repr_recursion_set;
|
||||||
|
|
||||||
ImportContext __import_context;
|
ImportContext __import_context;
|
||||||
PyVar __last_exception;
|
PyObject* __last_exception;
|
||||||
PyVar __curr_class;
|
PyObject* __curr_class;
|
||||||
PyVar __cached_object_new;
|
PyVar __cached_object_new;
|
||||||
std::map<std::string_view, CodeObject_> __cached_codes;
|
std::map<std::string_view, CodeObject_> __cached_codes;
|
||||||
std::map<std::string_view, PyVar> __cached_op_funcs;
|
std::map<std::string_view, PyVar> __cached_op_funcs;
|
||||||
@ -260,6 +261,8 @@ public:
|
|||||||
i64 normalized_index(i64 index, int size);
|
i64 normalized_index(i64 index, int size);
|
||||||
Str disassemble(CodeObject_ co);
|
Str disassemble(CodeObject_ co);
|
||||||
void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step);
|
void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step);
|
||||||
|
void obj_gc_mark(PyVar obj) { if(obj.is_ptr) __obj_gc_mark(obj.get()); }
|
||||||
|
void obj_gc_mark(PyObject* p) { if(p) __obj_gc_mark(p); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("Name Lookup Methods")
|
#if PK_REGION("Name Lookup Methods")
|
||||||
@ -273,7 +276,7 @@ public:
|
|||||||
#if PK_REGION("Source Execution Methods")
|
#if PK_REGION("Source Execution Methods")
|
||||||
CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
|
CodeObject_ compile(std::string_view source, const Str& filename, CompileMode mode, bool unknown_global_scope=false);
|
||||||
Str precompile(std::string_view source, const Str& filename, CompileMode mode);
|
Str precompile(std::string_view source, const Str& filename, CompileMode mode);
|
||||||
PyVar exec(std::string_view source, Str filename, CompileMode mode, PyVar _module=nullptr);
|
PyVar exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module=nullptr);
|
||||||
PyVar exec(std::string_view source);
|
PyVar exec(std::string_view source);
|
||||||
PyVar eval(std::string_view source);
|
PyVar eval(std::string_view source);
|
||||||
|
|
||||||
@ -353,25 +356,25 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("General Bindings")
|
#if PK_REGION("General Bindings")
|
||||||
PyVar bind_func(PyVar obj, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT);
|
PyObject* bind_func(PyObject*obj, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT);
|
||||||
PyVar bind_func(Type type, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT){
|
PyObject* bind_func(Type type, StrName name, int argc, NativeFuncC fn, any userdata={}, BindType bt=BindType::DEFAULT){
|
||||||
return bind_func(_t(type), name, argc, fn, std::move(userdata), bt);
|
return bind_func(_t(type), name, argc, fn, std::move(userdata), bt);
|
||||||
}
|
}
|
||||||
PyVar bind_property(PyVar, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
|
PyObject* bind_property(PyObject*, const char*, NativeFuncC fget, NativeFuncC fset=nullptr);
|
||||||
template<typename T, typename F, bool ReadOnly=false>
|
template<typename T, typename F, bool ReadOnly=false>
|
||||||
PyVar bind_field(PyVar, const char*, F T::*);
|
PyObject* bind_field(PyObject*, const char*, F T::*);
|
||||||
|
|
||||||
PyVar bind(PyVar, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
|
||||||
template<typename Ret, typename... Params>
|
template<typename Ret, typename... Params>
|
||||||
PyVar bind(PyVar, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
|
||||||
template<typename Ret, typename T, typename... Params>
|
template<typename Ret, typename T, typename... Params>
|
||||||
PyVar bind(PyVar, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
|
||||||
|
|
||||||
PyVar bind(PyVar, const char*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, const char*, NativeFuncC, any userdata={}, BindType bt=BindType::DEFAULT);
|
||||||
template<typename Ret, typename... Params>
|
template<typename Ret, typename... Params>
|
||||||
PyVar bind(PyVar, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, const char*, Ret(*)(Params...), BindType bt=BindType::DEFAULT);
|
||||||
template<typename Ret, typename T, typename... Params>
|
template<typename Ret, typename T, typename... Params>
|
||||||
PyVar bind(PyVar, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
|
PyObject* bind(PyObject*, const char*, const char*, Ret(T::*)(Params...), BindType bt=BindType::DEFAULT);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("Error Reporting Methods")
|
#if PK_REGION("Error Reporting Methods")
|
||||||
@ -406,19 +409,19 @@ public:
|
|||||||
Type _tp(PyVar obj){ return obj.type; }
|
Type _tp(PyVar obj){ return obj.type; }
|
||||||
const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
|
const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
|
||||||
const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
|
const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
|
||||||
PyVar _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
|
PyObject* _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
|
||||||
PyVar _t(Type type){ return _all_types[type].obj; }
|
PyObject* _t(Type type){ return _all_types[type].obj; }
|
||||||
|
|
||||||
// equivalent to `obj == NotImplemented` but faster
|
// equivalent to `obj == NotImplemented` but faster
|
||||||
static bool is_not_implemented(PyVar obj){ return obj.type == tp_not_implemented; }
|
static bool is_not_implemented(PyVar obj){ return obj.type == tp_not_implemented; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PK_REGION("User Type Registration")
|
#if PK_REGION("User Type Registration")
|
||||||
PyVar new_module(Str name, Str package="");
|
PyObject* new_module(Str name, Str package="");
|
||||||
PyVar new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt={});
|
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt={});
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
PyVar new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled){
|
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled){
|
||||||
return new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
|
return new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -428,9 +431,9 @@ public:
|
|||||||
bool is_user_type(PyVar obj){ return _tp(obj) == _tp_user<T>(); }
|
bool is_user_type(PyVar obj){ return _tp(obj) == _tp_user<T>(); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
PyVar register_user_class(PyVar, StrName, RegisterFunc, Type base=tp_object, bool subclass_enabled=false);
|
PyObject* register_user_class(PyObject*, StrName, RegisterFunc, Type base=tp_object, bool subclass_enabled=false);
|
||||||
template<typename T>
|
template<typename T>
|
||||||
PyVar register_user_class(PyVar, StrName, Type base=tp_object, bool subclass_enabled=false);
|
PyObject* register_user_class(PyObject*, StrName, Type base=tp_object, bool subclass_enabled=false);
|
||||||
|
|
||||||
template<typename T, typename ...Args>
|
template<typename T, typename ...Args>
|
||||||
PyVar new_user_object(Args&&... args){
|
PyVar new_user_object(Args&&... args){
|
||||||
@ -601,10 +604,8 @@ __T _py_cast__internal(VM* vm, PyVar obj) {
|
|||||||
return (T)obj.as<i64>();
|
return (T)obj.as<i64>();
|
||||||
}else if constexpr(is_floating_point_v<T>){
|
}else if constexpr(is_floating_point_v<T>){
|
||||||
static_assert(!std::is_reference_v<__T>);
|
static_assert(!std::is_reference_v<__T>);
|
||||||
// float
|
|
||||||
if(is_float(obj)) return (T)obj.as<f64>();
|
if(is_float(obj)) return (T)obj.as<f64>();
|
||||||
i64 bits;
|
if(is_int(obj)) return (T)obj.as<i64>();
|
||||||
if(try_cast_int(obj, &bits)) return (T)bits;
|
|
||||||
vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
|
vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}else if constexpr(std::is_enum_v<T>){
|
}else if constexpr(std::is_enum_v<T>){
|
||||||
@ -641,15 +642,15 @@ template<typename __T>
|
|||||||
__T _py_cast(VM* vm, PyVar obj) { return _py_cast__internal<__T, false>(vm, obj); }
|
__T _py_cast(VM* vm, PyVar obj) { return _py_cast__internal<__T, false>(vm, obj); }
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
PyVar VM::register_user_class(PyVar mod, StrName name, RegisterFunc _register, Type base, bool subclass_enabled){
|
PyObject* VM::register_user_class(PyObject* mod, StrName name, RegisterFunc _register, Type base, bool subclass_enabled){
|
||||||
PyVar type = new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
|
PyObject* type = new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
|
||||||
mod->attr().set(name, type);
|
mod->attr().set(name, type);
|
||||||
_cxx_typeid_map[typeid(T)] = PK_OBJ_GET(Type, type);
|
_cxx_typeid_map[typeid(T)] = type->as<Type>();
|
||||||
_register(this, mod, type);
|
_register(this, mod, type);
|
||||||
if(!type->attr().contains(__new__)){
|
if(!type->attr().contains(__new__)){
|
||||||
if constexpr(std::is_default_constructible_v<T>) {
|
if constexpr(std::is_default_constructible_v<T>) {
|
||||||
bind_func(type, __new__, -1, [](VM* vm, ArgsView args){
|
bind_func(type, __new__, -1, [](VM* vm, ArgsView args){
|
||||||
Type cls_t = PK_OBJ_GET(Type, args[0]);
|
Type cls_t = args[0]->as<Type>();
|
||||||
return vm->new_object<T>(cls_t);
|
return vm->new_object<T>(cls_t);
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
@ -660,7 +661,7 @@ PyVar VM::register_user_class(PyVar mod, StrName name, RegisterFunc _register, T
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
PyVar VM::register_user_class(PyVar mod, StrName name, Type base, bool subclass_enabled){
|
PyObject* VM::register_user_class(PyObject* mod, StrName name, Type base, bool subclass_enabled){
|
||||||
return register_user_class<T>(mod, name, &T::_register, base, subclass_enabled);
|
return register_user_class<T>(mod, name, &T::_register, base, subclass_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ struct Array2d{
|
|||||||
data[row * n_cols + col] = value;
|
data[row * n_cols + col] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind(type, "__new__(cls, *args, **kwargs)", [](VM* vm, ArgsView args){
|
vm->bind(type, "__new__(cls, *args, **kwargs)", [](VM* vm, ArgsView args){
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
return vm->new_object<Array2d>(cls);
|
return vm->new_object<Array2d>(cls);
|
||||||
@ -113,11 +113,13 @@ struct Array2d{
|
|||||||
int slice_height = stop_row - start_row; \
|
int slice_height = stop_row - start_row; \
|
||||||
if(slice_width <= 0 || slice_height <= 0) vm->ValueError("slice width and height must be positive");
|
if(slice_width <= 0 || slice_height <= 0) vm->ValueError("slice width and height must be positive");
|
||||||
|
|
||||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
vm->bind__getitem__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){
|
||||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||||
const Tuple& xy = CAST(Tuple&, _1);
|
const Tuple& xy = CAST(Tuple&, _1);
|
||||||
i64 col, row;
|
|
||||||
if(try_cast_int(xy[0], &col) && try_cast_int(xy[1], &row)){
|
if(is_int(xy[0]) && is_int(xy[1])){
|
||||||
|
i64 col = xy[0].as<i64>();
|
||||||
|
i64 row = xy[1].as<i64>();
|
||||||
self.check_valid(vm, col, row);
|
self.check_valid(vm, col, row);
|
||||||
return self._get(col, row);
|
return self._get(col, row);
|
||||||
}
|
}
|
||||||
@ -137,11 +139,12 @@ struct Array2d{
|
|||||||
vm->TypeError("expected `tuple[int, int]` or `tuple[slice, slice]` as index");
|
vm->TypeError("expected `tuple[int, int]` or `tuple[slice, slice]` as index");
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1, PyVar _2){
|
vm->bind__setitem__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1, PyVar _2){
|
||||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||||
const Tuple& xy = CAST(Tuple&, _1);
|
const Tuple& xy = CAST(Tuple&, _1);
|
||||||
i64 col, row;
|
if(is_int(xy[0]) && is_int(xy[1])){
|
||||||
if(try_cast_int(xy[0], &col) && try_cast_int(xy[1], &row)){
|
i64 col = xy[0].as<i64>();
|
||||||
|
i64 row = xy[1].as<i64>();
|
||||||
self.check_valid(vm, col, row);
|
self.check_valid(vm, col, row);
|
||||||
self._set(col, row, _2);
|
self._set(col, row, _2);
|
||||||
return;
|
return;
|
||||||
@ -195,12 +198,12 @@ struct Array2d{
|
|||||||
return VAR(std::move(t));
|
return VAR(std::move(t));
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){
|
vm->bind__len__(type->as<Type>(), [](VM* vm, PyVar _0){
|
||||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||||
return (i64)self.numel;
|
return (i64)self.numel;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> Str{
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar _0) -> Str{
|
||||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||||
return _S("array2d(", self.n_cols, ", ", self.n_rows, ')');
|
return _S("array2d(", self.n_cols, ", ", self.n_rows, ')');
|
||||||
});
|
});
|
||||||
@ -269,7 +272,7 @@ struct Array2d{
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
vm->bind__eq__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){
|
||||||
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
Array2d& self = PK_OBJ_GET(Array2d, _0);
|
||||||
if(!vm->is_user_type<Array2d>(_1)) return vm->NotImplemented;
|
if(!vm->is_user_type<Array2d>(_1)) return vm->NotImplemented;
|
||||||
Array2d& other = PK_OBJ_GET(Array2d, _1);
|
Array2d& other = PK_OBJ_GET(Array2d, _1);
|
||||||
@ -352,7 +355,7 @@ struct Array2d{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _gc_mark(VM* vm) const{
|
void _gc_mark(VM* vm) const{
|
||||||
for(int i = 0; i < numel; i++) PK_OBJ_MARK(data[i]);
|
for(int i = 0; i < numel; i++) vm->obj_gc_mark(data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
~Array2d(){
|
~Array2d(){
|
||||||
@ -370,11 +373,11 @@ struct Array2dIter{
|
|||||||
|
|
||||||
Array2dIter(PyVar ref, Array2d* a): ref(ref), a(a), i(0){}
|
Array2dIter(PyVar ref, Array2d* a): ref(ref), a(a), i(0){}
|
||||||
|
|
||||||
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
|
void _gc_mark(VM* vm) const{ vm->obj_gc_mark(ref); }
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) { return _0; });
|
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0) { return _0; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
|
||||||
Array2dIter& self = PK_OBJ_GET(Array2dIter, _0);
|
Array2dIter& self = PK_OBJ_GET(Array2dIter, _0);
|
||||||
if(self.i == self.a->numel) return 0;
|
if(self.i == self.a->numel) return 0;
|
||||||
std::div_t res = std::div(self.i, self.a->n_cols);
|
std::div_t res = std::div(self.i, self.a->n_cols);
|
||||||
@ -387,7 +390,7 @@ struct Array2dIter{
|
|||||||
};
|
};
|
||||||
|
|
||||||
void add_module_array2d(VM* vm){
|
void add_module_array2d(VM* vm){
|
||||||
PyVar mod = vm->new_module("array2d");
|
PyObject* mod = vm->new_module("array2d");
|
||||||
|
|
||||||
vm->register_user_class<Array2d>(mod, "array2d", VM::tp_object, true);
|
vm->register_user_class<Array2d>(mod, "array2d", VM::tp_object, true);
|
||||||
vm->register_user_class<Array2dIter>(mod, "_array2d_iter");
|
vm->register_user_class<Array2dIter>(mod, "_array2d_iter");
|
||||||
|
@ -166,7 +166,7 @@ base64_decode(const char *in, unsigned int inlen, unsigned char *out)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_base64(VM* vm){
|
void add_module_base64(VM* vm){
|
||||||
PyVar mod = vm->new_module("base64");
|
PyObject* mod = vm->new_module("base64");
|
||||||
|
|
||||||
// b64encode
|
// b64encode
|
||||||
vm->bind_func(mod, "b64encode", 1, [](VM* vm, ArgsView args){
|
vm->bind_func(mod, "b64encode", 1, [](VM* vm, ArgsView args){
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "pocketpy/ceval.h"
|
#include "pocketpy/ceval.h"
|
||||||
|
#include "pocketpy/codeobject.h"
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
@ -194,22 +195,22 @@ __NEXT_STEP:
|
|||||||
PUSH(*slot);
|
PUSH(*slot);
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
}
|
}
|
||||||
PyVar _0 = frame->f_closure_try_get(_name);
|
PyVar* _0 = frame->f_closure_try_get(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
|
||||||
_0 = frame->f_globals().try_get_likely_found(_name);
|
_0 = frame->f_globals().try_get_2_likely_found(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
|
||||||
_0 = vm->builtins->attr().try_get_likely_found(_name);
|
_0 = vm->builtins->attr().try_get_2_likely_found(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
|
||||||
vm->NameError(_name);
|
vm->NameError(_name);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_LOAD_NONLOCAL: {
|
case OP_LOAD_NONLOCAL: {
|
||||||
StrName _name(byte.arg);
|
StrName _name(byte.arg);
|
||||||
PyVar _0 = frame->f_closure_try_get(_name);
|
PyVar* _0 = frame->f_closure_try_get(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
|
||||||
_0 = frame->f_globals().try_get_likely_found(_name);
|
_0 = frame->f_globals().try_get_2_likely_found(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
|
||||||
_0 = vm->builtins->attr().try_get_likely_found(_name);
|
_0 = vm->builtins->attr().try_get_2_likely_found(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
|
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
|
||||||
vm->NameError(_name);
|
vm->NameError(_name);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_LOAD_GLOBAL:{
|
case OP_LOAD_GLOBAL:{
|
||||||
@ -282,7 +283,7 @@ __NEXT_STEP:
|
|||||||
if(slot != nullptr){
|
if(slot != nullptr){
|
||||||
*slot = _0; // store in locals if possible
|
*slot = _0; // store in locals if possible
|
||||||
}else{
|
}else{
|
||||||
Function& func = PK_OBJ_GET(Function, frame->_callable);
|
Function& func = frame->_callable->as<Function>();
|
||||||
if(func.decl == __dynamic_func_decl){
|
if(func.decl == __dynamic_func_decl){
|
||||||
PK_DEBUG_ASSERT(func._closure != nullptr);
|
PK_DEBUG_ASSERT(func._closure != nullptr);
|
||||||
func._closure->set(_name, _0);
|
func._closure->set(_name, _0);
|
||||||
@ -338,7 +339,7 @@ __NEXT_STEP:
|
|||||||
if(slot != nullptr){
|
if(slot != nullptr){
|
||||||
slot->set_null();
|
slot->set_null();
|
||||||
}else{
|
}else{
|
||||||
Function& func = PK_OBJ_GET(Function, frame->_callable);
|
Function& func = frame->_callable->as<Function>();
|
||||||
if(func.decl == __dynamic_func_decl){
|
if(func.decl == __dynamic_func_decl){
|
||||||
PK_DEBUG_ASSERT(func._closure != nullptr);
|
PK_DEBUG_ASSERT(func._closure != nullptr);
|
||||||
bool ok = func._closure->del(_name);
|
bool ok = func._closure->del(_name);
|
||||||
@ -949,7 +950,7 @@ __NEXT_STEP:
|
|||||||
StrName _name(byte.arg);
|
StrName _name(byte.arg);
|
||||||
frame->_module->attr().set(_name, __curr_class);
|
frame->_module->attr().set(_name, __curr_class);
|
||||||
// call on_end_subclass
|
// call on_end_subclass
|
||||||
PyTypeInfo* ti = &_all_types[PK_OBJ_GET(Type, __curr_class)];
|
PyTypeInfo* ti = &_all_types[__curr_class->as<Type>()];
|
||||||
if(ti->base != tp_object){
|
if(ti->base != tp_object){
|
||||||
PyTypeInfo* base_ti = &_all_types[ti->base];
|
PyTypeInfo* base_ti = &_all_types[ti->base];
|
||||||
if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti);
|
if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti);
|
||||||
@ -969,12 +970,12 @@ __NEXT_STEP:
|
|||||||
PUSH(__curr_class);
|
PUSH(__curr_class);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_END_CLASS_DECORATION:{
|
case OP_END_CLASS_DECORATION:{
|
||||||
__curr_class = POPX();
|
__curr_class = POPX().get();
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
case OP_ADD_CLASS_ANNOTATION: {
|
case OP_ADD_CLASS_ANNOTATION: {
|
||||||
PK_ASSERT(__curr_class != nullptr);
|
PK_ASSERT(__curr_class != nullptr);
|
||||||
StrName _name(byte.arg);
|
StrName _name(byte.arg);
|
||||||
Type type = PK_OBJ_GET(Type, __curr_class);
|
Type type = __curr_class->as<Type>();
|
||||||
_all_types[type].annotated_fields.push_back(_name);
|
_all_types[type].annotated_fields.push_back(_name);
|
||||||
} DISPATCH()
|
} DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
@ -1016,7 +1017,7 @@ __NEXT_STEP:
|
|||||||
}
|
}
|
||||||
DISPATCH()
|
DISPATCH()
|
||||||
case OP_RE_RAISE: __raise_exc(true); DISPATCH()
|
case OP_RE_RAISE: __raise_exc(true); DISPATCH()
|
||||||
case OP_POP_EXCEPTION: __last_exception = POPX(); DISPATCH()
|
case OP_POP_EXCEPTION: __last_exception = POPX().get(); DISPATCH()
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
case OP_FORMAT_STRING: {
|
case OP_FORMAT_STRING: {
|
||||||
PyVar _0 = POPX();
|
PyVar _0 = POPX();
|
||||||
|
22
src/cffi.cpp
22
src/cffi.cpp
@ -2,25 +2,25 @@
|
|||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
void VoidP::_register(VM* vm, PyVar mod, PyVar type){
|
void VoidP::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
|
vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
i64 addr = CAST(i64, args[1]);
|
i64 addr = CAST(i64, args[1]);
|
||||||
return vm->new_object<VoidP>(cls, reinterpret_cast<void*>(addr));
|
return vm->new_object<VoidP>(cls, reinterpret_cast<void*>(addr));
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
|
vm->bind__hash__(type->as<Type>(), [](VM* vm, PyVar obj){
|
||||||
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
|
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
|
||||||
return reinterpret_cast<i64>(self.ptr);
|
return reinterpret_cast<i64>(self.ptr);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str{
|
||||||
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
|
obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
|
||||||
return _S("<void* at ", self.hex(), ">");
|
return _S("<void* at ", self.hex(), ">");
|
||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_CMP(name, op) \
|
#define BIND_CMP(name, op) \
|
||||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyVar lhs, PyVar rhs){ \
|
vm->bind##name(type->as<Type>(), [](VM* vm, PyVar lhs, PyVar rhs){ \
|
||||||
if(!vm->isinstance(rhs, vm->_tp_user<VoidP>())) return vm->NotImplemented; \
|
if(!vm->isinstance(rhs, vm->_tp_user<VoidP>())) return vm->NotImplemented; \
|
||||||
void* _0 = PK_OBJ_GET(VoidP, lhs).ptr; \
|
void* _0 = PK_OBJ_GET(VoidP, lhs).ptr; \
|
||||||
void* _1 = PK_OBJ_GET(VoidP, rhs).ptr; \
|
void* _1 = PK_OBJ_GET(VoidP, rhs).ptr; \
|
||||||
@ -37,7 +37,7 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Struct::_register(VM* vm, PyVar mod, PyVar type){
|
void Struct::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
|
vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
int size = CAST(int, args[1]);
|
int size = CAST(int, args[1]);
|
||||||
@ -72,7 +72,7 @@ namespace pkpy{
|
|||||||
return vm->new_user_object<Struct>(std::move(buffer));
|
return vm->new_user_object<Struct>(std::move(buffer));
|
||||||
}, {}, BindType::STATICMETHOD);
|
}, {}, BindType::STATICMETHOD);
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj){
|
||||||
Struct& self = _CAST(Struct&, obj);
|
Struct& self = _CAST(Struct&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss << "<struct object of " << self.size << " bytes>";
|
ss << "<struct object of " << self.size << " bytes>";
|
||||||
@ -94,7 +94,7 @@ namespace pkpy{
|
|||||||
return vm->new_object<Struct>(vm->_tp(args[0]), self);
|
return vm->new_object<Struct>(vm->_tp(args[0]), self);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar lhs, PyVar rhs){
|
vm->bind__eq__(type->as<Type>(), [](VM* vm, PyVar lhs, PyVar rhs){
|
||||||
Struct& self = _CAST(Struct&, lhs);
|
Struct& self = _CAST(Struct&, lhs);
|
||||||
if(!vm->is_user_type<Struct>(rhs)) return vm->NotImplemented;
|
if(!vm->is_user_type<Struct>(rhs)) return vm->NotImplemented;
|
||||||
Struct& other = _CAST(Struct&, rhs);
|
Struct& other = _CAST(Struct&, rhs);
|
||||||
@ -134,7 +134,7 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_c(VM* vm){
|
void add_module_c(VM* vm){
|
||||||
PyVar mod = vm->new_module("c");
|
PyObject* mod = vm->new_module("c");
|
||||||
|
|
||||||
vm->bind_func(mod, "malloc", 1, [](VM* vm, ArgsView args){
|
vm->bind_func(mod, "malloc", 1, [](VM* vm, ArgsView args){
|
||||||
i64 size = CAST(i64, args[0]);
|
i64 size = CAST(i64, args[0]);
|
||||||
@ -187,7 +187,7 @@ void add_module_c(VM* vm){
|
|||||||
return vm->new_object<VoidP>(args[0].type, value);
|
return vm->new_object<VoidP>(args[0].type, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
PyVar type;
|
PyObject* type;
|
||||||
Type type_t;
|
Type type_t;
|
||||||
|
|
||||||
#define BIND_PRIMITIVE(T, CNAME) \
|
#define BIND_PRIMITIVE(T, CNAME) \
|
||||||
@ -197,7 +197,7 @@ void add_module_c(VM* vm){
|
|||||||
}); \
|
}); \
|
||||||
type = vm->new_type_object(mod, CNAME "_p", vm->_tp_user<VoidP>(), true); \
|
type = vm->new_type_object(mod, CNAME "_p", vm->_tp_user<VoidP>(), true); \
|
||||||
mod->attr().set(CNAME "_p", type); \
|
mod->attr().set(CNAME "_p", type); \
|
||||||
type_t = PK_OBJ_GET(Type, type); \
|
type_t = type->as<Type>(); \
|
||||||
vm->bind_func(type, "read", 1, [](VM* vm, ArgsView args){ \
|
vm->bind_func(type, "read", 1, [](VM* vm, ArgsView args){ \
|
||||||
obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]); \
|
obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]); \
|
||||||
T* target = (T*)voidp.ptr; \
|
T* target = (T*)voidp.ptr; \
|
||||||
@ -255,7 +255,7 @@ void add_module_c(VM* vm){
|
|||||||
|
|
||||||
#undef BIND_PRIMITIVE
|
#undef BIND_PRIMITIVE
|
||||||
|
|
||||||
PyVar char_p_t = mod->attr("char_p");
|
PyObject* char_p_t = mod->attr("char_p").get();
|
||||||
vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args){
|
vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args){
|
||||||
obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);
|
obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);
|
||||||
const char* target = (const char*)voidp.ptr;
|
const char* target = (const char*)voidp.ptr;
|
||||||
|
@ -18,14 +18,14 @@ namespace pkpy
|
|||||||
{
|
{
|
||||||
this->is_reversed = true;
|
this->is_reversed = true;
|
||||||
}
|
}
|
||||||
void _gc_mark(VM* vm) const { PK_OBJ_MARK(ref); }
|
void _gc_mark(VM* vm) const { vm->obj_gc_mark(ref); }
|
||||||
static void _register(VM *vm, PyVar mod, PyVar type);
|
static void _register(VM *vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
void PyDequeIter::_register(VM *vm, PyVar mod, PyVar type)
|
void PyDequeIter::_register(VM *vm, PyObject* mod, PyObject* type)
|
||||||
{
|
{
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar obj)
|
vm->bind__iter__(type->as<Type>(), [](VM *vm, PyVar obj)
|
||||||
{ return obj; });
|
{ return obj; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar obj) -> unsigned
|
vm->bind__next__(type->as<Type>(), [](VM *vm, PyVar obj) -> unsigned
|
||||||
{
|
{
|
||||||
PyDequeIter& self = _CAST(PyDequeIter&, obj);
|
PyDequeIter& self = _CAST(PyDequeIter&, obj);
|
||||||
if(self.is_reversed){
|
if(self.is_reversed){
|
||||||
@ -52,10 +52,10 @@ namespace pkpy
|
|||||||
PyVar popObj(bool front, bool back, PyVar item, VM *vm); // pop at index, used purely for internal purposes: pop, popleft, remove methods
|
PyVar popObj(bool front, bool back, PyVar item, VM *vm); // pop at index, used purely for internal purposes: pop, popleft, remove methods
|
||||||
int findIndex(VM *vm, PyVar obj, int start, int stop); // find the index of the given object in the deque
|
int findIndex(VM *vm, PyVar obj, int start, int stop); // find the index of the given object in the deque
|
||||||
// Special methods
|
// Special methods
|
||||||
static void _register(VM *vm, PyVar mod, PyVar type); // register the type
|
static void _register(VM *vm, PyObject* mod, PyObject* type); // register the type
|
||||||
void _gc_mark(VM*) const; // needed for container types, mark all objects in the deque for gc
|
void _gc_mark(VM*) const; // needed for container types, mark all objects in the deque for gc
|
||||||
};
|
};
|
||||||
void PyDeque::_register(VM *vm, PyVar mod, PyVar type)
|
void PyDeque::_register(VM *vm, PyObject* mod, PyObject* type)
|
||||||
{
|
{
|
||||||
vm->bind(type, "__new__(cls, iterable=None, maxlen=None)",
|
vm->bind(type, "__new__(cls, iterable=None, maxlen=None)",
|
||||||
[](VM *vm, ArgsView args)
|
[](VM *vm, ArgsView args)
|
||||||
@ -67,7 +67,7 @@ namespace pkpy
|
|||||||
});
|
});
|
||||||
// gets the item at the given index, if index is negative, it will be treated as index + len(deque)
|
// gets the item at the given index, if index is negative, it will be treated as index + len(deque)
|
||||||
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1)
|
vm->bind__getitem__(type->as<Type>(), [](VM *vm, PyVar _0, PyVar _1)
|
||||||
{
|
{
|
||||||
PyDeque &self = _CAST(PyDeque &, _0);
|
PyDeque &self = _CAST(PyDeque &, _0);
|
||||||
i64 index = CAST(i64, _1);
|
i64 index = CAST(i64, _1);
|
||||||
@ -76,7 +76,7 @@ namespace pkpy
|
|||||||
});
|
});
|
||||||
// sets the item at the given index, if index is negative, it will be treated as index + len(deque)
|
// sets the item at the given index, if index is negative, it will be treated as index + len(deque)
|
||||||
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1, PyVar _2)
|
vm->bind__setitem__(type->as<Type>(), [](VM *vm, PyVar _0, PyVar _1, PyVar _2)
|
||||||
{
|
{
|
||||||
PyDeque &self = _CAST(PyDeque&, _0);
|
PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
i64 index = CAST(i64, _1);
|
i64 index = CAST(i64, _1);
|
||||||
@ -85,7 +85,7 @@ namespace pkpy
|
|||||||
});
|
});
|
||||||
// erases the item at the given index, if index is negative, it will be treated as index + len(deque)
|
// erases the item at the given index, if index is negative, it will be treated as index + len(deque)
|
||||||
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
// if the index is out of range, IndexError will be thrown --> required for [] operator
|
||||||
vm->bind__delitem__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1)
|
vm->bind__delitem__(type->as<Type>(), [](VM *vm, PyVar _0, PyVar _1)
|
||||||
{
|
{
|
||||||
PyDeque &self = _CAST(PyDeque&, _0);
|
PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
i64 index = CAST(i64, _1);
|
i64 index = CAST(i64, _1);
|
||||||
@ -93,19 +93,19 @@ namespace pkpy
|
|||||||
self.dequeItems.erase(self.dequeItems.begin() + index);
|
self.dequeItems.erase(self.dequeItems.begin() + index);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__len__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0)
|
vm->bind__len__(type->as<Type>(), [](VM *vm, PyVar _0)
|
||||||
{
|
{
|
||||||
PyDeque &self = _CAST(PyDeque&, _0);
|
PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
return (i64)self.dequeItems.size();
|
return (i64)self.dequeItems.size();
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0)
|
vm->bind__iter__(type->as<Type>(), [](VM *vm, PyVar _0)
|
||||||
{
|
{
|
||||||
PyDeque &self = _CAST(PyDeque &, _0);
|
PyDeque &self = _CAST(PyDeque &, _0);
|
||||||
return vm->new_user_object<PyDequeIter>(_0, self.dequeItems.begin(), self.dequeItems.end());
|
return vm->new_user_object<PyDequeIter>(_0, self.dequeItems.begin(), self.dequeItems.end());
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0) -> Str
|
vm->bind__repr__(type->as<Type>(), [](VM *vm, PyVar _0) -> Str
|
||||||
{
|
{
|
||||||
if(vm->_repr_recursion_set.count(_0)) return "[...]";
|
if(vm->_repr_recursion_set.count(_0)) return "[...]";
|
||||||
const PyDeque &self = _CAST(PyDeque&, _0);
|
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
@ -123,7 +123,7 @@ namespace pkpy
|
|||||||
});
|
});
|
||||||
|
|
||||||
// enables comparison between two deques, == and != are supported
|
// enables comparison between two deques, == and != are supported
|
||||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM *vm, PyVar _0, PyVar _1)
|
vm->bind__eq__(type->as<Type>(), [](VM *vm, PyVar _0, PyVar _1)
|
||||||
{
|
{
|
||||||
const PyDeque &self = _CAST(PyDeque&, _0);
|
const PyDeque &self = _CAST(PyDeque&, _0);
|
||||||
if(!vm->is_user_type<PyDeque>(_0)) return vm->NotImplemented;
|
if(!vm->is_user_type<PyDeque>(_0)) return vm->NotImplemented;
|
||||||
@ -534,13 +534,12 @@ namespace pkpy
|
|||||||
/// @brief marks the deque items for garbage collection
|
/// @brief marks the deque items for garbage collection
|
||||||
void PyDeque::_gc_mark(VM* vm) const
|
void PyDeque::_gc_mark(VM* vm) const
|
||||||
{
|
{
|
||||||
for (PyVar obj : this->dequeItems)
|
for (PyVar obj : this->dequeItems) vm->obj_gc_mark(obj);
|
||||||
PK_OBJ_MARK(obj);
|
|
||||||
}
|
}
|
||||||
/// @brief registers the PyDeque class
|
/// @brief registers the PyDeque class
|
||||||
void add_module_collections(VM *vm)
|
void add_module_collections(VM *vm)
|
||||||
{
|
{
|
||||||
PyVar mod = vm->new_module("collections");
|
PyObject* mod = vm->new_module("collections");
|
||||||
vm->register_user_class<PyDeque>(mod, "deque", VM::tp_object, true);
|
vm->register_user_class<PyDeque>(mod, "deque", VM::tp_object, true);
|
||||||
vm->register_user_class<PyDequeIter>(mod, "_deque_iter");
|
vm->register_user_class<PyDequeIter>(mod, "_deque_iter");
|
||||||
CodeObject_ code = vm->compile(kPythonLibs_collections, "collections.py", EXEC_MODE);
|
CodeObject_ code = vm->compile(kPythonLibs_collections, "collections.py", EXEC_MODE);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
void add_module_csv(VM *vm){
|
void add_module_csv(VM *vm){
|
||||||
PyVar mod = vm->new_module("csv");
|
PyObject* mod = vm->new_module("csv");
|
||||||
|
|
||||||
vm->bind(mod, "reader(csvfile: list[str]) -> list[list]", [](VM* vm, ArgsView args){
|
vm->bind(mod, "reader(csvfile: list[str]) -> list[list]", [](VM* vm, ArgsView args){
|
||||||
const List& csvfile = CAST(List&, args[0]);
|
const List& csvfile = CAST(List&, args[0]);
|
||||||
|
@ -77,7 +77,7 @@ static void patch__eq__(VM* vm, Type cls){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_dataclasses(VM* vm){
|
void add_module_dataclasses(VM* vm){
|
||||||
PyVar mod = vm->new_module("dataclasses");
|
PyObject* mod = vm->new_module("dataclasses");
|
||||||
|
|
||||||
vm->bind_func(mod, "dataclass", 1, [](VM* vm, ArgsView args){
|
vm->bind_func(mod, "dataclass", 1, [](VM* vm, ArgsView args){
|
||||||
vm->check_type(args[0], VM::tp_type);
|
vm->check_type(args[0], VM::tp_type);
|
||||||
|
@ -206,7 +206,7 @@ static double easeInOutBounce( double x ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_easing(VM* vm){
|
void add_module_easing(VM* vm){
|
||||||
PyVar mod = vm->new_module("easing");
|
PyObject* mod = vm->new_module("easing");
|
||||||
|
|
||||||
#define EASE(name) \
|
#define EASE(name) \
|
||||||
vm->bind_func(mod, #name, 1, [](VM* vm, ArgsView args){ \
|
vm->bind_func(mod, #name, 1, [](VM* vm, ArgsView args){ \
|
||||||
|
@ -120,16 +120,14 @@ namespace pkpy{
|
|||||||
}else{
|
}else{
|
||||||
co->consts.push_back(VAR(key));
|
co->consts.push_back(VAR(key));
|
||||||
int index = co->consts.size() - 1;
|
int index = co->consts.size() - 1;
|
||||||
_co_consts_string_dedup_map[std::string(key)] = index;
|
key = co->consts.back().obj_get<Str>().sv();
|
||||||
|
_co_consts_string_dedup_map[key] = index;
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CodeEmitContext::add_const(PyVar v){
|
int CodeEmitContext::add_const(PyVar v){
|
||||||
if(is_type(v, vm->tp_str)){
|
PK_ASSERT(!is_type(v, VM::tp_str))
|
||||||
// warning: should use add_const_string() instead
|
|
||||||
return add_const_string(PK_OBJ_GET(Str, v).sv());
|
|
||||||
}else{
|
|
||||||
// non-string deduplication
|
// non-string deduplication
|
||||||
auto it = _co_consts_nonstring_dedup_map.find(v);
|
auto it = _co_consts_nonstring_dedup_map.find(v);
|
||||||
if(it != _co_consts_nonstring_dedup_map.end()){
|
if(it != _co_consts_nonstring_dedup_map.end()){
|
||||||
@ -141,7 +139,6 @@ namespace pkpy{
|
|||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int CodeEmitContext::add_func_decl(FuncDecl_ decl){
|
int CodeEmitContext::add_func_decl(FuncDecl_ decl){
|
||||||
co->func_decls.push_back(decl);
|
co->func_decls.push_back(decl);
|
||||||
|
@ -16,11 +16,11 @@ namespace pkpy{
|
|||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar Frame::f_closure_try_get(StrName name){
|
PyVar* Frame::f_closure_try_get(StrName name){
|
||||||
if(_callable == nullptr) return nullptr;
|
if(_callable == nullptr) return nullptr;
|
||||||
Function& fn = PK_OBJ_GET(Function, _callable);
|
Function& fn = _callable->as<Function>();
|
||||||
if(fn._closure == nullptr) return nullptr;
|
if(fn._closure == nullptr) return nullptr;
|
||||||
return fn._closure->try_get(name);
|
return fn._closure->try_get_2(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Frame::prepare_jump_exception_handler(ValueStack* _s){
|
int Frame::prepare_jump_exception_handler(ValueStack* _s){
|
||||||
|
@ -15,7 +15,7 @@ struct FileIO {
|
|||||||
|
|
||||||
FileIO(VM* vm, const Str& file, const Str& mode);
|
FileIO(VM* vm, const Str& file, const Str& mode);
|
||||||
void close();
|
void close();
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type);
|
static void _register(VM* vm, PyObject* mod, PyObject* type);
|
||||||
};
|
};
|
||||||
|
|
||||||
static FILE* io_fopen(const char* name, const char* mode){
|
static FILE* io_fopen(const char* name, const char* mode){
|
||||||
@ -53,7 +53,7 @@ unsigned char* _default_import_handler(const char* name, int* out_size){
|
|||||||
return buffer;
|
return buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
void FileIO::_register(VM* vm, PyVar mod, PyVar type){
|
void FileIO::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_func(type, __new__, 3, [](VM* vm, ArgsView args){
|
vm->bind_func(type, __new__, 3, [](VM* vm, ArgsView args){
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
return vm->new_object<FileIO>(cls, vm,
|
return vm->new_object<FileIO>(cls, vm,
|
||||||
@ -138,7 +138,7 @@ void FileIO::close(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_io(VM* vm){
|
void add_module_io(VM* vm){
|
||||||
PyVar mod = vm->new_module("io");
|
PyObject* mod = vm->new_module("io");
|
||||||
vm->register_user_class<FileIO>(mod, "FileIO");
|
vm->register_user_class<FileIO>(mod, "FileIO");
|
||||||
|
|
||||||
mod->attr().set("SEEK_SET", VAR(SEEK_SET));
|
mod->attr().set("SEEK_SET", VAR(SEEK_SET));
|
||||||
@ -153,7 +153,7 @@ void add_module_io(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_os(VM* vm){
|
void add_module_os(VM* vm){
|
||||||
PyVar mod = vm->new_module("os");
|
PyObject* mod = vm->new_module("os");
|
||||||
PyVar path_obj = vm->new_object<DummyInstance>(vm->tp_object);
|
PyVar path_obj = vm->new_object<DummyInstance>(vm->tp_object);
|
||||||
mod->attr().set("path", path_obj);
|
mod->attr().set("path", path_obj);
|
||||||
|
|
||||||
|
36
src/iter.cpp
36
src/iter.cpp
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
void RangeIter::_register(VM* vm, PyVar mod, PyVar type){
|
void RangeIter::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
|
||||||
RangeIter& self = PK_OBJ_GET(RangeIter, _0);
|
RangeIter& self = PK_OBJ_GET(RangeIter, _0);
|
||||||
if(self.current >= self.r.stop) return 0;
|
if(self.current >= self.r.stop) return 0;
|
||||||
vm->s_data.emplace(VM::tp_int, self.current);
|
vm->s_data.emplace(VM::tp_int, self.current);
|
||||||
@ -13,9 +13,9 @@ namespace pkpy{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void RangeIterR::_register(VM* vm, PyVar mod, PyVar type){
|
void RangeIterR::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
|
||||||
RangeIterR& self = PK_OBJ_GET(RangeIterR, _0);
|
RangeIterR& self = PK_OBJ_GET(RangeIterR, _0);
|
||||||
if(self.current <= self.r.stop) return 0;
|
if(self.current <= self.r.stop) return 0;
|
||||||
vm->s_data.emplace(VM::tp_int, self.current);
|
vm->s_data.emplace(VM::tp_int, self.current);
|
||||||
@ -24,9 +24,9 @@ namespace pkpy{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrayIter::_register(VM* vm, PyVar mod, PyVar type){
|
void ArrayIter::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
|
||||||
ArrayIter& self = _CAST(ArrayIter&, _0);
|
ArrayIter& self = _CAST(ArrayIter&, _0);
|
||||||
if(self.current == self.end) return 0;
|
if(self.current == self.end) return 0;
|
||||||
vm->s_data.push(*self.current++);
|
vm->s_data.push(*self.current++);
|
||||||
@ -34,9 +34,9 @@ namespace pkpy{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringIter::_register(VM* vm, PyVar mod, PyVar type){
|
void StringIter::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
|
||||||
StringIter& self = _CAST(StringIter&, _0);
|
StringIter& self = _CAST(StringIter&, _0);
|
||||||
Str& s = PK_OBJ_GET(Str, self.ref);
|
Str& s = PK_OBJ_GET(Str, self.ref);
|
||||||
if(self.i == s.size) return 0;
|
if(self.i == s.size) return 0;
|
||||||
@ -99,9 +99,9 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Generator::_register(VM* vm, PyVar mod, PyVar type){
|
void Generator::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
|
||||||
Generator& self = _CAST(Generator&, _0);
|
Generator& self = _CAST(Generator&, _0);
|
||||||
PyVar retval = self.next(vm);
|
PyVar retval = self.next(vm);
|
||||||
if(retval == vm->StopIteration) return 0;
|
if(retval == vm->StopIteration) return 0;
|
||||||
@ -110,9 +110,9 @@ namespace pkpy{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DictItemsIter::_register(VM *vm, PyVar mod, PyVar type){
|
void DictItemsIter::_register(VM *vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
|
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
|
||||||
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
|
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
|
||||||
DictItemsIter& self = _CAST(DictItemsIter&, _0);
|
DictItemsIter& self = _CAST(DictItemsIter&, _0);
|
||||||
Dict& d = PK_OBJ_GET(Dict, self.ref);
|
Dict& d = PK_OBJ_GET(Dict, self.ref);
|
||||||
if(self.i == -1) return 0;
|
if(self.i == -1) return 0;
|
||||||
|
@ -3,14 +3,14 @@
|
|||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
#define BIND_VEC_VEC_OP(D, name, op) \
|
#define BIND_VEC_VEC_OP(D, name, op) \
|
||||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
vm->bind##name(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||||
Vec##D self = _CAST(Vec##D, _0); \
|
Vec##D self = _CAST(Vec##D, _0); \
|
||||||
Vec##D other = CAST(Vec##D, _1); \
|
Vec##D other = CAST(Vec##D, _1); \
|
||||||
return VAR(self op other); \
|
return VAR(self op other); \
|
||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_VEC_FLOAT_OP(D, name, op) \
|
#define BIND_VEC_FLOAT_OP(D, name, op) \
|
||||||
vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
vm->bind##name(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||||
Vec##D self = _CAST(Vec##D, _0); \
|
Vec##D self = _CAST(Vec##D, _0); \
|
||||||
f64 other = CAST(f64, _1); \
|
f64 other = CAST(f64, _1); \
|
||||||
return VAR(self op other); \
|
return VAR(self op other); \
|
||||||
@ -30,7 +30,7 @@ namespace pkpy{
|
|||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_VEC_MUL_OP(D) \
|
#define BIND_VEC_MUL_OP(D) \
|
||||||
vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
vm->bind__mul__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||||
Vec##D self = _CAST(Vec##D, _0); \
|
Vec##D self = _CAST(Vec##D, _0); \
|
||||||
if(vm->is_user_type<Vec##D>(_1)){ \
|
if(vm->is_user_type<Vec##D>(_1)){ \
|
||||||
Vec##D other = _CAST(Vec##D, _1); \
|
Vec##D other = _CAST(Vec##D, _1); \
|
||||||
@ -44,14 +44,14 @@ namespace pkpy{
|
|||||||
f64 other = CAST(f64, args[1]); \
|
f64 other = CAST(f64, args[1]); \
|
||||||
return VAR(self * other); \
|
return VAR(self * other); \
|
||||||
}); \
|
}); \
|
||||||
vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
vm->bind__truediv__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||||
Vec##D self = _CAST(Vec##D, _0); \
|
Vec##D self = _CAST(Vec##D, _0); \
|
||||||
f64 other = CAST(f64, _1); \
|
f64 other = CAST(f64, _1); \
|
||||||
return VAR(self / other); \
|
return VAR(self / other); \
|
||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_VEC_GETITEM(D) \
|
#define BIND_VEC_GETITEM(D) \
|
||||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj, PyVar index){ \
|
vm->bind__getitem__(type->as<Type>(), [](VM* vm, PyVar obj, PyVar index){ \
|
||||||
Vec##D self = _CAST(Vec##D, obj); \
|
Vec##D self = _CAST(Vec##D, obj); \
|
||||||
i64 i = CAST(i64, index); \
|
i64 i = CAST(i64, index); \
|
||||||
if(i < 0 || i >= D) vm->IndexError("index out of range"); \
|
if(i < 0 || i >= D) vm->IndexError("index out of range"); \
|
||||||
@ -59,7 +59,7 @@ namespace pkpy{
|
|||||||
});
|
});
|
||||||
|
|
||||||
#define BIND_SSO_VEC_COMMON(D) \
|
#define BIND_SSO_VEC_COMMON(D) \
|
||||||
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
|
vm->bind__eq__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){ \
|
||||||
Vec##D self = _CAST(Vec##D, _0); \
|
Vec##D self = _CAST(Vec##D, _0); \
|
||||||
if(!vm->is_user_type<Vec##D>(_1)) return vm->NotImplemented; \
|
if(!vm->is_user_type<Vec##D>(_1)) return vm->NotImplemented; \
|
||||||
Vec##D other = _CAST(Vec##D, _1); \
|
Vec##D other = _CAST(Vec##D, _1); \
|
||||||
@ -127,7 +127,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return Vec2(output_x, output_y);
|
return Vec2(output_x, output_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vec2::_register(VM* vm, PyVar mod, PyVar type){
|
void Vec2::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
type->attr().set("ZERO", vm->new_user_object<Vec2>(0, 0));
|
type->attr().set("ZERO", vm->new_user_object<Vec2>(0, 0));
|
||||||
type->attr().set("ONE", vm->new_user_object<Vec2>(1, 1));
|
type->attr().set("ONE", vm->new_user_object<Vec2>(1, 1));
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return VAR(val);
|
return VAR(val);
|
||||||
}, {}, BindType::STATICMETHOD);
|
}, {}, BindType::STATICMETHOD);
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str{
|
||||||
Vec2 self = _CAST(Vec2, obj);
|
Vec2 self = _CAST(Vec2, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
@ -190,7 +190,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
BIND_SSO_VEC_COMMON(2)
|
BIND_SSO_VEC_COMMON(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vec3::_register(VM* vm, PyVar mod, PyVar type){
|
void Vec3::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
type->attr().set("ZERO", vm->new_user_object<Vec3>(0, 0, 0));
|
type->attr().set("ZERO", vm->new_user_object<Vec3>(0, 0, 0));
|
||||||
type->attr().set("ONE", vm->new_user_object<Vec3>(1, 1, 1));
|
type->attr().set("ONE", vm->new_user_object<Vec3>(1, 1, 1));
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->new_object<Vec3>(PK_OBJ_GET(Type, args[0]), x, y, z);
|
return vm->new_object<Vec3>(PK_OBJ_GET(Type, args[0]), x, y, z);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str{
|
||||||
Vec3 self = _CAST(Vec3, obj);
|
Vec3 self = _CAST(Vec3, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
@ -225,7 +225,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
BIND_SSO_VEC_COMMON(3)
|
BIND_SSO_VEC_COMMON(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Vec4::_register(VM* vm, PyVar mod, PyVar type){
|
void Vec4::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
PY_STRUCT_LIKE(Vec4)
|
PY_STRUCT_LIKE(Vec4)
|
||||||
|
|
||||||
type->attr().set("ZERO", vm->new_user_object<Vec4>(0, 0, 0, 0));
|
type->attr().set("ZERO", vm->new_user_object<Vec4>(0, 0, 0, 0));
|
||||||
@ -239,7 +239,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->new_object<Vec4>(PK_OBJ_GET(Type, args[0]), x, y, z, w);
|
return vm->new_object<Vec4>(PK_OBJ_GET(Type, args[0]), x, y, z, w);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str{
|
||||||
Vec4 self = _CAST(Vec4&, obj);
|
Vec4 self = _CAST(Vec4&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
@ -270,7 +270,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
#undef BIND_VEC_FUNCTION_1
|
#undef BIND_VEC_FUNCTION_1
|
||||||
#undef BIND_VEC_GETITEM
|
#undef BIND_VEC_GETITEM
|
||||||
|
|
||||||
void Mat3x3::_register(VM* vm, PyVar mod, PyVar type){
|
void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
PY_STRUCT_LIKE(Mat3x3)
|
PY_STRUCT_LIKE(Mat3x3)
|
||||||
|
|
||||||
vm->bind_func(type, __new__, -1, [](VM* vm, ArgsView args){
|
vm->bind_func(type, __new__, -1, [](VM* vm, ArgsView args){
|
||||||
@ -298,7 +298,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
|
vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str{
|
||||||
const Mat3x3& self = _CAST(Mat3x3&, obj);
|
const Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||||
SStream ss;
|
SStream ss;
|
||||||
ss.setprecision(3);
|
ss.setprecision(3);
|
||||||
@ -308,7 +308,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__getitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj, PyVar index){
|
vm->bind__getitem__(type->as<Type>(), [](VM* vm, PyVar obj, PyVar index){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, obj);
|
Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||||
Tuple& t = CAST(Tuple&, index);
|
Tuple& t = CAST(Tuple&, index);
|
||||||
if(t.size() != 2){
|
if(t.size() != 2){
|
||||||
@ -322,7 +322,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return VAR(self.m[i][j]);
|
return VAR(self.m[i][j]);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__setitem__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj, PyVar index, PyVar value){
|
vm->bind__setitem__(type->as<Type>(), [](VM* vm, PyVar obj, PyVar index, PyVar value){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, obj);
|
Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||||
const Tuple& t = CAST(Tuple&, index);
|
const Tuple& t = CAST(Tuple&, index);
|
||||||
if(t.size() != 2){
|
if(t.size() != 2){
|
||||||
@ -346,19 +346,19 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
vm->bind_field(type, "_32", &Mat3x3::_32);
|
vm->bind_field(type, "_32", &Mat3x3::_32);
|
||||||
vm->bind_field(type, "_33", &Mat3x3::_33);
|
vm->bind_field(type, "_33", &Mat3x3::_33);
|
||||||
|
|
||||||
vm->bind__add__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
vm->bind__add__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||||
Mat3x3& other = CAST(Mat3x3&, _1);
|
Mat3x3& other = CAST(Mat3x3&, _1);
|
||||||
return vm->new_user_object<Mat3x3>(self + other);
|
return vm->new_user_object<Mat3x3>(self + other);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__sub__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
vm->bind__sub__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||||
Mat3x3& other = CAST(Mat3x3&, _1);
|
Mat3x3& other = CAST(Mat3x3&, _1);
|
||||||
return vm->new_user_object<Mat3x3>(self - other);
|
return vm->new_user_object<Mat3x3>(self - other);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
vm->bind__mul__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||||
f64 other = CAST_F(_1);
|
f64 other = CAST_F(_1);
|
||||||
return vm->new_user_object<Mat3x3>(self * other);
|
return vm->new_user_object<Mat3x3>(self * other);
|
||||||
@ -370,13 +370,13 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->new_user_object<Mat3x3>(self * other);
|
return vm->new_user_object<Mat3x3>(self * other);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
vm->bind__truediv__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||||
f64 other = CAST_F(_1);
|
f64 other = CAST_F(_1);
|
||||||
return vm->new_user_object<Mat3x3>(self / other);
|
return vm->new_user_object<Mat3x3>(self / other);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__matmul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){
|
vm->bind__matmul__(type->as<Type>(), [](VM* vm, PyVar _0, PyVar _1){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, _0);
|
Mat3x3& self = _CAST(Mat3x3&, _0);
|
||||||
if(vm->is_user_type<Mat3x3>(_1)){
|
if(vm->is_user_type<Mat3x3>(_1)){
|
||||||
const Mat3x3& other = _CAST(Mat3x3&, _1);
|
const Mat3x3& other = _CAST(Mat3x3&, _1);
|
||||||
@ -411,7 +411,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
return vm->new_user_object<Mat3x3>(self.transpose());
|
return vm->new_user_object<Mat3x3>(self.transpose());
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind__invert__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
|
vm->bind__invert__(type->as<Type>(), [](VM* vm, PyVar obj){
|
||||||
Mat3x3& self = _CAST(Mat3x3&, obj);
|
Mat3x3& self = _CAST(Mat3x3&, obj);
|
||||||
Mat3x3 ret;
|
Mat3x3 ret;
|
||||||
if(!self.inverse(ret)) vm->ValueError("matrix is not invertible");
|
if(!self.inverse(ret)) vm->ValueError("matrix is not invertible");
|
||||||
@ -548,7 +548,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
|
|||||||
|
|
||||||
|
|
||||||
void add_module_linalg(VM* vm){
|
void add_module_linalg(VM* vm){
|
||||||
PyVar linalg = vm->new_module("linalg");
|
PyObject* linalg = vm->new_module("linalg");
|
||||||
|
|
||||||
vm->register_user_class<Vec2>(linalg, "vec2", VM::tp_object);
|
vm->register_user_class<Vec2>(linalg, "vec2", VM::tp_object);
|
||||||
vm->register_user_class<Vec3>(linalg, "vec3", VM::tp_object);
|
vm->register_user_class<Vec3>(linalg, "vec3", VM::tp_object);
|
||||||
|
@ -26,7 +26,7 @@ struct PyStructTime{
|
|||||||
tm_isdst = tm->tm_isdst;
|
tm_isdst = tm->tm_isdst;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
PY_READONLY_FIELD(PyStructTime, "tm_year", tm_year);
|
PY_READONLY_FIELD(PyStructTime, "tm_year", tm_year);
|
||||||
PY_READONLY_FIELD(PyStructTime, "tm_mon", tm_mon);
|
PY_READONLY_FIELD(PyStructTime, "tm_mon", tm_mon);
|
||||||
PY_READONLY_FIELD(PyStructTime, "tm_mday", tm_mday);
|
PY_READONLY_FIELD(PyStructTime, "tm_mday", tm_mday);
|
||||||
@ -40,7 +40,7 @@ struct PyStructTime{
|
|||||||
};
|
};
|
||||||
|
|
||||||
void add_module_time(VM* vm){
|
void add_module_time(VM* vm){
|
||||||
PyVar mod = vm->new_module("time");
|
PyObject* mod = vm->new_module("time");
|
||||||
vm->register_user_class<PyStructTime>(mod, "struct_time");
|
vm->register_user_class<PyStructTime>(mod, "struct_time");
|
||||||
|
|
||||||
vm->bind_func(mod, "time", 0, [](VM* vm, ArgsView args) {
|
vm->bind_func(mod, "time", 0, [](VM* vm, ArgsView args) {
|
||||||
@ -67,12 +67,12 @@ void add_module_time(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_sys(VM* vm){
|
void add_module_sys(VM* vm){
|
||||||
PyVar mod = vm->new_module("sys");
|
PyObject* mod = vm->new_module("sys");
|
||||||
vm->setattr(mod, "version", VAR(PK_VERSION));
|
vm->setattr(mod, "version", VAR(PK_VERSION));
|
||||||
vm->setattr(mod, "platform", VAR(kPlatformStrings[PK_SYS_PLATFORM]));
|
vm->setattr(mod, "platform", VAR(kPlatformStrings[PK_SYS_PLATFORM]));
|
||||||
|
|
||||||
PyVar stdout_ = vm->new_object<DummyInstance>(vm->tp_object);
|
PyObject* stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||||
PyVar stderr_ = vm->new_object<DummyInstance>(vm->tp_object);
|
PyObject* stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
|
||||||
vm->setattr(mod, "stdout", stdout_);
|
vm->setattr(mod, "stdout", stdout_);
|
||||||
vm->setattr(mod, "stderr", stderr_);
|
vm->setattr(mod, "stderr", stderr_);
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ void add_module_sys(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_json(VM* vm){
|
void add_module_json(VM* vm){
|
||||||
PyVar mod = vm->new_module("json");
|
PyObject* mod = vm->new_module("json");
|
||||||
vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args) {
|
vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args) {
|
||||||
std::string_view sv;
|
std::string_view sv;
|
||||||
if(is_type(args[0], vm->tp_bytes)){
|
if(is_type(args[0], vm->tp_bytes)){
|
||||||
@ -109,7 +109,7 @@ void add_module_json(VM* vm){
|
|||||||
|
|
||||||
// https://docs.python.org/3.5/library/math.html
|
// https://docs.python.org/3.5/library/math.html
|
||||||
void add_module_math(VM* vm){
|
void add_module_math(VM* vm){
|
||||||
PyVar mod = vm->new_module("math");
|
PyObject* mod = vm->new_module("math");
|
||||||
mod->attr().set("pi", VAR(3.1415926535897932384));
|
mod->attr().set("pi", VAR(3.1415926535897932384));
|
||||||
mod->attr().set("e" , VAR(2.7182818284590452354));
|
mod->attr().set("e" , VAR(2.7182818284590452354));
|
||||||
mod->attr().set("inf", VAR(std::numeric_limits<double>::infinity()));
|
mod->attr().set("inf", VAR(std::numeric_limits<double>::infinity()));
|
||||||
@ -196,7 +196,7 @@ void add_module_math(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_traceback(VM* vm){
|
void add_module_traceback(VM* vm){
|
||||||
PyVar mod = vm->new_module("traceback");
|
PyObject* mod = vm->new_module("traceback");
|
||||||
vm->bind_func(mod, "print_exc", 0, [](VM* vm, ArgsView args) {
|
vm->bind_func(mod, "print_exc", 0, [](VM* vm, ArgsView args) {
|
||||||
if(vm->__last_exception==nullptr) vm->ValueError("no exception");
|
if(vm->__last_exception==nullptr) vm->ValueError("no exception");
|
||||||
Exception& e = _CAST(Exception&, vm->__last_exception);
|
Exception& e = _CAST(Exception&, vm->__last_exception);
|
||||||
@ -212,7 +212,7 @@ void add_module_traceback(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_dis(VM* vm){
|
void add_module_dis(VM* vm){
|
||||||
PyVar mod = vm->new_module("dis");
|
PyObject* mod = vm->new_module("dis");
|
||||||
|
|
||||||
vm->bind_func(mod, "dis", 1, [](VM* vm, ArgsView args) {
|
vm->bind_func(mod, "dis", 1, [](VM* vm, ArgsView args) {
|
||||||
CodeObject_ code;
|
CodeObject_ code;
|
||||||
@ -230,12 +230,12 @@ void add_module_dis(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_gc(VM* vm){
|
void add_module_gc(VM* vm){
|
||||||
PyVar mod = vm->new_module("gc");
|
PyObject* mod = vm->new_module("gc");
|
||||||
vm->bind_func(mod, "collect", 0, PK_LAMBDA(VAR(vm->heap.collect())));
|
vm->bind_func(mod, "collect", 0, PK_LAMBDA(VAR(vm->heap.collect())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_module_enum(VM* vm){
|
void add_module_enum(VM* vm){
|
||||||
PyVar mod = vm->new_module("enum");
|
PyObject* mod = vm->new_module("enum");
|
||||||
CodeObject_ code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE);
|
CodeObject_ code = vm->compile(kPythonLibs__enum, "enum.py", EXEC_MODE);
|
||||||
vm->_exec(code, mod);
|
vm->_exec(code, mod);
|
||||||
PyVar Enum = mod->attr("Enum");
|
PyVar Enum = mod->attr("Enum");
|
||||||
@ -253,7 +253,7 @@ void add_module_enum(VM* vm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module___builtins(VM* vm){
|
void add_module___builtins(VM* vm){
|
||||||
PyVar mod = vm->new_module("__builtins");
|
PyObject* mod = vm->new_module("__builtins");
|
||||||
|
|
||||||
vm->bind_func(mod, "next", 1, [](VM* vm, ArgsView args){
|
vm->bind_func(mod, "next", 1, [](VM* vm, ArgsView args){
|
||||||
return vm->py_next(args[0]);
|
return vm->py_next(args[0]);
|
||||||
@ -284,7 +284,7 @@ struct _LpGuard{
|
|||||||
struct LineProfilerW{
|
struct LineProfilerW{
|
||||||
LineProfiler profiler;
|
LineProfiler profiler;
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_func(type, __new__, 1, [](VM* vm, ArgsView args){
|
vm->bind_func(type, __new__, 1, [](VM* vm, ArgsView args){
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
return vm->new_object<LineProfilerW>(cls);
|
return vm->new_object<LineProfilerW>(cls);
|
||||||
@ -333,7 +333,7 @@ _LpGuard::~_LpGuard(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
void add_module_line_profiler(VM *vm){
|
void add_module_line_profiler(VM *vm){
|
||||||
PyVar mod = vm->new_module("line_profiler");
|
PyObject* mod = vm->new_module("line_profiler");
|
||||||
vm->register_user_class<LineProfilerW>(mod, "LineProfiler");
|
vm->register_user_class<LineProfilerW>(mod, "LineProfiler");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "pocketpy/obj.h"
|
#include "pocketpy/obj.h"
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
PyVar::PyVar(PyObject* p): PyVar(p->type, p) {}
|
||||||
|
|
||||||
bool Bytes::operator==(const Bytes& rhs) const{
|
bool Bytes::operator==(const Bytes& rhs) const{
|
||||||
if(_size != rhs._size) return false;
|
if(_size != rhs._size) return false;
|
||||||
for(int i=0; i<_size; i++) if(_data[i] != rhs._data[i]) return false;
|
for(int i=0; i<_size; i++) if(_data[i] != rhs._data[i]) return false;
|
||||||
|
@ -10,8 +10,8 @@ template<typename T>
|
|||||||
PyVar PyArrayGetItem(VM* vm, PyVar _0, PyVar _1){
|
PyVar PyArrayGetItem(VM* vm, PyVar _0, PyVar _1){
|
||||||
static_assert(std::is_same_v<T, List> || std::is_same_v<T, Tuple>);
|
static_assert(std::is_same_v<T, List> || std::is_same_v<T, Tuple>);
|
||||||
const T& self = _CAST(T&, _0);
|
const T& self = _CAST(T&, _0);
|
||||||
i64 index;
|
if(is_int(_1)){
|
||||||
if(try_cast_int(_1, &index)){
|
i64 index = _1.as<i64>();
|
||||||
index = vm->normalized_index(index, self.size());
|
index = vm->normalized_index(index, self.size());
|
||||||
return self[index];
|
return self[index];
|
||||||
}
|
}
|
||||||
@ -29,14 +29,12 @@ PyVar PyArrayGetItem(VM* vm, PyVar _0, PyVar _1){
|
|||||||
void __init_builtins(VM* _vm) {
|
void __init_builtins(VM* _vm) {
|
||||||
#define BIND_NUM_ARITH_OPT(name, op) \
|
#define BIND_NUM_ARITH_OPT(name, op) \
|
||||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||||
i64 val; \
|
if(is_int(rhs)) return VAR(_CAST(i64, lhs) op _CAST(i64, rhs)); \
|
||||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(i64, lhs) op val); \
|
|
||||||
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
|
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
|
||||||
return vm->NotImplemented; \
|
return vm->NotImplemented; \
|
||||||
}); \
|
}); \
|
||||||
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||||
i64 val; \
|
if(is_int(rhs)) return VAR(_CAST(f64, lhs) op _CAST(i64, rhs)); \
|
||||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(f64, lhs) op val); \
|
|
||||||
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
|
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
|
||||||
return vm->NotImplemented; \
|
return vm->NotImplemented; \
|
||||||
});
|
});
|
||||||
@ -49,14 +47,12 @@ void __init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
#define BIND_NUM_LOGICAL_OPT(name, op) \
|
#define BIND_NUM_LOGICAL_OPT(name, op) \
|
||||||
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||||
i64 val; \
|
if(is_int(rhs)) return VAR(_CAST(i64, lhs) op _CAST(i64, rhs)); \
|
||||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(i64, lhs) op val); \
|
|
||||||
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
|
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
|
||||||
return vm->NotImplemented; \
|
return vm->NotImplemented; \
|
||||||
}); \
|
}); \
|
||||||
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
|
||||||
i64 val; \
|
if(is_int(rhs)) return VAR(_CAST(f64, lhs) op _CAST(i64, rhs)); \
|
||||||
if(try_cast_int(rhs, &val)) return VAR(_CAST(f64, lhs) op val); \
|
|
||||||
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
|
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
|
||||||
return vm->NotImplemented; \
|
return vm->NotImplemented; \
|
||||||
});
|
});
|
||||||
@ -79,15 +75,15 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_func(_vm->builtins, "super", -1, [](VM* vm, ArgsView args) {
|
_vm->bind_func(_vm->builtins, "super", -1, [](VM* vm, ArgsView args) {
|
||||||
PyVar class_arg = nullptr;
|
PyObject* class_arg = nullptr;
|
||||||
PyVar self_arg = nullptr;
|
PyVar self_arg = nullptr;
|
||||||
if(args.size() == 2){
|
if(args.size() == 2){
|
||||||
class_arg = args[0];
|
class_arg = args[0].get();
|
||||||
self_arg = args[1];
|
self_arg = args[1];
|
||||||
}else if(args.size() == 0){
|
}else if(args.size() == 0){
|
||||||
Frame* frame = &vm->callstack.top();
|
Frame* frame = &vm->callstack.top();
|
||||||
if(frame->_callable != nullptr){
|
if(frame->_callable != nullptr){
|
||||||
class_arg = PK_OBJ_GET(Function, frame->_callable)._class;
|
class_arg = frame->_callable->as<Function>()._class;
|
||||||
if(frame->_locals.size() > 0) self_arg = frame->_locals[0];
|
if(frame->_locals.size() > 0) self_arg = frame->_locals[0];
|
||||||
}
|
}
|
||||||
if(class_arg == nullptr || self_arg == nullptr){
|
if(class_arg == nullptr || self_arg == nullptr){
|
||||||
@ -97,7 +93,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
vm->TypeError("super() takes 0 or 2 arguments");
|
vm->TypeError("super() takes 0 or 2 arguments");
|
||||||
}
|
}
|
||||||
vm->check_type(class_arg, vm->tp_type);
|
vm->check_type(class_arg, vm->tp_type);
|
||||||
Type type = PK_OBJ_GET(Type, class_arg);
|
Type type = class_arg->as<Type>();
|
||||||
if(!vm->isinstance(self_arg, type)){
|
if(!vm->isinstance(self_arg, type)){
|
||||||
StrName _0 = _type_name(vm, vm->_tp(self_arg));
|
StrName _0 = _type_name(vm, vm->_tp(self_arg));
|
||||||
StrName _1 = _type_name(vm, type);
|
StrName _1 = _type_name(vm, type);
|
||||||
@ -123,7 +119,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
Tuple& types = _CAST(Tuple&, args[1]);
|
Tuple& types = _CAST(Tuple&, args[1]);
|
||||||
for(PyVar type : types){
|
for(PyVar type : types){
|
||||||
vm->check_type(type, vm->tp_type);
|
vm->check_type(type, vm->tp_type);
|
||||||
if(vm->isinstance(args[0], PK_OBJ_GET(Type, type))) return vm->True;
|
if(vm->isinstance(args[0], type->as<Type>())) return vm->True;
|
||||||
}
|
}
|
||||||
return vm->False;
|
return vm->False;
|
||||||
}
|
}
|
||||||
@ -139,7 +135,7 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_func(_vm->builtins, "globals", 0, [](VM* vm, ArgsView args) {
|
_vm->bind_func(_vm->builtins, "globals", 0, [](VM* vm, ArgsView args) {
|
||||||
PyVar mod = vm->callstack.top()._module;
|
PyObject* mod = vm->callstack.top()._module;
|
||||||
return VAR(MappingProxy(mod));
|
return VAR(MappingProxy(mod));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -395,8 +391,9 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
auto py_number_pow = [](VM* vm, PyVar _0, PyVar _1) {
|
auto py_number_pow = [](VM* vm, PyVar _0, PyVar _1) {
|
||||||
i64 lhs, rhs;
|
if(is_int(_0) && is_int(_1)){
|
||||||
if(try_cast_int(_0, &lhs) && try_cast_int(_1, &rhs)){
|
i64 lhs = _CAST(i64, _0);
|
||||||
|
i64 rhs = _CAST(i64, _1);
|
||||||
if(rhs < 0) {
|
if(rhs < 0) {
|
||||||
if(lhs == 0) vm->ZeroDivisionError("0.0 cannot be raised to a negative power");
|
if(lhs == 0) vm->ZeroDivisionError("0.0 cannot be raised to a negative power");
|
||||||
return VAR((f64)std::pow(lhs, rhs));
|
return VAR((f64)std::pow(lhs, rhs));
|
||||||
@ -1484,12 +1481,12 @@ void __init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// tp_exception
|
// tp_exception
|
||||||
_vm->bind_func(VM::tp_exception, __new__, -1, [](VM* vm, ArgsView args){
|
_vm->bind_func(VM::tp_exception, __new__, -1, [](VM* vm, ArgsView args) -> PyVar{
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
StrName cls_name = _type_name(vm, cls);
|
StrName cls_name = _type_name(vm, cls);
|
||||||
PyVar e_obj = vm->new_object<Exception>(cls, cls_name);
|
PyObject* e_obj = vm->heap.gcnew<Exception>(cls, cls_name);
|
||||||
e_obj->_enable_instance_dict();
|
e_obj->_enable_instance_dict();
|
||||||
PK_OBJ_GET(Exception, e_obj)._self = e_obj;
|
e_obj->as<Exception>()._self = e_obj;
|
||||||
return e_obj;
|
return e_obj;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1560,7 +1557,7 @@ void VM::__post_init_builtin_types(){
|
|||||||
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
|
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
|
||||||
return VAR(info.name.sv());
|
return VAR(info.name.sv());
|
||||||
});
|
});
|
||||||
bind_property(_t(tp_type), "__module__", [](VM* vm, ArgsView args){
|
bind_property(_t(tp_type), "__module__", [](VM* vm, ArgsView args) -> PyVar{
|
||||||
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
|
const PyTypeInfo& info = vm->_all_types[PK_OBJ_GET(Type, args[0])];
|
||||||
if(info.mod == nullptr) return vm->None;
|
if(info.mod == nullptr) return vm->None;
|
||||||
return info.mod;
|
return info.mod;
|
||||||
@ -1591,7 +1588,7 @@ void VM::__post_init_builtin_types(){
|
|||||||
|
|
||||||
bind_property(_t(tp_object), "__dict__", [](VM* vm, ArgsView args){
|
bind_property(_t(tp_object), "__dict__", [](VM* vm, ArgsView args){
|
||||||
if(is_tagged(args[0]) || !args[0]->is_attr_valid()) return vm->None;
|
if(is_tagged(args[0]) || !args[0]->is_attr_valid()) return vm->None;
|
||||||
return VAR(MappingProxy(args[0]));
|
return VAR(MappingProxy(args[0].get()));
|
||||||
});
|
});
|
||||||
|
|
||||||
bind(builtins, "print(*args, sep=' ', end='\\n')", [](VM* vm, ArgsView args) {
|
bind(builtins, "print(*args, sep=' ', end='\\n')", [](VM* vm, ArgsView args) {
|
||||||
|
@ -48,8 +48,8 @@ static PyVar stack_item(VM* vm, int index){
|
|||||||
vm->__c.error = e.self(); \
|
vm->__c.error = e.self(); \
|
||||||
return false; \
|
return false; \
|
||||||
} catch(const std::exception& re){ \
|
} catch(const std::exception& re){ \
|
||||||
PyVar e_t = vm->_t(vm->tp_exception); \
|
PyObject* e_t = vm->_t(vm->tp_exception); \
|
||||||
vm->__c.error = vm->call(e_t, VAR(re.what())); \
|
vm->__c.error = vm->call(e_t, VAR(re.what())).get(); \
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,12 +76,12 @@ bool pkpy_exec_2(pkpy_vm* vm_handle, const char* source, const char* filename, i
|
|||||||
VM* vm = (VM*) vm_handle;
|
VM* vm = (VM*) vm_handle;
|
||||||
PK_ASSERT_NO_ERROR()
|
PK_ASSERT_NO_ERROR()
|
||||||
PyVar res;
|
PyVar res;
|
||||||
PyVar mod;
|
PyObject* mod;
|
||||||
PK_PROTECTED(
|
PK_PROTECTED(
|
||||||
if(module == nullptr){
|
if(module == nullptr){
|
||||||
mod = vm->_main;
|
mod = vm->_main;
|
||||||
}else{
|
}else{
|
||||||
mod = vm->_modules[module]; // may raise
|
mod = vm->_modules[module].get(); // may raise
|
||||||
}
|
}
|
||||||
CodeObject_ code = vm->compile(source, filename, (CompileMode)mode);
|
CodeObject_ code = vm->compile(source, filename, (CompileMode)mode);
|
||||||
res = vm->_exec(code, mod);
|
res = vm->_exec(code, mod);
|
||||||
@ -342,7 +342,7 @@ static PyVar c_function_wrapper(VM* vm, ArgsView args) {
|
|||||||
|
|
||||||
// propagate_if_errored
|
// propagate_if_errored
|
||||||
if (vm->__c.error != nullptr){
|
if (vm->__c.error != nullptr){
|
||||||
PyVar e_obj = PK_OBJ_GET(Exception, vm->__c.error).self();
|
PyObject* e_obj = vm->__c.error;
|
||||||
vm->__c.error = nullptr;
|
vm->__c.error = nullptr;
|
||||||
vm->_error(e_obj);
|
vm->_error(e_obj);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -370,8 +370,8 @@ bool pkpy_push_module(pkpy_vm* vm_handle, const char* name) {
|
|||||||
VM* vm = (VM*) vm_handle;
|
VM* vm = (VM*) vm_handle;
|
||||||
PK_ASSERT_NO_ERROR()
|
PK_ASSERT_NO_ERROR()
|
||||||
PK_PROTECTED(
|
PK_PROTECTED(
|
||||||
PyVar module = vm->new_module(name);
|
PyObject* module = vm->new_module(name);
|
||||||
vm->s_data.push(module);
|
vm->s_data.emplace(module);
|
||||||
)
|
)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -511,7 +511,7 @@ bool pkpy_error(pkpy_vm* vm_handle, const char* name, pkpy_CString message) {
|
|||||||
std::cerr << "[warning] pkpy_error(): " << Str(name).escape() << " not found, fallback to 'Exception'" << std::endl;
|
std::cerr << "[warning] pkpy_error(): " << Str(name).escape() << " not found, fallback to 'Exception'" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm->__c.error = vm->call(e_t, VAR(message));
|
vm->__c.error = vm->call(e_t, VAR(message)).get();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,7 +524,7 @@ bool pkpy_clear_error(pkpy_vm* vm_handle, char** message) {
|
|||||||
VM* vm = (VM*) vm_handle;
|
VM* vm = (VM*) vm_handle;
|
||||||
// no error
|
// no error
|
||||||
if (vm->__c.error == nullptr) return false;
|
if (vm->__c.error == nullptr) return false;
|
||||||
Exception& e = PK_OBJ_GET(Exception, vm->__c.error);
|
Exception& e = vm->__c.error->as<Exception>();
|
||||||
if (message != nullptr)
|
if (message != nullptr)
|
||||||
*message = strdup(e.summary().c_str());
|
*message = strdup(e.summary().c_str());
|
||||||
else
|
else
|
||||||
|
@ -133,7 +133,7 @@ struct Random{
|
|||||||
gen.seed((uint32_t)count);
|
gen.seed((uint32_t)count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _register(VM* vm, PyVar mod, PyVar type){
|
static void _register(VM* vm, PyObject* mod, PyObject* type){
|
||||||
vm->bind_func(type, __new__, 1, [](VM* vm, ArgsView args){
|
vm->bind_func(type, __new__, 1, [](VM* vm, ArgsView args){
|
||||||
Type cls = PK_OBJ_GET(Type, args[0]);
|
Type cls = PK_OBJ_GET(Type, args[0]);
|
||||||
return vm->new_object<Random>(cls);
|
return vm->new_object<Random>(cls);
|
||||||
@ -215,7 +215,7 @@ struct Random{
|
|||||||
};
|
};
|
||||||
|
|
||||||
void add_module_random(VM* vm){
|
void add_module_random(VM* vm){
|
||||||
PyVar mod = vm->new_module("random");
|
PyObject* mod = vm->new_module("random");
|
||||||
vm->register_user_class<Random>(mod, "Random");
|
vm->register_user_class<Random>(mod, "Random");
|
||||||
PyVar instance = vm->new_user_object<Random>();
|
PyVar instance = vm->new_user_object<Random>();
|
||||||
mod->attr().set("seed", vm->getattr(instance, "seed"));
|
mod->attr().set("seed", vm->getattr(instance, "seed"));
|
||||||
|
15
src/str.cpp
15
src/str.cpp
@ -376,8 +376,8 @@ int utf8len(unsigned char c, bool suppress){
|
|||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, uint16_t, std::less<>>& StrName::_interned(){
|
std::map<std::string_view, uint16_t>& StrName::_interned(){
|
||||||
static std::map<std::string, uint16_t, std::less<>> interned;
|
static std::map<std::string_view, uint16_t> interned;
|
||||||
return interned;
|
return interned;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,17 +395,14 @@ int utf8len(unsigned char c, bool suppress){
|
|||||||
// https://github.com/python/cpython/blob/3.12/Objects/dictobject.c#L175
|
// https://github.com/python/cpython/blob/3.12/Objects/dictobject.c#L175
|
||||||
uint16_t index = ((_pesudo_random_index*5) + 1) & 65535;
|
uint16_t index = ((_pesudo_random_index*5) + 1) & 65535;
|
||||||
if(index == 0) throw std::runtime_error("StrName index overflow");
|
if(index == 0) throw std::runtime_error("StrName index overflow");
|
||||||
_interned()[std::string(s)] = index;
|
auto res = _r_interned().emplace(index, s);
|
||||||
if(is_valid(index)) throw std::runtime_error("StrName index conflict");
|
PK_ASSERT(res.second);
|
||||||
_r_interned()[index] = std::string(s);
|
s = std::string_view(res.first->second);
|
||||||
|
_interned()[s] = index;
|
||||||
_pesudo_random_index = index;
|
_pesudo_random_index = index;
|
||||||
return StrName(index);
|
return StrName(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StrName::is_valid(int index) {
|
|
||||||
return _r_interned().find(index) != _r_interned().end();
|
|
||||||
}
|
|
||||||
|
|
||||||
Str SStream::str(){
|
Str SStream::str(){
|
||||||
// after this call, the buffer is no longer valid
|
// after this call, the buffer is no longer valid
|
||||||
buffer.reserve(buffer.size() + 1); // allocate one more byte for '\0'
|
buffer.reserve(buffer.size() + 1); // allocate one more byte for '\0'
|
||||||
|
108
src/vm.cpp
108
src/vm.cpp
@ -1,4 +1,5 @@
|
|||||||
#include "pocketpy/vm.h"
|
#include "pocketpy/vm.h"
|
||||||
|
#include "pocketpy/obj.h"
|
||||||
|
|
||||||
static const char* OP_NAMES[] = {
|
static const char* OP_NAMES[] = {
|
||||||
#define OPCODE(name) #name,
|
#define OPCODE(name) #name,
|
||||||
@ -78,6 +79,7 @@ namespace pkpy{
|
|||||||
_ceval_on_step = nullptr;
|
_ceval_on_step = nullptr;
|
||||||
_stdout = [](const char* buf, int size) { std::cout.write(buf, size); };
|
_stdout = [](const char* buf, int size) { std::cout.write(buf, size); };
|
||||||
_stderr = [](const char* buf, int size) { std::cerr.write(buf, size); };
|
_stderr = [](const char* buf, int size) { std::cerr.write(buf, size); };
|
||||||
|
builtins = nullptr;
|
||||||
_main = nullptr;
|
_main = nullptr;
|
||||||
__last_exception = nullptr;
|
__last_exception = nullptr;
|
||||||
_import_handler = [](const char* name, int* out_size) -> unsigned char*{ return nullptr; };
|
_import_handler = [](const char* name, int* out_size) -> unsigned char*{ return nullptr; };
|
||||||
@ -167,7 +169,7 @@ namespace pkpy{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::exec(std::string_view source, Str filename, CompileMode mode, PyVar _module){
|
PyVar VM::exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module){
|
||||||
if(_module == nullptr) _module = _main;
|
if(_module == nullptr) _module = _main;
|
||||||
try {
|
try {
|
||||||
#if PK_DEBUG_PRECOMPILED_EXEC == 1
|
#if PK_DEBUG_PRECOMPILED_EXEC == 1
|
||||||
@ -204,8 +206,8 @@ namespace pkpy{
|
|||||||
return exec(source, "<eval>", EVAL_MODE);
|
return exec(source, "<eval>", EVAL_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt){
|
PyObject* VM::new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt){
|
||||||
PyVar obj = heap._new<Type>(tp_type, Type(_all_types.size()));
|
PyObject* obj = heap._new<Type>(tp_type, Type(_all_types.size()));
|
||||||
const PyTypeInfo& base_info = _all_types[base];
|
const PyTypeInfo& base_info = _all_types[base];
|
||||||
if(!base_info.subclass_enabled){
|
if(!base_info.subclass_enabled){
|
||||||
Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`");
|
Str error = _S("type ", base_info.name.escape(), " is not `subclass_enabled`");
|
||||||
@ -399,7 +401,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
Str name_cpnt = path_cpnts.back();
|
Str name_cpnt = path_cpnts.back();
|
||||||
path_cpnts.pop_back();
|
path_cpnts.pop_back();
|
||||||
PyVar new_mod = new_module(name_cpnt, f_join(path_cpnts));
|
PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts));
|
||||||
_exec(code, new_mod);
|
_exec(code, new_mod);
|
||||||
return new_mod;
|
return new_mod;
|
||||||
}
|
}
|
||||||
@ -442,7 +444,7 @@ void VM::__obj_gc_mark(PyObject* obj){
|
|||||||
if(ti->vt._gc_mark) ti->vt._gc_mark(obj->_value_ptr(), this);
|
if(ti->vt._gc_mark) ti->vt._gc_mark(obj->_value_ptr(), this);
|
||||||
if(obj->is_attr_valid()){
|
if(obj->is_attr_valid()){
|
||||||
obj->attr().apply([this](StrName _, PyVar obj){
|
obj->attr().apply([this](StrName _, PyVar obj){
|
||||||
PK_OBJ_MARK(obj);
|
if (obj.is_ptr) vm->__obj_gc_mark((obj).get());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -564,7 +566,7 @@ PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar local
|
|||||||
|
|
||||||
auto _lock = heap.gc_scope_lock(); // for safety
|
auto _lock = heap.gc_scope_lock(); // for safety
|
||||||
|
|
||||||
PyVar globals_obj = nullptr;
|
PyObject* globals_obj = nullptr;
|
||||||
Dict* globals_dict = nullptr;
|
Dict* globals_dict = nullptr;
|
||||||
|
|
||||||
NameDict_ locals_closure = nullptr;
|
NameDict_ locals_closure = nullptr;
|
||||||
@ -578,7 +580,7 @@ PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar local
|
|||||||
}else{
|
}else{
|
||||||
check_compatible_type(globals, VM::tp_dict);
|
check_compatible_type(globals, VM::tp_dict);
|
||||||
// make a temporary object and copy globals into it
|
// make a temporary object and copy globals into it
|
||||||
globals_obj = new_object<DummyInstance>(VM::tp_object);
|
globals_obj = new_object<DummyInstance>(VM::tp_object).get();
|
||||||
globals_obj->_enable_instance_dict();
|
globals_obj->_enable_instance_dict();
|
||||||
globals_dict = &PK_OBJ_GET(Dict, globals);
|
globals_dict = &PK_OBJ_GET(Dict, globals);
|
||||||
globals_dict->apply([&](PyVar k, PyVar v){
|
globals_dict->apply([&](PyVar k, PyVar v){
|
||||||
@ -598,7 +600,7 @@ PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar local
|
|||||||
locals_dict->apply([&](PyVar k, PyVar v){
|
locals_dict->apply([&](PyVar k, PyVar v){
|
||||||
locals_closure->set(CAST(Str&, k), v);
|
locals_closure->set(CAST(Str&, k), v);
|
||||||
});
|
});
|
||||||
PyVar _callable = VAR(Function(__dynamic_func_decl, globals_obj, nullptr, locals_closure));
|
PyObject* _callable = heap.gcnew<Function>(tp_function, __dynamic_func_decl, globals_obj, nullptr, locals_closure);
|
||||||
retval = vm->_exec(code.get(), globals_obj, _callable, vm->s_data._sp);
|
retval = vm->_exec(code.get(), globals_obj, _callable, vm->s_data._sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,8 +715,8 @@ PyVar VM::__format_object(PyVar obj, Str spec){
|
|||||||
return VAR(ret);
|
return VAR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::new_module(Str name, Str package) {
|
PyObject* VM::new_module(Str name, Str package) {
|
||||||
PyVar obj = heap._new<DummyModule>(tp_module);
|
PyObject* obj = heap._new<DummyModule>(tp_module);
|
||||||
obj->attr().set(__name__, VAR(name));
|
obj->attr().set(__name__, VAR(name));
|
||||||
obj->attr().set(__package__, VAR(package));
|
obj->attr().set(__package__, VAR(package));
|
||||||
// convert to fullname
|
// convert to fullname
|
||||||
@ -1091,7 +1093,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
case FuncType::GENERATOR:
|
case FuncType::GENERATOR:
|
||||||
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
s_data.reset(p0);
|
s_data.reset(p0);
|
||||||
callstack.emplace(nullptr, co, fn._module, callable, nullptr);
|
callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
|
||||||
return __py_generator(
|
return __py_generator(
|
||||||
callstack.popx(),
|
callstack.popx(),
|
||||||
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)
|
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)
|
||||||
@ -1104,7 +1106,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
};
|
};
|
||||||
|
|
||||||
// simple or normal
|
// simple or normal
|
||||||
callstack.emplace(p0, co, fn._module, callable, args.begin());
|
callstack.emplace(p0, co, fn._module, callable.get(), args.begin());
|
||||||
if(op_call) return PY_OP_CALL;
|
if(op_call) return PY_OP_CALL;
|
||||||
return __run_top_frame();
|
return __run_top_frame();
|
||||||
/*****************_py_call*****************/
|
/*****************_py_call*****************/
|
||||||
@ -1357,22 +1359,26 @@ void VM::setattr(PyVar obj, StrName name, PyVar value){
|
|||||||
obj->attr().set(name, value);
|
obj->attr().set(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::bind_func(PyVar obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
|
PyObject* VM::bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
|
||||||
PyVar nf = VAR(NativeFunc(fn, argc, std::move(userdata)));
|
PyObject* nf = heap.gcnew<NativeFunc>(tp_native_func, fn, argc, std::move(userdata));
|
||||||
switch(bt){
|
switch(bt){
|
||||||
case BindType::DEFAULT: break;
|
case BindType::DEFAULT: break;
|
||||||
case BindType::STATICMETHOD: nf = VAR(StaticMethod(nf)); break;
|
case BindType::STATICMETHOD:
|
||||||
case BindType::CLASSMETHOD: nf = VAR(ClassMethod(nf)); break;
|
nf = heap.gcnew<StaticMethod>(tp_staticmethod, nf);
|
||||||
|
break;
|
||||||
|
case BindType::CLASSMETHOD:
|
||||||
|
nf = heap.gcnew<ClassMethod>(tp_classmethod, nf);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(obj != nullptr) obj->attr().set(name, nf);
|
if(obj != nullptr) obj->attr().set(name, nf);
|
||||||
return nf;
|
return nf;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::bind(PyVar obj, const char* sig, NativeFuncC fn, any userdata, BindType bt){
|
PyObject* VM::bind(PyObject* obj, const char* sig, NativeFuncC fn, any userdata, BindType bt){
|
||||||
return bind(obj, sig, nullptr, fn, std::move(userdata), bt);
|
return bind(obj, sig, nullptr, fn, std::move(userdata), bt);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::bind(PyVar obj, const char* sig, const char* docstring, NativeFuncC fn, any userdata, BindType bt){
|
PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, NativeFuncC fn, any userdata, BindType bt){
|
||||||
CodeObject_ co;
|
CodeObject_ co;
|
||||||
try{
|
try{
|
||||||
// fn(a, b, *c, d=1) -> None
|
// fn(a, b, *c, d=1) -> None
|
||||||
@ -1385,14 +1391,14 @@ PyVar VM::bind(PyVar obj, const char* sig, const char* docstring, NativeFuncC fn
|
|||||||
}
|
}
|
||||||
FuncDecl_ decl = co->func_decls[0];
|
FuncDecl_ decl = co->func_decls[0];
|
||||||
decl->docstring = docstring;
|
decl->docstring = docstring;
|
||||||
PyVar f_obj = VAR(NativeFunc(fn, decl, std::move(userdata)));
|
PyObject* f_obj = heap.gcnew<NativeFunc>(tp_native_func, fn, decl, std::move(userdata));
|
||||||
|
|
||||||
switch(bt){
|
switch(bt){
|
||||||
case BindType::STATICMETHOD:
|
case BindType::STATICMETHOD:
|
||||||
f_obj = VAR(StaticMethod(f_obj));
|
f_obj = heap.gcnew<StaticMethod>(tp_staticmethod, f_obj);
|
||||||
break;
|
break;
|
||||||
case BindType::CLASSMETHOD:
|
case BindType::CLASSMETHOD:
|
||||||
f_obj = VAR(ClassMethod(f_obj));
|
f_obj = heap.gcnew<ClassMethod>(tp_classmethod, f_obj);
|
||||||
break;
|
break;
|
||||||
case BindType::DEFAULT:
|
case BindType::DEFAULT:
|
||||||
break;
|
break;
|
||||||
@ -1401,14 +1407,14 @@ PyVar VM::bind(PyVar obj, const char* sig, const char* docstring, NativeFuncC fn
|
|||||||
return f_obj;
|
return f_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar VM::bind_property(PyVar obj, const char* name, NativeFuncC fget, NativeFuncC fset){
|
PyObject* VM::bind_property(PyObject* obj, const char* name, NativeFuncC fget, NativeFuncC fset){
|
||||||
PK_ASSERT(is_type(obj, tp_type));
|
PK_ASSERT(is_type(obj, tp_type));
|
||||||
std::string_view name_sv(name); int pos = name_sv.find(':');
|
std::string_view name_sv(name); int pos = name_sv.find(':');
|
||||||
if(pos > 0) name_sv = name_sv.substr(0, pos);
|
if(pos > 0) name_sv = name_sv.substr(0, pos);
|
||||||
PyVar _0 = new_object<NativeFunc>(tp_native_func, fget, 1);
|
PyVar _0 = new_object<NativeFunc>(tp_native_func, fget, 1);
|
||||||
PyVar _1 = vm->None;
|
PyVar _1 = vm->None;
|
||||||
if(fset != nullptr) _1 = new_object<NativeFunc>(tp_native_func, fset, 2);
|
if(fset != nullptr) _1 = new_object<NativeFunc>(tp_native_func, fset, 2);
|
||||||
PyVar prop = VAR(Property(_0, _1));
|
PyObject* prop = heap.gcnew<Property>(tp_property, _0, _1);
|
||||||
obj->attr().set(StrName(name_sv), prop);
|
obj->attr().set(StrName(name_sv), prop);
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
@ -1474,14 +1480,14 @@ StrName _type_name(VM *vm, Type type){
|
|||||||
void VM::bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar)){
|
void VM::bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar)){
|
||||||
_all_types[type].m__getitem__ = f;
|
_all_types[type].m__getitem__ = f;
|
||||||
bind_func(type, __getitem__, 2, [](VM* vm, ArgsView args){
|
bind_func(type, __getitem__, 2, [](VM* vm, ArgsView args){
|
||||||
return lambda_get_userdata<PyVar(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
|
return lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0], args[1]);
|
||||||
}, f);
|
}, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
|
void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
|
||||||
_all_types[type].m__setitem__ = f;
|
_all_types[type].m__setitem__ = f;
|
||||||
bind_func(type, __setitem__, 3, [](VM* vm, ArgsView args){
|
bind_func(type, __setitem__, 3, [](VM* vm, ArgsView args){
|
||||||
lambda_get_userdata<void(*)(VM* vm, PyVar, PyVar, PyVar)>(args.begin())(vm, args[0], args[1], args[2]);
|
lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0], args[1], args[2]);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
}, f);
|
}, f);
|
||||||
}
|
}
|
||||||
@ -1489,7 +1495,7 @@ void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
|
|||||||
void VM::bind__delitem__(Type type, void (*f)(VM*, PyVar, PyVar)){
|
void VM::bind__delitem__(Type type, void (*f)(VM*, PyVar, PyVar)){
|
||||||
_all_types[type].m__delitem__ = f;
|
_all_types[type].m__delitem__ = f;
|
||||||
bind_func(type, __delitem__, 2, [](VM* vm, ArgsView args){
|
bind_func(type, __delitem__, 2, [](VM* vm, ArgsView args){
|
||||||
lambda_get_userdata<void(*)(VM*, PyVar, PyVar)>(args.begin())(vm, args[0], args[1]);
|
lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0], args[1]);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
}, f);
|
}, f);
|
||||||
}
|
}
|
||||||
@ -1505,7 +1511,7 @@ PyVar VM::__pack_next_retval(unsigned n){
|
|||||||
void VM::bind__next__(Type type, unsigned (*f)(VM*, PyVar)){
|
void VM::bind__next__(Type type, unsigned (*f)(VM*, PyVar)){
|
||||||
_all_types[type].op__next__ = f;
|
_all_types[type].op__next__ = f;
|
||||||
bind_func(type, __next__, 1, [](VM* vm, ArgsView args){
|
bind_func(type, __next__, 1, [](VM* vm, ArgsView args){
|
||||||
int n = lambda_get_userdata<unsigned(*)(VM*, PyVar)>(args.begin())(vm, args[0]);
|
int n = lambda_get_userdata<decltype(f)>(args.begin())(vm, args[0]);
|
||||||
return vm->__pack_next_retval(n);
|
return vm->__pack_next_retval(n);
|
||||||
}, f);
|
}, f);
|
||||||
}
|
}
|
||||||
@ -1792,7 +1798,7 @@ void Function::_gc_mark(VM* vm) const{
|
|||||||
decl->_gc_mark(vm);
|
decl->_gc_mark(vm);
|
||||||
if(_closure){
|
if(_closure){
|
||||||
_closure->apply([=](StrName _, PyVar obj){
|
_closure->apply([=](StrName _, PyVar obj){
|
||||||
PK_OBJ_MARK(obj);
|
vm->obj_gc_mark(obj);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1803,67 +1809,67 @@ void NativeFunc::_gc_mark(VM* vm) const{
|
|||||||
|
|
||||||
void FuncDecl::_gc_mark(VM* vm) const{
|
void FuncDecl::_gc_mark(VM* vm) const{
|
||||||
code->_gc_mark(vm);
|
code->_gc_mark(vm);
|
||||||
for(int i=0; i<kwargs.size(); i++) PK_OBJ_MARK(kwargs[i].value);
|
for(int i=0; i<kwargs.size(); i++) vm->obj_gc_mark(kwargs[i].value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void List::_gc_mark(VM* vm) const{
|
void List::_gc_mark(VM* vm) const{
|
||||||
for(PyVar obj: *this) PK_OBJ_MARK(obj);
|
for(PyVar obj: *this) vm->obj_gc_mark(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Tuple::_gc_mark(VM* vm) const{
|
void Tuple::_gc_mark(VM* vm) const{
|
||||||
for(PyVar obj: *this) PK_OBJ_MARK(obj);
|
for(PyVar obj: *this) vm->obj_gc_mark(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MappingProxy::_gc_mark(VM* vm) const{
|
void MappingProxy::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(obj);
|
vm->__obj_gc_mark(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BoundMethod::_gc_mark(VM* vm) const{
|
void BoundMethod::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(func);
|
vm->obj_gc_mark(func);
|
||||||
PK_OBJ_MARK(self);
|
vm->obj_gc_mark(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StarWrapper::_gc_mark(VM* vm) const{
|
void StarWrapper::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(obj);
|
vm->obj_gc_mark(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticMethod::_gc_mark(VM* vm) const{
|
void StaticMethod::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(func);
|
vm->obj_gc_mark(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassMethod::_gc_mark(VM* vm) const{
|
void ClassMethod::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(func);
|
vm->obj_gc_mark(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Property::_gc_mark(VM* vm) const{
|
void Property::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(getter);
|
vm->obj_gc_mark(getter);
|
||||||
PK_OBJ_MARK(setter);
|
vm->obj_gc_mark(setter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Slice::_gc_mark(VM* vm) const{
|
void Slice::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(start);
|
vm->obj_gc_mark(start);
|
||||||
PK_OBJ_MARK(stop);
|
vm->obj_gc_mark(stop);
|
||||||
PK_OBJ_MARK(step);
|
vm->obj_gc_mark(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Super::_gc_mark(VM* vm) const{
|
void Super::_gc_mark(VM* vm) const{
|
||||||
PK_OBJ_MARK(first);
|
vm->obj_gc_mark(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::_gc_mark(VM* vm) const {
|
void Frame::_gc_mark(VM* vm) const {
|
||||||
PK_OBJ_MARK(_module);
|
vm->obj_gc_mark(_module);
|
||||||
co->_gc_mark(vm);
|
co->_gc_mark(vm);
|
||||||
// Frame could be stored in a generator, so mark _callable for safety
|
// Frame could be stored in a generator, so mark _callable for safety
|
||||||
if(_callable != nullptr) PK_OBJ_MARK(_callable);
|
vm->obj_gc_mark(_callable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ManagedHeap::mark() {
|
void ManagedHeap::mark() {
|
||||||
for(PyObject* obj: _no_gc) vm->__obj_gc_mark(obj);
|
for(PyObject* obj: _no_gc) vm->__obj_gc_mark(obj);
|
||||||
vm->callstack.apply([this](Frame& frame){ frame._gc_mark(vm); });
|
vm->callstack.apply([this](Frame& frame){ frame._gc_mark(vm); });
|
||||||
for(auto [_, co]: vm->__cached_codes) co->_gc_mark(vm);
|
for(auto [_, co]: vm->__cached_codes) co->_gc_mark(vm);
|
||||||
if(vm->__last_exception) PK_OBJ_MARK(vm->__last_exception);
|
vm->obj_gc_mark(vm->__last_exception);
|
||||||
if(vm->__curr_class) PK_OBJ_MARK(vm->__curr_class);
|
vm->obj_gc_mark(vm->__curr_class);
|
||||||
if(vm->__c.error != nullptr) PK_OBJ_MARK(vm->__c.error);
|
vm->obj_gc_mark(vm->__c.error);
|
||||||
vm->__stack_gc_mark(vm->s_data.begin(), vm->s_data.end());
|
vm->__stack_gc_mark(vm->s_data.begin(), vm->s_data.end());
|
||||||
if(_gc_marker_ex) _gc_marker_ex(vm);
|
if(_gc_marker_ex) _gc_marker_ex(vm);
|
||||||
}
|
}
|
||||||
@ -1880,13 +1886,13 @@ void ManagedHeap::_delete(PyObject* obj){
|
|||||||
|
|
||||||
void Dict::_gc_mark(VM* vm) const{
|
void Dict::_gc_mark(VM* vm) const{
|
||||||
apply([vm](PyVar k, PyVar v){
|
apply([vm](PyVar k, PyVar v){
|
||||||
PK_OBJ_MARK(k);
|
vm->obj_gc_mark(k);
|
||||||
PK_OBJ_MARK(v);
|
vm->obj_gc_mark(v);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeObject::_gc_mark(VM* vm) const {
|
void CodeObject::_gc_mark(VM* vm) const {
|
||||||
for(PyVar v : consts) PK_OBJ_MARK(v);
|
for(PyVar v : consts) vm->obj_gc_mark(v);
|
||||||
for(auto& decl: func_decls) decl->_gc_mark(vm);
|
for(auto& decl: func_decls) decl->_gc_mark(vm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user