浏览代码

Update extending.md

Marco Bambini 5 年之前
父节点
当前提交
3d1ffe0be4
共有 1 个文件被更改,包括 82 次插入47 次删除
  1. 82 47
      docs/extending.md

+ 82 - 47
docs/extending.md

@@ -1,53 +1,88 @@
-## API
+## Extending Gravity
 
-Gravity can be extended at runtime using C API. The right step to proceed is usually to create a new class, then add methods and properties to it and finally register that class inside the VM.
+Gravity can be extended at runtime using the C API (please read the Embedding section before proceeding).
+
+Three steps are required:
+1. Create a new class
+2. Add methods and properties to the class
+3. Register this class inside the VM
+
+In this simple example we'll create a "Foo" class with a "bar" method in C and then we'll execute it from Gravity.
 ```c
-	// report error callback function
-	void report_error (error_type_t error_type, const char *message,
-	                   error_desc_t error_desc, void *xdata) {
-		printf("%s\n", message);
-		exit(0);
-	}
-
-	// function to be executed inside Gravity VM
-	bool my_function (gravity_vm *vm, gravity_value_t *args,
-	                  uint16_t nargs, uint32_t rindex) {
-		// do something useful here
-	}
-
-	// Configure VM delegate
-	gravity_delegate_t delegate = {.error_callback = report_error};
-
-	// Create a new VM
-	gravity_vm *vm = gravity_vm_new(&delegate);
-
-	// Create a new class
-	gravity_class_t *c = gravity_class_new_pair (vm, "MyClass", NULL, 0, 0);
-
-	// Allocate and bind closures to the newly created class
-	gravity_closure_t *closure = gravity_closure_new(vm, my_function);
-	gravity_class_bind(c, "myfunc", VALUE_FROM_OBJECT(closure));
-
-	// Register class inside VM
-	gravity_vm_setvalue(vm, "MyClass", VALUE_FROM_OBJECT(c));
-```
+#include "gravity_compiler.h"
+#include "gravity_macros.h"
+#include "gravity_core.h"
+#include "gravity_vm.h"
+#include "gravity_vmmacros.h"
 
-Using the above C code a "MyClass" class has been registered inside the VM and ready to be used by Gravity:
-```swift
-	func main() {
-		// allocate a new class
-		var foo = MyClass();
+const char *source_code = " \
+extern var Foo; \
+func main () {   \
+    var c = Foo();  \
+    return c.sum(30, 40);   \
+}   \
+";
 
-		// execute the myfunc C function
-		foo.myfunc();
-	}
-```
+static bool sum (gravity_vm *vm, gravity_value_t *args, uint16_t nargs, uint32_t rindex) {
+    // SKIPPED: check nargs (must be 3 because arg[0] is self)
+    gravity_value_t v1 = GET_VALUE(1);
+    gravity_value_t v2 = GET_VALUE(2);
+    
+    // SKIPPED: check that both v1 and v2 are int numbers
+    RETURN_VALUE(VALUE_FROM_INT(v1.n + v2.n), rindex);
+}
 
-### Execute Gravity code from C
-```c
-```
+void setup_foo (gravity_vm *vm) {
+    // create a new Foo class
+    gravity_class_t *c = gravity_class_new_pair (vm, "Foo", NULL, 0, 0);
+    
+    // allocate and bind bar closure to the newly created class
+    gravity_class_bind(c, "sum", NEW_CLOSURE_VALUE(sum));
+    
+    // register class c inside VM
+    gravity_vm_setvalue(vm, "Foo", VALUE_FROM_OBJECT(c));
+}
+
+int main (void) {
+    // setup a delegate struct
+    gravity_delegate_t delegate = {.error_callback = report_error};
+    
+    // allocate a new compiler
+    gravity_compiler_t *compiler = gravity_compiler_create(&delegate);
+    
+    // compile Gravity source code into bytecode
+    gravity_closure_t *closure = gravity_compiler_run(compiler, source_code, strlen(source_code), 0, true, true);
+    
+    // allocate a new Gravity VM
+    gravity_vm *vm = gravity_vm_new(&delegate);
+    
+    // transfer memory from the compiler (front-end) to the VM (back-end)
+    gravity_compiler_transfer(compiler, vm);
+    
+    // once memory has been trasferred, you can get rid of the front-end
+    gravity_compiler_free(compiler);
+    
+    // register my Foo class inside Gravity VM
+    setup_foo(vm);
+    
+    // execute main closure
+    if (gravity_vm_runmain(vm, closure)) {
+        // retrieve returned result
+        gravity_value_t result = gravity_vm_result(vm);
+    
+        // dump result to a C string and print it to stdout
+        char buffer[512];
+        gravity_value_dump(vm, result, buffer, sizeof(buffer));
+        printf("RESULT: %s\n", buffer);
+    }
+    
+    // free VM and core libraries (implicitly allocated by the VM)
+    gravity_vm_free(vm);
+    gravity_core_free();
+    
+    return 0;
+}
 
-### Bridge API
-Gravity C API offers much more flexibility using the delegate bridge API.
-TO DO: more information here.
-TO DO: post objc bridge.
+For more examples see the file gravity_core.c in the src/runtime/ directory. Most of the Gravity classes are built using these same APIs.
+
+```