more FFI error checking, plus bugfixes
This commit is contained in:
parent
1bc96f5557
commit
627a7e0771
157
src/ffi.c
157
src/ffi.c
@ -265,6 +265,50 @@ static void printFFIType(FILE* f, B x) {
|
||||
|
||||
#if FFI==2
|
||||
|
||||
#if FFI_CHECKS
|
||||
static char* typeDesc(i32 typeNum) {
|
||||
switch(typeNum) {
|
||||
default: return "(unknown)";
|
||||
case 0: return "an array";
|
||||
case 1: return "a number";
|
||||
case 2: return "a character";
|
||||
case 3: return "a function";
|
||||
case 4: return "a 1-modifier";
|
||||
case 5: return "a 2-modifier";
|
||||
case 6: return "a namespace";
|
||||
}
|
||||
}
|
||||
static NOINLINE i32 nonNumber(B x) { // returns -1 if x is all numeric, otherwise •Type of the offending element
|
||||
if (elNum(TI(x,elType))) return -1;
|
||||
usz ia = IA(x); SGetU(x)
|
||||
i32 r = -1;
|
||||
for (ux i = 0; i < ia; i++) {
|
||||
B c = GetU(x,i);
|
||||
if (!isNum(c)) { r = typeInt(c); break; }
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static NOINLINE void ffi_checkRange(B x, i32 mode, char* desc, i64 min, i64 max) { // doesn't consume; assumes non-array has already been checked for; if min==max, doesn't check range
|
||||
if (IA(x)==0) return;
|
||||
|
||||
char* ref = mode==1? "&" : mode==0? "*" : ":";
|
||||
i32 nonNum = nonNumber(x);
|
||||
if (nonNum!=-1) thrF("FFI: Array provided for %S%S contained %S", ref, desc, typeDesc(nonNum));
|
||||
|
||||
if (min==max) return;
|
||||
incG(x); x = elNum(TI(x,elType))? x : taga(cpyF64Arr(x));
|
||||
|
||||
i64 buf[2];
|
||||
if (!getRange_fns[TI(x,elType)](tyany_ptr(x), buf, IA(x))) thrF("FFI: Array provided for %S%S contained non-integer", ref, desc);
|
||||
if (buf[0]<min) thrF("FFI: Array provided for %S%S contained %l", ref, desc, buf[0]);
|
||||
if (buf[1]>max) thrF("FFI: Array provided for %S%S contained %l", ref, desc, buf[1]);
|
||||
decG(x);
|
||||
}
|
||||
#else
|
||||
static void ffi_checkRange(B x, i32 mode, char* desc, i64 min, i64 max) { }
|
||||
#endif
|
||||
|
||||
|
||||
enum ScalarTy {
|
||||
sty_void, sty_a, sty_ptr,
|
||||
sty_u8, sty_u16, sty_u32, sty_u64,
|
||||
@ -444,9 +488,13 @@ BQNFFIEnt ffi_parseTypeStr(u32** src, bool inPtr, bool top) { // parse actual ty
|
||||
c++;
|
||||
u8 t = *c++;
|
||||
u32 n = readUInt(&c);
|
||||
if (t=='i' | t=='c') if (n!=8 & n!=16 & n!=32) { badW: thrF("Unsupported width in :%c%i", (u32)t, n); }
|
||||
if (t=='u') if (n!=1) goto badW;
|
||||
if (t=='f') if (n!=64) goto badW;
|
||||
if (t=='i' || t=='c') {
|
||||
if (n!=8 & n!=16 & n!=32) { badW: thrF("FFI: Unsupported width in :%c%i", (u32)t, n); }
|
||||
} else if (t=='u') {
|
||||
if (n!=1) goto badW;
|
||||
} else if (t=='f') {
|
||||
if (n!=64) goto badW;
|
||||
} else thrM("FFI: Unexpected character after \":\"");
|
||||
|
||||
if (isC32(ro) && n > myWidth*8) thrF("FFI: Representation wider than the value for \"%S:%c%i\"", sty_names[o2cG(ro)], (u32)t, n);
|
||||
// TODO figure out what to do with i32:i32 etc
|
||||
@ -512,13 +560,13 @@ static usz ffiTmpAlign(usz n) {
|
||||
|
||||
static B ffiObjs;
|
||||
|
||||
static B toW(u8 reT, u8 reW, B x) {
|
||||
static NOINLINE B toW(u8 reT, u8 reW, B x) {
|
||||
switch(reW) { default: UD;
|
||||
case 0: return taga(toBitArr(x)); break;
|
||||
case 3: return reT=='c'? toC8Any(x) : toI8Any(x); break;
|
||||
case 4: return reT=='c'? toC16Any(x) : toI16Any(x); break;
|
||||
case 5: return reT=='c'? toC32Any(x) : toI32Any(x); break;
|
||||
case 6: return toF64Any(x); break;
|
||||
case 0: ffi_checkRange(x, 2, "u1", 0, 1); return taga(toBitArr(x)); break;
|
||||
case 3: if (reT=='i') ffi_checkRange(x, 2, "i8", I8_MIN, I8_MAX); return reT=='c'? toC8Any(x) : toI8Any(x); break;
|
||||
case 4: if (reT=='i') ffi_checkRange(x, 2, "i16", I16_MIN, I16_MAX); return reT=='c'? toC16Any(x) : toI16Any(x); break;
|
||||
case 5: if (reT=='i') ffi_checkRange(x, 2, "i32", I32_MIN, I32_MAX); return reT=='c'? toC32Any(x) : toI32Any(x); break;
|
||||
case 6: ffi_checkRange(x, 2, "f64", 0, 0); return toF64Any(x); break;
|
||||
}
|
||||
}
|
||||
static u8 reTyMapC[] = { [3]=t_c8arr, [4]=t_c16arr, [5]=t_c32arr };
|
||||
@ -534,49 +582,6 @@ static B makeRe(u8 reT, u8 reW/*log*/, u8* src, u32 elW/*bytes*/) {
|
||||
|
||||
FORCE_INLINE u64 i64abs(i64 x) { return x<0?-x:x; }
|
||||
|
||||
#if FFI_CHECKS
|
||||
static char* typeDesc(i32 typeNum) {
|
||||
switch(typeNum) {
|
||||
default: return "(unknown)";
|
||||
case 0: return "an array";
|
||||
case 1: return "a number";
|
||||
case 2: return "a character";
|
||||
case 3: return "a function";
|
||||
case 4: return "a 1-modifier";
|
||||
case 5: return "a 2-modifier";
|
||||
case 6: return "a namespace";
|
||||
}
|
||||
}
|
||||
static NOINLINE i32 nonNumber(B x) { // returns -1 if x is all numeric, otherwise •Type of the offending element
|
||||
if (elNum(TI(x,elType))) return -1;
|
||||
usz ia = IA(x); SGetU(x)
|
||||
i32 r = -1;
|
||||
for (ux i = 0; i < ia; i++) {
|
||||
B c = GetU(x,i);
|
||||
if (!isNum(c)) { r = typeInt(c); break; }
|
||||
}
|
||||
return r;
|
||||
}
|
||||
static NOINLINE void ffi_checkRange(B x, bool mut, char* desc, i64 min, i64 max) { // doesn't consume; assumes non-array has already been checked for; if min==max, doesn't check range
|
||||
if (IA(x)==0) return;
|
||||
|
||||
char ref = mut? '&' : '*';
|
||||
i32 nonNum = nonNumber(x);
|
||||
if (nonNum!=-1) thrF("FFI: Array provided for %c%S contained %S", ref, desc, typeDesc(nonNum));
|
||||
|
||||
if (min==max) return;
|
||||
incG(x); x = elNum(TI(x,elType))? x : taga(cpyF64Arr(x));
|
||||
|
||||
i64 buf[2];
|
||||
if (!getRange_fns[TI(x,elType)](tyany_ptr(x), buf, IA(x))) thrF("Array provided for %c%S contained non-integer", ref, desc);
|
||||
if (buf[0]<min) thrF("FFI: Array provided for %c%S contained %l", ref, desc, buf[0]);
|
||||
if (buf[1]>max) thrF("FFI: Array provided for %c%S contained %l", ref, desc, buf[1]);
|
||||
decG(x);
|
||||
}
|
||||
#else
|
||||
static void ffi_checkRange(B x, bool mut, char* desc, i64 min, i64 max) { }
|
||||
#endif
|
||||
|
||||
#define CPY_UNSIGNED(REL, UEL, DIRECT, WIDEN, WEL) \
|
||||
if (TI(x,elType)<=el_##REL) return taga(DIRECT(x)); \
|
||||
usz ia = IA(x); \
|
||||
@ -605,10 +610,10 @@ static B toU16Bits(B x) { return TI(x,elType)==el_i16? x : cpyU16Bits(x); }
|
||||
static B toU8Bits(B x) { return TI(x,elType)==el_i8? x : cpyU8Bits(x); }
|
||||
|
||||
// read x as the specified type (assuming a container of the respective width signed integer array); consumes x
|
||||
NOINLINE B readU8Bits(B x) { usz ia=IA(x); u8* xp=tyarr_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return num_squeeze(r); }
|
||||
NOINLINE B readU16Bits(B x) { usz ia=IA(x); u16* xp=tyarr_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return num_squeeze(r); }
|
||||
NOINLINE B readU32Bits(B x) { usz ia=IA(x); u32* xp=tyarr_ptr(x); f64* rp; B r=m_f64arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return num_squeeze(r); }
|
||||
NOINLINE B readF32Bits(B x) { usz ia=IA(x); float*xp=tyarr_ptr(x); f64* rp; B r=m_f64arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return r; }
|
||||
NOINLINE B readU8Bits(B x) { usz ia=IA(x); u8* xp=tyarr_ptr(x); i16* rp; B r=m_i16arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return num_squeeze(r); }
|
||||
NOINLINE B readU16Bits(B x) { usz ia=IA(x); u16* xp=tyarr_ptr(x); i32* rp; B r=m_i32arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return num_squeeze(r); }
|
||||
NOINLINE B readU32Bits(B x) { usz ia=IA(x); u32* xp=tyarr_ptr(x); f64* rp; B r=m_f64arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return num_squeeze(r); }
|
||||
NOINLINE B readF32Bits(B x) { usz ia=IA(x); f32* xp=tyarr_ptr(x); f64* rp; B r=m_f64arrv(&rp, ia); for (usz i=0; i<ia; i++) rp[i]=xp[i]; return r; }
|
||||
|
||||
void genObj(B o, B c, bool anyMut, void* ptr) {
|
||||
// printFFIType(stdout,o); printf(" = "); printI(c); printf("\n");
|
||||
@ -677,28 +682,32 @@ void genObj(B o, B c, bool anyMut, void* ptr) {
|
||||
u8 reW = t->a[0].reWidth;
|
||||
if (isC32(o2)) { // scalar:any
|
||||
u8 et = o2cG(o2);
|
||||
u8 etw = sty_w[et]*8;
|
||||
u8 mul = (sty_w[et]*8) >> reW;
|
||||
if (!isArr(c)) thrF("FFI: Expected array corresponding to \"%S:%c%i\"", sty_names[et], (u32)reT, 1<<reW);
|
||||
if (IA(c) != etw>>reW) thrF("FFI: Bad array corresponding to \"%S:%c%i\": expected %s elements, got %s", sty_names[et], (u32)reT, 1<<reW, (usz)(etw>>reW), IA(c));
|
||||
if (IA(c) != mul) thrF("FFI: Bad array corresponding to \"%S:%c%i\": expected %s elements, got %s", sty_names[et], (u32)reT, 1<<reW, (usz)mul, IA(c));
|
||||
B cG = toW(reT, reW, incG(c));
|
||||
memcpy(ptr, tyany_ptr(cG), 8); // may over-read, ¯\_(ツ)_/¯
|
||||
dec(cG);
|
||||
} else { // *scalar:any / &scalar:any
|
||||
if (!isArr(c)) thrM("FFI: Expected array corresponding to a pointer");
|
||||
BQNFFIType* t2 = c(BQNFFIType, o2);
|
||||
B ore = t2->a[0].o;
|
||||
assert(t2->ty==cty_ptr && isC32(ore)); // we shouldn't be generating anything else
|
||||
incG(c);
|
||||
B cG;
|
||||
bool mut = t->a[0].mutPtr;
|
||||
bool mut = t2->a[0].mutPtr;
|
||||
|
||||
u8 et = o2cG(ore);
|
||||
u8 mul = (sty_w[et]*8) >> reW;
|
||||
if (!isArr(c)) thrF("FFI: Expected array corresponding to \"%S%S:%c%i\"", mut?"&":"*", sty_names[et], (u32)reT, 1<<reW);
|
||||
if (mul && (IA(c) & (mul-1)) != 0) thrF("FFI: Bad array corresponding to \"%S%S:%c%i\": expected a multiple of %s elements, got %s", mut?"&":"*", sty_names[et], (u32)reT, 1<<reW, (usz)mul, IA(c));
|
||||
|
||||
incG(c); B cG;
|
||||
if (mut) {
|
||||
Arr* cGp;
|
||||
switch(reW) { default: UD;
|
||||
case 0: cGp = (Arr*) cpyBitArr(c); break;
|
||||
case 3: cGp = reT=='c'? (Arr*) cpyC8Arr(c) : (Arr*) cpyI8Arr(c); break;
|
||||
case 4: cGp = reT=='c'? (Arr*)cpyC16Arr(c) : (Arr*)cpyI16Arr(c); break;
|
||||
case 5: cGp = reT=='c'? (Arr*)cpyC32Arr(c) : (Arr*)cpyI32Arr(c); break;
|
||||
case 6: cGp = (Arr*) cpyF64Arr(c); break;
|
||||
case 0: ffi_checkRange(c, 2, "u1", 0, 1); cGp = (Arr*) cpyBitArr(c); break;
|
||||
case 3: if (reT=='i') ffi_checkRange(c, 2, "i8", I8_MIN, I8_MAX); cGp = reT=='c'? (Arr*) cpyC8Arr(c) : (Arr*) cpyI8Arr(c); break;
|
||||
case 4: if (reT=='i') ffi_checkRange(c, 2, "i16", I16_MIN, I16_MAX); cGp = reT=='c'? (Arr*)cpyC16Arr(c) : (Arr*)cpyI16Arr(c); break;
|
||||
case 5: if (reT=='i') ffi_checkRange(c, 2, "i32", I32_MIN, I32_MAX); cGp = reT=='c'? (Arr*)cpyC32Arr(c) : (Arr*)cpyI32Arr(c); break;
|
||||
case 6: ffi_checkRange(c, 2, "f64", 0, 0); cGp = (Arr*) cpyF64Arr(c); break;
|
||||
}
|
||||
cG = taga(cGp);
|
||||
} else cG = toW(reT, reW, c);
|
||||
@ -774,8 +783,7 @@ B buildObj(BQNFFIEnt ent, bool anyMut, B* objs, usz* objPos) {
|
||||
if (t->ty==cty_ptr) { // *any / &any
|
||||
B e = t->a[0].o;
|
||||
B f = objs[(*objPos)++];
|
||||
bool mut = t->a[0].mutPtr;
|
||||
if (mut) {
|
||||
if (t->a[0].mutPtr) {
|
||||
if (isC32(e)) {
|
||||
switch(o2cG(e)) { default: UD;
|
||||
case sty_i8: case sty_i16: case sty_i32: case sty_f64: return incG(f);
|
||||
@ -801,10 +809,11 @@ B buildObj(BQNFFIEnt ent, bool anyMut, B* objs, usz* objPos) {
|
||||
} else if (t->ty==cty_repr) { // any:any
|
||||
B o2 = t->a[0].o;
|
||||
if (isC32(o2)) return m_f64(0); // scalar:any
|
||||
// *scalar:any / &scalar:any
|
||||
|
||||
BQNFFIType* t2 = c(BQNFFIType,o2); // *scalar:any / &scalar:any
|
||||
assert(t2->ty == cty_ptr);
|
||||
B f = objs[(*objPos)++];
|
||||
bool mut = t->a[0].mutPtr;
|
||||
if (!mut) return m_f64(0);
|
||||
if (!t2->a[0].mutPtr) return m_f64(0);
|
||||
return inc(f);
|
||||
} else thrM("FFI: Unimplemented type (buildObj)");
|
||||
}
|
||||
@ -1007,14 +1016,14 @@ B ffiload_c2(B t, B w, B x) {
|
||||
|
||||
if (ws) freeCStr(ws);
|
||||
dec(w);
|
||||
if (dl==NULL) thrF("Failed to load: %S", dlerror());
|
||||
if (dl==NULL) thrF("FFI: Failed to load library: %S", dlerror());
|
||||
|
||||
char* nameStr = toCStr(name);
|
||||
void* sym = dlsym(dl, nameStr);
|
||||
freeCStr(nameStr);
|
||||
dec(x);
|
||||
|
||||
if (sym==NULL) thrF("Failed to find symbol: %S", dlerror());
|
||||
if (sym==NULL) thrF("FFI: Failed to find symbol: %S", dlerror());
|
||||
#if FFI==1
|
||||
return m_ffiFn(foreignFnDesc, bi_N, directFn_c1, directFn_c2, sym, sym);
|
||||
#else
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
%DEF var V←•internal.Variation ⋄ LV←•internal.ListVariations ⋄ CLR←•internal.ClearRefs
|
||||
%DEF tvar %USE var ⋄ _tvar ← {F _𝕣 x: (CLR@) ⊢ {F 𝕩 V x}¨ LV 𝕩; w F _𝕣 x: (CLR@) ⊢ (LV 𝕨) {(𝕨 V w) F 𝕩 V x}⌜ LV 𝕩}
|
||||
%DEF defs size_t ← "u64"
|
||||
%DEF defs size_t ← "u64" ⋄ size_tw ← 64
|
||||
|
||||
|
||||
# bad •FFI invocation
|
||||
# generally weird
|
||||
@ •FFI⎊9 ""‿"bqn_this symbol doesn't exist" %% 9
|
||||
"file that doesn't exist" •FFI⎊'e' ""‿"abort" %% 'e'
|
||||
@ •FFI⎊'e' ""‿"bqn_this symbol doesn't exist" %% 'e'
|
||||
!"FFI: Type must be a string" % @•FFI "hello"
|
||||
!"FFI: Error parsing type: Unexpected character '?'" % @•FFI""‿"bqn_init"‿"?"
|
||||
!"FFI: Bad array type" % @•FFI""‿"bqn_init"‿"["
|
||||
@ -50,12 +51,13 @@
|
||||
!"FFI: Structs currently cannot contain mutable references" % @•FFI""‿"bqn_init"‿"{&i32}"
|
||||
|
||||
# :
|
||||
!"FFI: Garbage at end of type" % @•FFI""‿"bqn_init"‿"i32:"
|
||||
!"Unsupported width in :i0" % @•FFI""‿"bqn_init"‿"i32:i"
|
||||
!"Unsupported width in :i9" % @•FFI""‿"bqn_init"‿"i32:i9"
|
||||
!"Unsupported width in :u16" % @•FFI""‿"bqn_init"‿"i32:u16"
|
||||
!"Unsupported width in :i64" % @•FFI"i32:i64"‿"bqn_init"
|
||||
!"Unsupported width in :f32" % @•FFI""‿"bqn_init"‿"i32:f32"
|
||||
!"FFI: Unexpected character after "":""" % @•FFI""‿"bqn_init"‿"i32:"
|
||||
!"FFI: Unexpected character after "":""" % f←@•FFI""‿"bqn_init"‿">*u64:q8"
|
||||
!"FFI: Unsupported width in :i0" % @•FFI""‿"bqn_init"‿"i32:i"
|
||||
!"FFI: Unsupported width in :i9" % @•FFI""‿"bqn_init"‿"i32:i9"
|
||||
!"FFI: Unsupported width in :u16" % @•FFI""‿"bqn_init"‿"i32:u16"
|
||||
!"FFI: Unsupported width in :i64" % @•FFI"i32:i64"‿"bqn_init"
|
||||
!"FFI: Unsupported width in :f32" % @•FFI""‿"bqn_init"‿"i32:f32"
|
||||
!"FFI: number literal too large" % @•FFI""‿"bqn_init"‿"i32:u9999999999999999"
|
||||
!"FFI: Representation wider than the value for ""i32:f64""" % @•FFI""‿"bqn_init"‿"i32:f64"
|
||||
!"FFI: Garbage at end of type" % @•FFI""‿"bqn_init"‿"i32 hello world"
|
||||
@ -77,6 +79,9 @@
|
||||
%USE defs ⋄ f←@•FFI"&"‿"memcpy"‿"&i16"‿"*i8"‿size_t ⋄ G←{F⟨𝕩,↕0,0⟩} ⋄ G ¯32768‿32767 %% ¯32768‿32767
|
||||
%USE defs ⋄ f←@•FFI"&"‿"memcpy"‿"&{i16}"‿"*i8"‿size_t ⋄ G←{F⟨𝕩,↕0,0⟩} ⋄ G ⋈¨¯32768‿32767 %% ⋈¨¯32768‿32767
|
||||
%USE defs ⋄ f←@•FFI"&"‿"memcpy"‿"&f32"‿"*i8"‿size_t ⋄ G←{F⟨𝕩,↕0,0⟩} ⋄ G ⟨∞,¯∞,∞÷∞⟩∾10÷˜↕10 %% ⟨∞,¯∞,∞÷∞⟩∾0‿0.10000000149011612‿0.20000000298023224‿0.30000001192092896‿0.4000000059604645‿0.5‿0.6000000238418579‿0.699999988079071‿0.800000011920929‿0.8999999761581421
|
||||
%USE defs ⋄ f←@•FFI"&"‿"memcpy"‿"&i32"‿"*i16:u1"‿size_t ⋄ F ⟨⋈5, 32⥊1, 4⟩ %% ⋈¯1
|
||||
%USE defs ⋄ f←@•FFI⟨"&","memcpy","&i8","*i8",size_t∾":u1"⟩ ⋄ F ⟨¯100+↕10, ↕10, size_tw↑0‿0‿1⟩ %% (↕4)∾4↓¯100+↕10
|
||||
%USE defs ⋄ f←@•FFI"&"‿"memcpy"‿"&i16"‿"*i16:i32"‿size_t ⋄ F ⟨¯100+↕10, ⟨123+456×2⋆16, ¯2⟩, 8⟩ %% 123‿456‿¯2‿¯1∾4↓¯100+↕10
|
||||
|
||||
|
||||
|
||||
@ -90,13 +95,6 @@
|
||||
!"FFI: Array provided for &u16 contained ¯1" % f←@•FFI"&"‿"bqn_init"‿">&u16" ⋄ F ⋈¯1
|
||||
!"FFI: Array provided for &u32 contained ¯1" % f←@•FFI"&"‿"bqn_init"‿">&u32" ⋄ F ⋈¯1
|
||||
|
||||
!"FFI: Array provided for &i16 contained 32768" % f←@•FFI"&"‿"bqn_init"‿">&i16" ⋄ F ¯32768‿32768
|
||||
!"FFI: Array provided for &i16 contained ¯32769" % f←@•FFI"&"‿"bqn_init"‿">&i16" ⋄ F ¯32768‿¯32769
|
||||
|
||||
!"FFI: Array provided for &u8 contained an array" % f←@•FFI"&"‿"bqn_init"‿">&u8" ⋄ F ⟨↕300⟩
|
||||
!"FFI: Array provided for &i16 contained a character" % f←@•FFI"&"‿"bqn_init"‿">&i16" ⋄ F "hi"
|
||||
!"FFI: Array provided for &f64 contained a namespace" % f←@•FFI"&"‿"bqn_init"‿">&f64" ⋄ F 1‿2‿{⇐}
|
||||
|
||||
# bad scalars
|
||||
!"FFI: u8 argument not exact" % f←@•FFI""‿"bqn_init"‿">u8" ⋄ F 256
|
||||
!"FFI: u16 argument not exact" % f←@•FFI""‿"bqn_init"‿">u16" ⋄ F ¯1
|
||||
@ -120,11 +118,6 @@
|
||||
|
||||
|
||||
# wrong argument internal structure
|
||||
!"FFI: Expected array corresponding to ""i32:i8""" % f←@•FFI""‿"bqn_init"‿">i32:i8" ⋄ F @
|
||||
!"FFI: Bad array corresponding to ""i32:i8"": expected 4 elements, got 10" % f←@•FFI""‿"bqn_init"‿">i32:i8" ⋄ F ↕10
|
||||
|
||||
!"FFI: Expected array corresponding to a pointer" % f←@•FFI""‿"bqn_init"‿">*i32:i8" ⋄ F @
|
||||
|
||||
!"FFI: Expected array corresponding to *{...}" % f←@•FFI""‿"bqn_init"‿">*{i32}" ⋄ F @
|
||||
!"FFI: Expected array corresponding to a struct" % f←@•FFI""‿"bqn_init"‿">{i32}" ⋄ F @
|
||||
!"FFI: Expected array corresponding to a struct" % f←@•FFI""‿"bqn_init"‿">*{i32}" ⋄ F ⟨@⟩
|
||||
@ -133,6 +126,31 @@
|
||||
!"FFI: Incorrect list length corresponding to an array: expected 2, got 0" % f←@•FFI""‿"bqn_init"‿">*[2]i32" ⋄ F ⟨⟨⟩⟩
|
||||
!"FFI: Incorrect list length corresponding to an array: expected 2, got 3" % f←@•FFI""‿"bqn_init"‿">*[2]i32" ⋄ F ⟨1‿2‿3⟩
|
||||
|
||||
# bad :
|
||||
!"FFI: Expected array corresponding to ""i32:i8""" % f←@•FFI""‿"bqn_init"‿">i32:i8" ⋄ F @
|
||||
!"FFI: Expected array corresponding to ""*i32:i8""" % f←@•FFI""‿"bqn_init"‿">*i32:i8" ⋄ F @
|
||||
|
||||
!"FFI: Bad array corresponding to ""i32:i8"": expected 4 elements, got 10" % f←@•FFI""‿"bqn_init"‿">i32:i8" ⋄ F ↕10
|
||||
!"FFI: Bad array corresponding to ""u64:u1"": expected 64 elements, got 128" % f←@•FFI""‿"bqn_init"‿">u64:u1" ⋄ F 128⥊1
|
||||
|
||||
!"FFI: Array provided for :u1 contained 63" % f←@•FFI""‿"bqn_init"‿">u64:u1" ⋄ F ↕64
|
||||
!"FFI: Bad array corresponding to ""u64:i8"": expected 8 elements, got 64" % f←@•FFI""‿"bqn_init"‿">u64:i8" ⋄ F ↕64
|
||||
|
||||
!"FFI: Expected array corresponding to ""*u64:i8""" % f←@•FFI""‿"bqn_init"‿">*u64:i8" ⋄ F @
|
||||
!"FFI: Array provided for :i8 contained 199" % f←@•FFI""‿"bqn_init"‿">*u64:i8" ⋄ F ↕200
|
||||
!"FFI: Array provided for :i8 contained 199" % f←@•FFI""‿"bqn_init"‿">&u64:i8" ⋄ F ↕200
|
||||
!"FFI: Array provided for :u1 contained 63" % f←@•FFI""‿"bqn_init"‿">&u64:u1" ⋄ F ↕64
|
||||
!"FFI: Bad array corresponding to ""*u64:i8"": expected a multiple of 8 elements, got 2" % f←@•FFI""‿"bqn_init"‿">*u64:i8" ⋄ F ↕2
|
||||
!"FFI: Bad array corresponding to ""*u32:i16"": expected a multiple of 2 elements, got 1" % f←@•FFI""‿"bqn_init"‿">*u32:i16" ⋄ F ↕1
|
||||
!"FFI: Bad array corresponding to ""&u64:u1"": expected a multiple of 64 elements, got 32" % f←@•FFI""‿"bqn_init"‿">&u64:u1" ⋄ F 32⥊0
|
||||
|
||||
!"FFI: Array provided for &i16 contained 32768" % f←@•FFI"&"‿"bqn_init"‿">&i16" ⋄ F ¯32768‿32768
|
||||
!"FFI: Array provided for &i16 contained ¯32769" % f←@•FFI"&"‿"bqn_init"‿">&i16" ⋄ F ¯32768‿¯32769
|
||||
|
||||
!"FFI: Array provided for &u8 contained an array" % f←@•FFI"&"‿"bqn_init"‿">&u8" ⋄ F ⟨↕300⟩
|
||||
!"FFI: Array provided for &i16 contained a character" % f←@•FFI"&"‿"bqn_init"‿">&i16" ⋄ F "hi"
|
||||
!"FFI: Array provided for &f64 contained a namespace" % f←@•FFI"&"‿"bqn_init"‿">&f64" ⋄ F 1‿2‿{⇐}
|
||||
|
||||
|
||||
|
||||
# unimplemented stuff
|
||||
|
||||
@ -39,16 +39,16 @@ f ↩ "lib.so" •FFI "f32"‿"sumF32Arr"‿"*f32:i32"‿"i32" ⋄ •Show F ⟨
|
||||
Section "# mutate i32*"
|
||||
f ↩ "lib.so" •FFI ⟨"","incI32s","&u32", "i32"⟩ ⋄ •Show F ⟨1e8×20+↕10 ⋄ 10⟩
|
||||
f ↩ "lib.so" •FFI ⟨"","incI32s","&i32:u1", "i32"⟩ ⋄ •Show ⊑F ⟨1‿0‿1‿0‿1‿0‿1‿0‿0‿1‿0‿1‿0‿0‿1‿1‿0‿1‿1‿0‿0‿0‿0‿1‿0‿1‿0‿1‿0‿0‿1‿0‿0‿0‿1‿0‿0‿0‿1‿0‿0‿0‿1‿1‿1‿0‿1‿1‿1‿1‿1‿1‿0‿0‿1‿1‿0‿0‿1‿0‿0‿1‿0‿0, 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"","incI32s","&i32:c8", "i32"⟩ ⋄ •Show ⊑F ⟨"helloworld", 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"","incI32s",">𝕨&i32:c8",">i32"⟩ ⋄ •Show ⊑ "helloworld" F 2
|
||||
f ↩ "lib.so" •FFI ⟨"","incI32s","&i32:c8", "i32"⟩ ⋄ •Show ⊑F ⟨"hello, world", 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"","incI32s",">𝕨&i32:c8",">i32"⟩ ⋄ •Show ⊑ "hello, world" F 2
|
||||
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8", "i32"⟩ ⋄ •Show ⊑F ⟨"helloworld", 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8", "𝕨i32"⟩ ⋄ •Show ⊑ ⟨2⟩ F ⟨"helloworld"⟩
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8",">𝕨i32"⟩ ⋄ •Show ⊑ 2 F ⟨"helloworld"⟩
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", ">&i32:c8",">𝕨i32"⟩ ⋄ •Show ⊑ 2 F "helloworld"
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s",">𝕨&i32:c8", ">i32"⟩ ⋄ •Show ⊑ "helloworld" F 2
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8", "i32"⟩ ⋄ •Show F ⟨"helloworld", 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"&","incI32s", "&i32:c8", "i32"⟩ ⋄ •Show F ⟨"helloworld", 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8", "i32"⟩ ⋄ •Show ⊑F ⟨"hello, world", 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8", "𝕨i32"⟩ ⋄ •Show ⊑ ⟨2⟩ F ⟨"hello, world"⟩
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8",">𝕨i32"⟩ ⋄ •Show ⊑ 2 F ⟨"hello, world"⟩
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", ">&i32:c8",">𝕨i32"⟩ ⋄ •Show ⊑ 2 F "hello, world"
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s",">𝕨&i32:c8", ">i32"⟩ ⋄ •Show ⊑ "hello, world" F 2
|
||||
f ↩ "lib.so" •FFI ⟨"", "incI32s", "&i32:c8", "i32"⟩ ⋄ •Show F ⟨"hello, world", 2⟩
|
||||
f ↩ "lib.so" •FFI ⟨"&","incI32s", "&i32:c8", "i32"⟩ ⋄ •Show F ⟨"hello, world", 2⟩
|
||||
|
||||
Section "# mutate i32*, i16*, i8*"
|
||||
f ↩ "lib.so" •FFI ⟨"","incInts","&i32", "&i16","&i8"⟩ ⋄ •Show F ⥊¨ 10‿20‿30
|
||||
|
||||
@ -54,15 +54,15 @@ ff7fdfefefdf7bb4 ff7fdfefefdf7bb4 fefffdfff7ffbffb bffff7fffdfffeff
|
||||
# mutate i32*
|
||||
⟨ ⟨ 2000000001 2100000001 2200000001 2300000001 2400000001 2500000001 2600000001 2700000001 2800000001 2900000001 ⟩ ⟩
|
||||
⟨ 0 1 1 0 1 0 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 0 0 1 0 1 0 1 0 0 1 0 1 0 1 0 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 1 0 0 1 1 0 0 1 0 0 1 0 0 ⟩
|
||||
"iellpworld"
|
||||
"iellpworld"
|
||||
"iellpworld"
|
||||
"iellpworld"
|
||||
"iellpworld"
|
||||
"iellpworld"
|
||||
"iellpworld"
|
||||
⟨ "iellpworld" ⟩
|
||||
"iellpworld"
|
||||
"iellp, world"
|
||||
"iellp, world"
|
||||
"iellp, world"
|
||||
"iellp, world"
|
||||
"iellp, world"
|
||||
"iellp, world"
|
||||
"iellp, world"
|
||||
⟨ "iellp, world" ⟩
|
||||
"iellp, world"
|
||||
|
||||
# mutate i32*, i16*, i8*
|
||||
10 20 30
|
||||
|
||||
Loading…
Reference in New Issue
Block a user