Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: call dictu from native code #755

Merged
merged 13 commits into from
Nov 15, 2024
11 changes: 9 additions & 2 deletions src/include/dictu_ffi_include.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ extern "C" {

// This is used ti determine if we can safely load the function pointers without
// UB.
#define FFI_MOD_API_VERSION 2
#define FFI_MOD_API_VERSION 3

#define UNUSED(__x__) (void)__x__

Expand Down Expand Up @@ -343,7 +343,7 @@ struct _vm {
};

#define DICTU_MAJOR_VERSION "0"
#define DICTU_MINOR_VERSION "29"
#define DICTU_MINOR_VERSION "30"
#define DICTU_PATCH_VERSION "0"

#define DICTU_STRING_VERSION \
Expand All @@ -364,6 +364,7 @@ struct sObjString {
int length;
char *chars;
uint32_t hash;
int character_len;
};

struct sObjList {
Expand Down Expand Up @@ -550,6 +551,9 @@ typedef void defineNative_t(DictuVM *vm, Table *table, const char *name,

typedef void defineNativeProperty_t(DictuVM *vm, Table *table, const char *name,
Value value);

typedef Value callFunction_t(DictuVM* vm, Value function, int argCount, Value* args);

reallocate_t * reallocate = NULL;

copyString_t *copyString = NULL;
Expand Down Expand Up @@ -616,6 +620,8 @@ defineNative_t *defineNative = NULL;

defineNativeProperty_t *defineNativeProperty = NULL;

callFunction_t *callFunction = NULL;

// This needs to be implemented by the user and register all functions
int dictu_ffi_init(DictuVM *vm, Table *method_table);

Expand Down Expand Up @@ -665,6 +671,7 @@ int dictu_internal_ffi_init(void **function_ptrs, DictuVM *vm,
defineNative = (defineNative_t *)function_ptrs[count++];
defineNativeProperty = (defineNativeProperty_t *)function_ptrs[count++];
reallocate = (reallocate_t *)function_ptrs[count++];
callFunction = (callFunction_t *)function_ptrs[count++];
int initResult = dictu_ffi_init(vm, methodTable);
if (initResult > 0)
return 3 + initResult;
Expand Down
3 changes: 2 additions & 1 deletion src/optionals/ffi/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ void *ffi_function_pointers[] = {&copyString,
&compareStringGreater,
&defineNative,
&defineNativeProperty,
&reallocate};
&reallocate,
&callFunction};

void freeFFI(DictuVM *vm, ObjAbstract *abstract) {
FFIInstance *instance = (FFIInstance *)abstract->data;
Expand Down
2 changes: 1 addition & 1 deletion src/optionals/ffi/ffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

// This is used to determine if we can safely load the function pointers without UB,
// if this is greater then the version from the mod we error in the internal mod load function.
#define DICTU_FFI_API_VERSION 2
#define DICTU_FFI_API_VERSION 3


Value createFFIModule(DictuVM *vm);
Expand Down
8 changes: 8 additions & 0 deletions src/vm/datatypes/strings.c
Original file line number Diff line number Diff line change
Expand Up @@ -884,6 +884,13 @@ static Value isValidUtf8(DictuVM *vm, int argCount, Value *args) {
return BOOL_VAL(string->character_len != -1);
}

static Value testThing(DictuVM *vm, int argCount, Value *args) {
int argC = argCount-1;
Value func = args[1];
Value* func_args = args +2;
return callFunction(vm, func, argC, func_args);
}

void declareStringMethods(DictuVM *vm) {
// Note(Liz3): We need functions from the c stdlib for iswalpha, iswlower,
// iswupper(the utf8.c library functions do not work)
Expand Down Expand Up @@ -916,4 +923,5 @@ void declareStringMethods(DictuVM *vm) {
defineNative(vm, &vm->stringMethods, "collapseSpaces",
collapseSpacesString);
defineNative(vm, &vm->stringMethods, "wrap", wrapString);
defineNative(vm, &vm->stringMethods, "testThing", testThing);
}
32 changes: 31 additions & 1 deletion src/vm/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "datatypes/enums.h"
#include "natives.h"
#include "../optionals/optionals.h"
#include "value.h"

static void resetStack(DictuVM *vm) {
vm->stackTop = vm->stack;
Expand Down Expand Up @@ -866,7 +867,9 @@ static void copyAnnotations(DictuVM *vm, ObjDict *superAnnotations, ObjDict *kla
}
}

static DictuInterpretResult run(DictuVM *vm) {


static DictuInterpretResult runWithBreakFrame(DictuVM *vm, int breakFrame) {
CallFrame *frame = &vm->frames[vm->frameCount - 1];
register uint8_t* ip = frame->ip;

Expand All @@ -877,6 +880,7 @@ static DictuInterpretResult run(DictuVM *vm) {
#define READ_CONSTANT() \
(frame->closure->function->chunk.constants.values[READ_BYTE()])


#define READ_STRING() AS_STRING(READ_CONSTANT())

#define UNSUPPORTED_OPERAND_TYPE_ERROR(op) \
Expand Down Expand Up @@ -2253,6 +2257,7 @@ static DictuInterpretResult run(DictuVM *vm) {
}

CASE_CODE(RETURN): {

Value result = pop(vm);

// Close any upvalues still in scope.
Expand All @@ -2270,6 +2275,10 @@ static DictuInterpretResult run(DictuVM *vm) {

frame = &vm->frames[vm->frameCount - 1];
ip = frame->ip;
if (breakFrame != -1 && vm->frameCount == breakFrame) {
return INTERPRET_OK;
}

DISPATCH();
}

Expand Down Expand Up @@ -2435,6 +2444,9 @@ static DictuInterpretResult run(DictuVM *vm) {

return INTERPRET_RUNTIME_ERROR;
}
static DictuInterpretResult run(DictuVM *vm) {
return runWithBreakFrame(vm, -1);
}

DictuInterpretResult dictuInterpret(DictuVM *vm, char *moduleName, char *source) {
ObjString *name = copyString(vm, moduleName, strlen(moduleName));
Expand All @@ -2457,3 +2469,21 @@ DictuInterpretResult dictuInterpret(DictuVM *vm, char *moduleName, char *source)

return result;
}
Value callFunction(DictuVM* vm, Value function, int argCount, Value* args) {
if(!IS_FUNCTION(function) && !IS_CLOSURE(function))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it would be nice to return an EMPTY val and throw a runtime error (happy you're just testing so may not have put that in yet etc)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also be nice to handle natives here too, that should be a lot easier as we don't need to handle call frames

return NIL_VAL;
int currentFrameCount = vm->frameCount;
Value* currentStack = vm->stackTop;
CallFrame *frame = &vm->frames[vm->frameCount++];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we need to be careful we actually have enough frames, we may need to reallocate if not

uint8_t code[4] = {OP_CALL, argCount, 0, OP_RETURN};
frame->ip = code;
push(vm, function);
for(int i = argCount -1; i >= 0; i--) {
push(vm, args[i]);
}
runWithBreakFrame(vm, currentFrameCount+1);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we would need to handle a runtime error as at the minute (without testing) I'm assuming this will probably dump

Value v = pop(vm);
vm->stackTop = currentStack;
vm->frameCount--;
return v;
}
2 changes: 2 additions & 0 deletions src/vm/vm.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,6 @@ bool isFalsey(Value value);

ObjClosure *compileModuleToClosure(DictuVM *vm, char *name, char *source);

Value callFunction(DictuVM* vm, Value function, int argCount, Value* args);

#endif
Loading