Skip to content

Commit

Permalink
Merge branch 'develop' into feature/type_hints
Browse files Browse the repository at this point in the history
  • Loading branch information
Jason2605 committed Nov 15, 2024
2 parents 643f2c9 + ac22490 commit dfa3135
Show file tree
Hide file tree
Showing 13 changed files with 120 additions and 10 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ jobs:
- uses: actions/checkout@v3
- name: Make dictu and run tests (No HTTP)
run: |
cd examples/ffi-example
cmake -DCMAKE_BUILD_TYPE=Debug -B ./build
cmake --build ./build
cd ../..
cmake -DCMAKE_BUILD_TYPE=Debug -DDISABLE_HTTP=1 -B ./build
cmake --build ./build
./dictu tests/runTests.du ci | tee /dev/stderr | grep -q 'Total bytes lost: 0'
Expand All @@ -54,6 +58,10 @@ jobs:
- uses: actions/checkout@v3
- name: Make dictu and run tests (No HTTP)
run: |
cd examples/ffi-example
cmake -DCMAKE_BUILD_TYPE=Debug -B ./build
cmake --build ./build
cd ../..
cmake -DCMAKE_BUILD_TYPE=Debug -DDISABLE_HTTP=1 -B ./build
cmake --build ./build
./dictu tests/runTests.du ci | tee /dev/stderr | grep -q 'Total bytes lost: 0'
Expand All @@ -76,6 +84,10 @@ jobs:
- uses: actions/checkout@v3
- name: Make dictu and run tests (No HTTP)
run: |
cd examples\ffi-example
cmake -DCMAKE_BUILD_TYPE=Debug -B .\build
cmake --build ./build --config Debug
cd ..\..
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_SYSTEM_VERSION="10.0.18362.0" -DCICD=1 -DDISABLE_HTTP=1 -B build
cmake --build build
Debug\dictu.exe tests/runTests.du ci
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
\.idea/
.cache
build/
\.DS_Store
dictu
Expand Down
8 changes: 8 additions & 0 deletions examples/ffi-example/src/lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ Value dictu_ffi_test_str(DictuVM *vm, int argCount, Value *args) {
return OBJ_VAL(copyString(vm, "Hello From Dictu FFI module!", 28));
}

Value dictu_ffi_test_callback(DictuVM *vm, int argCount, Value *args) {
if(argCount < 1)
return NIL_VAL;
Value* funcs = args+1;
return callFunction(vm, args[0], argCount-1, funcs);
}

int dictu_ffi_init(DictuVM *vm, Table *method_table) {
defineNative(vm, method_table, "dictuFFITestAdd", dictu_ffi_test);
defineNative(vm, method_table, "dictuFFITestStr", dictu_ffi_test_str);
defineNative(vm, method_table, "dictuFFITestCallback", dictu_ffi_test_callback);
defineNativeProperty(
vm, method_table, "test",
OBJ_VAL(copyString(vm, "Dictu!", 6)));
Expand Down
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
50 changes: 49 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 @@ -58,6 +59,10 @@ void runtimeError(DictuVM *vm, const char *format, ...) {
for (int i = vm->frameCount - 1; i >= 0; i--) {
CallFrame *frame = &vm->frames[i];

if(frame->closure == NULL) {
// synthetic frame created by callFunction
continue;
}
ObjFunction *function = frame->closure->function;

// -1 because the IP is sitting on the next instruction to be
Expand Down Expand Up @@ -866,7 +871,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 Down Expand Up @@ -2270,6 +2277,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 +2446,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 +2471,37 @@ 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)){
if(IS_NATIVE(function)) {
NativeFn native = AS_NATIVE(function);
return native(vm, argCount, args);
}
runtimeError(vm, "Value passed to callFunction is not callable");
return EMPTY_VAL;
}
int currentFrameCount = vm->frameCount;
Value* currentStack = vm->stackTop;
if (vm->frameCount == vm->frameCapacity) {
int oldCapacity = vm->frameCapacity;
vm->frameCapacity = GROW_CAPACITY(vm->frameCapacity);
vm->frames = GROW_ARRAY(vm, vm->frames, CallFrame,
oldCapacity, vm->frameCapacity);
}
CallFrame *frame = &vm->frames[vm->frameCount++];
uint8_t code[4] = {OP_CALL, argCount, 0, OP_RETURN};
frame->ip = code;
frame->closure = NULL;
push(vm, function);
for(int i = 0; i < argCount; i++) {
push(vm, args[i]);
}
DictuInterpretResult result = runWithBreakFrame(vm, currentFrameCount+1);
if(result != INTERPRET_OK) {
exit(70);
}
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
41 changes: 36 additions & 5 deletions tests/ffi/ffi.du
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,49 @@ import FFI;
import Path;

class TestFFIModule < UnitTest {
var mod = nil;
setUp() {
if(this.mod != nil)
return;
const parts = ["examples", "ffi-example", "build"];
if(System.platform == "windows"){
parts.push("Debug");
parts.push("ffi-test.dll");
} else {
parts.push("libffi-test{}".format(FFI.suffix));
}

const path = Path.join(parts);
this.mod = FFI.load(path);
}
testFFIModule() {
const path = Path.join(Path.dirname(__file__), "libs", "test-lib{}{}".format(
System.platform == "darwin" ? System.arch == "x86_64" ? "_64" : "_arm" : "",
FFI.suffix
));
const mod = FFI.load(path);
const mod = this.mod;
this.assertEquals(mod.test, "Dictu!");
for(var i = 0; i < 40; i+=2) {
this.assertEquals(mod.dictuFFITestAdd(i, i), i+i);
}
this.assertEquals(mod.dictuFFITestStr(), "Hello From Dictu FFI module!");
}
testFFIModuleCallback() {
const mod = this.mod;
var count = 0;
const list = [];
def callback(value){
count += value;
list.push(value);
return value * value;
}
def greet(name) {
return "Hello, {}!".format(name);
}
for(var i = 0; i < 5; i+=1){
this.assertEquals(mod.dictuFFITestCallback(callback, i * i), i * i * i * i);
}
// 1, 4, 9, 16
this.assertEquals(list, [0,1,4,9,16]);
this.assertEquals(count, 1 + 4 + 9 + 16);
this.assertEquals(mod.dictuFFITestCallback(greet, "World"), "Hello, World!");
}
}

TestFFIModule().run();
Binary file removed tests/ffi/libs/test-lib.dll
Binary file not shown.
Binary file removed tests/ffi/libs/test-lib.so
Binary file not shown.
Binary file removed tests/ffi/libs/test-lib_64.dylib
Binary file not shown.
Binary file removed tests/ffi/libs/test-lib_arm.dylib
Binary file not shown.

0 comments on commit dfa3135

Please sign in to comment.