From a6a14483826738abb836b091d64d0e7d280de2df Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 30 Jun 2022 17:44:01 +0300 Subject: [PATCH] bqn_copy & bqnffi.h comment cleanup --- include/bqnffi.h | 39 +++++++++++++++++++++++---------------- include/syms | 1 + src/ffi.c | 6 ++++++ test/ffi/ffiTest.c | 4 ++++ test/ffi/test.bqn | 1 + test/ffi/test.expected | 1 + 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/include/bqnffi.h b/include/bqnffi.h index d98c8641..eb32e6d7 100644 --- a/include/bqnffi.h +++ b/include/bqnffi.h @@ -1,7 +1,10 @@ #include #include #include - +/* + FFI interface for interfacing with BQN implementations + In general, the functions assume the argument(s) are of the expected type (if applicable), and cause undefined behavior if not +*/ typedef uint64_t BQNV; #ifdef __cplusplus @@ -11,6 +14,7 @@ extern "C" { void bqn_init(void); void bqn_free(BQNV v); +BQNV bqn_copy(BQNV v); // create a new BQNV which can be freed separately from `v` double bqn_toF64 (BQNV v); // includes bqn_free(v) uint32_t bqn_toChar(BQNV v); // includes bqn_free(v) @@ -19,22 +23,25 @@ uint32_t bqn_readChar(BQNV v); // doesn't include bqn_free(v) int bqn_type(BQNV v); // equivalent of BQN •Type -// invoke BQN function +// Invoke BQN function; f can be any BQN object other than modifiers BQNV bqn_call1(BQNV f, BQNV x); BQNV bqn_call2(BQNV f, BQNV w, BQNV x); -// evaluate BQN code in a fresh environment -BQNV bqn_eval(BQNV src); +// Evaluate BQN code in a fresh environment +BQNV bqn_eval(BQNV src); // src must be a character vector BQNV bqn_evalCStr(const char* str); // evaluates the null-terminated UTF8-encoded str; equal to `BQNV s = bqn_makeUTF8Str(str, strlen(str)); result = bqn_eval(s); bqn_free(s);` -// read array data -size_t bqn_bound(BQNV a); // aka product of shape, ×´≢a -size_t bqn_rank(BQNV a); +// Read array data +size_t bqn_bound(BQNV a); // aka product of shape, aka "×´≢a" +size_t bqn_rank(BQNV a); // "=a" void bqn_shape(BQNV a, size_t* buf); // writes bqn_rank(a) items in buf -BQNV bqn_pick(BQNV a, size_t pos); +BQNV bqn_pick(BQNV a, size_t pos); // pos⊑⥊a -// read all elements of `a` into the specified buffer +// Functions for reading all elements of `a` into a pre-allocated buffer (whose count must be at least `bqn_bound(a)`). +// Defined if and only if the input `a` consists of elements whose types exactly fit in the wanted type. +// e.g. bqn_readObjArr is always defined (assuming `a` is an array and `buf` isn't null and has enough slots) +// but bqn_readI8Arr is illegal to invoke on `⟨1.2,3.4⟩` or `⟨200,201⟩` void bqn_readI8Arr (BQNV a, int8_t* buf); void bqn_readI16Arr(BQNV a, int16_t* buf); void bqn_readI32Arr(BQNV a, int32_t* buf); @@ -44,10 +51,10 @@ void bqn_readC16Arr(BQNV a, uint16_t* buf); void bqn_readC32Arr(BQNV a, uint32_t* buf); void bqn_readObjArr(BQNV a, BQNV* buf); -bool bqn_hasField(BQNV ns, BQNV name); // test if the namespace has the wanted field (name must be all lowercase with no underscores) -BQNV bqn_getField(BQNV ns, BQNV name); // return the value of the field with the name. Assumes the field does exist. +bool bqn_hasField(BQNV ns, BQNV name); // test if the namespace has the wanted field (result is unspecified if `name` isn't lowercase or has underscores) +BQNV bqn_getField(BQNV ns, BQNV name); // gives the value of the field with the requested name. Assumes the field exists in the namespace. -// create objects +// Create objects BQNV bqn_makeF64(double d); BQNV bqn_makeChar(uint32_t c); BQNV bqn_makeI8Arr (size_t rank, const size_t* shape, const int8_t* data); @@ -72,16 +79,16 @@ BQNV bqn_makeUTF8Str(size_t len, const char* str); // len is the number of chars typedef BQNV (*bqn_boundFn1)(BQNV obj, BQNV x); typedef BQNV (*bqn_boundFn2)(BQNV obj, BQNV w, BQNV x); -// when called, 1st arg to `f` will be `obj` +// When the result is called, the first arg given to `f` will be `obj`, and the rest will be the corresponding BQN arguments BQNV bqn_makeBoundFn1(bqn_boundFn1 f, BQNV obj); BQNV bqn_makeBoundFn2(bqn_boundFn2 f, BQNV obj); -// direct (zero copy) array item access +// Direct (zero copy) array item access typedef enum { elt_unk, elt_i8, elt_i16, elt_i32, elt_f64, elt_c8, elt_c16, elt_c32 } BQNElType; // note that more types may be added in the future BQNElType bqn_directArrType(BQNV a); -// can only use the functions below if bqn_directArrType returns the corresponding type -// a valid implementation of bqn_directArrType would be to always return elt_unk, thus disallowing the use of direct access entirely +// The functions below can only be used if if bqn_directArrType returns the exact equivalent type +// A valid implementation of bqn_directArrType would be to always return elt_unk, thus disallowing the use of direct access entirely int8_t* bqn_directI8 (BQNV a); int16_t* bqn_directI16(BQNV a); int32_t* bqn_directI32(BQNV a); diff --git a/include/syms b/include/syms index 560473da..27aaacdc 100644 --- a/include/syms +++ b/include/syms @@ -1,6 +1,7 @@ { bqn_init; bqn_free; + bqn_copy; bqn_toF64; bqn_toChar; bqn_readF64; diff --git a/src/ffi.c b/src/ffi.c index 44e81df1..cb6fecf9 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -20,10 +20,16 @@ static B getB(BQNV v) { static BQNV makeX(B x) { return x.u; } + void bqn_free(BQNV v) { dec(getB(v)); } +BQNV bqn_copy(BQNV v) { + return makeX(inc(getB(v))); +} + static void freeTagged(BQNV v) { } + #define DIRECT_BQNV 1 double bqn_toF64 (BQNV v) { double r = o2fu(getB(v)); freeTagged(v); return r; } diff --git a/test/ffi/ffiTest.c b/test/ffi/ffiTest.c index 11125b51..ee1c0cae 100644 --- a/test/ffi/ffiTest.c +++ b/test/ffi/ffiTest.c @@ -111,6 +111,10 @@ BQNV makeArrays() { return bqn_makeObjVec(16, res); } +BQNV makeThree(BQNV x) { + return bqn_makeObjVec(3, (BQNV[]){bqn_copy(x), bqn_copy(x), x}); +} + int32_t directAccess(BQNV x) { BQNElType e = bqn_directArrType(x); uint32_t res = 0; diff --git a/test/ffi/test.bqn b/test/ffi/test.bqn index 64c58f53..8b7d1cf5 100644 --- a/test/ffi/test.bqn +++ b/test/ffi/test.bqn @@ -11,6 +11,7 @@ f ↩ "lib.so" •FFI "a"‿"readTyped"‿">a" ⋄ •Show F (10×↕7) + (4⥊< 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 "a"‿"makeThree"‿">a" ⋄ •Show F "foo" 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 diff --git a/test/ffi/test.expected b/test/ffi/test.expected index d67b3f96..29b6edda 100644 --- a/test/ffi/test.expected +++ b/test/ffi/test.expected @@ -24,6 +24,7 @@ "abcABC;" "abcABC;" "{𝕨+𝕩}" +⟨ "foo" "foo" "foo" ⟩ 165029893 127