瀏覽代碼

native modules are lazy by default

BLUELOVETH 2 年之前
父節點
當前提交
1e7fe28998
共有 4 個文件被更改,包括 28 次插入16 次删除
  1. 4 4
      docs/quick-start/modules.md
  2. 2 0
      include/pocketpy/vm.h
  3. 13 12
      src/pocketpy.cpp
  4. 9 0
      src/vm.cpp

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

@@ -25,7 +25,7 @@ print(test.pi)  # 3.14
 ### Native modules
 
 A native module is a module written in c++ or mixed c++/python.
-Native modules are always compiled and executed when the VM is created.
+Native modules can be added into `_modules` or `_lazy_native_modules`.
 
 To creata a native module,
 use `vm->new_module(...)`.
@@ -52,9 +52,9 @@ print(test.add(1, 2))  # 3
 When you do `import` a module, the VM will try to find it in the following order:
 
 1. Search `vm->_modules`, if found, return it.
-2. Search `vm->_lazy_modules`, if found, compile and execute it, then return it.
-3. Try `vm->_import_handler`.
-
+2. Search `vm->_lazy_native_modules`, if found, compile and execute it, then return it.
+3. Search `vm->_lazy_modules`, if found, compile and execute it, then return it.
+4. Try `vm->_import_handler`.
 
 ### Customized import handler
 

+ 2 - 0
include/pocketpy/vm.h

@@ -47,6 +47,7 @@ namespace pkpy{
 
 
 typedef PyObject* (*BinaryFuncC)(VM*, PyObject*, PyObject*);
+typedef void (*NativeModuleInitializer)(VM*);
 
 struct PyTypeInfo{
     PyObject* obj;
@@ -116,6 +117,7 @@ public:
     
     NameDict _modules;                                 // loaded modules
     std::map<StrName, Str> _lazy_modules;              // lazy loaded modules
+    std::map<StrName, NativeModuleInitializer> _lazy_native_modules;  // lazy loaded native modules
 
     struct{
         PyObject* error;

+ 13 - 12
src/pocketpy.cpp

@@ -1554,17 +1554,18 @@ void VM::post_init(){
 
 #if !PK_DEBUG_NO_BUILTINS
     add_module_sys(this);
-    add_module_traceback(this);
-    add_module_time(this);
-    add_module_json(this);
-    add_module_math(this);
-    add_module_re(this);
-    add_module_dis(this);
     add_module_c(this);
-    add_module_gc(this);
-    add_module_random(this);
-    add_module_base64(this);
-    add_module_timeit(this);
+    // lazy modules
+    vm->_lazy_native_modules["traceback"] = &add_module_traceback;
+    vm->_lazy_native_modules["time"] = &add_module_time;
+    vm->_lazy_native_modules["json"] = &add_module_json;
+    vm->_lazy_native_modules["math"] = &add_module_math;
+    vm->_lazy_native_modules["re"] = &add_module_re;
+    vm->_lazy_native_modules["dis"] = &add_module_dis;
+    vm->_lazy_native_modules["gc"] = &add_module_gc;
+    vm->_lazy_native_modules["random"] = &add_module_random;
+    vm->_lazy_native_modules["base64"] = &add_module_base64;
+    vm->_lazy_native_modules["timeit"] = &add_module_timeit;
 
     for(const char* name: {"this", "functools", "collections", "heapq", "bisect", "pickle", "_long", "colorsys"}){
         _lazy_modules[name] = kPythonLibs[name];
@@ -1587,8 +1588,8 @@ void VM::post_init(){
         _import_handler = _default_import_handler;
     }
 
-    add_module_linalg(this);
-    add_module_easing(this);
+    vm->_lazy_native_modules["linalg"] = &add_module_linalg;
+    vm->_lazy_native_modules["easing"] = &add_module_easing;
 #endif
 }
 

+ 9 - 0
src/vm.cpp

@@ -239,6 +239,14 @@ namespace pkpy{
         }
         PyObject* ext_mod = _modules.try_get(name);
         if(ext_mod == nullptr){
+            auto it2 = _lazy_native_modules.find(name);
+            if(it2 != _lazy_native_modules.end()){
+                it2->second(this);  // init
+                ext_mod = _modules.try_get(name);
+                PK_ASSERT(ext_mod != nullptr);
+                _lazy_native_modules.erase(it2);
+                return ext_mod;
+            }
             Str source;
             auto it = _lazy_modules.find(name);
             if(it == _lazy_modules.end()){
@@ -271,6 +279,7 @@ namespace pkpy{
         _all_types.clear();
         _modules.clear();
         _lazy_modules.clear();
+        _lazy_native_modules.clear();
     }
 
 PyObject* VM::py_negate(PyObject* obj){