Skip to content

Commit

Permalink
Dynamic access to Umka API (#333)
Browse files Browse the repository at this point in the history
  • Loading branch information
vtereshkov committed Jan 15, 2024
1 parent e55d43f commit 12a7bb8
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 3 deletions.
30 changes: 30 additions & 0 deletions doc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,33 @@ UMKA_API int umkaGetDynArrayLen(const void *array);

Returns the length of the dynamic `array` (treated as a pointer to `UmkaDynArray(T)`).

## Accessing Umka API dynamically

Using the Umka API functions generally requires linking against the Umka interpreter library. This dependency is undesirable when implementing UMIs. In such cases, the same Umka API functions can be accessed dynamically, through the Umka interpreter instance passed to UMI functions.

### Types

```
typedef struct
{
// Function pointers
} UmkaAPI;
```

A set of pointers to all Umka API functions. For any function `umkaXXXX()`, there is a corresponding field `umkaXXXX` in `UmkaAPI`.

### Functions

```
static inline UmkaAPI *umkaGetAPI(void *umka);
```
Returns Umka API function pointers. Here, `umka` is the interpreter instance handle previously initialized by calling `umkaInit()`.

Example:

```
UmkaAPI *api = umkaGetAPI(umka);
char *s = api->umkaMakeStr(umka, "Hello");
```
2 changes: 1 addition & 1 deletion playground/umka.js

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions src/umka_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,33 @@ typedef struct
typedef void (*UmkaWarningCallback)(UmkaError *warning);


typedef struct
{
void *(*umkaAlloc) (void);
bool (*umkaInit) (void *umka, const char *fileName, const char *sourceString, int stackSize, const char *locale, int argc, char **argv, bool fileSystemEnabled, bool implLibsEnabled, UmkaWarningCallback warningCallback);
bool (*umkaCompile) (void *umka);
bool (*umkaRun) (void *umka);
bool (*umkaCall) (void *umka, int entryOffset, int numParamSlots, UmkaStackSlot *params, UmkaStackSlot *result);
void (*umkaFree) (void *umka);
void (*umkaGetError) (void *umka, UmkaError *err);
char *(*umkaAsm) (void *umka);
bool (*umkaAddModule) (void *umka, const char *fileName, const char *sourceString);
bool (*umkaAddFunc) (void *umka, const char *name, UmkaExternFunc func);
int (*umkaGetFunc) (void *umka, const char *moduleName, const char *funcName);
bool (*umkaGetCallStack) (void *umka, int depth, int nameSize, int *offset, char *fileName, char *fnName, int *line);
void (*umkaSetHook) (void *umka, UmkaHookEvent event, UmkaHookFunc hook);
void *(*umkaAllocData) (void *umka, int size, UmkaExternFunc onFree);
void (*umkaIncRef) (void *umka, void *ptr);
void (*umkaDecRef) (void *umka, void *ptr);
void *(*umkaGetMapItem) (void *umka, UmkaMap *map, UmkaStackSlot key);
char *(*umkaMakeStr) (void *umka, const char *str);
int (*umkaGetStrLen) (const char *str);
void (*umkaMakeDynArray) (void *umka, void *array, void *type, int len);
int (*umkaGetDynArrayLen) (const void *array);
const char *(*umkaGetVersion) (void);
} UmkaAPI;


UMKA_API void *umkaAlloc (void);
UMKA_API bool umkaInit (void *umka, const char *fileName, const char *sourceString, int stackSize, const char *locale, int argc, char **argv, bool fileSystemEnabled, bool implLibsEnabled, UmkaWarningCallback warningCallback);
UMKA_API bool umkaCompile (void *umka);
Expand All @@ -110,6 +137,11 @@ UMKA_API void umkaMakeDynArray (void *umka, void *array, void *type, int le
UMKA_API int umkaGetDynArrayLen (const void *array);
UMKA_API const char *umkaGetVersion (void);

static inline UmkaAPI *umkaGetAPI (void *umka)
{
return (UmkaAPI *)umka;
}


#if defined(__cplusplus)
}
Expand Down
29 changes: 29 additions & 0 deletions src/umka_compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,33 @@
void parseProgram(Compiler *comp);


static void compilerSetAPI(Compiler *comp)
{
comp->api.umkaAlloc = umkaAlloc;
comp->api.umkaInit = umkaInit;
comp->api.umkaCompile = umkaCompile;
comp->api.umkaRun = umkaRun;
comp->api.umkaCall = umkaCall;
comp->api.umkaFree = umkaFree;
comp->api.umkaGetError = umkaGetError;
comp->api.umkaAsm = umkaAsm;
comp->api.umkaAddModule = umkaAddModule;
comp->api.umkaAddFunc = umkaAddFunc;
comp->api.umkaGetFunc = umkaGetFunc;
comp->api.umkaGetCallStack = umkaGetCallStack;
comp->api.umkaSetHook = umkaSetHook;
comp->api.umkaAllocData = umkaAllocData;
comp->api.umkaIncRef = umkaIncRef;
comp->api.umkaDecRef = umkaDecRef;
comp->api.umkaGetMapItem = umkaGetMapItem;
comp->api.umkaMakeStr = umkaMakeStr;
comp->api.umkaGetStrLen = umkaGetStrLen;
comp->api.umkaMakeDynArray = umkaMakeDynArray;
comp->api.umkaGetDynArrayLen = umkaGetDynArrayLen;
comp->api.umkaGetVersion = umkaGetVersion;
}


static void compilerDeclareBuiltinTypes(Compiler *comp)
{
comp->voidType = typeAdd(&comp->types, &comp->blocks, TYPE_VOID);
Expand Down Expand Up @@ -152,6 +179,8 @@ static void compilerDeclareExternalFuncs(Compiler *comp, bool fileSystemEnabled)

void compilerInit(Compiler *comp, const char *fileName, const char *sourceString, int stackSize, const char *locale, int argc, char **argv, bool fileSystemEnabled, bool implLibsEnabled)
{
compilerSetAPI(comp);

storageInit (&comp->storage);
moduleInit (&comp->modules, implLibsEnabled, &comp->error);
blocksInit (&comp->blocks, &comp->error);
Expand Down
3 changes: 3 additions & 0 deletions src/umka_compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@
#include "umka_ident.h"
#include "umka_const.h"
#include "umka_runtime.h"
#include "umka_api.h"


typedef struct
{
UmkaAPI api; // Must be the first field

Storage storage;
Modules modules;
Blocks blocks;
Expand Down
2 changes: 1 addition & 1 deletion tests/extlib.um
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "lib/lib.um"

fn test*() {
printf("%f %f\n", lib.add(3, 5), lib.sub(3, 5))
printf("%f %f %s\n", lib.add(3, 5), lib.sub(3, 5), lib.hello())
}

fn main() {
Expand Down
8 changes: 8 additions & 0 deletions tests/lib/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,12 @@ void sub(UmkaStackSlot *params, UmkaStackSlot *result)
double a = params[1].realVal;
double b = params[0].realVal;
result->realVal = a - b;
}


void hello(UmkaStackSlot *params, UmkaStackSlot *result)
{
void *umka = result->ptrVal;
UmkaAPI *api = umkaGetAPI(umka);
result->ptrVal = api->umkaMakeStr(umka, "Hello");
}
3 changes: 2 additions & 1 deletion tests/lib/lib.um
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
fn add*(a, b: real): real
fn sub*(a, b: real): real
fn sub*(a, b: real): real
fn hello*(): str

0 comments on commit 12a7bb8

Please sign in to comment.