Gravity can be easily embedded into any C/C++ code. Suppose to have the following Gravity code:
func sum (a, b) {
return a + b
}
func mul (a, b) {
return a * b
}
func main () {
var a = 10
var b = 20
return sum(a, b) + mul(a, b)
}
To keep the code as simple as possible I skipped any error check condition that would be required. The bare minimum C code to embed the above Gravity code would be:
#include "gravity_compiler.h"
#include "gravity_macros.h"
#include "gravity_core.h"
#include "gravity_vm.h"
const char *source_code = " \
func sum (a, b) { \
return a + b \
} \
\
func mul (a, b) { \
return a * b \
} \
\
func main () { \
var a = 10 \
var b = 20 \
return sum(a, b) + mul(a, b) \
} \
";
// a very simple report error callback function
void report_error (gravity_vm *vm, error_type_t error_type, const char *message,
error_desc_t error_desc, void *xdata) {
printf("%s\n", message);
exit(0);
}
int main (void) {
// setup a delegate struct (much more options are available)
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 a closure (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 the memory has been transferred, you can get rid of the front-end
gravity_compiler_free(compiler);
// 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;
}
To load and execute a myfile Gravity source code from disk the required changes would be minimum:
int main (void) {
size_t size = 0;
const char *source_code = file_read("myfile.gravity", &size);
...
// compile Gravity source code into bytecode (embedded into a closure)
// notice the change of the is_static bool parameter to false
gravity_closure_t *closure = gravity_compiler_run(compiler, source_code, size, 0, false, true);
...
}
To directly execute the mul Gravity function and pass some parameter from C to Gravity some minor changes need to be performed:
#include "gravity_compiler.h"
#include "gravity_macros.h"
#include "gravity_core.h"
#include "gravity_vm.h"
const char *source_code = " \
func sum (a, b) { \
return a + b \
} \
\
func mul (a, b) { \
return a * b \
} \
";
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 the memory has been transferred, you can get rid of the front-end
gravity_compiler_free(compiler);
// load closure into VM
gravity_vm_loadclosure(vm, closure);
// lookup a reference to the mul closure into the Gravity VM
gravity_value_t mul_function = gravity_vm_getvalue(vm, "mul", (uint32_t)strlen("mul"));
if (!VALUE_ISA_CLOSURE(mul_function)) {
printf("Unable to find mul function into Gravity VM.\n");
return -1;
}
// convert function to closure
gravity_closure_t *mul_closure = VALUE_AS_CLOSURE(mul_function);
// prepare parameters
gravity_value_t p1 = VALUE_FROM_INT(30);
gravity_value_t p2 = VALUE_FROM_INT(40);
gravity_value_t params[] = {p1, p2};
// execute mul closure
if (gravity_vm_runclosure (vm, mul_closure, VALUE_FROM_NULL, params, 2)) {
// 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;
}