blueloveTH 3 anni fa
parent
commit
5e9082b960
8 ha cambiato i file con 45 aggiunte e 55 eliminazioni
  1. 2 1
      README.md
  2. 1 0
      README_zh.md
  3. 3 2
      src/common.h
  4. 4 16
      src/iter.h
  5. 8 2
      src/obj.h
  6. 11 18
      src/pocketpy.h
  7. 16 9
      src/vm.h
  8. 0 7
      test_cpp.sh

+ 2 - 1
README.md

@@ -52,7 +52,7 @@ For C/C++ developers, you can download the `pocketpy.h` on our GitHub release pa
 
 https://github.com/blueloveTH/pocketpy/releases/latest
 
-Check [C-API](https://pocketpy.dev/c-api/vm/) for references.
+Check [C-API](https://pocketpy.dev/c-api/vm/) for references. C++ APIs will be available soon.
 
 ```cpp
 #include "pocketpy.h"
@@ -139,6 +139,7 @@ You can download `artifact.zip` from [Github Release](https://github.com/bluelov
 - linux/
   - x86_64/
     - pocketpy
+    - pocketpy.so
 - macos/
   - pocketpy.bundle/
 - web/

+ 1 - 0
README_zh.md

@@ -132,6 +132,7 @@ flutter pub add pocketpy
 - linux/
   - x86_64/
     - pocketpy
+    - pocketpy.so
 - macos/
   - pocketpy.bundle/
 - web/

+ 3 - 2
src/common.h

@@ -35,10 +35,11 @@
 #include <emscripten.h>
 #endif
 
-#define PK_VERSION "0.8.1"
+#define PK_VERSION "0.8.2"
 
 typedef int64_t i64;
 typedef double f64;
 #define DUMMY_VAL (i64)0
 
-#define CPP_LAMBDA(x) ([](VM* vm, const pkpy::Args& args) { return x; })
+#define CPP_LAMBDA(x) ([](VM* vm, const pkpy::Args& args) { return x; })
+#define CPP_NOT_IMPLEMENTED() ([](VM* vm, const pkpy::Args& args) { vm->notImplementedError(); return vm->None; })

+ 4 - 16
src/iter.h

@@ -13,11 +13,7 @@ public:
     }
 
     bool hasNext() override {
-        if(r.step > 0){
-            return current < r.stop;
-        }else{
-            return current > r.stop;
-        }
+        return r.step > 0 ? current < r.stop : current > r.stop;
     }
 
     PyVar next() override;
@@ -32,13 +28,8 @@ public:
         vec = &OBJ_GET(PyVarList, _ref);
     }
 
-    bool hasNext(){
-        return index < vec->size();
-    }
-
-    PyVar next(){
-        return vec->operator[](index++);
-    }
+    bool hasNext(){ return index < vec->size(); }
+    PyVar next(){ return vec->operator[](index++); }
 };
 
 class StringIterator : public BaseIterator {
@@ -50,9 +41,6 @@ public:
         str = OBJ_GET(_Str, _ref);
     }
 
-    bool hasNext(){
-        return index < str.u8_length();
-    }
-
+    bool hasNext(){ return index < str.u8_length(); }
     PyVar next();
 };

+ 8 - 2
src/obj.h

@@ -93,7 +93,13 @@ struct Py_ : PyObject {
     virtual void* value() override { return &_value; }
 };
 
-//#define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
+// Unsafe cast from PyObject to C++ type
 #define OBJ_GET(T, obj) (*static_cast<T*>((obj)->value()))
 #define OBJ_NAME(obj) OBJ_GET(_Str, (obj)->attribs[__name__])
-#define OBJ_TP_NAME(obj) OBJ_GET(_Str, (obj)->type->attribs[__name__])
+#define OBJ_TP_NAME(obj) OBJ_GET(_Str, (obj)->type->attribs[__name__])
+
+#define PY_CLASS(mod, name) \
+    inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attribs[#name]; } \
+    inline static const char* _name() { return #name; }
+
+#define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->_tp_##name; }

+ 11 - 18
src/pocketpy.h

@@ -573,8 +573,6 @@ void __add_module_dis(VM* vm){
     });
 }
 
-#define PY_CLASS(mod, name) inline static PyVar _tp(VM* vm) { return vm->_modules[#mod]->attribs[#name]; }
-
 struct ReMatch {
     PY_CLASS(re, Match)
 
@@ -583,27 +581,22 @@ struct ReMatch {
     std::smatch m;
     ReMatch(i64 start, i64 end, std::smatch m) : start(start), end(end), m(m) {}
 
-    static PyVar _register(VM* vm, PyVar mod){
-        PyVar _tp_match = vm->new_user_type_object(mod, "Match", vm->_tp_object);
-        vm->bindMethod<-1>(_tp_match, "__init__", [](VM* vm, const pkpy::Args& args){
-            vm->notImplementedError();
-            return vm->None;
-        });
-        vm->bindMethod<0>(_tp_match, "start", CPP_LAMBDA(vm->PyInt(OBJ_GET(ReMatch, args[0]).start)));
-        vm->bindMethod<0>(_tp_match, "end", CPP_LAMBDA(vm->PyInt(OBJ_GET(ReMatch, args[0]).end)));
+    static void _register(VM* vm, PyVar mod, PyVar type){
+        vm->bindMethod<-1>(type, "__init__", CPP_NOT_IMPLEMENTED());
+        vm->bindMethod<0>(type, "start", CPP_LAMBDA(vm->PyInt(vm->py_cast<ReMatch>(args[0]).start)));
+        vm->bindMethod<0>(type, "end", CPP_LAMBDA(vm->PyInt(vm->py_cast<ReMatch>(args[0]).end)));
 
-        vm->bindMethod<0>(_tp_match, "span", [](VM* vm, const pkpy::Args& args) {
-            auto& self = OBJ_GET(ReMatch, args[0]);
+        vm->bindMethod<0>(type, "span", [](VM* vm, const pkpy::Args& args) {
+            auto& self = vm->py_cast<ReMatch>(args[0]);
             return vm->PyTuple({ vm->PyInt(self.start), vm->PyInt(self.end) });
         });
 
-        vm->bindMethod<1>(_tp_match, "group", [](VM* vm, const pkpy::Args& args) {
-            auto& self = OBJ_GET(ReMatch, args[0]);
+        vm->bindMethod<1>(type, "group", [](VM* vm, const pkpy::Args& args) {
+            auto& self = vm->py_cast<ReMatch>(args[0]);
             int index = (int)vm->PyInt_AS_C(args[1]);
             index = vm->normalized_index(index, self.m.size());
             return vm->PyStr(self.m[index].str());
         });
-        return _tp_match;
     }
 };
 
@@ -614,14 +607,14 @@ PyVar __regex_search(const _Str& pattern, const _Str& string, bool fromStart, VM
         if(fromStart && m.position() != 0) return vm->None;
         i64 start = string.__to_u8_index(m.position());
         i64 end = string.__to_u8_index(m.position() + m.length());
-        return vm->new_object_c<ReMatch>(start, end, m);
+        return vm->new_object<ReMatch>(start, end, m);
     }
     return vm->None;
 };
 
 void __add_module_re(VM* vm){
     PyVar mod = vm->new_module("re");
-    ReMatch::_register(vm, mod);
+    vm->register_class<ReMatch>(mod);
 
     vm->bindFunc<2>(mod, "match", [](VM* vm, const pkpy::Args& args) {
         const _Str& pattern = vm->PyStr_AS_C(args[0]);
@@ -827,7 +820,7 @@ extern "C" {
         for(int i=0; mod[i]; i++) if(mod[i] == ' ') return nullptr;
         for(int i=0; name[i]; i++) if(name[i] == ' ') return nullptr;
         std::string f_header = std::string(mod) + '.' + name + '#' + std::to_string(kGlobalBindId++);
-        PyVar obj = vm->new_module_if_not_existed(mod);
+        PyVar obj = vm->_modules.contains(mod) ? vm->_modules[mod] : vm->new_module(mod);
         vm->bindFunc<-1>(obj, name, [ret_code, f_header](VM* vm, const pkpy::Args& args){
             _StrStream ss;
             ss << f_header;

+ 16 - 9
src/vm.h

@@ -613,23 +613,17 @@ public:
     }
 
     template<typename T, typename... Args>
-    inline PyVar new_object_c(Args&&... args) {
-        return new_object(T::_tp(this), T(std::forward<Args>(args)...));
+    inline PyVar new_object(Args&&... args) {
+        return new_object(T::_type(this), T(std::forward<Args>(args)...));
     }
 
-    PyVar new_module(_Str name) {
+    PyVar new_module(const _Str& name) {
         PyVar obj = new_object(_tp_module, DUMMY_VAL);
         setattr(obj, __name__, PyStr(name));
         _modules[name] = obj;
         return obj;
     }
 
-    PyVar new_module_if_not_existed(_Str name) {
-        PyVar* it = _modules.try_get(name);
-        if(it != nullptr) return *it;
-        return new_module(name);
-    }
-
     PyVarOrNull getattr(const PyVar& obj, const _Str& name, bool throw_err=true) {
         PyVarDict::iterator it;
         PyObject* cls;
@@ -944,6 +938,19 @@ public:
         if(!obj->is_type(type)) typeError("expected '" + OBJ_NAME(type) + "', but got '" + OBJ_TP_NAME(obj) + "'");
     }
 
+    template<typename T>
+    PyVar register_class(PyVar mod){
+        PyVar type = new_user_type_object(mod, T::_name(), _tp_object);
+        T::_register(this, mod, type);
+        return type;
+    }
+
+    template<typename T>
+    T& py_cast(const PyVar& obj){
+        check_type(obj, T::_type(this));
+        return OBJ_GET(T, obj);
+    }
+
     ~VM() {
         if(!use_stdio){
             delete _stdout;

+ 0 - 7
test_cpp.sh

@@ -1,7 +0,0 @@
-g++ -o pocketpy src/main.cpp --std=c++17 -pg -O1 -fno-rtti
-
-./pocketpy tests/1.py
-
-gprof pocketpy gmon.out > gprof.txt
-
-rm gmon.out