From a6081600ae0fa12e0f07dce90796a6ff0182efd2 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 25 Jun 2022 17:32:41 +0300 Subject: [PATCH] namespace reading functions for FFI --- include/bqnffi.h | 2 ++ include/syms | 2 ++ src/builtins/fns.c | 5 +++++ src/ffi.c | 7 +++++++ src/ns.c | 11 ++++++----- src/ns.h | 1 + test/README.md | 2 +- test/ffi/ffiTest.c | 13 +++++++++++++ test/ffi/test.bqn | 3 +++ test/ffi/test.expected | 4 ++++ 10 files changed, 44 insertions(+), 6 deletions(-) diff --git a/include/bqnffi.h b/include/bqnffi.h index afcc0625..7b4064c3 100644 --- a/include/bqnffi.h +++ b/include/bqnffi.h @@ -44,6 +44,8 @@ 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. // create objects BQNV bqn_makeF64(double d); diff --git a/include/syms b/include/syms index f4aa1947..560473da 100644 --- a/include/syms +++ b/include/syms @@ -22,6 +22,8 @@ bqn_readC16Arr; bqn_readC32Arr; bqn_readObjArr; + bqn_hasField; + bqn_getField; bqn_makeF64; bqn_makeChar; bqn_makeI8Arr; diff --git a/src/builtins/fns.c b/src/builtins/fns.c index 25fd91d4..f1d22449 100644 --- a/src/builtins/fns.c +++ b/src/builtins/fns.c @@ -337,6 +337,11 @@ i32 str2gid(B s) { return r; } +i32 str2gidQ(B s) { // if the name doesn't exist yet, return -1 + if (globalNames==NULL) return -1; // if there are no names, there certainly won't be the queried one + return getD_b2i(globalNames, s, -1); +} + B gid2str(i32 n) { B r = IGetU(globalNameList, n); // print_fmt("gid2str %i → %R\n", n, r); diff --git a/src/ffi.c b/src/ffi.c index 68a2a27f..385bd214 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -10,6 +10,7 @@ #if FFI==2 #include #include "utils/mut.h" +#include "ns.h" #endif // base interface defs for when GC stuff needs to be added in @@ -84,6 +85,12 @@ void bqn_readObjArr(BQNV a, BQNV* buf) { B b = getB(a); } } +bool bqn_hasField(BQNV ns, BQNV name) { + return !q_N(ns_getNU(getB(ns), getB(name), false)); +} +BQNV bqn_getField(BQNV ns, BQNV name) { + return makeX(inc(ns_getNU(getB(ns), getB(name), true))); +} BQNV bqn_makeF64(double d) { return makeX(m_f64(d)); } BQNV bqn_makeChar(uint32_t c) { return makeX(m_c32(c)); } diff --git a/src/ns.c b/src/ns.c index c0b09c3c..72d28b2e 100644 --- a/src/ns.c +++ b/src/ns.c @@ -60,11 +60,12 @@ B ns_qgetU(B ns, i32 gid) { VTY(ns, t_ns); B ns_getNU(B ns, B name, bool thrEmpty) { VTY(ns, t_ns); NS* n = c(NS, ns); NSDesc* d = n->desc; - i32 gid = str2gid(name); - - i32 ia = d->varAm; - for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i]; - if (thrEmpty) thrM("No key found"); + i32 gid = str2gidQ(name); + if (gid!=-1) { + i32 ia = d->varAm; + for (i32 i = 0; i < ia; i++) if (d->expGIDs[i]==gid) return n->sc->vars[i]; + } + if (thrEmpty) thrF("No field named %B found", name); return bi_N; } B ns_getC(B ns, char* name) { diff --git a/src/ns.h b/src/ns.h index 5e1447d4..42684c86 100644 --- a/src/ns.h +++ b/src/ns.h @@ -23,6 +23,7 @@ void ns_set(B ns, B name, B val); // consumes val i32 pos2gid(Body* body, i32 pos); // converts a variable position to a gid; errors on special name variables i32 str2gid(B s); // doesn't consume +i32 str2gidQ(B s); // doesn't consume B gid2str(i32 n); // returns unowned object diff --git a/test/README.md b/test/README.md index 3fea34fd..6fcc2490 100644 --- a/test/README.md +++ b/test/README.md @@ -12,7 +12,7 @@ test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations ./BQN test/bitcpy.bqn // fuzz-test bit_cpy; requires a CBQN build with -DTEST_BITCPY ./BQN test/squeeze.bqn // fuzz-test squeezing; requires a CBQN build with -DEEQUAL_NEGZERO ./BQN test/random.bqn // various random tests -make -C test/ffi // test FFI functionality +make -C test/ffi // test FFI functionality; expects both regular and shared library CBQN builds to already exist legacy utilities: test/readTests.bqn // read mlochbaum/BQN tests in various formats diff --git a/test/ffi/ffiTest.c b/test/ffi/ffiTest.c index bd156e09..11125b51 100644 --- a/test/ffi/ffiTest.c +++ b/test/ffi/ffiTest.c @@ -51,6 +51,19 @@ BQNV readTyped(BQNV x) { return bqn_makeF64(res); } +BQNV getField(BQNV ns, BQNV name, BQNV def) { + BQNV res; + if (bqn_hasField(ns, name)) { + res = bqn_getField(ns, name); + bqn_free(def); + } else { + res = def; + } + bqn_free(ns); + bqn_free(name); + return res; +} + BQNV getShape(BQNV x) { size_t n = bqn_rank(x); size_t sh[n]; diff --git a/test/ffi/test.bqn b/test/ffi/test.bqn index 7104d158..64c58f53 100644 --- a/test/ffi/test.bqn +++ b/test/ffi/test.bqn @@ -14,6 +14,9 @@ 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 "# namespaces" +f ↩ "lib.so" •FFI "a"‿"getField"‿">𝕨a"‿"a"‿"a" ⋄ •Show {ab⇐1‿2 ⋄ cd⇐3‿4} F ⟨"ab" ⋄ "default"⟩ +f ↩ "lib.so" •FFI "a"‿"getField"‿">𝕨a"‿"a"‿"a" ⋄ •Show {ab⇐1‿2 ⋄ cd⇐3‿4} F ⟨"ef" ⋄ "default"⟩ 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 9f23dbe9..d67b3f96 100644 --- a/test/ffi/test.expected +++ b/test/ffi/test.expected @@ -27,6 +27,10 @@ 165029893 127 +# namespaces +⟨ 1 2 ⟩ +"default" + # print args args: -123 -12323 -212312312 250 50000 3123456789 3.141592741012573242 0.333333333333333315 @