Răsfoiți Sursa

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
blueloveTH 1 an în urmă
părinte
comite
1e365ca72c

+ 155 - 155
.github/workflows/main.yml

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

+ 39 - 39
.github/workflows/website.yml

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

+ 1 - 1
3rd/cjson/src/cJSONw.cpp

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

+ 4 - 4
3rd/lua_bridge/src/lua_bridge.cpp

@@ -38,8 +38,8 @@ struct PyLuaObject{
 };
 };
 
 
 struct PyLuaTable: 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];
         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");

+ 5 - 5
docs/1_5_0.md

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

+ 3 - 3
docs/bindings.md

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

+ 1 - 1
docs/cheatsheet.md

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

+ 1 - 1
docs/quick-start/modules.md

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

+ 9 - 9
include/pocketpy/bindings.h

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

+ 3 - 3
include/pocketpy/cffi.h

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

+ 3 - 3
include/pocketpy/codeobject.h

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

+ 6 - 4
include/pocketpy/common.h

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

+ 2 - 2
include/pocketpy/error.h

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

+ 1 - 1
include/pocketpy/expr.h

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

+ 8 - 14
include/pocketpy/frame.h

@@ -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;
-    PyVar _callable;    // a function object or nullptr (global scope)
+    PyObject* _module;
+    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; }

+ 4 - 4
include/pocketpy/gc.h

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

+ 8 - 8
include/pocketpy/iter.h

@@ -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); }
-    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{
 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); }
-    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
 } // namespace pkpy

+ 4 - 4
include/pocketpy/linalg.h

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

+ 5 - 0
include/pocketpy/namedict.h

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

+ 6 - 11
include/pocketpy/obj.h

@@ -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;
-    MappingProxy(PyVar obj) : obj(obj) {}
+    PyObject* 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_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 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;

+ 1 - 2
include/pocketpy/str.h

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

+ 2 - 2
include/pocketpy/tuplelist.h

@@ -7,8 +7,8 @@
 
 
 namespace pkpy {
 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;
     void _gc_mark(VM*) const;
 };
 };
 
 

+ 2 - 1
include/pocketpy/vector.h

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

+ 35 - 34
include/pocketpy/vm.h

@@ -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;
-    PyVar __curr_class; 
+    PyObject* __last_exception;
+    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);
-    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);
         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; }
-    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
     // 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="");
-    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>
     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(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());
         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){
-    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);
     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);
 }
 }
 
 

+ 19 - 16
src/array2d.cpp

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

+ 1 - 1
src/base64.cpp

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

+ 19 - 18
src/ceval.cpp

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

+ 11 - 11
src/cffi.cpp

@@ -2,25 +2,25 @@
 
 
 namespace pkpy{
 namespace pkpy{
 
 
-    void VoidP::_register(VM* vm, PyVar mod, PyVar type){
+    void VoidP::_register(VM* vm, PyObject* mod, PyObject* type){
         vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
         vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
             Type cls = PK_OBJ_GET(Type, args[0]);
             Type cls = PK_OBJ_GET(Type, args[0]);
             i64 addr = CAST(i64, args[1]);
             i64 addr = CAST(i64, args[1]);
             return vm->new_object<VoidP>(cls, reinterpret_cast<void*>(addr));
             return vm->new_object<VoidP>(cls, reinterpret_cast<void*>(addr));
         });
         });
 
 
-        vm->bind__hash__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
+        vm->bind__hash__(type->as<Type>(), [](VM* vm, PyVar obj){
             obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
             obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
             return reinterpret_cast<i64>(self.ptr);
             return reinterpret_cast<i64>(self.ptr);
         });
         });
 
 
-        vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj) -> Str{
+        vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj) -> Str{
             obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
             obj_get_t<VoidP> self = PK_OBJ_GET(VoidP, obj);
             return _S("<void* at ", self.hex(), ">");
             return _S("<void* at ", self.hex(), ">");
         });
         });
 
 
 #define BIND_CMP(name, op)  \
 #define BIND_CMP(name, op)  \
-        vm->bind##name(PK_OBJ_GET(Type, type), [](VM* vm, PyVar lhs, PyVar rhs){        \
+        vm->bind##name(type->as<Type>(), [](VM* vm, PyVar lhs, PyVar rhs){        \
             if(!vm->isinstance(rhs, vm->_tp_user<VoidP>())) return vm->NotImplemented;          \
             if(!vm->isinstance(rhs, vm->_tp_user<VoidP>())) return vm->NotImplemented;          \
             void* _0 = PK_OBJ_GET(VoidP, lhs).ptr;                                              \
             void* _0 = PK_OBJ_GET(VoidP, lhs).ptr;                                              \
             void* _1 = PK_OBJ_GET(VoidP, rhs).ptr;                                              \
             void* _1 = PK_OBJ_GET(VoidP, rhs).ptr;                                              \
@@ -37,7 +37,7 @@ namespace pkpy{
     }
     }
 
 
 
 
-    void Struct::_register(VM* vm, PyVar mod, PyVar type){
+    void Struct::_register(VM* vm, PyObject* mod, PyObject* type){
         vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
         vm->bind_func(type, __new__, 2, [](VM* vm, ArgsView args){
             Type cls = PK_OBJ_GET(Type, args[0]);
             Type cls = PK_OBJ_GET(Type, args[0]);
             int size = CAST(int, args[1]);
             int size = CAST(int, args[1]);
@@ -72,7 +72,7 @@ namespace pkpy{
             return vm->new_user_object<Struct>(std::move(buffer));
             return vm->new_user_object<Struct>(std::move(buffer));
         }, {}, BindType::STATICMETHOD);
         }, {}, BindType::STATICMETHOD);
 
 
-        vm->bind__repr__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar obj){
+        vm->bind__repr__(type->as<Type>(), [](VM* vm, PyVar obj){
             Struct& self = _CAST(Struct&, obj);
             Struct& self = _CAST(Struct&, obj);
             SStream ss;
             SStream ss;
             ss << "<struct object of " << self.size << " bytes>";
             ss << "<struct object of " << self.size << " bytes>";
@@ -94,7 +94,7 @@ namespace pkpy{
             return vm->new_object<Struct>(vm->_tp(args[0]), self);
             return vm->new_object<Struct>(vm->_tp(args[0]), self);
         });
         });
 
 
-        vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar lhs, PyVar rhs){
+        vm->bind__eq__(type->as<Type>(), [](VM* vm, PyVar lhs, PyVar rhs){
             Struct& self = _CAST(Struct&, lhs);
             Struct& self = _CAST(Struct&, lhs);
             if(!vm->is_user_type<Struct>(rhs)) return vm->NotImplemented;
             if(!vm->is_user_type<Struct>(rhs)) return vm->NotImplemented;
             Struct& other = _CAST(Struct&, rhs);
             Struct& other = _CAST(Struct&, rhs);
@@ -134,7 +134,7 @@ namespace pkpy{
     }
     }
 
 
 void add_module_c(VM* vm){
 void add_module_c(VM* vm){
-    PyVar mod = vm->new_module("c");
+    PyObject* mod = vm->new_module("c");
     
     
     vm->bind_func(mod, "malloc", 1, [](VM* vm, ArgsView args){
     vm->bind_func(mod, "malloc", 1, [](VM* vm, ArgsView args){
         i64 size = CAST(i64, args[0]);
         i64 size = CAST(i64, args[0]);
@@ -187,7 +187,7 @@ void add_module_c(VM* vm){
         return vm->new_object<VoidP>(args[0].type, value);
         return vm->new_object<VoidP>(args[0].type, value);
     });
     });
 
 
-    PyVar type;
+    PyObject* type;
     Type type_t;
     Type type_t;
 
 
 #define BIND_PRIMITIVE(T, CNAME) \
 #define BIND_PRIMITIVE(T, CNAME) \
@@ -197,7 +197,7 @@ void add_module_c(VM* vm){
     });                                                                             \
     });                                                                             \
     type = vm->new_type_object(mod, CNAME "_p", vm->_tp_user<VoidP>(), true);       \
     type = vm->new_type_object(mod, CNAME "_p", vm->_tp_user<VoidP>(), true);       \
     mod->attr().set(CNAME "_p", type);                                  \
     mod->attr().set(CNAME "_p", type);                                  \
-    type_t = PK_OBJ_GET(Type, type);                                    \
+    type_t = type->as<Type>();                                    \
     vm->bind_func(type, "read", 1, [](VM* vm, ArgsView args){           \
     vm->bind_func(type, "read", 1, [](VM* vm, ArgsView args){           \
         obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);            \
         obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);            \
         T* target = (T*)voidp.ptr;                                      \
         T* target = (T*)voidp.ptr;                                      \
@@ -255,7 +255,7 @@ void add_module_c(VM* vm){
 
 
 #undef BIND_PRIMITIVE
 #undef BIND_PRIMITIVE
 
 
-    PyVar char_p_t = mod->attr("char_p");
+    PyObject* char_p_t = mod->attr("char_p").get();
     vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args){
     vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args){
         obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);
         obj_get_t<VoidP> voidp = PK_OBJ_GET(VoidP, args[0]);
         const char* target = (const char*)voidp.ptr;
         const char* target = (const char*)voidp.ptr;

+ 16 - 17
src/collections.cpp

@@ -18,14 +18,14 @@ namespace pkpy
         {
         {
             this->is_reversed = true;
             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; });
                          { 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)
-            PK_OBJ_MARK(obj);
+        for (PyVar obj : this->dequeItems) vm->obj_gc_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);

+ 1 - 1
src/csv.cpp

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

+ 1 - 1
src/dataclasses.cpp

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

+ 1 - 1
src/easing.cpp

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

+ 11 - 14
src/expr.cpp

@@ -120,26 +120,23 @@ 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)){
-            // 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{
         }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;
         }
         }
     }
     }
 
 

+ 3 - 3
src/frame.cpp

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

+ 4 - 4
src/io.cpp

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

+ 18 - 18
src/iter.cpp

@@ -2,9 +2,9 @@
 
 
 namespace pkpy{
 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);
             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){
-        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);
             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){
-        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);
             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){
-        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);
             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){
-        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);
             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){
-        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);
             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;

+ 23 - 23
src/linalg.cpp

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

+ 14 - 14
src/modules.cpp

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

+ 2 - 0
src/obj.cpp

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

+ 26 - 29
src/pocketpy.cpp

@@ -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(try_cast_int(_1, &index)){
+    if(is_int(_1)){
+        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];
     }
     }
@@ -28,16 +28,14 @@ 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) {                              \
-        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;                                                                      \
         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;                                                                      \
         return vm->NotImplemented;                                                                      \
     });
     });
 
 
@@ -48,15 +46,13 @@ void __init_builtins(VM* _vm) {
 #undef BIND_NUM_ARITH_OPT
 #undef BIND_NUM_ARITH_OPT
 
 
 #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) {      \
-        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));     \
         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) {    \
-        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));     \
         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(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(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) {

+ 9 - 9
src/pocketpy_c.cpp

@@ -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); \
-        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; \
         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);
-        vm->s_data.push(module);
+        PyObject* module = vm->new_module(name);
+        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

+ 2 - 2
src/random.cpp

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

+ 6 - 9
src/str.cpp

@@ -376,8 +376,8 @@ int utf8len(unsigned char c, bool suppress){
         return cnt;
         return cnt;
     }
     }
 
 
-    std::map<std::string, uint16_t, std::less<>>& StrName::_interned(){
-        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;
         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;
-        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;
         _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'

+ 57 - 51
src/vm.cpp

@@ -1,4 +1,5 @@
 #include "pocketpy/vm.h"
 #include "pocketpy/vm.h"
+#include "pocketpy/obj.h"
 
 
 static const char* OP_NAMES[] = {
 static const char* OP_NAMES[] = {
     #define OPCODE(name) #name,
     #define OPCODE(name) #name,
@@ -78,6 +79,7 @@ namespace pkpy{
         _ceval_on_step = nullptr;
         _ceval_on_step = nullptr;
         _stdout = [](const char* buf, int size) { std::cout.write(buf, size); };
         _stdout = [](const char* buf, int size) { std::cout.write(buf, size); };
         _stderr = [](const char* buf, int size) { std::cerr.write(buf, size); };
         _stderr = [](const char* buf, int size) { std::cerr.write(buf, size); };
+        builtins = nullptr;
         _main = nullptr;
         _main = nullptr;
         __last_exception = nullptr;
         __last_exception = nullptr;
         _import_handler = [](const char* name, int* out_size) -> unsigned char*{ return nullptr; };
         _import_handler = [](const char* name, int* out_size) -> unsigned char*{ return nullptr; };
@@ -167,7 +169,7 @@ namespace pkpy{
         return false;
         return false;
     }
     }
 
 
-    PyVar VM::exec(std::string_view source, Str filename, CompileMode mode, PyVar _module){
+    PyVar VM::exec(std::string_view source, Str filename, CompileMode mode, PyObject* _module){
         if(_module == nullptr) _module = _main;
         if(_module == nullptr) _module = _main;
         try {
         try {
 #if PK_DEBUG_PRECOMPILED_EXEC == 1
 #if PK_DEBUG_PRECOMPILED_EXEC == 1
@@ -204,8 +206,8 @@ namespace pkpy{
         return exec(source, "<eval>", EVAL_MODE);
         return exec(source, "<eval>", EVAL_MODE);
     }
     }
 
 
-    PyVar VM::new_type_object(PyVar mod, StrName name, Type base, bool subclass_enabled, PyTypeInfo::Vt vt){
-        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];
         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) {
-    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(__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) {
-    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){
     switch(bt){
         case BindType::DEFAULT: break;
         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);
     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);
-    PK_OBJ_MARK(self);
+    vm->obj_gc_mark(func);
+    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);
-    PK_OBJ_MARK(setter);
+    vm->obj_gc_mark(getter);
+    vm->obj_gc_mark(setter);
 }
 }
 
 
 void Slice::_gc_mark(VM* vm) const{
 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{
 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);
-    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());
     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);
-        PK_OBJ_MARK(v);
+        vm->obj_gc_mark(k);
+        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);
 }
 }