# Ground Libraries This repo folder details the process for creating libraries with Ground, as well as some core libraries that are preinstalled with Ground. ## Building Libraries Ground comes with the `groundvm.h` and `groundext.h` header files for interfacing with Ground. If you're building something that wraps Ground, use `groundvm.h`. If you're building something that Ground itself uses (a library), use `groundext.h` (it includes `groundvm.h` but also has some extlib-specific things). You can build your library in C or C++, or whichever language you can convince to interop with C code. Note: C++ Ground extlibs and CGround extlibs are not compatible. Update your code for CGround. ### Making a Function for CGround Create a function with the following signature: ```c GroundValue myFn(GroundScope* scope, List args) {} ``` * `GroundScope* scope`: For now does nothing. Will do something when structs are added. * `List args`: A list of args. The `List` struct and associated structures look like this: ```c typedef enum GroundValueType { INT, DOUBLE, STRING, CHAR, BOOL, LIST, FUNCTION, CUSTOM, NONE } GroundValueType; typedef struct List { size_t size; struct GroundValue* values; } List; typedef struct GroundValue { GroundValueType type; union { int64_t intVal; double doubleVal; char* stringVal; char charVal; bool boolVal; List listVal; struct GroundFunction* fnVal; void* customVal; } data; } GroundValue; ``` Your function needs to return a `GroundValue`. This can easily be created with the `groundCreateValue()` function, used like this: ```c // TYPE is one of the enum values from the GroundValueType enum. // CONTENT is the associated data type (char* for string, int64_t for int, etc, etc) groundCreateValue(TYPE, content); // Real use: groundCreateValue(STRING, "dingus"); groundCreateValue(INT, 32); ``` Once you've created your functions, you can create a `ground_init()` function to let Ground know about your functions. Use the `groundAddNativeFunction()` function to add your functions to Ground. If your function fails, print some debug stuff to the console and return `groundCreateValue(NONE)`. Proper error handling will be added soon. ```c GroundValue say_hi(GroundScope* scope, List args) { char* greeting = "Hello, "; if (list.size < 1) { printf("Expecting an argument!"); return groundCreateValue(NONE); } if (list.values[0].type != STRING) { printf("Expecting a string"); return groundCreateValue(NONE); } // Insert stupid memory stuff here return groundCreateValue(STRING, greeting); } // ground_init takes a GroundScope* so it can add your functions to Ground void ground_init(GroundScope* scope) { // groundAddNativeFunction(scope, "namespace_FnName", name_of_function, RETURNTYPE, // amountOfArgs, ARGTYPE, "argName", ARGTYPE, "argName", ...) groundAddNativeFunction(scope, "utility_SayHi", say_hi, STRING, 1, STRING, "name"); } ``` ### Notes When naming your functions, give them a prefix namespace like in C. Use `camelCase` for the namespace and `CamelCase` for the function name. Document your functions somewhere! We want to be able to use them!