improve error messages of o2i/o2i64/o2u64 & usum

This commit is contained in:
dzaima 2023-12-05 16:47:23 +02:00
parent 9984d720c9
commit b9b90fbe8f
5 changed files with 65 additions and 23 deletions

View File

@ -300,6 +300,15 @@ NOINLINE i64 bit_sum(u64* x, u64 am) {
return r;
}
NOINLINE static u64 usum_generic(B x, usz xia) {
SGetU(x)
u64 r = 0;
for (usz i = 0; i < xia; i++) {
u64 c = o2u64(GetU(x,i));
if (addOn(r,c)) thrM("Sum too big");
}
return r;
}
u64 usum(B x) { // doesn't consume; will error on non-integers, or elements <0, or if sum overflows u64
assert(isArr(x));
u64 r = 0;
@ -313,22 +322,19 @@ u64 usum(B x) { // doesn't consume; will error on non-integers, or elements <0,
f64* p = f64any_ptr(x);
for (usz i = 0; i < xia; i++) {
f64 c = p[i];
if (!q_fu64(c)) expU_f64(c);
u64 ci = (u64)c;
if (c!=ci) thrM("Expected integer");
if (ci<0) goto neg;
if (addOn(r,ci)) goto overflow;
}
} else {
SGetU(x)
for (usz i = 0; i < xia; i++) {
u64 c = o2u64(GetU(x,i));
if (c<0) thrM("Didn't expect negative integer");
if (addOn(r,c)) goto overflow;
}
return usum_generic(x, xia);
}
return r;
overflow: thrM("Sum too big");
neg: thrM("Didn't expect negative integer");
neg: return usum_generic(x, xia); // ensure proper error message
}
B select_c1(B, B);

View File

@ -360,6 +360,34 @@ NOINLINE void thrF(char* p, ...) {
thr(r);
}
char* genericDesc(B x) {
if (isNum(x)) return "number";
if (isC32(x)) return "character";
if (isArr(x)) return "array";
if (isFun(x)) return "function";
if (isMd1(x)) return "1-modifier";
if (isMd2(x)) return "2-modifier";
if (isNsp(x)) return "namespace";
return "object of unknown type";
}
NOINLINE NORETURN void expI_B(B what) {
if (isF64(what)) expI_f64(o2fG(what));
thrF("Expected integer, got %S", genericDesc(what));
}
NOINLINE NORETURN void expU_B(B what) {
if (isF64(what)) expU_f64(o2fG(what));
thrF("Expected non-negative integer, got %S", genericDesc(what));
}
NOINLINE NORETURN void expI_f64(f64 what) {
if (what != floor(what)) thrF("Expected integer, got %f", what);
thrF("Integer out of range: %f", what);
}
NOINLINE NORETURN void expU_f64(f64 what) {
if (what != floor(what) || what < 0) thrF("Expected non-negative integer, got %f", what);
thrF("Integer out of range: %f", what);
}
usz depthF(B x) { // doesn't consume

View File

@ -227,6 +227,7 @@ char* pfn_repr(u8 u);
char* pm1_repr(u8 u);
char* pm2_repr(u8 u);
char* eltype_repr(u8 u);
char* genericDesc(B x); // doesn't consume
bool isPureFn(B x); // doesn't consume
bool isStr(B x); // doesn't consume; returns if x is a rank 1 array of characters (includes any empty array)
B bqn_merge(B x, u32 type); // consumes

15
src/h.h
View File

@ -95,6 +95,7 @@ typedef size_t ux;
#define I32_MIN -2147483648
#define I32_MAX 2147483647
#define I64_MIN ((i64)(1ULL<<63))
#define I64_MAX ((i64)((1ULL<<63)-1))
#define CHR_MAX 1114111
#define U8_MAX ((u8 )~(u8 )0)
#define U16_MAX ((u16)~(u16)0)
@ -474,13 +475,15 @@ FORCE_INLINE bool q_N (B x) { return x.u==bi_N.u; } // is ·
FORCE_INLINE bool noFill(B x) { return x.u==bi_noFill.u; }
NORETURN void expI_f64(f64 what); NORETURN void expI_B(B what);
NORETURN void expU_f64(f64 what); NORETURN void expU_B(B what);
FORCE_INLINE bool o2bG(B x) { return(x.u<<1)!=0;} FORCE_INLINE bool o2b(B x) { i32 t=(i32)x.f; if(t!=x.f || t!=0&t!=1)thrM("Expected boolean"); return o2bG(x); }
FORCE_INLINE i32 o2iG(B x) { return (i32)x.f; } FORCE_INLINE i32 o2i(B x) { if (!q_i32(x)) thrM("Expected integer"); return o2iG(x); }
FORCE_INLINE u32 o2cG(B x) { return (u32)x.u; } FORCE_INLINE u32 o2c(B x) { if (!isC32(x)) thrM("Expected character"); return o2cG(x); }
FORCE_INLINE usz o2sG(B x) { return (usz)x.f; } FORCE_INLINE usz o2s(B x) { if (!q_usz(x)) thrM("Expected non-negative integer"); return o2sG(x); }
FORCE_INLINE f64 o2fG(B x) { return x.f; } FORCE_INLINE f64 o2f(B x) { if (!isNum(x)) thrM("Expected number"); return o2fG(x); }
FORCE_INLINE i64 o2i64G(B x) { return (i64)x.f; } FORCE_INLINE i64 o2i64(B x) { if (!q_i64(x)) thrM("Expected integer"); return o2i64G(x); }
FORCE_INLINE u64 o2u64G(B x) { return (u64)x.f; } FORCE_INLINE u64 o2u64(B x) { if (!q_u64(x)) thrM("Expected integer"); return o2u64G(x); }
FORCE_INLINE i32 o2iG(B x) { return (i32)x.f; } FORCE_INLINE i32 o2i(B x) { if (!q_i32(x)) expI_B(x); return o2iG(x); }
FORCE_INLINE u32 o2cG(B x) { return (u32)x.u; } FORCE_INLINE u32 o2c(B x) { if (!isC32(x)) thrM("Expected character"); return o2cG(x); }
FORCE_INLINE usz o2sG(B x) { return (usz)x.f; } FORCE_INLINE usz o2s(B x) { if (!q_usz(x)) expU_B(x); return o2sG(x); }
FORCE_INLINE f64 o2fG(B x) { return x.f; } FORCE_INLINE f64 o2f(B x) { if (!isNum(x)) thrM("Expected number"); return o2fG(x); }
FORCE_INLINE i64 o2i64G(B x) { return (i64)x.f; } FORCE_INLINE i64 o2i64(B x) { if (!q_i64(x)) expI_B(x); return o2i64G(x); }
FORCE_INLINE u64 o2u64G(B x) { return (u64)x.f; } FORCE_INLINE u64 o2u64(B x) { if (!q_u64(x)) expU_B(x); return o2u64G(x); }
// some aliases for macro-generated code
typedef u8 c8; typedef u16 c16; typedef u32 c32;

View File

@ -62,16 +62,20 @@
2301/4312 %% ¨6301201234534534591011
2301/4 %% 6001113
2301/4 %% ¨6001113
!"Didn't expect negative integer" % 2¯3/2
!"Expected non-negative integer, got ¯3" % 2¯3/2
!"Expected non-negative integer, got ¯3e20" % 2¯3e20/2
!"/: Lengths of components of 𝕨 must match 𝕩 (3 ≠ 4)" % 123/4567
!"Didn't expect negative integer" % (4/1000¯1000) / 81
!"Didn't expect negative integer" % (4/1000¯1000) / 81
!"Expected non-negative integer, got ¯1000" % (4/1000¯1000) / 81
!"Expected non-negative integer, got ¯1000" % (4/1000¯1000) / 81
%USE tvar 24e19 0/(•CurrentError@) _tvar 2 %% "Integer out of range: 4e19"
# /𝕩
!"Didn't expect negative integer" % / 4/1000¯1000
!"Expected non-negative integer, got ¯1000" % / 4/1000¯1000
!"/: Argument must have rank 1 (3‿3 ≡ ≢𝕩)" % /33
!"/: Argument must have rank 1 (⟨⟩ ≡ ≢𝕩)" % /0
%USE tvar /•CurrentError _tvar ¯1(100) 20010 %% "Didn't expect negative integer""Expected integer" # TODO shouldn't have different error messages
%USE tvar 0/•CurrentError _tvar ¯1(100) 20010 %% "Expected non-negative integer, got ¯1"
%USE tvar 0/•CurrentError _tvar 1e2262 %% "Sum too big"
%USE tvar 0/•CurrentError _tvar 1e20(100) 20010 %% "Integer out of range: 1e20"
! (//)81525329010115516558459489491213121328135013671391140714691486155915661576158215921599160916161626163540864093411441224141414941694177
# 𝕨⊏𝕩
@ -83,10 +87,10 @@
!"⊏: Indexing out-of-bounds (¯24∊𝕨, 4≡≠𝕩)" % 1¯2444
!"𝕨⊏𝕩: 𝕨 must be an array of numbers or list of such arrays" % (1¯26@)@5
!"⊏: Indexing out-of-bounds (¯26∊𝕨, 5≡≠𝕩)" % ¯265
!"Expected integer" % ¯26.55
!"Expected integer, got ¯26.5" % ¯26.55
!"⊏: Indexing out-of-bounds (¯26∊𝕨, 5≡≠𝕩)" % 1¯265
!"⊏: Indexing out-of-bounds (26∊𝕨, 5≡≠𝕩)" % 1265
!"Expected integer" % 01.12 10
!"Expected integer, got 1.1" % 01.12 10
!"⊏: Indexing out-of-bounds (1∊𝕨, 1≡≠𝕩)" % 001 1310000
!"⊏: Indexing out-of-bounds (2∊𝕨, 2≡≠𝕩)" % (1+9=10)12,3
%USE tvar !¨ {𝕨 (•CurrentError) _tvar 𝕩}´¨ 01, 0 01, "?" 01, 01
@ -226,8 +230,8 @@ w←1‿1⥊1 ⋄ x←2⥊1 ⋄ w‿x <¨↩ ⋄ {! (∾⟨•Repr𝕩,": Expe
!"⊔: ≠𝕨 must be either ≠𝕩 or one bigger (2≡≠𝕨, 3≡≠𝕩)" % 003
# ↕𝕩
!"Expected non-negative integer" % @
!"Expected non-negative integer" % "hi"
!"Expected non-negative integer, got character" % @
!"Expected non-negative integer, got character" % "hi"
!"↕: Argument must be either an integer or integer list (had rank 2)" % 221
!"↕: Result rank too large (300≡≠𝕩)" % 3001