From a4befbd8bfb709cc9e603245527858613e38a4ce Mon Sep 17 00:00:00 2001 From: dzaima Date: Sun, 29 Oct 2023 01:01:29 +0300 Subject: [PATCH] =?UTF-8?q?FFI:=20check=20for=20=F0=9D=95=A8=20being=20pre?= =?UTF-8?q?sent=20when=20required?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ffi.c | 19 ++++++++++--------- test/cases/ffi.bqn | 26 ++++++++++++++++---------- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/src/ffi.c b/src/ffi.c index 899e1421..c746867e 100644 --- a/src/ffi.c +++ b/src/ffi.c @@ -623,14 +623,14 @@ void genObj(B o, B c, bool anyMut, void* ptr) { switch(t) { default: UD; // thrF("FFI: Unimplemented scalar type \"%S\"", sty_names[t]); case sty_a: *(BQNV*)ptr = makeX(inc(c)); break; case sty_ptr: thrM("FFI: \"*\" unimplemented"); break; - case sty_u8: { if(!q_fu8 (f)) thrM("FFI: u8 argument not exact" ); *( u8*)ptr = ( u8)f; break; } - case sty_i8: { if(!q_fi8 (f)) thrM("FFI: i8 argument not exact" ); *( i8*)ptr = ( i8)f; break; } - case sty_u16: { if(!q_fu16(f)) thrM("FFI: u16 argument not exact"); *(u16*)ptr = (u16)f; break; } - case sty_i16: { if(!q_fi16(f)) thrM("FFI: i16 argument not exact"); *(i16*)ptr = (i16)f; break; } - case sty_u32: { if(!q_fu32(f)) thrM("FFI: u32 argument not exact"); *(u32*)ptr = (u32)f; break; } - case sty_i32: { if(!q_fi32(f)) thrM("FFI: i32 argument not exact"); *(i32*)ptr = (i32)f; break; } - case sty_u64: { if(!q_fu64(f)) thrM("FFI: u64 argument not exact"); u64 i=(u64)f; if (i>=(1ULL<<53)) thrM("FFI: u64 argument value ≥ 2⋆53"); *(u64*)ptr = i; break; } - case sty_i64: { if(!q_fi64(f)) thrM("FFI: i64 argument not exact"); i64 i=(i64)f; if (i>=(1LL<<53) || i<=-(1LL<<53)) thrM("FFI: i64 argument absolute value ≥ 2⋆53"); *(i64*)ptr = i; 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_u16: { if(!q_fu16(f)) thrM("FFI: improper value for u16"); *(u16*)ptr = (u16)f; break; } + case sty_i16: { if(!q_fi16(f)) thrM("FFI: improper value for i16"); *(i16*)ptr = (i16)f; break; } + case sty_u32: { if(!q_fu32(f)) thrM("FFI: improper value for u32"); *(u32*)ptr = (u32)f; break; } + case sty_i32: { if(!q_fi32(f)) thrM("FFI: improper value for i32"); *(i32*)ptr = (i32)f; break; } + case sty_u64: { if(!q_fu64(f)) thrM("FFI: improper value for u64"); u64 i=(u64)f; if (i>=(1ULL<<53)) thrM("FFI: u64 argument value ≥ 2⋆53"); *(u64*)ptr = i; break; } + case sty_i64: { if(!q_fi64(f)) thrM("FFI: improper value for i64"); i64 i=(i64)f; if (i>=(1LL<<53) || i<=-(1LL<<53)) thrM("FFI: i64 argument absolute value ≥ 2⋆53"); *(i64*)ptr = i; break; } case sty_f32: *(float* )ptr = f; break; case sty_f64: *(double*)ptr = f; break; } @@ -835,9 +835,10 @@ B libffiFn_c2(B t, B w, B x) { L##a = a(L); \ L##f = TIv(L##a,getU); \ } else if (FFI_CHECKS && bf->L##Len==0 && (ISX? 1 : !q_N(w)) && (isAtm(L) || RNK(L)!=1 || IA(L)!=0)) { \ - thrF("FFI: " S " must %S", ISX? "be an empty list" : "either be an empty list, or not present"); \ + thrF("FFI: " S " must %S", ISX? "be an empty list" : "either be an empty list, or not be present"); \ } + if (FFI_CHECKS && bf->wLen!=0 && q_N(w)) thrM("FFI: 𝕨 must be present"); PROC_ARG(0, w, W, "𝕨") PROC_ARG(1, x, X, "𝕩") diff --git a/test/cases/ffi.bqn b/test/cases/ffi.bqn index 2236698a..d8f9b27c 100644 --- a/test/cases/ffi.bqn +++ b/test/cases/ffi.bqn @@ -96,16 +96,18 @@ !"FFI: Array provided for &u32 contained ¯1" % f←@•FFI"&"‿"bqn_init"‿">&u32" ⋄ F ⋈¯1 # 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 -!"FFI: u32 argument not exact" % f←@•FFI""‿"bqn_init"‿">u32" ⋄ F ¯1 -!"FFI: u64 argument not exact" % f←@•FFI""‿"bqn_init"‿">u64" ⋄ F ¯1 -!"FFI: u32 argument not exact" % f←@•FFI""‿"bqn_init"‿">u32" ⋄ F 2⋆32 -!"FFI: u32 argument not exact" % f←@•FFI""‿"bqn_init"‿">u32" ⋄ F 1e20 +!"FFI: improper value for u8" % f←@•FFI""‿"bqn_init"‿">u8" ⋄ F 256 +!"FFI: improper value for u16" % f←@•FFI""‿"bqn_init"‿">u16" ⋄ F ¯1 +!"FFI: improper value for u32" % f←@•FFI""‿"bqn_init"‿">u32" ⋄ F ¯1 +!"FFI: improper value for u64" % f←@•FFI""‿"bqn_init"‿">u64" ⋄ F ¯1 +!"FFI: improper value for u32" % f←@•FFI""‿"bqn_init"‿">u32" ⋄ F 2⋆32 +!"FFI: improper value for u32" % f←@•FFI""‿"bqn_init"‿">u32" ⋄ F 1e20 !"FFI: u64 argument value ≥ 2⋆53" % f←@•FFI""‿"bqn_init"‿">u64" ⋄ F 2⋆53 !"FFI: i64 argument absolute value ≥ 2⋆53" % f←@•FFI""‿"bqn_init"‿">i64" ⋄ F 2⋆53 !"FFI: i64 argument absolute value ≥ 2⋆53" % f←@•FFI""‿"bqn_init"‿">i64" ⋄ F -2⋆53 - +!"FFI: improper value for i32" % f←@•FFI""‿"bqn_init"‿">𝕨i32"‿">i64" ⋄ @ F 3 +!"FFI: improper value for i32" % f←@•FFI""‿"bqn_init"‿">𝕨i32"‿">i64" ⋄ ⟨1⟩ F 3 +!"FFI: improper value for i64" % f←@•FFI""‿"bqn_init"‿"i64" ⋄ F ⟨@⟩ # bad overall argument separation @@ -118,8 +120,11 @@ !"FFI: 𝕩 must be an empty list" % f←@•FFI""‿"bqn_init" ⋄ F ⟨1⟩ !"FFI: 𝕩 must be an empty list" % f←@•FFI""‿"bqn_init" ⋄ F @ !"FFI: 𝕩 must be an empty list" % f←@•FFI""‿"bqn_init"‿"𝕨i32"‿"𝕨i32" ⋄ 1‿2 F @ -!"FFI: 𝕨 must either be an empty list, or not present" % f←@•FFI""‿"bqn_init"‿"*i8" ⋄ ⟨1,2⟩ F 1‿2‿3‿0 -!"FFI: 𝕨 must either be an empty list, or not present" % f←@•FFI""‿"bqn_init"‿"*i8" ⋄ @ F 1‿2‿3‿0 +!"FFI: 𝕨 must either be an empty list, or not be present" % f←@•FFI""‿"bqn_init"‿"*i8" ⋄ ⟨1,2⟩ F 1‿2‿3‿0 +!"FFI: 𝕨 must either be an empty list, or not be present" % f←@•FFI""‿"bqn_init"‿"*i8" ⋄ @ F 1‿2‿3‿0 +!"FFI: 𝕨 must be present" % f←@•FFI""‿"bqn_init"‿"𝕨i32"‿"𝕨i32" ⋄ F ⟨⟩ +!"FFI: 𝕨 must be present" % f←@•FFI""‿"bqn_init"‿"𝕨i32"‿"i32" ⋄ F ⟨3⟩ +!"FFI: 𝕨 must be present" % f←@•FFI""‿"bqn_init"‿">𝕨i32"‿">i32" ⋄ F 3 @@ -166,4 +171,5 @@ !"FFI: ""*u64"" argument type not yet implemented" % f←@•FFI""‿"bqn_init"‿">&u64" ⋄ F ↕10 !"FFI: Pointer element type not implemented" % f←@•FFI""‿"bqn_init"‿">**u64" ⋄ F ⟨↕2⟩ - +# unchecked stuff +# !"FFI: Bad array corresponding to ""i64:c8"": expected 8 elements, got 1" % f←@•FFI""‿"bqn_init"‿">i64:c8" ⋄ F 8⥊2