diff --git a/src/c32arr.c b/src/c32arr.c index 4f128361..af911f59 100644 --- a/src/c32arr.c +++ b/src/c32arr.c @@ -46,6 +46,13 @@ B m_str8(usz sz, char* s) { for (u64 i = 0; i < sz; i++) rp[i] = (u32)s[i]; return r; } +B m_str8l(char* s) { + usz sz = strlen(s); + u32* rp; B r = m_c32arrv(&rp, sz); + for (u64 i = 0; i < sz; i++) rp[i] = (u32)s[i]; + return r; +} + NOINLINE B m_str32(u32* s) { usz sz = 0; while(s[sz]) sz++; u32* rp; B r = m_c32arrv(&rp, sz); @@ -93,4 +100,6 @@ static inline void c32arr_init() { ti[t_i32arr].arrD1 = true; ti[t_i32slice].arrD1 = true; ti[t_c32arr].elType = el_c32; ti[t_c32slice].elType = el_c32; ti[t_c32arr].canStore = c32arr_canStore; + u32* tmp; bi_emptyCVec = m_c32arrv(&tmp, 0); + gc_add(bi_emptyCVec); } diff --git a/src/file.c b/src/file.c index 45738b67..c2a1d234 100644 --- a/src/file.c +++ b/src/file.c @@ -9,7 +9,7 @@ TmpFile* file_bytes(B path) { // consumes; may throw toUTF8(path, p); p[plen] = 0; FILE* f = fopen(p, "r"); - if (f==NULL) thrM("Couldn't read file"); + if (f==NULL) thrF("Couldn't read file \"%R\"", path); fseek(f, 0, SEEK_END); u64 len = ftell(f); fseek(f, 0, SEEK_SET); diff --git a/src/fns.c b/src/fns.c index eac8db05..f3b7560c 100644 --- a/src/fns.c +++ b/src/fns.c @@ -41,8 +41,8 @@ B ud_c1(B t, B x) { } BS2B xgetU = TI(x).getU; usz xia = a(x)->ia; - if (rnk(x)!=1) thrM("↕: Argument must be a vector"); - if (xia>UR_MAX) thrM("↕: Result rank too large"); + if (rnk(x)!=1) thrF("↕: Argument must be either an integer or integer list (had rank %i)", rnk(x)); + if (xia>UR_MAX) thrF("↕: Result rank too large (%s≡≠𝕩)", xia); usz sh[xia]; usz ria = 1; for (usz i = 0; i < xia; i++) { diff --git a/src/h.h b/src/h.h index 779cc250..6b74d166 100644 --- a/src/h.h +++ b/src/h.h @@ -31,6 +31,7 @@ #define f64 double #define I32_MAX ((i32)((1LL<<31)-1)) #define I32_MIN ((i32)(-(1LL<<31))) +#define I64_MIN ((i64)(-(1LL<<63))) #define CHR_MAX 1114111 #define U16_MAX ((u16)~(u16)0) #define U32_MAX ((u32)~(u32)0) @@ -231,6 +232,7 @@ void gsAdd(B x); // may throw B gsPop(); // some primitive actions +B bi_N, bi_noVar, bi_badHdr, bi_optOut, bi_noFill, bi_emptyHVec, bi_emptyIVec, bi_emptyCVec; void dec(B x); B inc(B x); void ptr_dec(void* x); @@ -248,6 +250,7 @@ bool atomEqual(B w, B x); // doesn't consume B toCells(B x); // consumes B toKCells(B x, ur k); // consumes B withFill(B x, B f); // consumes both +B vec_join(B w, B x); // consumes both bool eqShPrefix(usz* w, usz* x, ur len); B m_v1(B a ); // consumes all @@ -263,10 +266,11 @@ B bqn_execFile(B path, B args); // consumes NOINLINE NORETURN void thr(B b); NOINLINE NORETURN void thrM(char* s); +#define thrF(...) thr(append_fmt(inc(bi_emptyCVec), __VA_ARGS__)) NOINLINE NORETURN void thrOOM(); jmp_buf* prepareCatch(); #ifdef CATCH_ERRORS -#define CATCH setjmp(*prepareCatch()) // use as `if (CATCH) { /*handle error; dec(catchMessage);*/ } /*potentially erroring thing*/ popCatch();` +#define CATCH setjmp(*prepareCatch()) // use as `if (CATCH) { /*handle error*/ dec(catchMessage); } /*potentially erroring thing*/ popCatch();` #else // note: popCatch() must always be called if no error was caught, so no returns before it! #define CATCH false #endif @@ -448,8 +452,6 @@ TypeInfo ti[t_COUNT]; #define TI(x) (ti[v(x)->type]) -B bi_N, bi_noVar, bi_badHdr, bi_optOut, bi_noFill, bi_emptyHVec, bi_emptyIVec; - bool isNothing(B b) { return b.u==bi_N.u; } // refcount diff --git a/src/main.c b/src/main.c index 7ecab218..3ce904ba 100644 --- a/src/main.c +++ b/src/main.c @@ -157,6 +157,10 @@ int main(int argc, char* argv[]) { printf("Error: "); print(catchMessage); putchar('\n'); vm_pst(envCurr, envStart+envPrevHeight); dec(catchMessage); + #ifdef HEAP_VERIFY + heapVerify(); + #endif + gc_maybeGC(); } B replPath = m_str32(U"REPL"); gc_add(replPath); while (true) { // exit by evaluating an empty expression @@ -187,11 +191,9 @@ int main(int argc, char* argv[]) { #endif #ifdef HEAP_VERIFY - heapVerify(); + heapVerify(); #endif gc_maybeGC(); - #ifdef DEBUG - #endif } popCatch(); } diff --git a/src/md1.c b/src/md1.c index 222f8c37..6d5db805 100644 --- a/src/md1.c +++ b/src/md1.c @@ -64,7 +64,7 @@ B tbl_c2(B d, B w, B x) { B f = c(Md1D,d)->f; usz wia = a(w)->ia; ur wr = rnk(w); usz xia = a(x)->ia; ur xr = rnk(x); usz ria = wia*xia; ur rr = wr+xr; - if (rrf; if (isArr(w)) { ur wr = rnk(w); usz* wsh = a(w)->sh; BS2B wget = TI(w).get; - if (wr+1 != xr) thrM("`: Shape of 𝕨 must match the cell of 𝕩"); - if (memcmp(wsh, xsh+1, wr)) thrM("`: Shape of 𝕨 must match the cell of 𝕩"); + if (wr+1!=xr || !eqShPrefix(wsh, xsh+1, wr)) thrF("`: Shape of 𝕨 must match the cell of 𝕩 (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); if (ia==0) return x; usz csz = arr_csz(x); for (; i < csz; i++) r.a[i] = fc2(f, wget(w,i), xget(x,i)); for (; i < ia; i++) r.a[i] = fc2(f, inc(r.a[i-csz]), xget(x,i)); dec(w); } else { - if (xr!=1) thrM("`: Shape of 𝕨 must match the cell of 𝕩"); + if (xr!=1) thrF("`: Shape of 𝕨 must match the cell of 𝕩 (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); if (ia==0) return x; B pr = r.a[0] = fc2(f, w, xget(x,0)); i++; for (; i < ia; i++) r.a[i] = pr = fc2(f, inc(pr), xget(x,i)); @@ -153,7 +152,7 @@ B scan_c2(B d, B w, B x) { B f = c(Md1D,d)->f; } B fold_c1(B d, B x) { B f = c(Md1D,d)->f; - if (isAtm(x) || rnk(x)!=1) thrM("´: argument must be a list"); + if (isAtm(x) || rnk(x)!=1) thrF("´: Argument must be a list (%H ≡ ≢𝕩)", x); usz ia = a(x)->ia; if (ia==0) { dec(x); @@ -178,7 +177,7 @@ B fold_c1(B d, B x) { B f = c(Md1D,d)->f; return c; } B fold_c2(B d, B w, B x) { B f = c(Md1D,d)->f; - if (isAtm(x) || rnk(x)!=1) thrM("´: 𝕩 must be a list"); + if (isAtm(x) || rnk(x)!=1) thrF("´: 𝕩 must be a list (%H ≡ ≢𝕩)", x); usz ia = a(x)->ia; B c = w; BS2B xget = TI(x).get; diff --git a/src/md2.c b/src/md2.c index 53f0eaea..09221a60 100644 --- a/src/md2.c +++ b/src/md2.c @@ -35,8 +35,8 @@ B fillBy_c2(B d, B w, B x) { popCatch(); return withFill(r, fill); } -B catch_c1(B d, B x) { if(CATCH) return c1(c(Md2D,d)->g, x); inc(x); B r = c1(c(Md2D,d)->f, x); popCatch(); dec(x); return r; } -B catch_c2(B d, B w, B x) { if(CATCH) return c2(c(Md2D,d)->g, w,x); inc(w); inc(x); B r = c2(c(Md2D,d)->f, w,x); popCatch(); dec(w); dec(x); return r; } +B catch_c1(B d, B x) { if(CATCH) { dec(catchMessage); return c1(c(Md2D,d)->g, x); } inc(x); B r = c1(c(Md2D,d)->f, x); popCatch(); dec(x); return r; } +B catch_c2(B d, B w, B x) { if(CATCH) { dec(catchMessage); return c2(c(Md2D,d)->g, w,x); } inc(w); inc(x); B r = c2(c(Md2D,d)->f, w,x); popCatch(); dec(w); dec(x); return r; } #else B fillBy_c1(B d, B x) { return c1(c(Md2D,d)->f, x); } B fillBy_c2(B d, B w, B x) { return c2(c(Md2D,d)->f, w,x); } diff --git a/src/sfns.c b/src/sfns.c index b9f5f586..37eddfdf 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -15,7 +15,7 @@ B eachd_fn(BBB2B f, B fo, B w, B x) { // consumes w,x; assumes at least one is a dec(w); dec(x); return m_hunit(r); } - if (rm && !eqShPrefix(a(w)->sh, a(x)->sh, rm)) thrM("Mapping: Expected equal shape prefix"); + if (rm && !eqShPrefix(a(w)->sh, a(x)->sh, rm)) thrF("Mapping: Expected equal shape prefix (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); bool rw = rM==wr && ((v(w)->type==t_harr) & reusable(w)); // v(…) is safe as rank>0 bool rx = rM==xr && ((v(x)->type==t_harr) & reusable(x)); if (rw|rx && (wr==xr | rm==0)) { @@ -190,7 +190,7 @@ B pick_c2(B t, B w, B x) { i64 p = o2i64(w); usz xia = a(x)->ia; if (p<0) p+= (i64)xia; - if ((u64)p >= xia) thrM("⊑: indexing out-of-bounds"); + if ((u64)p >= xia) thrF("⊑: indexing out-of-bounds (𝕨≡%R, %s≡≠𝕩)", w, xia); B r = TI(x).get(x, p); dec(x); return r; @@ -203,7 +203,7 @@ B select_c1(B t, B x) { if (isAtm(x)) thrM("⊏: Argument cannot be an atom"); ur xr = rnk(x); if (xr==0) thrM("⊏: Argument cannot be rank 0"); - if (a(x)->sh[0]==0) thrM("⊏: Argument shape cannot start with 0"); + if (a(x)->sh[0]==0) thrF("⊏: Argument shape cannot start with 0 (%H ≡ ≢𝕩)", x); B r = TI(x).slice(inc(x),0); usz* sh = arr_shAllocR(r, xr-1); usz ia = 1; @@ -224,7 +224,7 @@ B select_c2(B t, B w, B x) { usz cam = a(x)->sh[0]; i64 wi = o2i64(w); if (wi<0) wi+= cam; - if ((usz)wi >= cam) thrM("⊏: Indexing out-of-bounds"); + if ((usz)wi >= cam) thrF("⊏: Indexing out-of-bounds (𝕨≡%R, %s≡≠𝕩)", w, cam); B r = TI(x).slice(inc(x), wi*csz); usz* sh = arr_shAllocI(r, csz, xr-1); if (sh) memcpy(sh, a(x)->sh+1, (xr-1)*sizeof(usz)); @@ -245,7 +245,7 @@ B select_c2(B t, B w, B x) { for (usz i = 0; i < wia; i++) { i64 c = wp[i]; if (c<0) c+= xia; - if (c<0 | c>=xia) thrM("⊏: Indexing out-of-bounds"); + if (c<0 | c>=xia) thrF("⊏: Indexing out-of-bounds (%i∊𝕨, %s≡≠𝕩)", wp[i], xia); rp[i] = xp[c]; } dec(w); dec(x); @@ -255,7 +255,7 @@ B select_c2(B t, B w, B x) { for (usz i = 0; i < wia; i++) { i64 c = wp[i]; if (c<0) c+= xia; - if (c<0 | c>=xia) thrM("⊏: Indexing out-of-bounds"); + if (c<0 | c>=xia) thrF("⊏: Indexing out-of-bounds (%i∊𝕨, %s≡≠𝕩)", wp[i], xia); r.a[i] = xget(x, c); } dec(w); dec(x); @@ -269,7 +269,7 @@ B select_c2(B t, B w, B x) { if (!isNum(cw)) { harr_pfree(r.b, i); goto base; } f64 c = o2f(cw); if (c<0) c+= xia; - if ((usz)c >= xia) thrM("⊏: Indexing out-of-bounds"); + if ((usz)c >= xia) thrF("⊏: Indexing out-of-bounds (%R∊𝕨, %s≡≠𝕩)", cw, xia); r.a[i] = xget(x, c); } dec(w); dec(x); @@ -278,9 +278,9 @@ B select_c2(B t, B w, B x) { } else { BS2B wgetU = TI(w).getU; ur wr = rnk(w); - ur rr = wr+xr-1; + i32 rr = wr+xr-1; if (xr==0) thrM("⊏: 𝕩 cannot be a unit"); - if (rr>UR_MAX) thrM("⊏: Result rank too large"); + if (rr>UR_MAX) thrF("⊏: Result rank too large (%i≡=𝕨, %i≡=𝕩)", wr, xr); usz csz = arr_csz(x); usz cam = a(x)->sh[0]; MAKE_MUT(r, wia*csz); @@ -290,7 +290,7 @@ B select_c2(B t, B w, B x) { if (!isNum(cw)) { mut_pfree(r, i*csz); goto base; } f64 c = o2f(cw); if (c<0) c+= cam; - if ((usz)c >= cam) thrM("⊏: Indexing out-of-bounds"); + if ((usz)c >= cam) { mut_pfree(r, i*csz); thrF("⊏: Indexing out-of-bounds (%R∊𝕨, %s≡≠𝕩)", cw, cam); } mut_copy(r, i*csz, x, csz*(usz)c, csz); } B rb = mut_fp(r); @@ -309,8 +309,7 @@ B select_c2(B t, B w, B x) { B rt_slash; B slash_c1(B t, B x) { - if (isAtm(x)) thrM("/: Argument must be a list"); - if (rnk(x)!=1) thrM("/: Argument must have rank 1"); + if (isAtm(x) || rnk(x)!=1) thrF("/: Argument must have rank 1 (%H ≡ ≢𝕩)", x); i64 s = isum(x); if(s<0) thrM("/: Argument must consist of natural numbers"); usz xia = a(x)->ia; @@ -338,7 +337,7 @@ B slash_c2(B t, B w, B x) { usz wia = a(w)->ia; usz xia = a(x)->ia; B xf = getFillQ(x); - if (wia!=xia) thrM("/: Lengths of components of 𝕨 must match 𝕩"); + if (wia!=xia) thrF("/: Lengths of components of 𝕨 must match 𝕩 (%s ≠ %s)", wia, xia); i64 wsum = isum(w); if (wsum>USZ_MAX) thrOOM(); usz ria = wsum; usz ri = 0; @@ -349,7 +348,7 @@ B slash_c2(B t, B w, B x) { i32* rp; B r = m_i32arrv(&rp, ria); for (usz i = 0; i < wia; i++) { i32 c = wp[i]; - if (c<0) thrM("/: 𝕨 must consist of natural numbers"); + if (c<0) thrF("/: 𝕨 must consist of natural numbers (%i∊𝕨)", c); i32 cx = xp[i]; for (usz j = 0; j < c; j++) *rp++ = cx; } @@ -361,7 +360,7 @@ B slash_c2(B t, B w, B x) { for (usz i = 0; i < wia; i++) { i32 c = wp[i]; if (c==0) continue; - if (c<0) thrM("/: 𝕨 must consist of natural numbers"); + if (c<0) thrF("/: 𝕨 must consist of natural numbers (%i∊𝕨)", c); B cx = xgetU(x, i); for (usz j = 0; j < c; j++) r.a[ri++] = inc(cx); } @@ -468,9 +467,9 @@ B join_c1(B t, B x) { usz cam = x0sh[0]; for (usz i = 1; i < xia; i++) { B c = xgetU(x, i); - if (!isArr(c) || rnk(c)!=ir) thrM("∾: All items in argument should have same rank"); + if (!isArr(c) || rnk(c)!=ir) thrF("∾: All items in argument should have same rank (contained items with ranks %i and %i)", ir, isArr(c)? rnk(c) : 0); usz* csh = a(c)->sh; - if (ir>1) for (usz j = 1; j < ir; j++) if (csh[j]!=x0sh[j]) thrM("∾: Item trailing shapes must be equal"); + if (ir>1) for (usz j = 1; j < ir; j++) if (csh[j]!=x0sh[j]) thrF("∾: Item trailing shapes must be equal (contained arrays with shapes %H and %H)", x0, c); cam+= a(c)->sh[0]; if (SFNS_FILLS && !noFill(rf)) rf = fill_or(rf, getFillQ(c)); } @@ -506,7 +505,7 @@ B join_c2(B t, B w, B x) { r.a[1] = TI(x).get(x,0); dec(x); return withFill(r.b, f); } - if (c-wr > 1 || c-xr > 1) thrM("∾: Argument ranks must differ by 1 or less"); + if (c-wr > 1 || c-xr > 1) thrF("∾: Argument ranks must differ by 1 or less (%i≡=𝕨, %i≡=𝕩)", wr, xr); if (c==1) { B r = vec_join(w, x); if (rnk(r)==0) srnk(r,1); @@ -521,7 +520,7 @@ B join_c2(B t, B w, B x) { if (sh) { for (i32 i = 1; i < c; i++) { usz s = xsh[i+xr-c]; - if (wsh[i+wr-c] != s) { mut_pfree(r, wia+xia); thrM("∾: Lengths not matchable"); } + if (wsh[i+wr-c] != s) { mut_pfree(r, wia+xia); thrF("∾: Lengths not matchable (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); } sh[i] = s; } sh[0] = (wr==c? wsh[0] : 1) + (xr==c? xsh[0] : 1); @@ -556,7 +555,7 @@ B couple_c2(B t, B w, B x) { } if (isAtm(w)) w = m_atomUnit(w); if (isAtm(x)) x = m_atomUnit(x); - if (!eqShape(w, x)) thrM("≍: 𝕨 and 𝕩 must have equal shapes"); + if (!eqShape(w, x)) thrF("≍: 𝕨 and 𝕩 must have equal shapes (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); usz ia = a(w)->ia; ur wr = rnk(w); MAKE_MUT(r, ia*2); @@ -575,8 +574,8 @@ B couple_c2(B t, B w, B x) { static void shift_check(B w, B x) { ur wr = rnk(w); usz* wsh = a(w)->sh; ur xr = rnk(x); usz* xsh = a(x)->sh; - if (wr+1!=xr & wr!=xr) thrM("shift: =𝕨 must be =𝕩 or ¯1+=𝕩"); - for (i32 i = 1; i < xr; i++) if (wsh[i+wr-xr] != xsh[i]) thrM("shift: Lengths not matchable"); + if (wr+1!=xr & wr!=xr) thrF("shift: =𝕨 must be =𝕩 or ¯1+=𝕩 (%i≡=𝕨, %i≡=𝕩)", wr, xr); + for (i32 i = 1; i < xr; i++) if (wsh[i+wr-xr] != xsh[i]) thrF("shift: Lengths not matchable (%H ≡ ≢𝕨, %H ≡ ≢𝕩)", w, x); } B shiftb_c1(B t, B x) { @@ -644,7 +643,7 @@ B group_c2(B t, B w, B x) { if (isArr(w)&isArr(x) && rnk(w)==1 && rnk(x)==1) { usz wia = a(w)->ia; usz xia = a(x)->ia; - if (wia-xia > 1) thrM("⊔: ≠𝕨 must be either ≠𝕩 or one bigger"); + if (wia-xia > 1) thrF("⊔: ≠𝕨 must be either ≠𝕩 or one bigger (%s≡≠𝕨, %s≡≠𝕩)", wia, xia); if (TI(w).elType==el_i32) { i32* wp = i32any_ptr(w); @@ -757,7 +756,7 @@ B pick_ucw(B t, B o, B w, B x) { usz xia = a(x)->ia; i64 wi = o2i64(w); if (wi<0) wi+= (i64)xia; - if ((u64)wi >= xia) thrM("⌾(n⊸⊑): reading out-of-bounds"); + if ((u64)wi >= xia) thrF("𝔽⌾(n⊸⊑)𝕩: reading out-of-bounds (n≡%R, %s≡≠𝕩)", w, xia); B arg = TI(x).get(x, wi); B rep = c1(o, arg); if (reusable(x) && TI(x).canStore(rep)) { @@ -796,7 +795,7 @@ B slash_ucw(B t, B o, B w, B x) { B arg = slash_c2(t, inc(w), inc(x)); usz argIA = a(arg)->ia; B rep = c1(o, arg); - if (isAtm(rep) || rnk(rep)!=1 || a(rep)->ia != argIA) thrM("𝔽⌾(a⊸/)𝕩: Result of 𝔽 must have the same shape as a/𝕩"); + if (isAtm(rep) || rnk(rep)!=1 || a(rep)->ia != argIA) thrF("𝔽⌾(a⊸/)𝕩: Result of 𝔽 must have the same shape as a/𝕩 (expected ⟨%s⟩, got %H)", argIA, rep); MAKE_MUT(r, ia); mut_to(r, el_or(TI(x).elType, TI(rep).elType)); BS2B xget = TI(x).get; BS2B rgetU = TI(rep).getU; diff --git a/src/stuff.c b/src/stuff.c index 7105b776..8ecde982 100644 --- a/src/stuff.c +++ b/src/stuff.c @@ -29,6 +29,122 @@ B def_m2_d(B m, B f, B g) { thrM("cannot derive this"); } B def_slice(B x, usz s) { thrM("cannot slice non-array!"); } bool def_canStore(B x) { return false; } +B m_c32arrv(u32** p, usz ia); +B m_str8l(char* s); +B m_str32c(u32 c) { + u32* rp; B r = m_c32arrv(&rp, 1); + rp[0] = c; + return r; +} +B fromUTF8(char* x, i64 len); +B fromUTF8l(char* x); +#define A8(X) s = vec_join(s,m_str8l(X)) +#define AU(X) s = vec_join(s,fromUTF8l(X)) +#define AC(X) s = vec_join(s,m_str32c(X)) +#define AFMT(...) s = append_fmt(s, __VA_ARGS__) +NOINLINE B append_fmt(B s, char* p, ...) { + va_list a; + va_start(a, p); + char buf[30]; + char c; + char* lp = p; + while ((c = *p++) != 0) { + if (c!='%') continue; + if (lp!=p-1) s = vec_join(s, fromUTF8(lp, p-1-lp)); + switch(c = *p++) { default: printf("Unknown format character '%c'", c); UD; + case 'R': { // TODO proper + B b = va_arg(a, B); + if (isNum(b)) { + AFMT("%f", o2f(b)); + } else { assert(isArr(b) && rnk(b)==1); + s = vec_join(s, inc(b)); + } + break; + } + case 'H': { + B o = va_arg(a, B); + ur r = isArr(o)? rnk(o) : 0; + usz* sh = isArr(o)? a(o)->sh : NULL; + if (r==0) AU("⟨⟩"); + else if (r==1) AFMT("⟨%s⟩", sh[0]); + else { + for (i32 i = 0; i < r; i++) { + if(i) AU("‿"); + AFMT("%s", sh[i]); + } + } + break; + } + case 'S': { + A8(va_arg(a, char*)); + break; + } + case 'U': { + AU(va_arg(a, char*)); + break; + } + case 'u': case 'x': case 'i': case 'l': { + i32 mode = c=='u'? 1 : c=='x'? 2 : 0; + if (mode) c = *p++; + assert(c); + if (mode) { + assert(c=='l'||c=='i'); + if (c=='i') snprintf(buf, 30, mode==1? "%u" : "%x", va_arg(a, u32)); + else snprintf(buf, 30, mode==1? "%lu" : "%lx", va_arg(a, u64)); + } else { + if (c=='i') { + i32 v = va_arg(a, i32); + if (v<0) AU("¯"); + snprintf(buf, 30, "%lu", (u64)(v<0?-v:v)); + } else { assert(c=='l'); + i64 v = va_arg(a, i64); + if (v<0) AU("¯"); + if (v==I64_MIN) snprintf(buf, 30, "9223372036854775808"); + else snprintf(buf, 30, "%lu", (u64)(v<0?-v:v)); + } + } + A8(buf); + break; + } + case 's': { + usz v = va_arg(a, usz); + snprintf(buf, 30, sizeof(usz)==4? "%u" : "%lu", v); + A8(buf); + break; + } + case 'p': { + snprintf(buf, 30, "%p", va_arg(a, void*)); + A8(buf); + break; + } + case 'f': { + f64 f = va_arg(a, f64); + if (f<0) { + AU("¯"); + f=-f; + } + snprintf(buf, 30, "%g", f); + A8(buf); + break; + } + case 'c': { + buf[0] = va_arg(a, int); buf[1] = 0; + A8(buf); + break; + } + case '%': { + buf[0] = '%'; buf[1] = 0; + A8(buf); + break; + } + } + lp = p; + } + if (lp!=p) s = vec_join(s, fromUTF8(lp, p-lp)); + va_end(a); + return s; +} + B rt_under, bi_before; B rtUnder_c1(B f, B g, B x) { // consumes x B fn = m2_d(inc(rt_under), inc(f), inc(g)); diff --git a/src/sysfn.c b/src/sysfn.c index 9fa180c2..a52787cf 100644 --- a/src/sysfn.c +++ b/src/sysfn.c @@ -115,7 +115,7 @@ B asrt_c2(B t, B w, B x) { bool isPureFn(B x); B internal_c2(B t, B w, B x) { B r; - u64 id = o2s(w); + i32 id = o2i(w); if(id==0) { if(isVal(x)) { char* c = format_type(v(x)->type); r = m_str8(strlen(c), c); } else { @@ -130,7 +130,7 @@ B internal_c2(B t, B w, B x) { else if(id==2) { r = isVal(x)? m_i32(v(x)->refc) : m_str32(U"(not heap-allocated)"); } else if(id==3) { printf("%p\n", (void*)x.u); r = inc(x); } else if(id==4) { r = m_f64(isPureFn(x)); } - else { dec(x); thrM("Bad 𝕨 argument for •Internal"); } + else { dec(x); thrF("•Internal: 𝕨≡%i is invalid", id); } dec(x); return r; } @@ -189,7 +189,7 @@ B sys_c1(B t, B x) { else if (eqStr(c, U"args")) { if(isNothing(comp_currArgs)) thrM("No arguments present for •args"); r.a[i] = inc(comp_currArgs); - } else { dec(x); thrM("Unknown system function"); } + } else { dec(x); thrF("Unknown system function •%R", c); } } return harr_fcd(r, x); }