blueloveTH hai 1 ano
pai
achega
d1e6fdc948

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

@@ -1,206 +1,206 @@
-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@v4
-    #   with:
-    #     name: amalgamated
-    #     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/x86_64
-        python cmake_build.py
-        cp main.exe output/x86_64
-        cp pocketpy.dll output/x86_64
-    - uses: actions/upload-artifact@v4
-      with:
-        name: windows
-        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/x86_64
-        python cmake_build.py
-        cp main output/x86_64
-        cp libpocketpy.so output/x86_64
-      env:
-        CXX: clang++
-        CC: clang
-    - uses: actions/upload-artifact@v4
-      with:
-        name: linux
-        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 output
-          xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
-          cp -r build/Release/pocketpy.bundle output
-      - uses: actions/upload-artifact@v4
-        with:
-          name: macos
-          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@v4
+#     #   with:
+#     #     name: amalgamated
+#     #     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/x86_64
+#         python cmake_build.py
+#         cp main.exe output/x86_64
+#         cp pocketpy.dll output/x86_64
+#     - uses: actions/upload-artifact@v4
+#       with:
+#         name: windows
+#         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/x86_64
+#         python cmake_build.py
+#         cp main output/x86_64
+#         cp libpocketpy.so output/x86_64
+#       env:
+#         CXX: clang++
+#         CC: clang
+#     - uses: actions/upload-artifact@v4
+#       with:
+#         name: linux
+#         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 output
+#           xcodebuild clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
+#           cp -r build/Release/pocketpy.bundle output
+#       - uses: actions/upload-artifact@v4
+#         with:
+#           name: macos
+#           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/arm64-v8a
-          mkdir -p output/armeabi-v7a
-          mkdir -p output/x86_64
+#           mkdir -p output/arm64-v8a
+#           mkdir -p output/armeabi-v7a
+#           mkdir -p output/x86_64
 
-          cp build/android/arm64-v8a/libpocketpy.so output/arm64-v8a
-          cp build/android/armeabi-v7a/libpocketpy.so output/armeabi-v7a
-          cp build/android/x86_64/libpocketpy.so output/x86_64
-        env:
-          ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
-      - uses: actions/upload-artifact@v4
-        with:
-          name: android
-          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
-          cp -r build/pocketpy.xcframework output/pocketpy.xcframework
-      - uses: actions/upload-artifact@v4
-        with:
-          name: ios
-          path: output
+#           cp build/android/arm64-v8a/libpocketpy.so output/arm64-v8a
+#           cp build/android/armeabi-v7a/libpocketpy.so output/armeabi-v7a
+#           cp build/android/x86_64/libpocketpy.so output/x86_64
+#         env:
+#           ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }}
+#       - uses: actions/upload-artifact@v4
+#         with:
+#           name: android
+#           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
+#           cp -r build/pocketpy.xcframework output/pocketpy.xcframework
+#       - uses: actions/upload-artifact@v4
+#         with:
+#           name: ios
+#           path: output
 
-  merge:
-      runs-on: ubuntu-latest
-      needs: [ build_win32, build_linux, build_darwin, build_android, build_ios ]
-      steps:
-      - name: "Create output directory"
-        run: "mkdir $GITHUB_WORKSPACE/output"
+#   merge:
+#       runs-on: ubuntu-latest
+#       needs: [ build_win32, build_linux, build_darwin, build_android, build_ios ]
+#       steps:
+#       - name: "Create output directory"
+#         run: "mkdir $GITHUB_WORKSPACE/output"
         
-      - name: "Merge win32"
-        uses: actions/download-artifact@v4.1.7
-        with:
-          name: windows
-          path: $GITHUB_WORKSPACE/output/windows
+#       - name: "Merge win32"
+#         uses: actions/download-artifact@v4.1.7
+#         with:
+#           name: windows
+#           path: $GITHUB_WORKSPACE/output/windows
 
-      - name: "Merge linux"
-        uses: actions/download-artifact@v4.1.7
-        with:
-          name: linux
-          path: $GITHUB_WORKSPACE/output/linux
+#       - name: "Merge linux"
+#         uses: actions/download-artifact@v4.1.7
+#         with:
+#           name: linux
+#           path: $GITHUB_WORKSPACE/output/linux
 
-      - name: "Merge darwin"
-        uses: actions/download-artifact@v4.1.7
-        with:
-          name: macos
-          path: $GITHUB_WORKSPACE/output/macos
+#       - name: "Merge darwin"
+#         uses: actions/download-artifact@v4.1.7
+#         with:
+#           name: macos
+#           path: $GITHUB_WORKSPACE/output/macos
 
-      - name: "Merge android"
-        uses: actions/download-artifact@v4.1.7
-        with:
-          name: android
-          path: $GITHUB_WORKSPACE/output/android
+#       - name: "Merge android"
+#         uses: actions/download-artifact@v4.1.7
+#         with:
+#           name: android
+#           path: $GITHUB_WORKSPACE/output/android
           
-      - name: "Merge ios"
-        uses: actions/download-artifact@v4.1.7
-        with:
-          name: ios
-          path: $GITHUB_WORKSPACE/output/ios
+#       - name: "Merge ios"
+#         uses: actions/download-artifact@v4.1.7
+#         with:
+#           name: ios
+#           path: $GITHUB_WORKSPACE/output/ios
 
-      - name: "Upload merged artifact"
-        uses: actions/upload-artifact@v4.3.3
-        with:
-          name: all-in-one
-          path: $GITHUB_WORKSPACE/output
+#       - name: "Upload merged artifact"
+#         uses: actions/upload-artifact@v4.3.3
+#         with:
+#           name: all-in-one
+#           path: $GITHUB_WORKSPACE/output

+ 57 - 11
include/pocketpy/common/vector.hpp

@@ -4,6 +4,7 @@
 #include <cstdlib>
 #include <cstring>
 #include <memory>
+#include <algorithm>
 
 #include "pocketpy/common/traits.hpp"
 #include "pocketpy/common/types.hpp"
@@ -193,24 +194,21 @@ struct vector {
             new (&_data[_size++]) T(begin[i]);
     }
 
-    void insert(int index, const T& t) {
+    void insert(T* it, const T& t) {
+        assert(it >= begin() && it <= end());
         if(_size == _capacity) reserve(_capacity * 2);
-        for(int i = _size; i > index; i--)
-            _data[i] = std::move(_data[i - 1]);
-        _data[index] = t;
-        _size++;
+        // TODO: implement
     }
 
-    void erase(int index) {
-        for(int i = index; i < _size - 1; i++)
-            _data[i] = std::move(_data[i + 1]);
-        _size--;
+    void erase(T* it) {
+        assert(it >= begin() && it < end());
+        // TODO: implement
     }
 
     void pop_back() {
         assert(_size > 0);
         _size--;
-        if constexpr(!std::is_trivially_destructible_v<T>) { _data[_size].~T(); }
+        _data[_size].~T();
     }
 
     T popx_back() {
@@ -412,7 +410,7 @@ public:
 
     void pop_back() {
         m_end--;
-        if constexpr(!std::is_trivially_destructible_v<T>) { m_end->~T(); }
+        m_end->~T();
     }
 
     void clear() {
@@ -430,4 +428,52 @@ public:
     small_vector_2(small_vector_2&& other) = delete;
     small_vector_2& operator= (small_vector_2&& other) = delete;
 };
+
+template <typename K, typename V>
+struct small_map {
+    struct Item{
+        K first;
+        V second;
+
+        bool operator< (const K& other) const { return first < other; }
+        bool operator< (const Item& other) const { return first < other.first; }
+    };
+    
+    vector<Item> _data;
+
+    small_map() = default;
+
+    using size_type = int;
+
+    int size() const { return _data.size(); }
+    bool empty() const { return _data.empty(); }
+    Item* begin() const { return _data.begin(); }
+    Item* end() const { return _data.end(); }
+    Item* data() const { return _data.data(); }
+
+    void insert(const K& key, const V& value) {
+        auto it = std::lower_bound(_data.begin(), _data.end(), key);
+        assert(it == _data.end() || it->first != key);
+        _data.insert(it, {key, value});
+    }
+
+    V* try_get(const K& key) const {
+        auto it = std::lower_bound(_data.begin(), _data.end(), key);
+        if(it == _data.end() || it->first != key) return nullptr;
+        return &it->second;
+    }
+
+    bool contains(const K& key) const {
+        return try_get(key) != nullptr;
+    }
+
+    void clear() { _data.clear(); }
+
+    const V& operator[] (const K& key) const {
+        auto it = try_get(key);
+        assert(it != nullptr);
+        return *it;
+    }
+};
+
 }  // namespace pkpy

+ 3 - 3
include/pocketpy/compiler/lexer.hpp

@@ -50,10 +50,10 @@ constexpr TokenIndex TK(const char token[]) {
 constexpr inline bool is_raw_string_used(TokenIndex t) { return t == TK("@id") || t == TK("@long"); }
 
 #define TK_STR(t) kTokens[t]
-const std::map<std::string_view, TokenIndex> kTokenKwMap = []() {
-    std::map<std::string_view, TokenIndex> map;
+const small_map<std::string_view, TokenIndex> kTokenKwMap = []() {
+    small_map<std::string_view, TokenIndex> map;
     for(int k = TK("class"); k < kTokenCount; k++)
-        map[kTokens[k]] = k;
+        map.insert(kTokens[k], k);
     return map;
 }();
 

+ 1 - 1
include/pocketpy/interpreter/profiler.hpp

@@ -25,7 +25,7 @@ struct _FrameRecord {
 
 struct LineProfiler {
     // filename -> records
-    std::map<std::string_view, vector<_LineRecord>> records;
+    small_map<std::string_view, vector<_LineRecord>> records;
     vector<_FrameRecord> frames;
     vector<FuncDecl*> functions;
 

+ 9 - 9
include/pocketpy/interpreter/vm.hpp

@@ -169,8 +169,8 @@ public:
     CallStack callstack;
     vector<PyTypeInfo> _all_types;
 
-    NameDict _modules;                     // loaded modules
-    std::map<StrName, Str> _lazy_modules;  // lazy loaded modules
+    NameDict _modules;                      // loaded modules
+    small_map<StrName, Str> _lazy_modules;  // lazy loaded modules
 
     struct {
         PyObject* error;
@@ -182,7 +182,7 @@ public:
     PyObject* _main;
 
     // typeid -> Type
-    std::map<const std::type_index, Type> _cxx_typeid_map;
+    small_map<std::type_index, Type> _cxx_typeid_map;
     // this is for repr() recursion detection (no need to mark)
     vector<PyVar> _repr_recursion_set;
 
@@ -190,8 +190,8 @@ public:
     PyObject* __last_exception;
     PyObject* __curr_class;
     PyVar __cached_object_new;
-    std::map<std::string_view, CodeObject_> __cached_codes;
-    std::map<std::string_view, PyVar> __cached_op_funcs;
+    small_map<std::string_view, CodeObject_> __cached_codes;
+    small_map<std::string_view, PyVar> __cached_op_funcs;
     FuncDecl_ __dynamic_func_decl;
     PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES];
 
@@ -469,8 +469,8 @@ public:
 
     template <typename T>
     Type _find_type_in_cxx_typeid_map() {
-        auto it = _cxx_typeid_map.find(typeid(T));
-        if(it == _cxx_typeid_map.end()) {
+        auto it = _cxx_typeid_map.try_get(typeid(T));
+        if(it == nullptr) {
 #if __GNUC__ || __clang__
             throw std::runtime_error(__PRETTY_FUNCTION__ + std::string(" failed: T not found"));
 #elif _MSC_VER
@@ -479,7 +479,7 @@ public:
             throw std::runtime_error("_find_type_in_cxx_typeid_map() failed: T not found");
 #endif
         }
-        return it->second;
+        return *it;
     }
 
     /********** private **********/
@@ -753,7 +753,7 @@ PyObject*
     VM::register_user_class(PyObject* mod, StrName name, RegisterFunc _register, Type base, bool subclass_enabled) {
     PyObject* type = new_type_object(mod, name, base, subclass_enabled, PyTypeInfo::Vt::get<T>());
     mod->attr().set(name, type);
-    _cxx_typeid_map[typeid(T)] = type->as<Type>();
+    _cxx_typeid_map.insert(typeid(T), type->as<Type>());
     _register(this, mod, type);
     if(!type->attr().contains(__new__)) {
         if constexpr(std::is_default_constructible_v<T>) {

+ 3 - 2
src/compiler/lexer.cpp

@@ -153,8 +153,9 @@ int Lexer::eat_name() {
         return 0;
     }
 
-    if(kTokenKwMap.count(name)) {
-        add_token(kTokenKwMap.at(name));
+    auto it = kTokenKwMap.try_get(name);
+    if(it != nullptr) {
+        add_token(*it);
     } else {
         add_token(TK("@id"));
     }

+ 4 - 4
src/interpreter/ceval.cpp

@@ -789,13 +789,13 @@ PyVar VM::__run_top_frame() {
                     case OP_FSTRING_EVAL: {
                         PyVar _0 = frame->co->consts[byte.arg];
                         std::string_view string = CAST(Str&, _0).sv();
-                        auto it = __cached_codes.find(string);
+                        auto it = __cached_codes.try_get(string);
                         CodeObject_ code;
-                        if(it == __cached_codes.end()) {
+                        if(it == nullptr) {
                             code = vm->compile(string, "<eval>", EVAL_MODE, true);
-                            __cached_codes[string] = code;
+                            __cached_codes.insert(string, code);
                         } else {
-                            code = it->second;
+                            code = *it;
                         }
                         _0 = vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals);
                         PUSH(_0);

+ 2 - 2
src/interpreter/profiler.cpp

@@ -28,7 +28,7 @@ void LineProfiler::_step(int callstack_size, Frame* frame) {
         _step_end(callstack_size, frame, line);
     }
 
-    auto& file_records = records[filename];
+    auto& file_records = *records.try_get(filename);
     if(file_records.empty()) {
         // initialize file_records
         int total_lines = frame->co->src->line_starts.size();
@@ -85,7 +85,7 @@ Str LineProfiler::stats() {
         int end_line = decl->code->end_line;
         if(start_line == -1 || end_line == -1) continue;
         std::string_view filename = decl->code->src->filename.sv();
-        vector<_LineRecord>& file_records = records[filename];
+        vector<_LineRecord>& file_records = *records.try_get(filename);
         if(file_records.empty()) continue;
         clock_t total_time = 0;
         for(int line = start_line; line <= end_line; line++) {

+ 8 - 8
src/interpreter/vm.cpp

@@ -242,12 +242,12 @@ bool VM::py_eq(PyVar lhs, PyVar rhs) {
 
 PyVar VM::py_op(std::string_view name) {
     PyVar func;
-    auto it = __cached_op_funcs.find(name);
-    if(it == __cached_op_funcs.end()) {
+    auto it = __cached_op_funcs.try_get(name);
+    if(it == nullptr) {
         func = py_import("operator")->attr(StrName::get(name));
-        __cached_op_funcs[name] = func;
+        __cached_op_funcs.insert(name, func);
     } else {
-        func = it->second;
+        func = *it;
     }
     return func;
 }
@@ -366,8 +366,8 @@ PyObject* VM::py_import(Str path, bool throw_err) {
     Str filename = path.replace('.', PK_PLATFORM_SEP) + ".py";
     Str source;
     bool is_init = false;
-    auto it = _lazy_modules.find(name);
-    if(it == _lazy_modules.end()) {
+    auto it = _lazy_modules.try_get(name);
+    if(it == nullptr) {
         int out_size;
         unsigned char* out = _import_handler(filename.c_str(), &out_size);
         if(out == nullptr) {
@@ -385,8 +385,8 @@ PyObject* VM::py_import(Str path, bool throw_err) {
         source = Str(std::string_view((char*)out, out_size));
         std::free(out);
     } else {
-        source = it->second;
-        _lazy_modules.erase(it);
+        source = *it;
+        // _lazy_modules.erase(it);  // no need to erase
     }
     auto _ = __import_context.scope(path, is_init);
     CodeObject_ code = compile(source, filename, EXEC_MODE);

+ 19 - 19
src/pocketpy.cpp

@@ -919,9 +919,9 @@ void __init_builtins(VM* _vm) {
     _vm->bind_func(VM::tp_list, "remove", 2, [](VM* vm, ArgsView args) {
         List& self = _CAST(List&, args[0]);
         PyVar obj = args[1];
-        for(int i = 0; i < self.size(); i++) {
-            if(vm->py_eq(self[i], obj)) {
-                self.erase(i);
+        for(PyVar* it = self.begin(); it != self.end(); it++) {
+            if(vm->py_eq(*it, obj)) {
+                self.erase(it);
                 return vm->None;
             }
         }
@@ -941,7 +941,7 @@ void __init_builtins(VM* _vm) {
             i64 index = CAST(i64, args[1]);
             index = vm->normalized_index(index, self.size());
             PyVar ret = self[index];
-            self.erase(index);
+            self.erase(self.begin() + index);
             return ret;
         }
         vm->TypeError("pop() takes at most 1 argument");
@@ -1000,7 +1000,7 @@ void __init_builtins(VM* _vm) {
         if(index < 0) index += self.size();
         if(index < 0) index = 0;
         if(index > self.size()) index = self.size();
-        self.insert(index, args[2]);
+        self.insert(self.begin() + index, args[2]);
         return vm->None;
     });
 
@@ -1069,7 +1069,7 @@ void __init_builtins(VM* _vm) {
         List& self = _CAST(List&, _0);
         i64 i = CAST(i64, _1);
         i = vm->normalized_index(i, self.size());
-        self.erase(i);
+        self.erase(self.begin() + i);
     });
 
     _vm->bind_func(VM::tp_tuple, __new__, -1, [](VM* vm, ArgsView args) {
@@ -1673,19 +1673,19 @@ void VM::__post_init_builtin_types() {
     add_module_random(this);
     add_module_base64(this);
 
-    _lazy_modules["this"] = kPythonLibs_this;
-    _lazy_modules["functools"] = kPythonLibs_functools;
-    _lazy_modules["heapq"] = kPythonLibs_heapq;
-    _lazy_modules["bisect"] = kPythonLibs_bisect;
-    _lazy_modules["pickle"] = kPythonLibs_pickle;
-    _lazy_modules["_long"] = kPythonLibs__long;
-    _lazy_modules["colorsys"] = kPythonLibs_colorsys;
-    _lazy_modules["typing"] = kPythonLibs_typing;
-    _lazy_modules["datetime"] = kPythonLibs_datetime;
-    _lazy_modules["cmath"] = kPythonLibs_cmath;
-    _lazy_modules["itertools"] = kPythonLibs_itertools;
-    _lazy_modules["operator"] = kPythonLibs_operator;
-    _lazy_modules["collections"] = kPythonLibs_collections;
+    _lazy_modules.insert("this", kPythonLibs_this);
+    _lazy_modules.insert("functools", kPythonLibs_functools);
+    _lazy_modules.insert("heapq", kPythonLibs_heapq);
+    _lazy_modules.insert("bisect", kPythonLibs_bisect);
+    _lazy_modules.insert("pickle", kPythonLibs_pickle);
+    _lazy_modules.insert("_long", kPythonLibs__long);
+    _lazy_modules.insert("colorsys", kPythonLibs_colorsys);
+    _lazy_modules.insert("typing", kPythonLibs_typing);
+    _lazy_modules.insert("datetime", kPythonLibs_datetime);
+    _lazy_modules.insert("cmath", kPythonLibs_cmath);
+    _lazy_modules.insert("itertools", kPythonLibs_itertools);
+    _lazy_modules.insert("operator", kPythonLibs_operator);
+    _lazy_modules.insert("collections", kPythonLibs_collections);
 
     try {
         // initialize dummy func_decl for exec/eval