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
on:
push:
paths-ignore:
- 'docs/**'
- 'web/**'
- '**.md'
pull_request:
paths-ignore:
- 'docs/**'
- 'web/**'
- '**.md'
jobs:
build_win32_amalgamated:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- name: Compile
shell: powershell
run: |
python amalgamate.py
cd amalgamated
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
with:
path: amalgamated/pkpy.exe
build_win32:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- name: Compile
shell: bash
run: |
mkdir -p output/windows/x86_64
python cmake_build.py
cp main.exe output/windows/x86_64
cp pocketpy.dll output/windows/x86_64
- uses: actions/upload-artifact@v3
with:
path: output
- name: Unit Test
run: python scripts/run_tests.py
- name: Benchmark
run: python scripts/run_tests.py benchmark
build_linux:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- name: Setup Clang
uses: egor-tensin/setup-clang@v1
with:
version: 15
platform: x64
- 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
- name: Unit Test with Coverage
run: bash run_tests.sh
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4
with:
token: ${{ secrets.CODECOV_TOKEN }}
directory: .coverage
if: github.ref == 'refs/heads/main'
- name: Compile
run: |
mkdir -p output/linux/x86_64
python cmake_build.py
cp main output/linux/x86_64
cp libpocketpy.so output/linux/x86_64
env:
CXX: clang++
CC: clang
- uses: actions/upload-artifact@v3
with:
path: output
- name: Benchmark
run: python scripts/run_tests.py benchmark
- name: C Binding Test
run: bash run_c_binding_test.sh
build_linux_x86:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Alpine Linux for aarch64
uses: jirutka/setup-alpine@v1
with:
arch: x86
packages: gcc g++ make cmake libc-dev linux-headers python3
- name: Build and Test
run: |
uname -m
python cmake_build.py
python scripts/run_tests.py
python scripts/run_tests.py benchmark
shell: alpine.sh --root {0}
build_darwin:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Compile and Test
run: |
python cmake_build.py
python scripts/run_tests.py
- name: Benchmark
run: python scripts/run_tests.py benchmark
- run: |
python amalgamate.py
cd plugins/macos/pocketpy
mkdir -p output/macos
xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
cp -r build/Release/pocketpy.bundle output/macos
- uses: actions/upload-artifact@v3
with:
path: plugins/macos/pocketpy/output
build_android:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: nttld/setup-ndk@v1
id: setup-ndk
with:
ndk-version: r23
local-cache: false
add-to-path: false
- name: Compile Shared Library
run: |
bash build_android.sh arm64-v8a
bash build_android.sh armeabi-v7a
bash build_android.sh x86_64
# name: build
# on:
# push:
# paths-ignore:
# - 'docs/**'
# - 'web/**'
# - '**.md'
# pull_request:
# paths-ignore:
# - 'docs/**'
# - 'web/**'
# - '**.md'
# jobs:
# build_win32_amalgamated:
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v4
# - uses: ilammy/msvc-dev-cmd@v1
# - name: Compile
# shell: powershell
# run: |
# python amalgamate.py
# cd amalgamated
# 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
# with:
# path: amalgamated/pkpy.exe
# build_win32:
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v4
# - uses: ilammy/msvc-dev-cmd@v1
# - name: Compile
# shell: bash
# run: |
# mkdir -p output/windows/x86_64
# python cmake_build.py
# cp main.exe output/windows/x86_64
# cp pocketpy.dll output/windows/x86_64
# - uses: actions/upload-artifact@v3
# with:
# path: output
# - name: Unit Test
# run: python scripts/run_tests.py
# - name: Benchmark
# run: python scripts/run_tests.py benchmark
# build_linux:
# runs-on: ubuntu-20.04
# steps:
# - uses: actions/checkout@v4
# - name: Setup Clang
# uses: egor-tensin/setup-clang@v1
# with:
# version: 15
# platform: x64
# - 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
# - name: Unit Test with Coverage
# run: bash run_tests.sh
# - name: Upload coverage reports to Codecov
# uses: codecov/codecov-action@v4
# with:
# token: ${{ secrets.CODECOV_TOKEN }}
# directory: .coverage
# if: github.ref == 'refs/heads/main'
# - name: Compile
# run: |
# mkdir -p output/linux/x86_64
# python cmake_build.py
# cp main output/linux/x86_64
# cp libpocketpy.so output/linux/x86_64
# env:
# CXX: clang++
# CC: clang
# - uses: actions/upload-artifact@v3
# with:
# path: output
# - name: Benchmark
# run: python scripts/run_tests.py benchmark
# - name: C Binding Test
# run: bash run_c_binding_test.sh
# build_linux_x86:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - name: Setup Alpine Linux for aarch64
# uses: jirutka/setup-alpine@v1
# with:
# arch: x86
# packages: gcc g++ make cmake libc-dev linux-headers python3
# - name: Build and Test
# run: |
# uname -m
# python cmake_build.py
# python scripts/run_tests.py
# python scripts/run_tests.py benchmark
# shell: alpine.sh --root {0}
# build_darwin:
# runs-on: macos-latest
# steps:
# - uses: actions/checkout@v4
# - name: Compile and Test
# run: |
# python cmake_build.py
# python scripts/run_tests.py
# - name: Benchmark
# run: python scripts/run_tests.py benchmark
# - run: |
# python amalgamate.py
# cd plugins/macos/pocketpy
# mkdir -p output/macos
# xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
# cp -r build/Release/pocketpy.bundle output/macos
# - uses: actions/upload-artifact@v3
# with:
# path: plugins/macos/pocketpy/output
# build_android:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# - uses: nttld/setup-ndk@v1
# id: setup-ndk
# with:
# ndk-version: r23
# local-cache: false
# add-to-path: false
# - name: Compile Shared Library
# run: |
# bash build_android.sh arm64-v8a
# bash build_android.sh armeabi-v7a
# bash build_android.sh x86_64
mkdir -p output/android/arm64-v8a
mkdir -p output/android/armeabi-v7a
mkdir -p output/android/x86_64
# mkdir -p output/android/arm64-v8a
# mkdir -p output/android/armeabi-v7a
# mkdir -p output/android/x86_64
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/x86_64/libpocketpy.so output/android/x86_64
env:
ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
- uses: actions/upload-artifact@v3
with:
path: output
build_ios:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Compile Frameworks
run: |
git clone https://github.com/leetal/ios-cmake --depth 1 ~/ios-cmake
bash build_ios.sh
mkdir -p output/ios
cp -r build/pocketpy.xcframework output/ios/pocketpy.xcframework
- uses: actions/upload-artifact@v3
with:
path: output
# 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/x86_64/libpocketpy.so output/android/x86_64
# env:
# ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
# - uses: actions/upload-artifact@v3
# with:
# path: output
# build_ios:
# runs-on: macos-latest
# steps:
# - uses: actions/checkout@v4
# - name: Compile Frameworks
# run: |
# git clone https://github.com/leetal/ios-cmake --depth 1 ~/ios-cmake
# bash build_ios.sh
# mkdir -p output/ios
# cp -r build/pocketpy.xcframework output/ios/pocketpy.xcframework
# - uses: actions/upload-artifact@v3
# with:
# path: output

View File

@ -1,42 +1,42 @@
name: website
# name: website
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# on:
# push:
# branches: [ main ]
# pull_request:
# branches: [ main ]
permissions:
contents: write
# permissions:
# contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
###################################################
- uses: actions/setup-node@v3.1.1
- name: Retype build
run: |
python scripts/build_references.py
cd docs
npm install retypeapp --global
retype build
###################################################
- name: Setup emsdk
uses: mymindstorm/setup-emsdk@v12
with:
version: 3.1.25
actions-cache-folder: 'emsdk-cache'
- name: Compile
run: |
bash build_web.sh
mv web docs/.retype/static
###################################################
- uses: crazy-max/ghaction-github-pages@v3
with:
target_branch: gh-pages
build_dir: docs/.retype
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
if: github.ref == 'refs/heads/main'
# jobs:
# deploy:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v4
# ###################################################
# - uses: actions/setup-node@v3.1.1
# - name: Retype build
# run: |
# python scripts/build_references.py
# cd docs
# npm install retypeapp --global
# retype build
# ###################################################
# - name: Setup emsdk
# uses: mymindstorm/setup-emsdk@v12
# with:
# version: 3.1.25
# actions-cache-folder: 'emsdk-cache'
# - name: Compile
# run: |
# bash build_web.sh
# mv web docs/.retype/static
# ###################################################
# - uses: crazy-max/ghaction-github-pages@v3
# with:
# target_branch: gh-pages
# build_dir: docs/.retype
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# 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){
PyVar mod = vm->new_module("cjson");
PyObject* mod = vm->new_module("cjson");
vm->bind_func(mod, "loads", 1, [](VM* vm, ArgsView args){
std::string_view sv;

View File

@ -38,8 +38,8 @@ struct PyLuaObject{
};
struct PyLuaTable: PyLuaObject{
static void _register(VM* vm, PyVar mod, PyVar type){
Type t = PK_OBJ_GET(Type, type);
static void _register(VM* vm, PyObject* mod, PyObject* type){
Type t = type->as<Type>();
PyTypeInfo* ti = &vm->_all_types[t];
ti->subclass_enabled = false;
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{
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){
if(args.size() < 1) vm->TypeError("__call__ takes at least 1 argument");
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){
PyVar mod = vm->new_module("lua");
PyObject* mod = vm->new_module("lua");
if(_L != nullptr){
throw std::runtime_error("lua bridge already initialized");

View File

@ -46,14 +46,14 @@ struct Point{
int x, y;
static void _register(VM* vm, PyVar mod, PyVar type){
static void _register(VM* vm, PyObject* mod, PyObject* type){
// do bindings here
}
};
int main(){
VM* vm = new VM();
PyVar mod = vm->new_module("test");
PyObject* mod = vm->new_module("test");
Point::register_class(vm, mod);
return 0;
}
@ -68,7 +68,7 @@ struct Point{
int main(){
VM* vm = new VM();
PyVar mod = vm->new_module("test");
PyObject* mod = vm->new_module("test");
vm->register_user_class<Point>(mod, "Point",
[](VM* vm, PyVar mod, PyVar type){
// do bindings here
@ -84,14 +84,14 @@ This is achieved by an overloaded version of `vm->register_user_class<>`. For ex
struct Point{
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)
}
};
int main(){
VM* vm = new VM();
PyVar mod = vm->new_module("test");
PyObject* mod = vm->new_module("test");
vm->register_user_class<Point>(mod, "Point");
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
int main(){
VM* vm = new VM();
PyVar mod = vm->new_module("test");
PyObject* mod = vm->new_module("test");
vm->register_user_class<Point>(mod, "Point",
[](VM* vm, PyVar mod, PyVar type){
// wrap field x
@ -165,11 +165,11 @@ struct Container{
void _gc_mark(VM* vm) const{
// mark a
if(a) PK_OBJ_MARK(a);
vm->obj_gc_mark(a);
// mark elements in 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
```cpp
PyVar mod = vm->new_module("test");
PyObject* mod = vm->new_module("test");
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)`.
```cpp
PyVar mod = vm->new_module("test");
PyObject* mod = vm->new_module("test");
mod->attr().set("pi", py_var(vm, 3.14));
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>
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);
return vm->bind(obj, sig, __proxy_wrapper, proxy, bt);
}
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);
return vm->bind(obj, sig, __proxy_wrapper, proxy, bt);
}
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);
return vm->bind(obj, sig, docstring, __proxy_wrapper, proxy, bt);
}
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);
return vm->bind(obj, sig, docstring, __proxy_wrapper, proxy, bt);
}
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>);
PK_ASSERT(is_type(obj, tp_type));
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);
}
PyVar prop = VAR(Property(_0, _1));
PyObject* prop = heap.gcnew<Property>(tp_property, _0, _1);
obj->attr().set(StrName(name_sv), 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){ \
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); \
if(!vm->isinstance(_1, vm->_tp_user<wT>())) return vm->NotImplemented; \
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) \
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); \
i64 i = CAST(i64, _1); \
T* tgt = reinterpret_cast<T*>(self.ptr); \
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); \
i64 i = CAST(i64, _1); \
T* tgt = reinterpret_cast<T*>(self.ptr); \

View File

@ -32,14 +32,14 @@ struct VoidP{
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) \
inline PyVar py_var(VM* vm, Tp val){ \
const static std::pair<StrName, StrName> P("c", NAME); \
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")
@ -84,7 +84,7 @@ struct Struct{
Struct(const Struct& other): Struct(other.p, other.size){}
~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);

View File

@ -145,11 +145,11 @@ struct NativeFunc {
struct Function{
FuncDecl_ decl;
PyVar _module; // weak ref
PyVar _class; // weak ref
PyObject* _module; // weak ref
PyObject* _class; // weak ref
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) {}
void _gc_mark(VM*) const;

View File

@ -89,7 +89,6 @@ using f64 = double; // always 64-bit
static_assert(sizeof(i64) == 8);
struct Dummy { }; // for special objects: True, False, None, Ellipsis, etc.
struct DummyInstance { };
struct DummyModule { };
struct NoReturn { };
@ -104,9 +103,9 @@ struct Type {
constexpr operator int() const { return index; }
};
#define PK_LAMBDA(x) ([](VM* vm, ArgsView args) { return x; })
#define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) { return VAR(x); })
#define PK_ACTION(x) ([](VM* vm, ArgsView args) { x; return vm->None; })
#define PK_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return x; })
#define PK_VAR_LAMBDA(x) ([](VM* vm, ArgsView args) -> PyVar { return VAR(x); })
#define PK_ACTION(x) ([](VM* vm, ArgsView args) -> PyVar { x; return vm->None; })
#define PK_REGION(name) 1
@ -190,6 +189,9 @@ struct PyVar final{
// uninitialized
PyVar() = default;
// implict conversion
PyVar(PyObject* p);
/* We must initialize all members to allow == operator to work correctly */
// constexpr initialized
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;
void* _code_on_error;
PyVar _self; // weak reference
PyObject* _self; // weak reference
stack<ExceptionLine> stacktrace;
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);
return _self;
}

View File

@ -106,7 +106,7 @@ struct CodeEmitContext{
bool is_compiling_class = false;
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;
CodeBlock* enter_block(CodeBlockType type);

View File

@ -29,6 +29,8 @@ struct FastLocals{
};
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`.
PyVar _begin[PK_VM_STACK_SIZE + PK_VM_STACK_SIZE/128];
PyVar* _sp;
@ -65,14 +67,6 @@ struct ValueStack {
new(_sp) PyVar(std::forward<Args>(args)...);
++_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{
@ -91,27 +85,27 @@ struct Frame {
PyVar* _sp_base;
const CodeObject* co;
PyVar _module;
PyVar _callable; // a function object or nullptr (global scope)
PyObject* _module;
PyObject* _callable; // a function object or nullptr (global scope)
FastLocals _locals;
// This list will be freed in __pop_frame
UnwindTarget* _uw_list;
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(); }
// 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) { }
// 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) { }
// 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) { }
PyVar* actual_sp_base() const { return _locals.a; }

View File

@ -39,7 +39,7 @@ struct ManagedHeap{
/********************/
template<typename T, typename... Args>
PyVar gcnew(Type type, Args&&... args){
PyObject* gcnew(Type type, Args&&... args){
using __T = std::decay_t<T>;
static_assert(!is_sso_v<__T>, "gcnew cannot be used with SSO types");
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
@ -47,17 +47,17 @@ struct ManagedHeap{
p->placement_new<__T>(std::forward<Args>(args)...);
gen.push_back(p);
gc_counter++;
return PyVar(type, p);
return p;
}
template<typename T, typename... Args>
PyVar _new(Type type, Args&&... args){
PyObject* _new(Type type, Args&&... args){
using __T = std::decay_t<T>;
static_assert(!is_sso_v<__T>);
PyObject* p = new(pool128_alloc(py_sizeof<__T>)) PyObject(type);
p->placement_new<__T>(std::forward<Args>(args)...);
_no_gc.push_back(p);
return PyVar(type, p);
return p;
}
void _delete(PyObject*);

View File

@ -11,7 +11,7 @@ struct RangeIter{ // step > 0
i64 current;
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
@ -19,7 +19,7 @@ struct RangeIterR{ // step < 0
i64 current;
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{
@ -31,15 +31,15 @@ struct ArrayIter{
: ref(ref), end(end), current(begin) {}
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{
PyVar ref;
int i; // byte index
StringIter(PyVar ref) : ref(ref), i(0) {}
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
static void _register(VM* vm, PyVar mod, PyVar type);
void _gc_mark(VM* vm) const{ vm->obj_gc_mark(ref); }
static void _register(VM* vm, PyObject* mod, PyObject* type);
};
struct Generator{
@ -58,7 +58,7 @@ struct Generator{
}
PyVar next(VM* vm);
static void _register(VM* vm, PyVar mod, PyVar type);
static void _register(VM* vm, PyObject* mod, PyObject* type);
~Generator(){
if(lf){
@ -74,8 +74,8 @@ struct DictItemsIter{
DictItemsIter(PyVar ref) : ref(ref) {
i = PK_OBJ_GET(Dict, ref)._head_idx;
}
void _gc_mark(VM* vm) const{ PK_OBJ_MARK(ref); }
static void _register(VM* vm, PyVar mod, PyVar type);
void _gc_mark(VM* vm) const{ vm->obj_gc_mark(ref); }
static void _register(VM* vm, PyObject* mod, PyObject* type);
};
} // namespace pkpy

View File

@ -7,7 +7,7 @@ namespace pkpy{
inline bool isclose(float a, float b){ return std::fabs(a - b) < 1e-4; }
struct Vec2{
static void _register(VM* vm, PyVar mod, PyVar type);
static void _register(VM* vm, PyObject* mod, PyObject* type);
float x, y;
Vec2() : x(0.0f), y(0.0f) {}
@ -31,7 +31,7 @@ struct Vec2{
};
struct Vec3{
static void _register(VM* vm, PyVar mod, PyVar type);
static void _register(VM* vm, PyObject* mod, PyObject* type);
float x, y, z;
Vec3() : x(0.0f), y(0.0f), z(0.0f) {}
@ -54,7 +54,7 @@ struct Vec3{
};
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;
Vec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {}
@ -78,7 +78,7 @@ struct Vec4{
};
struct Mat3x3{
static void _register(VM* vm, PyVar mod, PyVar type);
static void _register(VM* vm, PyObject* mod, PyObject* type);
union {
struct {

View File

@ -16,6 +16,11 @@ constexpr T default_invalid_value(){
#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 }
struct A{
uint16_t k;
PyVar v;
};
template<typename V>
struct SmallNameDict{
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 {};
struct MappingProxy{
PyVar obj;
MappingProxy(PyVar obj) : obj(obj) {}
PyObject* obj;
MappingProxy(PyObject* obj) : obj(obj) {}
NameDict& attr() { return obj->attr(); }
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_MARK(obj) if((obj).is_ptr) vm->__obj_gc_mark((obj).get());
#define PK_OBJ_GET(T, obj) ((obj).obj_get<T>())
// deprecated
#define PK_OBJ_MARK(obj) vm->obj_gc_mark(obj)
#define VAR(x) py_var(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)
/*****************************************************************/
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
extern PyVar const PY_OP_CALL;

View File

@ -119,9 +119,8 @@ struct StrName {
return sv() > other.sv();
}
static bool is_valid(int index);
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 uint32_t _pesudo_random_index;
};

View File

@ -7,8 +7,8 @@
namespace pkpy {
struct List: pod_vector<PyVar, 4>{
using pod_vector<PyVar, 4>::pod_vector;
struct List: pod_vector<PyVar>{
using pod_vector<PyVar>::pod_vector;
void _gc_mark(VM*) const;
};

View File

@ -5,10 +5,11 @@
namespace pkpy{
template<typename T, int Growth=2>
template<typename T>
struct pod_vector{
static constexpr int SizeT = sizeof(T);
static constexpr int N = 128 / SizeT;
static constexpr int Growth = 2;
// static_assert(128 % SizeT == 0);
static_assert(is_pod_v<T>);

View File

@ -27,7 +27,7 @@ namespace pkpy{
#define STACK_VIEW(n) (s_data.view(n))
typedef PyVar (*BinaryFuncC)(VM*, PyVar, PyVar);
typedef void (*RegisterFunc)(VM*, PyVar, PyVar);
typedef void (*RegisterFunc)(VM*, PyObject*, PyObject*);
#if PK_ENABLE_PROFILER
struct NextBreakpoint{
@ -64,14 +64,14 @@ struct PyTypeInfo{
}
};
PyVar obj; // never be garbage collected
PyObject* obj; // never be garbage collected
Type base;
PyVar mod; // never be garbage collected
PyObject* mod; // never be garbage collected
StrName name;
bool subclass_enabled;
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) {}
std::vector<StrName> annotated_fields = {};
@ -165,12 +165,13 @@ public:
std::map<StrName, Str> _lazy_modules; // lazy loaded modules
struct{
PyVar error;
PyObject* error;
stack_no_copy<ArgsView> s_view;
} __c;
PyVar StopIteration; // a special Exception class
PyVar builtins, _main;
PyObject* builtins;
PyObject* _main;
// typeid -> Type
std::map<const std::type_index, Type> _cxx_typeid_map;
@ -178,8 +179,8 @@ public:
std::set<PyVar> _repr_recursion_set;
ImportContext __import_context;
PyVar __last_exception;
PyVar __curr_class;
PyObject* __last_exception;
PyObject* __curr_class;
PyVar __cached_object_new;
std::map<std::string_view, CodeObject_> __cached_codes;
std::map<std::string_view, PyVar> __cached_op_funcs;
@ -260,6 +261,8 @@ public:
i64 normalized_index(i64 index, int size);
Str disassemble(CodeObject_ co);
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
#if PK_REGION("Name Lookup Methods")
@ -273,7 +276,7 @@ public:
#if PK_REGION("Source Execution Methods")
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);
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 eval(std::string_view source);
@ -353,25 +356,25 @@ public:
#endif
#if PK_REGION("General Bindings")
PyVar bind_func(PyVar 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(PyObject*obj, 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);
}
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>
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>
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>
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>
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>
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
#if PK_REGION("Error Reporting Methods")
@ -406,19 +409,19 @@ public:
Type _tp(PyVar obj){ return obj.type; }
const PyTypeInfo* _tp_info(PyVar obj) { return &_all_types[_tp(obj)]; }
const PyTypeInfo* _tp_info(Type type) { return &_all_types[type]; }
PyVar _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
PyVar _t(Type type){ return _all_types[type].obj; }
PyObject* _t(PyVar obj){ return _all_types[_tp(obj)].obj; }
PyObject* _t(Type type){ return _all_types[type].obj; }
// equivalent to `obj == NotImplemented` but faster
static bool is_not_implemented(PyVar obj){ return obj.type == tp_not_implemented; }
#endif
#if PK_REGION("User Type Registration")
PyVar new_module(Str name, Str package="");
PyVar new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt={});
PyObject* new_module(Str name, Str package="");
PyObject* new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt={});
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>());
}
@ -428,9 +431,9 @@ public:
bool is_user_type(PyVar obj){ return _tp(obj) == _tp_user<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>
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>
PyVar new_user_object(Args&&... args){
@ -601,10 +604,8 @@ __T _py_cast__internal(VM* vm, PyVar obj) {
return (T)obj.as<i64>();
}else if constexpr(is_floating_point_v<T>){
static_assert(!std::is_reference_v<__T>);
// float
if(is_float(obj)) return (T)obj.as<f64>();
i64 bits;
if(try_cast_int(obj, &bits)) return (T)bits;
if(is_int(obj)) return (T)obj.as<i64>();
vm->TypeError("expected 'int' or 'float', got " + _type_name(vm, vm->_tp(obj)).escape());
return 0.0f;
}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); }
template<typename T>
PyVar VM::register_user_class(PyVar 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* VM::register_user_class(PyObject* mod, StrName name, RegisterFunc _register, Type base, bool subclass_enabled){
PyObject* type = new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
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);
if(!type->attr().contains(__new__)){
if constexpr(std::is_default_constructible_v<T>) {
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);
});
}else{
@ -660,7 +661,7 @@ PyVar VM::register_user_class(PyVar mod, StrName name, RegisterFunc _register, 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);
}

View File

@ -41,7 +41,7 @@ struct Array2d{
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){
Type cls = PK_OBJ_GET(Type, args[0]);
return vm->new_object<Array2d>(cls);
@ -113,11 +113,13 @@ struct Array2d{
int slice_height = stop_row - start_row; \
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);
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);
return self._get(col, row);
}
@ -137,11 +139,12 @@ struct Array2d{
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);
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._set(col, row, _2);
return;
@ -195,12 +198,12 @@ struct Array2d{
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);
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);
return _S("array2d(", self.n_cols, ", ", self.n_rows, ')');
});
@ -269,7 +272,7 @@ struct Array2d{
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);
if(!vm->is_user_type<Array2d>(_1)) return vm->NotImplemented;
Array2d& other = PK_OBJ_GET(Array2d, _1);
@ -352,7 +355,7 @@ struct Array2d{
}
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(){
@ -370,11 +373,11 @@ struct Array2dIter{
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){
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) { return _0; });
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
static void _register(VM* vm, PyObject* mod, PyObject* type){
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0) { return _0; });
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
Array2dIter& self = PK_OBJ_GET(Array2dIter, _0);
if(self.i == self.a->numel) return 0;
std::div_t res = std::div(self.i, self.a->n_cols);
@ -387,7 +390,7 @@ struct Array2dIter{
};
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<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){
PyVar mod = vm->new_module("base64");
PyObject* mod = vm->new_module("base64");
// b64encode
vm->bind_func(mod, "b64encode", 1, [](VM* vm, ArgsView args){

View File

@ -1,4 +1,5 @@
#include "pocketpy/ceval.h"
#include "pocketpy/codeobject.h"
namespace pkpy{
@ -194,22 +195,22 @@ __NEXT_STEP:
PUSH(*slot);
DISPATCH()
}
PyVar _0 = frame->f_closure_try_get(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
_0 = frame->f_globals().try_get_likely_found(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
_0 = vm->builtins->attr().try_get_likely_found(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
PyVar* _0 = frame->f_closure_try_get(_name);
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
_0 = frame->f_globals().try_get_2_likely_found(_name);
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
_0 = vm->builtins->attr().try_get_2_likely_found(_name);
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
vm->NameError(_name);
} DISPATCH()
case OP_LOAD_NONLOCAL: {
StrName _name(byte.arg);
PyVar _0 = frame->f_closure_try_get(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
_0 = frame->f_globals().try_get_likely_found(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
_0 = vm->builtins->attr().try_get_likely_found(_name);
if(_0 != nullptr) { PUSH(_0); DISPATCH() }
PyVar* _0 = frame->f_closure_try_get(_name);
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
_0 = frame->f_globals().try_get_2_likely_found(_name);
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
_0 = vm->builtins->attr().try_get_2_likely_found(_name);
if(_0 != nullptr) { PUSH(*_0); DISPATCH() }
vm->NameError(_name);
} DISPATCH()
case OP_LOAD_GLOBAL:{
@ -282,7 +283,7 @@ __NEXT_STEP:
if(slot != nullptr){
*slot = _0; // store in locals if possible
}else{
Function& func = PK_OBJ_GET(Function, frame->_callable);
Function& func = frame->_callable->as<Function>();
if(func.decl == __dynamic_func_decl){
PK_DEBUG_ASSERT(func._closure != nullptr);
func._closure->set(_name, _0);
@ -338,7 +339,7 @@ __NEXT_STEP:
if(slot != nullptr){
slot->set_null();
}else{
Function& func = PK_OBJ_GET(Function, frame->_callable);
Function& func = frame->_callable->as<Function>();
if(func.decl == __dynamic_func_decl){
PK_DEBUG_ASSERT(func._closure != nullptr);
bool ok = func._closure->del(_name);
@ -949,7 +950,7 @@ __NEXT_STEP:
StrName _name(byte.arg);
frame->_module->attr().set(_name, __curr_class);
// 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){
PyTypeInfo* base_ti = &_all_types[ti->base];
if(base_ti->on_end_subclass) base_ti->on_end_subclass(this, ti);
@ -969,12 +970,12 @@ __NEXT_STEP:
PUSH(__curr_class);
} DISPATCH()
case OP_END_CLASS_DECORATION:{
__curr_class = POPX();
__curr_class = POPX().get();
} DISPATCH()
case OP_ADD_CLASS_ANNOTATION: {
PK_ASSERT(__curr_class != nullptr);
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);
} DISPATCH()
/*****************************************/
@ -1016,7 +1017,7 @@ __NEXT_STEP:
}
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: {
PyVar _0 = POPX();

View File

@ -2,25 +2,25 @@
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){
Type cls = PK_OBJ_GET(Type, args[0]);
i64 addr = CAST(i64, args[1]);
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);
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);
return _S("<void* at ", self.hex(), ">");
});
#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; \
void* _0 = PK_OBJ_GET(VoidP, lhs).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){
Type cls = PK_OBJ_GET(Type, args[0]);
int size = CAST(int, args[1]);
@ -72,7 +72,7 @@ namespace pkpy{
return vm->new_user_object<Struct>(std::move(buffer));
}, {}, 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);
SStream ss;
ss << "<struct object of " << self.size << " bytes>";
@ -94,7 +94,7 @@ namespace pkpy{
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);
if(!vm->is_user_type<Struct>(rhs)) return vm->NotImplemented;
Struct& other = _CAST(Struct&, rhs);
@ -134,7 +134,7 @@ namespace pkpy{
}
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){
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);
});
PyVar type;
PyObject* type;
Type type_t;
#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); \
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){ \
obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]); \
T* target = (T*)voidp.ptr; \
@ -255,7 +255,7 @@ void add_module_c(VM* vm){
#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){
obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);
const char* target = (const char*)voidp.ptr;

View File

@ -18,14 +18,14 @@ namespace pkpy
{
this->is_reversed = true;
}
void _gc_mark(VM* vm) const { PK_OBJ_MARK(ref); }
static void _register(VM *vm, PyVar mod, PyVar type);
void _gc_mark(VM* vm) const { vm->obj_gc_mark(ref); }
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; });
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);
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
int findIndex(VM *vm, PyVar obj, int start, int stop); // find the index of the given object in the deque
// 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 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 *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)
// 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);
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)
// 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);
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)
// 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);
i64 index = CAST(i64, _1);
@ -93,19 +93,19 @@ namespace pkpy
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);
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);
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 "[...]";
const PyDeque &self = _CAST(PyDeque&, _0);
@ -123,7 +123,7 @@ namespace pkpy
});
// 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);
if(!vm->is_user_type<PyDeque>(_0)) return vm->NotImplemented;
@ -534,13 +534,12 @@ namespace pkpy
/// @brief marks the deque items for garbage collection
void PyDeque::_gc_mark(VM* vm) const
{
for (PyVar obj : this->dequeItems)
PK_OBJ_MARK(obj);
for (PyVar obj : this->dequeItems) vm->obj_gc_mark(obj);
}
/// @brief registers the PyDeque class
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<PyDequeIter>(mod, "_deque_iter");
CodeObject_ code = vm->compile(kPythonLibs_collections, "collections.py", EXEC_MODE);

View File

@ -3,7 +3,7 @@
namespace pkpy{
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){
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){
PyVar mod = vm->new_module("dataclasses");
PyObject* mod = vm->new_module("dataclasses");
vm->bind_func(mod, "dataclass", 1, [](VM* vm, ArgsView args){
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){
PyVar mod = vm->new_module("easing");
PyObject* mod = vm->new_module("easing");
#define EASE(name) \
vm->bind_func(mod, #name, 1, [](VM* vm, ArgsView args){ \

View File

@ -120,26 +120,23 @@ namespace pkpy{
}else{
co->consts.push_back(VAR(key));
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;
}
}
int CodeEmitContext::add_const(PyVar v){
if(is_type(v, vm->tp_str)){
// warning: should use add_const_string() instead
return add_const_string(PK_OBJ_GET(Str, v).sv());
PK_ASSERT(!is_type(v, VM::tp_str))
// non-string deduplication
auto it = _co_consts_nonstring_dedup_map.find(v);
if(it != _co_consts_nonstring_dedup_map.end()){
return it->second;
}else{
// non-string deduplication
auto it = _co_consts_nonstring_dedup_map.find(v);
if(it != _co_consts_nonstring_dedup_map.end()){
return it->second;
}else{
co->consts.push_back(v);
int index = co->consts.size() - 1;
_co_consts_nonstring_dedup_map[v] = index;
return index;
}
co->consts.push_back(v);
int index = co->consts.size() - 1;
_co_consts_nonstring_dedup_map[v] = index;
return index;
}
}

View File

@ -16,11 +16,11 @@ namespace pkpy{
return dict;
}
PyVar Frame::f_closure_try_get(StrName name){
PyVar* Frame::f_closure_try_get(StrName name){
if(_callable == nullptr) return nullptr;
Function& fn = PK_OBJ_GET(Function, _callable);
Function& fn = _callable->as<Function>();
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){

View File

@ -15,7 +15,7 @@ struct FileIO {
FileIO(VM* vm, const Str& file, const Str& mode);
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){
@ -53,7 +53,7 @@ unsigned char* _default_import_handler(const char* name, int* out_size){
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){
Type cls = PK_OBJ_GET(Type, args[0]);
return vm->new_object<FileIO>(cls, vm,
@ -138,7 +138,7 @@ void FileIO::close(){
}
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");
mod->attr().set("SEEK_SET", VAR(SEEK_SET));
@ -153,7 +153,7 @@ void add_module_io(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);
mod->attr().set("path", path_obj);

View File

@ -2,9 +2,9 @@
namespace pkpy{
void RangeIter::_register(VM* vm, PyVar mod, PyVar type){
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
void RangeIter::_register(VM* vm, PyObject* mod, PyObject* type){
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
RangeIter& self = PK_OBJ_GET(RangeIter, _0);
if(self.current >= self.r.stop) return 0;
vm->s_data.emplace(VM::tp_int, self.current);
@ -13,9 +13,9 @@ namespace pkpy{
});
}
void RangeIterR::_register(VM* vm, PyVar mod, PyVar type){
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
void RangeIterR::_register(VM* vm, PyObject* mod, PyObject* type){
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
RangeIterR& self = PK_OBJ_GET(RangeIterR, _0);
if(self.current <= self.r.stop) return 0;
vm->s_data.emplace(VM::tp_int, self.current);
@ -24,9 +24,9 @@ namespace pkpy{
});
}
void ArrayIter::_register(VM* vm, PyVar mod, PyVar type){
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
void ArrayIter::_register(VM* vm, PyObject* mod, PyObject* type){
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
ArrayIter& self = _CAST(ArrayIter&, _0);
if(self.current == self.end) return 0;
vm->s_data.push(*self.current++);
@ -34,9 +34,9 @@ namespace pkpy{
});
}
void StringIter::_register(VM* vm, PyVar mod, PyVar type){
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
void StringIter::_register(VM* vm, PyObject* mod, PyObject* type){
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
StringIter& self = _CAST(StringIter&, _0);
Str& s = PK_OBJ_GET(Str, self.ref);
if(self.i == s.size) return 0;
@ -99,9 +99,9 @@ namespace pkpy{
}
}
void Generator::_register(VM* vm, PyVar mod, PyVar type){
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
void Generator::_register(VM* vm, PyObject* mod, PyObject* type){
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
Generator& self = _CAST(Generator&, _0);
PyVar retval = self.next(vm);
if(retval == vm->StopIteration) return 0;
@ -110,9 +110,9 @@ namespace pkpy{
});
}
void DictItemsIter::_register(VM *vm, PyVar mod, PyVar type){
vm->bind__iter__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0) -> unsigned{
void DictItemsIter::_register(VM *vm, PyObject* mod, PyObject* type){
vm->bind__iter__(type->as<Type>(), [](VM* vm, PyVar _0){ return _0; });
vm->bind__next__(type->as<Type>(), [](VM* vm, PyVar _0) -> unsigned{
DictItemsIter& self = _CAST(DictItemsIter&, _0);
Dict& d = PK_OBJ_GET(Dict, self.ref);
if(self.i == -1) return 0;

View File

@ -3,14 +3,14 @@
namespace pkpy{
#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 other = CAST(Vec##D, _1); \
return VAR(self op other); \
});
#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); \
f64 other = CAST(f64, _1); \
return VAR(self op other); \
@ -30,7 +30,7 @@ namespace pkpy{
});
#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); \
if(vm->is_user_type<Vec##D>(_1)){ \
Vec##D other = _CAST(Vec##D, _1); \
@ -44,14 +44,14 @@ namespace pkpy{
f64 other = CAST(f64, args[1]); \
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); \
f64 other = CAST(f64, _1); \
return VAR(self / other); \
});
#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); \
i64 i = CAST(i64, index); \
if(i < 0 || i >= D) vm->IndexError("index out of range"); \
@ -59,7 +59,7 @@ namespace pkpy{
});
#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); \
if(!vm->is_user_type<Vec##D>(_1)) return vm->NotImplemented; \
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);
}
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("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);
}, {}, 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);
SStream ss;
ss.setprecision(3);
@ -190,7 +190,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
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("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);
});
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);
SStream ss;
ss.setprecision(3);
@ -225,7 +225,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
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)
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);
});
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);
SStream ss;
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_GETITEM
void Mat3x3::_register(VM* vm, PyVar mod, PyVar type){
void Mat3x3::_register(VM* vm, PyObject* mod, PyObject* type){
PY_STRUCT_LIKE(Mat3x3)
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;
});
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);
SStream ss;
ss.setprecision(3);
@ -308,7 +308,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
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);
Tuple& t = CAST(Tuple&, index);
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]);
});
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);
const Tuple& t = CAST(Tuple&, index);
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, "_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& other = CAST(Mat3x3&, _1);
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& other = CAST(Mat3x3&, _1);
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);
f64 other = CAST_F(_1);
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);
});
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);
f64 other = CAST_F(_1);
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);
if(vm->is_user_type<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());
});
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 ret;
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){
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<Vec3>(linalg, "vec3", VM::tp_object);

View File

@ -26,7 +26,7 @@ struct PyStructTime{
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_mon", tm_mon);
PY_READONLY_FIELD(PyStructTime, "tm_mday", tm_mday);
@ -40,7 +40,7 @@ struct PyStructTime{
};
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->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){
PyVar mod = vm->new_module("sys");
PyObject* mod = vm->new_module("sys");
vm->setattr(mod, "version", VAR(PK_VERSION));
vm->setattr(mod, "platform", VAR(kPlatformStrings[PK_SYS_PLATFORM]));
PyVar stdout_ = vm->new_object<DummyInstance>(vm->tp_object);
PyVar stderr_ = vm->new_object<DummyInstance>(vm->tp_object);
PyObject* stdout_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
PyObject* stderr_ = vm->heap.gcnew<DummyInstance>(vm->tp_object);
vm->setattr(mod, "stdout", stdout_);
vm->setattr(mod, "stderr", stderr_);
@ -90,7 +90,7 @@ void add_module_sys(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) {
std::string_view sv;
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
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("e" , VAR(2.7182818284590452354));
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){
PyVar mod = vm->new_module("traceback");
PyObject* mod = vm->new_module("traceback");
vm->bind_func(mod, "print_exc", 0, [](VM* vm, ArgsView args) {
if(vm->__last_exception==nullptr) vm->ValueError("no exception");
Exception& e = _CAST(Exception&, vm->__last_exception);
@ -212,7 +212,7 @@ void add_module_traceback(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) {
CodeObject_ code;
@ -230,12 +230,12 @@ void add_module_dis(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())));
}
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);
vm->_exec(code, mod);
PyVar Enum = mod->attr("Enum");
@ -253,7 +253,7 @@ void add_module_enum(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){
return vm->py_next(args[0]);
@ -284,7 +284,7 @@ struct _LpGuard{
struct LineProfilerW{
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){
Type cls = PK_OBJ_GET(Type, args[0]);
return vm->new_object<LineProfilerW>(cls);
@ -333,7 +333,7 @@ _LpGuard::~_LpGuard(){
}
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");
}
#else

View File

@ -1,6 +1,8 @@
#include "pocketpy/obj.h"
namespace pkpy{
PyVar::PyVar(PyObject* p): PyVar(p->type, p) {}
bool Bytes::operator==(const Bytes& rhs) const{
if(_size != rhs._size) 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){
static_assert(std::is_same_v<T, List> || std::is_same_v<T, Tuple>);
const T& self = _CAST(T&, _0);
i64 index;
if(try_cast_int(_1, &index)){
if(is_int(_1)){
i64 index = _1.as<i64>();
index = vm->normalized_index(index, self.size());
return self[index];
}
@ -28,16 +28,14 @@ PyVar PyArrayGetItem(VM* vm, PyVar _0, PyVar _1){
void __init_builtins(VM* _vm) {
#define BIND_NUM_ARITH_OPT(name, op) \
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
i64 val; \
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)); \
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
if(is_int(rhs)) return VAR(_CAST(i64, lhs) op _CAST(i64, rhs)); \
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
return vm->NotImplemented; \
}); \
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
i64 val; \
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)); \
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
if(is_int(rhs)) return VAR(_CAST(f64, lhs) op _CAST(i64, rhs)); \
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
return vm->NotImplemented; \
});
@ -48,15 +46,13 @@ void __init_builtins(VM* _vm) {
#undef BIND_NUM_ARITH_OPT
#define BIND_NUM_LOGICAL_OPT(name, op) \
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
i64 val; \
if(try_cast_int(rhs, &val)) return VAR(_CAST(i64, lhs) op val); \
_vm->bind##name(VM::tp_int, [](VM* vm, PyVar lhs, PyVar rhs) { \
if(is_int(rhs)) return VAR(_CAST(i64, lhs) op _CAST(i64, rhs)); \
if(is_float(rhs)) return VAR(_CAST(i64, lhs) op _CAST(f64, rhs)); \
return vm->NotImplemented; \
}); \
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
i64 val; \
if(try_cast_int(rhs, &val)) return VAR(_CAST(f64, lhs) op val); \
_vm->bind##name(VM::tp_float, [](VM* vm, PyVar lhs, PyVar rhs) { \
if(is_int(rhs)) return VAR(_CAST(f64, lhs) op _CAST(i64, rhs)); \
if(is_float(rhs)) return VAR(_CAST(f64, lhs) op _CAST(f64, rhs)); \
return vm->NotImplemented; \
});
@ -79,15 +75,15 @@ void __init_builtins(VM* _vm) {
});
_vm->bind_func(_vm->builtins, "super", -1, [](VM* vm, ArgsView args) {
PyVar class_arg = nullptr;
PyObject* class_arg = nullptr;
PyVar self_arg = nullptr;
if(args.size() == 2){
class_arg = args[0];
class_arg = args[0].get();
self_arg = args[1];
}else if(args.size() == 0){
Frame* frame = &vm->callstack.top();
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(class_arg == nullptr || self_arg == nullptr){
@ -97,7 +93,7 @@ void __init_builtins(VM* _vm) {
vm->TypeError("super() takes 0 or 2 arguments");
}
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)){
StrName _0 = _type_name(vm, vm->_tp(self_arg));
StrName _1 = _type_name(vm, type);
@ -123,7 +119,7 @@ void __init_builtins(VM* _vm) {
Tuple& types = _CAST(Tuple&, args[1]);
for(PyVar type : types){
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;
}
@ -139,7 +135,7 @@ void __init_builtins(VM* _vm) {
});
_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));
});
@ -395,8 +391,9 @@ void __init_builtins(VM* _vm) {
});
auto py_number_pow = [](VM* vm, PyVar _0, PyVar _1) {
i64 lhs, rhs;
if(try_cast_int(_0, &lhs) && try_cast_int(_1, &rhs)){
if(is_int(_0) && is_int(_1)){
i64 lhs = _CAST(i64, _0);
i64 rhs = _CAST(i64, _1);
if(rhs < 0) {
if(lhs == 0) vm->ZeroDivisionError("0.0 cannot be raised to a negative power");
return VAR((f64)std::pow(lhs, rhs));
@ -1484,12 +1481,12 @@ void __init_builtins(VM* _vm) {
});
// 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]);
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();
PK_OBJ_GET(Exception, e_obj)._self = e_obj;
e_obj->as<Exception>()._self = 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])];
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])];
if(info.mod == nullptr) return vm->None;
return info.mod;
@ -1591,7 +1588,7 @@ void VM::__post_init_builtin_types(){
bind_property(_t(tp_object), "__dict__", [](VM* vm, ArgsView args){
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) {

View File

@ -48,8 +48,8 @@ static PyVar stack_item(VM* vm, int index){
vm->__c.error = e.self(); \
return false; \
} catch(const std::exception& re){ \
PyVar e_t = vm->_t(vm->tp_exception); \
vm->__c.error = vm->call(e_t, VAR(re.what())); \
PyObject* e_t = vm->_t(vm->tp_exception); \
vm->__c.error = vm->call(e_t, VAR(re.what())).get(); \
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;
PK_ASSERT_NO_ERROR()
PyVar res;
PyVar mod;
PyObject* mod;
PK_PROTECTED(
if(module == nullptr){
mod = vm->_main;
}else{
mod = vm->_modules[module]; // may raise
mod = vm->_modules[module].get(); // may raise
}
CodeObject_ code = vm->compile(source, filename, (CompileMode)mode);
res = vm->_exec(code, mod);
@ -342,7 +342,7 @@ static PyVar c_function_wrapper(VM* vm, ArgsView args) {
// propagate_if_errored
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->_error(e_obj);
return nullptr;
@ -370,8 +370,8 @@ bool pkpy_push_module(pkpy_vm* vm_handle, const char* name) {
VM* vm = (VM*) vm_handle;
PK_ASSERT_NO_ERROR()
PK_PROTECTED(
PyVar module = vm->new_module(name);
vm->s_data.push(module);
PyObject* module = vm->new_module(name);
vm->s_data.emplace(module);
)
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;
}
}
vm->__c.error = vm->call(e_t, VAR(message));
vm->__c.error = vm->call(e_t, VAR(message)).get();
return false;
}
@ -524,7 +524,7 @@ bool pkpy_clear_error(pkpy_vm* vm_handle, char** message) {
VM* vm = (VM*) vm_handle;
// no error
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)
*message = strdup(e.summary().c_str());
else

View File

@ -133,7 +133,7 @@ struct Random{
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){
Type cls = PK_OBJ_GET(Type, args[0]);
return vm->new_object<Random>(cls);
@ -215,7 +215,7 @@ struct Random{
};
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");
PyVar instance = vm->new_user_object<Random>();
mod->attr().set("seed", vm->getattr(instance, "seed"));

View File

@ -376,8 +376,8 @@ int utf8len(unsigned char c, bool suppress){
return cnt;
}
std::map<std::string, uint16_t, std::less<>>& StrName::_interned(){
static std::map<std::string, uint16_t, std::less<>> interned;
std::map<std::string_view, uint16_t>& StrName::_interned(){
static std::map<std::string_view, uint16_t> 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
uint16_t index = ((_pesudo_random_index*5) + 1) & 65535;
if(index == 0) throw std::runtime_error("StrName index overflow");
_interned()[std::string(s)] = index;
if(is_valid(index)) throw std::runtime_error("StrName index conflict");
_r_interned()[index] = std::string(s);
auto res = _r_interned().emplace(index, s);
PK_ASSERT(res.second);
s = std::string_view(res.first->second);
_interned()[s] = index;
_pesudo_random_index = index;
return StrName(index);
}
bool StrName::is_valid(int index) {
return _r_interned().find(index) != _r_interned().end();
}
Str SStream::str(){
// after this call, the buffer is no longer valid
buffer.reserve(buffer.size() + 1); // allocate one more byte for '\0'

View File

@ -1,4 +1,5 @@
#include "pocketpy/vm.h"
#include "pocketpy/obj.h"
static const char* OP_NAMES[] = {
#define OPCODE(name) #name,
@ -78,6 +79,7 @@ namespace pkpy{
_ceval_on_step = nullptr;
_stdout = [](const char* buf, int size) { std::cout.write(buf, size); };
_stderr = [](const char* buf, int size) { std::cerr.write(buf, size); };
builtins = nullptr;
_main = nullptr;
__last_exception = nullptr;
_import_handler = [](const char* name, int* out_size) -> unsigned char*{ return nullptr; };
@ -167,7 +169,7 @@ namespace pkpy{
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;
try {
#if PK_DEBUG_PRECOMPILED_EXEC == 1
@ -204,8 +206,8 @@ namespace pkpy{
return exec(source, "<eval>", EVAL_MODE);
}
PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt){
PyVar obj = heap._new<Type>(tp_type, Type(_all_types.size()));
PyObject* VM::new_type_object(PyObject* mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt){
PyObject* obj = heap._new<Type>(tp_type, Type(_all_types.size()));
const PyTypeInfo& base_info = _all_types[base];
if(!base_info.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();
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);
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(obj->is_attr_valid()){
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
PyVar globals_obj = nullptr;
PyObject* globals_obj = nullptr;
Dict* globals_dict = nullptr;
NameDict_ locals_closure = nullptr;
@ -578,7 +580,7 @@ PyVar VM::__py_exec_internal(const CodeObject_& code, PyVar globals, PyVar local
}else{
check_compatible_type(globals, VM::tp_dict);
// 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_dict = &PK_OBJ_GET(Dict, globals);
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_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);
}
@ -713,8 +715,8 @@ PyVar VM::__format_object(PyVar obj, Str spec){
return VAR(ret);
}
PyVar VM::new_module(Str name, Str package) {
PyVar obj = heap._new<DummyModule>(tp_module);
PyObject* VM::new_module(Str name, Str package) {
PyObject* obj = heap._new<DummyModule>(tp_module);
obj->attr().set(__name__, VAR(name));
obj->attr().set(__package__, VAR(package));
// convert to fullname
@ -1091,7 +1093,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
case FuncType::GENERATOR:
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
s_data.reset(p0);
callstack.emplace(nullptr, co, fn._module, callable, nullptr);
callstack.emplace(nullptr, co, fn._module, callable.get(), nullptr);
return __py_generator(
callstack.popx(),
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)
@ -1104,7 +1106,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
};
// 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;
return __run_top_frame();
/*****************_py_call*****************/
@ -1357,22 +1359,26 @@ void VM::setattr(PyVar obj, StrName name, PyVar value){
obj->attr().set(name, value);
}
PyVar VM::bind_func(PyVar obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
PyVar nf = VAR(NativeFunc(fn, argc, std::move(userdata)));
PyObject* VM::bind_func(PyObject* obj, StrName name, int argc, NativeFuncC fn, any userdata, BindType bt) {
PyObject* nf = heap.gcnew<NativeFunc>(tp_native_func, fn, argc, std::move(userdata));
switch(bt){
case BindType::DEFAULT: break;
case BindType::STATICMETHOD: nf = VAR(StaticMethod(nf)); break;
case BindType::CLASSMETHOD: nf = VAR(ClassMethod(nf)); break;
case BindType::STATICMETHOD:
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);
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);
}
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;
try{
// 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];
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){
case BindType::STATICMETHOD:
f_obj = VAR(StaticMethod(f_obj));
f_obj = heap.gcnew<StaticMethod>(tp_staticmethod, f_obj);
break;
case BindType::CLASSMETHOD:
f_obj = VAR(ClassMethod(f_obj));
f_obj = heap.gcnew<ClassMethod>(tp_classmethod, f_obj);
break;
case BindType::DEFAULT:
break;
@ -1401,14 +1407,14 @@ PyVar VM::bind(PyVar obj, const char* sig, const char* docstring, NativeFuncC fn
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));
std::string_view name_sv(name); int pos = name_sv.find(':');
if(pos > 0) name_sv = name_sv.substr(0, pos);
PyVar _0 = new_object<NativeFunc>(tp_native_func, fget, 1);
PyVar _1 = vm->None;
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);
return prop;
}
@ -1474,14 +1480,14 @@ StrName _type_name(VM *vm, Type type){
void VM::bind__getitem__(Type type, PyVar (*f)(VM*, PyVar, PyVar)){
_all_types[type].m__getitem__ = f;
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);
}
void VM::bind__setitem__(Type type, void (*f)(VM*, PyVar, PyVar, PyVar)){
_all_types[type].m__setitem__ = f;
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;
}, 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)){
_all_types[type].m__delitem__ = f;
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;
}, f);
}
@ -1505,7 +1511,7 @@ PyVar VM::__pack_next_retval(unsigned n){
void VM::bind__next__(Type type, unsigned (*f)(VM*, PyVar)){
_all_types[type].op__next__ = f;
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);
}, f);
}
@ -1792,7 +1798,7 @@ void Function::_gc_mark(VM* vm) const{
decl->_gc_mark(vm);
if(_closure){
_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{
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{
for(PyVar obj: *this) PK_OBJ_MARK(obj);
for(PyVar obj: *this) vm->obj_gc_mark(obj);
}
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{
PK_OBJ_MARK(obj);
vm->__obj_gc_mark(obj);
}
void BoundMethod::_gc_mark(VM* vm) const{
PK_OBJ_MARK(func);
PK_OBJ_MARK(self);
vm->obj_gc_mark(func);
vm->obj_gc_mark(self);
}
void StarWrapper::_gc_mark(VM* vm) const{
PK_OBJ_MARK(obj);
vm->obj_gc_mark(obj);
}
void StaticMethod::_gc_mark(VM* vm) const{
PK_OBJ_MARK(func);
vm->obj_gc_mark(func);
}
void ClassMethod::_gc_mark(VM* vm) const{
PK_OBJ_MARK(func);
vm->obj_gc_mark(func);
}
void Property::_gc_mark(VM* vm) const{
PK_OBJ_MARK(getter);
PK_OBJ_MARK(setter);
vm->obj_gc_mark(getter);
vm->obj_gc_mark(setter);
}
void Slice::_gc_mark(VM* vm) const{
PK_OBJ_MARK(start);
PK_OBJ_MARK(stop);
PK_OBJ_MARK(step);
vm->obj_gc_mark(start);
vm->obj_gc_mark(stop);
vm->obj_gc_mark(step);
}
void Super::_gc_mark(VM* vm) const{
PK_OBJ_MARK(first);
vm->obj_gc_mark(first);
}
void Frame::_gc_mark(VM* vm) const {
PK_OBJ_MARK(_module);
vm->obj_gc_mark(_module);
co->_gc_mark(vm);
// 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() {
for(PyObject* obj: _no_gc) vm->__obj_gc_mark(obj);
vm->callstack.apply([this](Frame& frame){ frame._gc_mark(vm); });
for(auto [_, co]: vm->__cached_codes) co->_gc_mark(vm);
if(vm->__last_exception) PK_OBJ_MARK(vm->__last_exception);
if(vm->__curr_class) PK_OBJ_MARK(vm->__curr_class);
if(vm->__c.error != nullptr) PK_OBJ_MARK(vm->__c.error);
vm->obj_gc_mark(vm->__last_exception);
vm->obj_gc_mark(vm->__curr_class);
vm->obj_gc_mark(vm->__c.error);
vm->__stack_gc_mark(vm->s_data.begin(), vm->s_data.end());
if(_gc_marker_ex) _gc_marker_ex(vm);
}
@ -1880,13 +1886,13 @@ void ManagedHeap::_delete(PyObject* obj){
void Dict::_gc_mark(VM* vm) const{
apply([vm](PyVar k, PyVar v){
PK_OBJ_MARK(k);
PK_OBJ_MARK(v);
vm->obj_gc_mark(k);
vm->obj_gc_mark(v);
});
}
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);
}