type formatting for error messages
This commit is contained in:
parent
7471c5c9f5
commit
61f142a1fd
83
src/ffi.c
83
src/ffi.c
@ -338,10 +338,10 @@ static char* const sty_names[] = {
|
|||||||
};
|
};
|
||||||
enum CompoundTy {
|
enum CompoundTy {
|
||||||
cty_ptr, // *... / &...; .a = {{.mutPtr = startsWith("&"), .o=eltype}}
|
cty_ptr, // *... / &...; .a = {{.mutPtr = startsWith("&"), .o=eltype}}
|
||||||
cty_tlarr, // top-level array; {{.o=eltype}}
|
cty_tlarr, // top-level array; {{.o=eltype}}, arrCount=n
|
||||||
cty_struct, // {...}; .a = {{.o=el0}, {.o=el1}, ..., {.o=elLast}, {.structData = ffi_type**}}
|
cty_struct, // {...}; .a = {{.o=el0}, {.o=el1}, ..., {.o=elLast}, {.structData = ffi_type**}}
|
||||||
cty_starr, // struct-based array; same as cty_struct
|
cty_starr, // struct-based array; same as cty_struct
|
||||||
cty_repr, // something:type; {{.o=el, .t=rt, .reType=one of "icuf", .reWidth=bit width of retype}}
|
cty_repr, // something:type; {{.o=el, .t=rt, .reType=one of "icuf", .reWidth=log bit width of retype}}
|
||||||
cty_ptrh, // data holder for pointer objects; {{.o=eltype}, {.ptrh_ptr, .ptrh_stride}}
|
cty_ptrh, // data holder for pointer objects; {{.o=eltype}, {.ptrh_ptr, .ptrh_stride}}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -632,7 +632,54 @@ NOINLINE B readU8Bits(B x) { usz ia=IA(x); u8* xp=tyarr_ptr(x); i16* rp; B r=m
|
|||||||
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 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 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; }
|
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; }
|
||||||
static void* ptrobj_checkget(B x); // doesn't consume
|
static NOINLINE B ptrobj_checkget(B x); // doesn't consume
|
||||||
|
static bool ptrty_equal(B a, B b);
|
||||||
|
static B ptrh_type(B n); // returns ptrty
|
||||||
|
static BQNFFIEnt* ptrh_more(B n);
|
||||||
|
static void* ptrh_ptr(B n);
|
||||||
|
|
||||||
|
static NOINLINE void ty_fmt_add(B* s0, B o) {
|
||||||
|
B s = *s0;
|
||||||
|
if (isC32(o)) {
|
||||||
|
A8(sty_names[o2cG(o)]);
|
||||||
|
} else {
|
||||||
|
BQNFFIType* t = c(BQNFFIType, o);
|
||||||
|
switch (t->ty) {
|
||||||
|
default:
|
||||||
|
A8("???");
|
||||||
|
break;
|
||||||
|
case cty_ptr:
|
||||||
|
ACHR(t->a[0].mutPtr? '&' : '*');
|
||||||
|
ty_fmt_add(&s, t->a[0].o);
|
||||||
|
break;
|
||||||
|
case cty_starr:
|
||||||
|
AFMT("[%i]", t->ia-1);
|
||||||
|
ty_fmt_add(&s, t->a[0].o);
|
||||||
|
break;
|
||||||
|
case cty_tlarr:
|
||||||
|
AFMT("[%i]", t->arrCount);
|
||||||
|
ty_fmt_add(&s, t->a[0].o);
|
||||||
|
break;
|
||||||
|
case cty_struct:
|
||||||
|
A8("{...}");
|
||||||
|
break;
|
||||||
|
case cty_repr:
|
||||||
|
ty_fmt_add(&s, t->a[0].o);
|
||||||
|
AFMT(":%c%i", (u32)t->a[0].reType, (i32)(1 << t->a[0].reWidth));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*s0 = s;
|
||||||
|
}
|
||||||
|
static NOINLINE B ty_fmt(B o) {
|
||||||
|
B s = emptyCVec();
|
||||||
|
ACHR('"');
|
||||||
|
ty_fmt_add(&s, o);
|
||||||
|
ACHR('"');
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STATIC_GLOBAL B ffiObjsGlobal;
|
STATIC_GLOBAL B ffiObjsGlobal;
|
||||||
void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
||||||
@ -642,7 +689,7 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
|||||||
f64 f = c.f;
|
f64 f = c.f;
|
||||||
switch(t) { default: UD; // thrF("FFI: Unimplemented scalar type \"%S\"", sty_names[t]);
|
switch(t) { default: UD; // thrF("FFI: Unimplemented scalar type \"%S\"", sty_names[t]);
|
||||||
case sty_a: *(BQNV*)ptr = makeX(inc(c)); break;
|
case sty_a: *(BQNV*)ptr = makeX(inc(c)); break;
|
||||||
case sty_ptr: *(void**)ptr = ptrobj_checkget(c); break;
|
case sty_ptr: *(void**)ptr = ptrh_ptr(ptrobj_checkget(c)); break;
|
||||||
case sty_u8: { if(!q_fu8 (f)) thrM("FFI: improper value for u8" ); *( u8*)ptr = ( u8)f; break; }
|
case sty_u8: { if(!q_fu8 (f)) thrM("FFI: improper value for u8" ); *( u8*)ptr = ( u8)f; break; }
|
||||||
case sty_i8: { if(!q_fi8 (f)) thrM("FFI: improper value for i8" ); *( i8*)ptr = ( i8)f; break; }
|
case sty_i8: { if(!q_fi8 (f)) thrM("FFI: improper value for i8" ); *( i8*)ptr = ( i8)f; break; }
|
||||||
case sty_u16: { if(!q_fu16(f)) thrM("FFI: improper value for u16"); *(u16*)ptr = (u16)f; break; }
|
case sty_u16: { if(!q_fu16(f)) thrM("FFI: improper value for u16"); *(u16*)ptr = (u16)f; break; }
|
||||||
@ -657,14 +704,12 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
|||||||
} else {
|
} else {
|
||||||
BQNFFIType* t = c(BQNFFIType, o);
|
BQNFFIType* t = c(BQNFFIType, o);
|
||||||
if (t->ty==cty_ptr || t->ty==cty_tlarr) { // *any / &any
|
if (t->ty==cty_ptr || t->ty==cty_tlarr) { // *any / &any
|
||||||
|
|
||||||
B e = t->a[0].o;
|
B e = t->a[0].o;
|
||||||
if (!isArr(c)) {
|
if (isAtm(c)) {
|
||||||
if (isC32(e)) thrF("FFI: Expected array corresponding to \"*%S\"", sty_names[o2cG(e)]);
|
thrF("FFI: Expected array or pointer object corresponding to %R", ty_fmt(o));
|
||||||
else thrM("FFI: Expected array corresponding to *...");
|
|
||||||
}
|
}
|
||||||
usz ia = IA(c);
|
usz ia = IA(c);
|
||||||
if (t->ty==cty_tlarr && t->arrCount!=ia) thrF("FFI: Incorrect item count of %s corresponding to \"[%s]...\"", ia, (usz)t->arrCount);
|
if (t->ty==cty_tlarr && t->arrCount!=ia) thrF("FFI: Incorrect item count of %s corresponding to %R", ia, ty_fmt(o));
|
||||||
if (isC32(e)) { // *num / &num
|
if (isC32(e)) { // *num / &num
|
||||||
incG(c);
|
incG(c);
|
||||||
B cG;
|
B cG;
|
||||||
@ -686,7 +731,6 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
|||||||
BQNFFIType* t2 = c(BQNFFIType, e);
|
BQNFFIType* t2 = c(BQNFFIType, e);
|
||||||
if (t2->ty!=cty_struct && t2->ty!=cty_starr) thrM("FFI: Pointer element type not implemented");
|
if (t2->ty!=cty_struct && t2->ty!=cty_starr) thrM("FFI: Pointer element type not implemented");
|
||||||
|
|
||||||
|
|
||||||
usz elSz = t2->structSize;
|
usz elSz = t2->structSize;
|
||||||
TALLOC(u8, dataAll, elSz*ia + sizeof(usz));
|
TALLOC(u8, dataAll, elSz*ia + sizeof(usz));
|
||||||
void* dataStruct = dataAll+sizeof(usz);
|
void* dataStruct = dataAll+sizeof(usz);
|
||||||
@ -703,8 +747,8 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
|||||||
if (isC32(o2)) { // scalar:any
|
if (isC32(o2)) { // scalar:any
|
||||||
u8 et = o2cG(o2);
|
u8 et = o2cG(o2);
|
||||||
u8 mul = (sty_w[et]*8) >> reW;
|
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 (!isArr(c)) thrF("FFI: Expected array corresponding to %R", ty_fmt(o));
|
||||||
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));
|
if (IA(c) != mul) thrF("FFI: Bad array corresponding to %R: expected %s elements, got %s", ty_fmt(o), (usz)mul, IA(c));
|
||||||
B cG = toW(reT, reW, incG(c));
|
B cG = toW(reT, reW, incG(c));
|
||||||
memcpy(ptr, tyany_ptr(cG), 8); // may over-read, ¯\_(ツ)_/¯
|
memcpy(ptr, tyany_ptr(cG), 8); // may over-read, ¯\_(ツ)_/¯
|
||||||
dec(cG);
|
dec(cG);
|
||||||
@ -716,8 +760,8 @@ void genObj(B o, B c, bool anyMut, void* ptr) { // doesn't consume
|
|||||||
|
|
||||||
u8 et = o2cG(ore);
|
u8 et = o2cG(ore);
|
||||||
u8 mul = (sty_w[et]*8) >> reW;
|
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 (!isArr(c)) thrF("FFI: Expected array corresponding to %R", ty_fmt(o));
|
||||||
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));
|
if (mul && (IA(c) & (mul-1)) != 0) thrF("FFI: Bad array corresponding to %R: expected a multiple of %s elements, got %s", ty_fmt(o), (usz)mul, IA(c));
|
||||||
|
|
||||||
incG(c); B cG;
|
incG(c); B cG;
|
||||||
if (mut) {
|
if (mut) {
|
||||||
@ -1135,7 +1179,7 @@ STATIC_GLOBAL NFnDesc* ptrFieldDesc;
|
|||||||
|
|
||||||
// ptrh - pointer holder - BQNFFIType object of {{.o=eltype}, {.ptrh_ptr, .ptrh_stride}}
|
// ptrh - pointer holder - BQNFFIType object of {{.o=eltype}, {.ptrh_ptr, .ptrh_stride}}
|
||||||
// eltype of sty_void is used for an untyped pointer
|
// eltype of sty_void is used for an untyped pointer
|
||||||
static B ptrh_type(B n) { return c(BQNFFIType, n)->a[0].o; }
|
static B ptrh_type(B n) { return c(BQNFFIType, n)->a[0].o; } // returns ptrty
|
||||||
static BQNFFIEnt* ptrh_more(B n) { return &c(BQNFFIType, n)->a[1]; }
|
static BQNFFIEnt* ptrh_more(B n) { return &c(BQNFFIType, n)->a[1]; }
|
||||||
static void* ptrh_ptr(B n) { return ptrh_more(n)->ptrh_ptr; }
|
static void* ptrh_ptr(B n) { return ptrh_more(n)->ptrh_ptr; }
|
||||||
static ux ptrh_stride(B n) { return ptrh_more(n)->ptrh_stride; }
|
static ux ptrh_stride(B n) { return ptrh_more(n)->ptrh_stride; }
|
||||||
@ -1160,14 +1204,11 @@ B m_ptrobj(void* ptr, B o, ux stride) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static B ptrobj_checkget_holder(B x) { // doesn't consume
|
static NOINLINE B ptrobj_checkget(B x) { // doesn't consume
|
||||||
if (!isNsp(x)) thrF("Expected pointer object, got %S", genericDesc(x));
|
if (!isNsp(x)) thrF("Expected pointer object, got %S", genericDesc(x));
|
||||||
if (c(NS,x)->desc != ptrobj_ns->nsDesc) thrM("Expected pointer object, got some other kind of namespace");
|
if (c(NS,x)->desc != ptrobj_ns->nsDesc) thrM("Expected pointer object, got some other kind of namespace");
|
||||||
return nfn_objU(c(NS,x)->sc->vars[0]);
|
return nfn_objU(c(NS,x)->sc->vars[0]);
|
||||||
}
|
}
|
||||||
static NOINLINE void* ptrobj_checkget(B x) {
|
|
||||||
return ptrh_ptr(ptrobj_checkget_holder(x));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void* ptrobj_elbase(B h, B off, bool negate) { // doesn't consume h, off doesn't matter
|
static void* ptrobj_elbase(B h, B off, bool negate) { // doesn't consume h, off doesn't matter
|
||||||
if (ptrh_type(h).u == m_c32(sty_void).u) thrM("Cannot offset an untyped pointer");
|
if (ptrh_type(h).u == m_c32(sty_void).u) thrM("Cannot offset an untyped pointer");
|
||||||
@ -1273,7 +1314,7 @@ static B ptrobjSub_c1(B t, B x) {
|
|||||||
B h = nfn_objU(t);
|
B h = nfn_objU(t);
|
||||||
if (isNum(x)) return m_ptrobj(ptrobj_elbase(h, x, true), inc(ptrh_type(h)), ptrh_stride(h));
|
if (isNum(x)) return m_ptrobj(ptrobj_elbase(h, x, true), inc(ptrh_type(h)), ptrh_stride(h));
|
||||||
if (isNsp(x)) {
|
if (isNsp(x)) {
|
||||||
B h2 = ptrobj_checkget_holder(x);
|
B h2 = ptrobj_checkget(x);
|
||||||
B t1 = ptrh_type(h);
|
B t1 = ptrh_type(h);
|
||||||
B t2 = ptrh_type(h2);
|
B t2 = ptrh_type(h2);
|
||||||
if (t1.u==m_c32(sty_void).u || t2.u==m_c32(sty_void).u) thrM("(pointer).Sub ptr: Both pointers must be typed");
|
if (t1.u==m_c32(sty_void).u || t2.u==m_c32(sty_void).u) thrM("(pointer).Sub ptr: Both pointers must be typed");
|
||||||
@ -1294,7 +1335,7 @@ static B ptrobjSub_c1(B t, B x) {
|
|||||||
void ffi_init(void) {
|
void ffi_init(void) {
|
||||||
boundFnDesc = registerNFn(m_c8vec_0("(foreign function)"), boundFn_c1, boundFn_c2);
|
boundFnDesc = registerNFn(m_c8vec_0("(foreign function)"), boundFn_c1, boundFn_c2);
|
||||||
foreignFnDesc = registerNFn(m_c8vec_0("(foreign function)"), directFn_c1, directFn_c2);
|
foreignFnDesc = registerNFn(m_c8vec_0("(foreign function)"), directFn_c1, directFn_c2);
|
||||||
ptrobj_ns = m_nnsDesc("read","write","cast","add","sub","field"); // first field must be an nfn whose object is the ptrh (needed for ptrobj_checkget_holder)
|
ptrobj_ns = m_nnsDesc("read","write","cast","add","sub","field"); // first field must be an nfn whose object is the ptrh (needed for ptrobj_checkget)
|
||||||
ptrReadDesc = registerNFn(m_c8vec_0("(pointer).Read"), ptrobjRead_c1, c2_bad);
|
ptrReadDesc = registerNFn(m_c8vec_0("(pointer).Read"), ptrobjRead_c1, c2_bad);
|
||||||
ptrWriteDesc = registerNFn(m_c8vec_0("(pointer).Write"), ptrobjWrite_c1, ptrobjWrite_c2);
|
ptrWriteDesc = registerNFn(m_c8vec_0("(pointer).Write"), ptrobjWrite_c1, ptrobjWrite_c2);
|
||||||
ptrCastDesc = registerNFn(m_c8vec_0("(pointer).Cast"), ptrobjCast_c1, c2_bad);
|
ptrCastDesc = registerNFn(m_c8vec_0("(pointer).Cast"), ptrobjCast_c1, c2_bad);
|
||||||
|
|||||||
@ -135,8 +135,8 @@
|
|||||||
|
|
||||||
|
|
||||||
# wrong argument internal structure
|
# wrong argument internal structure
|
||||||
!"FFI: Expected array corresponding to *..." % f←@•FFI""‿"bqn_init"‿">*[2]i32" ⋄ F @
|
!"FFI: Expected array or pointer object corresponding to ""*[2]i32""" % f←@•FFI""‿"bqn_init"‿">*[2]i32" ⋄ F @
|
||||||
!"FFI: Expected array corresponding to *..." % f←@•FFI""‿"bqn_init"‿">*{i32}" ⋄ F @
|
!"FFI: Expected array or pointer object 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 @
|
||||||
!"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 ⟨@⟩
|
||||||
!"FFI: Incorrect list length corresponding to a struct: expected 1, got 0" % f←@•FFI""‿"bqn_init"‿">*{i32}" ⋄ F ⟨⟨⟩⟩
|
!"FFI: Incorrect list length corresponding to a struct: expected 1, got 0" % f←@•FFI""‿"bqn_init"‿">*{i32}" ⋄ F ⟨⟨⟩⟩
|
||||||
@ -221,8 +221,6 @@
|
|||||||
!"(pointer).Sub ptr: Arguments must have compatible types" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ p.Sub p.Cast "u8"}}
|
!"(pointer).Sub ptr: Arguments must have compatible types" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ p.Sub p.Cast "u8"}}
|
||||||
!"(pointer).Sub ptr: Distance between pointers isn't an exact multiple of stride" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ (p.Cast "i32").Sub (p.Add 6).Cast "i32"}}
|
!"(pointer).Sub ptr: Distance between pointers isn't an exact multiple of stride" % %USE WallocE {{𝕊al: p←"i8" Al 1 ⋄ (p.Cast "i32").Sub (p.Add 6).Cast "i32"}}
|
||||||
!"Type parser: Structs currently cannot contain mutable references" % @•FFI ""‿"bqn_init"‿"{&i8}"
|
!"Type parser: Structs currently cannot contain mutable references" % @•FFI ""‿"bqn_init"‿"{&i8}"
|
||||||
# !"" % %USE Walloc {{𝕊al: p←"i8" Al 1 ⋄ (p.Cast "{{i8,i16},i32}").Sub p.Cast "{{u8,i16},i32}"}}
|
|
||||||
# !"" % %USE Walloc {{𝕊al: p←"i8" Al 1 ⋄ (p.Cast "{{i8,*i16},i32}").Sub p.Cast "{{u8,*u16},i32}"}}
|
|
||||||
|
|
||||||
# type comparison
|
# type comparison
|
||||||
%USE Walloc {{𝕊al: p←"i8" Al 1 ⋄ t←"{{i8,i16,**i8,[12]i8,*:i32,i64:f64,*,*f64},i32,i64:c8}" ⋄ (p.Cast t).Sub p.Cast t}} %% 0 # ⎊-less test of most passing things to run under heapverify
|
%USE Walloc {{𝕊al: p←"i8" Al 1 ⋄ t←"{{i8,i16,**i8,[12]i8,*:i32,i64:f64,*,*f64},i32,i64:c8}" ⋄ (p.Cast t).Sub p.Cast t}} %% 0 # ⎊-less test of most passing things to run under heapverify
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user