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:
blueloveTH 2024-06-01 12:50:38 +08:00
parent 17de5b3024
commit 1e365ca72c
44 changed files with 552 additions and 553 deletions

View File

@ -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

View File

@ -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'

View File

@ -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;

View File

@ -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");

View File

@ -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;
} }

View File

@ -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);
} }
} }
} }

View File

@ -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));
``` ```

View File

@ -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)",

View File

@ -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); \

View File

@ -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);

View File

@ -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;

View File

@ -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) {}

View File

@ -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;
} }

View File

@ -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);

View File

@ -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; }

View File

@ -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*);

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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;
}; };

View File

@ -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;
}; };

View File

@ -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>);

View File

@ -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);
} }

View File

@ -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");

View File

@ -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){

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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]);

View File

@ -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);

View File

@ -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){ \

View File

@ -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);

View File

@ -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){

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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"));

View File

@ -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'

View File

@ -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);
} }