blueloveTH пре 2 година
родитељ
комит
2f9b5eb700
3 измењених фајлова са 45 додато и 8 уклоњено
  1. 28 0
      docs/quick-start/bind.md
  2. 7 2
      src/obj.h
  3. 10 6
      src/vm.h

+ 28 - 0
docs/quick-start/bind.md

@@ -14,6 +14,34 @@ typedef PyObject* (*NativeFuncC)(VM*, ArgsView);
 + The second argument is an array-like object indicates the arguments list. You can use `[]` operator to get the element.
 + The return value is a `PyObject*`, which should not be `nullptr`. If there is no return value, return `vm->None`.
 
+
+## New style bindings
+
+Use `vm->bind` to bind a function or method.
+
++ `PyObject* bind(PyObject*, const char* sig, NativeFuncC)`
++ `PyObject* bind(PyObject*, const char* sig, const char* docstring, NativeFuncC)`
+
+```cpp
+
+vm->bind(obj, "add(a: int, b: int) -> int", [](VM* vm, ArgsView args){
+    int a = CAST(int, args[0]);
+    int b = CAST(int, args[1]);
+    return VAR(a + b);
+});
+
+// or you can provide a docstring
+vm->bind(obj,
+    "add(a: int, b: int) -> int",
+    "add two integers", [](VM* vm, ArgsView args){
+    int a = CAST(int, args[0]);
+    int b = CAST(int, args[1]);
+    return VAR(a + b);
+});
+```
+
+## Old style bindings
+
 !!!
 Native functions do not support keyword arguments.
 !!!

+ 7 - 2
src/obj.h

@@ -37,9 +37,13 @@ using FuncDecl_ = shared_ptr<FuncDecl>;
 
 struct NativeFunc {
     NativeFuncC f;
+
+    // old style argc-based call
     int argc;
 
-    FuncDecl_ decl;     // if this is not null, use ex call
+    // new style decl-based call
+    FuncDecl_ decl;
+    const char* docstring;
 
     using UserData = char[32];
     UserData _userdata;
@@ -71,10 +75,11 @@ struct NativeFunc {
         _has_userdata = false;
     }
 
-    NativeFunc(NativeFuncC f, FuncDecl_ decl){
+    NativeFunc(NativeFuncC f, FuncDecl_ decl, const char* docstring){
         this->f = f;
         this->argc = -1;
         this->decl = decl;
+        this->docstring = docstring;
         _has_userdata = false;
     }
 

+ 10 - 6
src/vm.h

@@ -689,7 +689,8 @@ public:
     void post_init();
     PyObject* _py_generator(Frame&& frame, ArgsView buffer);
     // new style binding api
-    PyObject* bind(PyObject*, const Str&, NativeFuncC);
+    PyObject* bind(PyObject*, const char*, const char*, NativeFuncC);
+    PyObject* bind(PyObject*, const char*, NativeFuncC);
     void _prepare_py_call(PyObject**, ArgsView, ArgsView, const FuncDecl_&);
 };
 
@@ -1544,20 +1545,23 @@ PyObject* VM::bind_func(PyObject* obj, Str name, NativeFuncC fn) {
     return nf;
 }
 
-inline PyObject* VM::bind(PyObject* obj, const Str& sig, NativeFuncC fn){
+inline PyObject* VM::bind(PyObject* obj, const char* sig, NativeFuncC fn){
+    return bind(obj, sig, nullptr, fn);
+}
+
+inline PyObject* VM::bind(PyObject* obj, const char* sig, const char* docstring, NativeFuncC fn){
     CodeObject_ co;
     try{
         // fn(a, b, *c, d=1) -> None
-        co = compile("def " + sig + " : pass", "<bind>", EXEC_MODE);
+        co = compile("def " + Str(sig) + " : pass", "<bind>", EXEC_MODE);
     }catch(Exception& e){
-        throw std::runtime_error(("invalid signature: " + sig).str());
+        throw std::runtime_error("invalid signature: " + std::string(sig));
     }
     if(co->func_decls.size() != 1){
         throw std::runtime_error("expected 1 function declaration");
     }
     FuncDecl_ decl = co->func_decls[0];
-    // return VAR(NativeFuncEx(fn, argc, false, sig));
-    return nullptr;
+    return VAR(NativeFunc(fn, decl, docstring));
 }
 
 inline void VM::_error(Exception e){