From 04c2ce7ade7ce9327ca1889bf5297f09090048f9 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 28 May 2022 17:35:30 +0300 Subject: [PATCH] tests for bqnffi.h --- docs/system.md | 9 +++- src/core/stuff.c | 2 +- test/ffi/ffiTest.c | 97 ++++++++++++++++++++++++++++++++++++++++-- test/ffi/test.bqn | 9 +++- test/ffi/test.expected | 22 ++++++++++ 5 files changed, 132 insertions(+), 7 deletions(-) diff --git a/docs/system.md b/docs/system.md index 327aec38..a02851f6 100644 --- a/docs/system.md +++ b/docs/system.md @@ -8,6 +8,7 @@ See [the BQN specification](https://mlochbaum.github.io/BQN/spec/system.html) fo | `•ReBQN` | Supported options: `repl`, `primitives` | | `•primitives` | | | `•Import` | | +| `•FFI` | see [FFI](#ffi) | | `•state` | | | `•args` | | | `•path` | | @@ -101,4 +102,10 @@ Namespace of various internal functions. May change at any time. | `•internal.ClearRefs` | Clear references `•internal.Variation` made for `*Inc` variations | | `•internal.Unshare` | Get a unique, reference count 1 version of the argument; recursively unshares array items, doesn't touch namespaces | | `•internal.EEqual` | exactly equal (NaN equals NaN); 0 and ¯0 aren't equal, but can be made so with the C compile-time flag `-DEEQUAL_NEGZERO` | -| `•internal.Temp` | place to test new features or temporarily expose some internal function | \ No newline at end of file +| `•internal.Temp` | place to test new features or temporarily expose some internal function | + +# FFI + +Currently, there is no support for structs, nested pointers, or constant-length arrays, aka the only supported types are scalars (e.g. `i8`, `u64`, `*`), pointers to those (e.g. `*i8`, `&u64`), and conversions of either of those (e.g. `u64:i32`, `**:c8`). + +Additionally, the `a` type maps to `BQNV` from [bqnffi.h](../include/bqnffi.h) (example usage in [FFI tests](../test/ffi/)). \ No newline at end of file diff --git a/src/core/stuff.c b/src/core/stuff.c index 57d7b0b1..f37ac709 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -762,7 +762,7 @@ B bqn_merge(B x) { usz rp = 0; for (usz i = 0; i < xia; i++) { B c = GetU(x, i); - if (isArr(c)? (elR!=rnk(c) || !eqShPrefix(elSh, a(c)->sh, elR)) : elR!=0) { mut_pfree(r, rp); thrF(">: Elements didn't have equal shapes (contained %H and %H)", x0, c); } + if (isArr(c)? (elR!=rnk(c) || !eqShPrefix(elSh, a(c)->sh, elR)) : elR!=0) { mut_pfree(r, rp); thrF(">: Elements didn't have equal shapes (contained shapes %H and %H)", x0, c); } if (isArr(c)) mut_copy(r, rp, c, 0, elIA); else mut_set(r, rp, inc(c)); if (!noFill(fill)) fill = fill_or(fill, getFillQ(c)); diff --git a/test/ffi/ffiTest.c b/test/ffi/ffiTest.c index 244866ba..698166f1 100644 --- a/test/ffi/ffiTest.c +++ b/test/ffi/ffiTest.c @@ -15,16 +15,105 @@ BQNV timesTen(BQNV v) { return res; } -BQNV add_args(BQNV t, BQNV x) { - return bqn_makeF64(bqn_toF64(t) + bqn_toF64(x)); +BQNV readAtoms(BQNV num, BQNV chr) { + uint32_t c1 = bqn_readChar(chr); uint32_t c2 = bqn_toChar(chr); + double f1 = bqn_readF64 (num); double f2 = bqn_toF64 (num); + printf("%u %u %.18f %.18f\n", c1, c2, f1, f2); + return bqn_makeChar(c1+1); } -BQNV bind_add(BQNV x) { - BQNV r = bqn_makeBoundFn1(add_args, x); + +BQNV readTyped(BQNV x) { + BQNV objs[7]; + bqn_readObjArr(x, objs); + + BQNV pick3 = bqn_pick(x, 3); + BQNV equal = bqn_evalCStr("≡"); + if (!bqn_toF64(bqn_call2(equal, pick3, objs[3]))) printf("bqn_pick didn't give the same element as bqn_readObjArr!\n"); + bqn_free(equal); + bqn_free(pick3); + + double res = 0; + int8_t bufI8 [10]; bqn_readI8Arr (objs[0], bufI8 ); bqn_free(objs[0]); for (int i=0; i<10; i++) res+= bufI8 [i]; + int16_t bufI16[10]; bqn_readI16Arr(objs[1], bufI16); bqn_free(objs[1]); for (int i=0; i<10; i++) res+= bufI16[i]; + int32_t bufI32[10]; bqn_readI32Arr(objs[2], bufI32); bqn_free(objs[2]); for (int i=0; i<10; i++) res+= bufI32[i]; + double bufF64[10]; bqn_readF64Arr(objs[3], bufF64); bqn_free(objs[3]); for (int i=0; i<10; i++) res+= bufF64[i]; + uint8_t bufC8 [10]; bqn_readC8Arr (objs[4], bufC8 ); bqn_free(objs[4]); for (int i=0; i<10; i++) res+= bufC8 [i]; + uint16_t bufC16[10]; bqn_readC16Arr(objs[5], bufC16); bqn_free(objs[5]); for (int i=0; i<10; i++) res+= bufC16[i]; + uint32_t bufC32[10]; bqn_readC32Arr(objs[6], bufC32); bqn_free(objs[6]); for (int i=0; i<10; i++) res+= bufC32[i]; + + bqn_free(x); + return bqn_makeF64(res); +} + +BQNV getShape(BQNV x) { + size_t n = bqn_rank(x); + size_t sh[n]; + + bqn_shape(x, sh); + bqn_free(x); + + int16_t res[n]; + for (int i = 0; i < n; i++) res[i] = sh[i]; + + return bqn_makeI16Vec(n, res); +} + +BQNV evalBQN(BQNV x) { + BQNV r = bqn_eval(x); bqn_free(x); return r; } +BQNV makeArrays() { + BQNV res[16]; + size_t shape[3] = {2,1,3}; + res[ 0] = bqn_makeI8Arr (3, shape, (int8_t []){1,2,3,4,5,6}); + res[ 1] = bqn_makeI16Arr(3, shape, (int16_t []){1,2,3,4,500,-600}); + res[ 2] = bqn_makeI32Arr(3, shape, (int32_t []){1,2,3,4,500000000,-600000000}); + res[ 3] = bqn_makeF64Arr(3, shape, (double []){1,2,3,4,5.25,6.9765625}); + res[ 4] = bqn_makeC8Arr (3, shape, (uint8_t []){48,49,50,51,52,53}); + res[ 5] = bqn_makeC16Arr(3, shape, (uint16_t[]){48,49,50,51,52,9033}); + res[ 6] = bqn_makeC32Arr(3, shape, (uint32_t[]){48,49,50,51,52,120169}); + res[ 7] = bqn_makeObjArr(2, (size_t[]){2,2}, (BQNV[]){ + bqn_makeChar(120169), + bqn_makeC8Arr(2, shape, (uint8_t[]){48,49,50}), + bqn_makeC8Arr(1, shape, (uint8_t[]){48,49,50}), + bqn_makeC8Arr(0, shape, (uint8_t[]){48}) + }); + res[ 8] = bqn_makeI8Vec (7, (int8_t []){3,1,4,1,5,9,7}); + res[ 9] = bqn_makeI16Vec(7, (int16_t []){3,1,4,1,5,9,7}); + res[10] = bqn_makeI32Vec(7, (int32_t []){3,1,4,1,5,9,7}); + res[11] = bqn_makeF64Vec(7, (double []){3,1,4,1,5,9,7}); + res[12] = bqn_makeC8Vec (7, (uint8_t []){97,98,99,65,66,67,59}); + res[13] = bqn_makeC16Vec(7, (uint16_t[]){97,98,99,65,66,67,59}); + res[14] = bqn_makeC32Vec(7, (uint32_t[]){97,98,99,65,66,67,59}); + res[15] = bqn_makeUTF8Str(11, "{𝕨+𝕩}"); + + return bqn_makeObjVec(16, res); +} +int32_t directAccess(BQNV x) { + BQNElType e = bqn_directType(x); + uint32_t res = 0; + if (e==elt_i32) { + size_t bound = bqn_bound(x); + int32_t* els = bqn_directI32(x); + for (size_t i = 0; i < bound; i++) res = res*31 + (uint32_t)els[i]; + } else { + printf("not elt_i32!\n"); + } + bqn_free(x); + return res; +} + +static BQNV add_args(BQNV t, BQNV x) { + return bqn_makeF64(bqn_toF64(t) + bqn_toF64(x)); +} +BQNV bindAdd(BQNV x) { + BQNV r = bqn_makeBoundFn1(add_args, x); + bqn_free(x); + return r; +} void printArgs(int8_t i8, int16_t i16, int32_t i32, uint8_t u8, uint16_t u16, uint32_t u32, float f, double d) { printf("args: %d %d %d %u %u %u %.18f %.18f\n", i8, i16, i32, u8, u16, u32, f, d); diff --git a/test/ffi/test.bqn b/test/ffi/test.bqn index 6cdf33e5..dd87fcd2 100644 --- a/test/ffi/test.bqn +++ b/test/ffi/test.bqn @@ -5,7 +5,14 @@ f ↩ "lib.so" •FFI ""‿"do_nothing" ⋄ •Show F ⟨⟩ Section "# ""a""" f ↩ "lib.so" •FFI "a"‿"timesTen"‿"a" ⋄ •Show F ⟨↕10⟩ -bind ← "lib.so" •FFI "a"‿"bind_add"‿">a" ⋄ g ← Bind 4 ⋄ •Show G 123 +f ↩ "lib.so" •FFI "a"‿"readAtoms"‿"a"‿"a" ⋄ •Show F ⟨÷5 ⋄ '𝕨'⟩ +f ↩ "lib.so" •FFI "a"‿"readTyped"‿">a" ⋄ •Show F (10×↕7) + (4⥊<↕10)∾3⥊<@+↕10 +f ↩ "lib.so" •FFI "a"‿"getShape"‿">a" ⋄ •Show F¨ {0⥊˜⌽⍟𝕩↕𝕩}¨ ↕5 +f ↩ "lib.so" •FFI "a"‿"evalBQN"‿">a" ⋄ •Show F "↕5" +f ↩ "lib.so" •FFI "a"‿"makeArrays" ⋄ •Out∘•Repr¨ F ⟨⟩ +f ↩ "lib.so" •FFI "i32"‿"directAccess"‿">a" ⋄ •Show F "Ai32"•internal.Variation ↕10 +bind ← "lib.so" •FFI "a"‿"bindAdd"‿">a" ⋄ g ← Bind 4 ⋄ •Show G 123 + Section "# print args" f ↩ "lib.so" •FFI ""‿"printArgs"‿"i8"‿"i16"‿"i32"‿"u8"‿"u16"‿"u32"‿"f32"‿"f64" ⋄ •Show F ¯123‿¯12323‿¯212312312‿250‿50000‿3123456789‿π∾÷3 diff --git a/test/ffi/test.expected b/test/ffi/test.expected index 2a0370ec..2c31d13a 100644 --- a/test/ffi/test.expected +++ b/test/ffi/test.expected @@ -2,6 +2,28 @@ # "a" ⟨ 0 10 20 30 40 50 60 70 80 90 ⟩ +120168 120168 0.200000000000000011 0.200000000000000011 +'𝕩' +2415 +⟨ ⟨⟩ ⟨ 0 ⟩ ⟨ 0 1 ⟩ ⟨ 2 1 0 ⟩ ⟨ 0 1 2 3 ⟩ ⟩ +⟨ 0 1 2 3 4 ⟩ +2‿1‿3⥊1‿2‿3‿4‿5‿6 +2‿1‿3⥊1‿2‿3‿4‿500‿¯600 +2‿1‿3⥊1‿2‿3‿4‿500000000‿¯600000000 +2‿1‿3⥊1‿2‿3‿4‿5.25‿6.9765625 +2‿1‿3⥊"012345" +2‿1‿3⥊"01234⍉" +2‿1‿3⥊"01234𝕩" +2‿2⥊⟨'𝕩',2‿1⥊"01","01",<'0'⟩ +3‿1‿4‿1‿5‿9‿7 +3‿1‿4‿1‿5‿9‿7 +3‿1‿4‿1‿5‿9‿7 +3‿1‿4‿1‿5‿9‿7 +"abcABC;" +"abcABC;" +"abcABC;" +"{𝕨+𝕩}" +165029893 127 # print args