diff --git a/src/c32arr.c b/src/c32arr.c index 8213f9bf..5c6a8948 100644 --- a/src/c32arr.c +++ b/src/c32arr.c @@ -28,7 +28,7 @@ B m_str8(usz sz, char* s) { for (u64 i = 0; i < sz; i++) p[i] = s[i]; return r; } -NOINLINE B m_str32(u32* s) { // meant to be used as m_str32(U"{𝕨‿𝕩}") +NOINLINE B m_str32(u32* s) { u64 sz = 0; while(s[sz]) sz++; B r = m_c32arrv(sz); u32* p = c32arr_ptr(r); for (u64 i = 0; i < sz; i++) p[i] = s[i]; diff --git a/src/h.h b/src/h.h index eec1f839..55babeb2 100644 --- a/src/h.h +++ b/src/h.h @@ -34,15 +34,15 @@ CTR_FOR(CTR_DEF) #ifdef DEBUG #include - #define VALIDATE(x) validate(x) - #define VALIDATEP(x) validateP(x) + B VALIDATE(B x); + Value* VALIDATEP(Value* x); #else #define assert(x) {if (!(x)) __builtin_unreachable();} #define VALIDATE(x) (x) #define VALIDATEP(x) (x) #endif -#define fsizeof(T,F,E,n) (offsetof(T, F) + sizeof(E)*(n)) // type; FAM name; FAM type; amount +#define fsizeof(T,F,E,n) (offsetof(T, F) + sizeof(E)*(n)) // type, flexible array member name, flexible array member type, item amount #define ftag(x) ((u64)(x) << 48) #define tag(v, t) b(((u64)(v)) | ftag(t)) // .111111111110000000000000000000000000000000000000000000000000000 infinity @@ -137,13 +137,6 @@ char* format_pm2(u8 u) { } -#ifdef USE_VALGRIND -#include -#include -void pst(char* msg) { - VALGRIND_PRINTF_BACKTRACE("%s", msg); -} -#endif typedef union B { u64 u; @@ -199,14 +192,22 @@ void dec(B x); B inc(B x); void ptr_dec(void* x); void ptr_inc(void* x); -void print(B x); -void arr_print(B x); -B m_v1(B a ); -B m_v2(B a, B b ); -B m_v3(B a, B b, B c ); -B m_v4(B a, B b, B c, B d); -B m_unit(B a); -B m_str32(u32* s); +void printUTF8(u32 c); +void printRaw(B x); // doesn't consume +void print(B x); // doesn't consume +bool equal(B w, B x); // doesn't consume +void arr_print(B x); // doesn't consume +bool eqShape(B w, B x); // doesn't consume +usz arr_csz(B x); // doesn't consume +bool eqShPrefix(usz* w, usz* x, ur len); + +B m_v1(B a ); // consumes all +B m_v2(B a, B b ); // consumes all +B m_v3(B a, B b, B c ); // consumes all +B m_v4(B a, B b, B c, B d); // consumes all +B m_unit(B a); // consumes +B m_str32(u32* s); // meant to be used as m_str32(U"{𝕨‿𝕩}"), so doesn't free for you + NORETURN void thr(B b); NORETURN void thrM(char* s); jmp_buf* prepareCatch(); @@ -219,6 +220,7 @@ void popCatch(); B catchMessage; + #define c(T,x) ((T*)((x).u&0xFFFFFFFFFFFFull)) #define v(x) c(Value, x) #define a(x) c(Arr , x) @@ -300,34 +302,6 @@ void arr_shCopy(B n, B o) { // copy shape from o to n a(n)->sh = a(o)->sh; } } -bool eqShPrefix(usz* w, usz* x, ur len) { - return memcmp(w, x, len*sizeof(usz))==0; -} -ur minRank(B w, B x) { // assumes both are arrays - ur wr = rnk(w); - ur xr = rnk(x); - return wrxr? wr : xr; -} -bool eqShape(B w, B x) { assert(isArr(w)); assert(isArr(x)); - ur wr = rnk(w); usz* wsh = a(w)->sh; - ur xr = rnk(x); usz* xsh = a(x)->sh; - if (wr!=xr) return false; - if (wsh==xsh) return true; - return eqShPrefix(wsh, xsh, wr); -} -usz arr_csz(B x) { - ur xr = rnk(x); - if (xr<=1) return 1; - usz* sh = a(x)->sh; - usz r = 1; - for (i32 i = 1; i < xr; i++) r*= sh[i]; - return r; -} // make objects B m_arr(usz min, u8 type) { return mm_alloc(min, type, ftag(ARR_TAG)); } @@ -397,7 +371,7 @@ void do_nothing(B x) { } void empty_free(B x) { err("FREEING EMPTY\n"); } void builtin_free(B x) { err("FREEING BUILTIN\n"); } void def_visit(B x) { printf("(no visit for %d=%s)\n", v(x)->type, format_type(v(x)->type)); } -void freeed_visit(B x) { +void freed_visit(B x) { #ifndef CATCH_ERRORS err("visiting t_freed\n"); #endif @@ -411,40 +385,12 @@ B def_m2_d(B m, B f, B g) { return err("cannot derive this"); } B def_slice(B x, usz s) { return err("cannot slice non-array!"); } B def_decompose(B x) { return m_v2(m_i32((isFun(x)|isMd(x))? 0 : -1),x); } bool def_canStore(B x) { return false; } -static inline void hdr_init() { - for (i32 i = 0; i < t_COUNT; i++) { - ti[i].free = do_nothing; - ti[i].visit = def_visit; - ti[i].get = def_get; - ti[i].getU = def_getU; - ti[i].print = def_print; - ti[i].m1_d = def_m1_d; - ti[i].m2_d = def_m2_d; - ti[i].isArr = false; - ti[i].arrD1 = false; - ti[i].identity = def_identity; - ti[i].decompose = def_decompose; - ti[i].slice = def_slice; - ti[i].canStore = def_canStore; - } - ti[t_empty].free = empty_free; - ti[t_freed].free = do_nothing; - ti[t_freed].visit = freeed_visit; - ti[t_shape].visit = do_nothing; - ti[t_funBI].visit = ti[t_md1BI].visit = ti[t_md2BI].visit = do_nothing; - ti[t_funBI].free = ti[t_md1BI].free = ti[t_md2BI].free = builtin_free; - bi_N = tag(0, TAG_TAG); - bi_noVar = tag(1, TAG_TAG); - bi_badHdr = tag(2, TAG_TAG); - bi_optOut = tag(3, TAG_TAG); - bi_noFill = tag(5, TAG_TAG); - assert((MD1_TAG>>1) == (MD2_TAG>>1)); // just to be sure it isn't changed incorrectly, `isMd` depends on this -} bool isNothing(B b) { return b.u==bi_N.u; } // refcount +bool reusable(B x) { return v(x)->refc==1; } static inline void value_free(B x, Value* vx) { ti[vx->type].free(x); mm_free(vx); @@ -456,89 +402,18 @@ void dec(B x) { Value* vx = v(x); if(!--vx->refc) value_free(x, vx); } -B inc(B x) { - if (isVal(VALIDATE(x))) v(x)->refc++; - return x; -} void ptr_dec(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_free(tag(x, OBJ_TAG), x); } -void ptr_inc(void* x) { VALIDATEP((Value*)x)->refc++; } void ptr_decR(void* x) { if(!--VALIDATEP((Value*)x)->refc) value_freeR1(x); } void decR(B x) { if (!isVal(VALIDATE(x))) return; Value* vx = v(x); if(!--vx->refc) value_freeR2(vx, x); } -bool reusable(B x) { return v(x)->refc==1; } - - - -void printUTF8(u32 c); - -void print(B x) { - if (isF64(x)) { - printf("%g", x.f); - } else if (isC32(x)) { - if ((u32)x.u>=32) { printf("'"); printUTF8((u32)x.u); printf("'"); } - else if((u32)x.u>15) printf("\\x%x", (u32)x.u); - else printf("\\x0%x", (u32)x.u); - } else if (isI32(x)) { - printf("%d", (i32)x.u); - } else if (isVal(x)) { - #ifdef DEBUG - if (isVal(x) && (v(x)->type==t_freed || v(x)->type==t_empty)) { - u8 t = v(x)->type; - v(x)->type = v(x)->flags; - printf(t==t_freed?"FREED:":"EMPTY:"); - TI(x).print(x); - v(x)->type = t; - return; - } - #endif - TI(x).print(x); - } - else if (isVar(x)) printf("(var d=%d i=%d)", (u16)(x.u>>32), (i32)x.u); - else if (x.u==bi_N.u) printf("·"); - else if (x.u==bi_optOut.u) printf("(value optimized out)"); - else if (x.u==bi_noVar.u) printf("(unset variable placeholder)"); - else if (x.u==bi_badHdr.u) printf("(bad header note)"); - else if (x.u==bi_noFill.u) printf("(no fill placeholder)"); - else printf("(todo tag %lx)", x.u>>48); -} -void printRaw(B x) { - if (isAtm(x)) { - if (isF64(x)) printf("%g", x.f); - else if (isC32(x)) printUTF8((u32)x.u); - else err("bad printRaw argument: atom arguments should be either numerical or characters"); - } else { - usz ia = a(x)->ia; - BS2B xget = TI(x).get; - for (usz i = 0; i < ia; i++) { - B c = xget(x,i); - if (c.u==0 || noFill(c)) { printf(" "); continue; } - if (!isC32(c)) err("bad printRaw argument: expected all character items"); - printUTF8((u32)c.u); - } - } -} - -B eq_c2(B t, B w, B x); -bool equal(B w, B x) { // doesn't consume - bool wa = isArr(w); - bool xa = isArr(x); - if (wa!=xa) return false; - if (!wa) return o2iu(eq_c2(bi_N, inc(w), inc(x)))?1:0; - if (!eqShape(w,x)) return false; - usz ia = a(x)->ia; - BS2B xget = TI(x).get; - BS2B wget = TI(w).get; - for (usz i = 0; i < ia; i++) { - B wc=wget(w,i); B xc=xget(x,i); // getdec - bool eq=equal(wc,xc); - decR(wc); decR(xc); - if(!eq) return false; - } - return true; +B inc(B x) { + if (isVal(VALIDATE(x))) v(x)->refc++; + return x; } +void ptr_inc(void* x) { VALIDATEP((Value*)x)->refc++; } @@ -589,40 +464,6 @@ B m_md2H(B m, B g); B m_fork(B f, B g, B h); B m_atop( B g, B h); -void arr_print(B x) { // should accept refc=0 arguments for debugging purposes - usz r = rnk(x); - BS2B xgetU = TI(x).getU; - usz ia = a(x)->ia; - if (r!=1) { - if (r==0) { - printf("<"); - print(xgetU(x,0)); - return; - } - usz* sh = a(x)->sh; - for (i32 i = 0; i < r; i++) { - if(i==0)printf("%d",sh[i]); - else printf("‿%d",sh[i]); - } - printf("⥊"); - } else if (ia>0) { - for (usz i = 0; i < ia; i++) { - B c = xgetU(x,i); - if (!isC32(c) || (u32)c.u=='\n') goto reg; - } - printf("\""); - for (usz i = 0; i < ia; i++) printUTF8((u32)xgetU(x,i).u); // c32, no need to decrement - printf("\""); - return; - } - reg:; - printf("⟨"); - for (usz i = 0; i < ia; i++) { - if (i!=0) printf(", "); - print(xgetU(x,i)); - } - printf("⟩"); -} #include @@ -631,71 +472,4 @@ u64 nsTime() { timespec_get(&t, TIME_UTC); // clock_gettime(CLOCK_REALTIME, &t); return t.tv_sec*1000000000ull + t.tv_nsec; -} - -#ifdef DEBUG - Value* validateP(Value* x) { - if (x->refc<=0 || (x->refc>>28) == 'a' || x->type==t_empty) { - printf("bad refcount for type %d: %d\nattempting to print: ", x->type, x->refc); fflush(stdout); - print(tag(x,OBJ_TAG)); puts(""); fflush(stdout); - err(""); - } - if (ti[x->type].isArr) { - Arr* a = (Arr*)x; - if (rnk(tag(x,ARR_TAG))<=1) assert(a->sh == &a->ia); - else validate(tag(shObj(tag(x,ARR_TAG)),OBJ_TAG)); - } - return x; - } - B validate(B x) { - if (!isVal(x)) return x; - validateP(v(x)); - if(isArr(x)!=TI(x).isArr && v(x)->type!=t_freed) { - printf("wat %d %p\n", v(x)->type, (void*)x.u); - print(x); - err("\nk"); - } - return x; - } -#endif - -#ifdef ALLOC_STAT -u64* ctr_a = 0; -u64* ctr_f = 0; -u64 actrc = 21000; -u64 talloc = 0; -#ifdef ALLOC_SIZES -u32** actrs; -#endif -#endif - -static inline void onAlloc(usz sz, u8 type) { - #ifdef ALLOC_STAT - if (!ctr_a) { - #ifdef ALLOC_SIZES - actrs = malloc(sizeof(u32*)*actrc); - for (i32 i = 0; i < actrc; i++) actrs[i] = calloc(t_COUNT, sizeof(u32)); - #endif - ctr_a = calloc(t_COUNT, sizeof(u64)); - ctr_f = calloc(t_COUNT, sizeof(u64)); - } - assert(type=actrc? actrc-1 : (sz+3)/4][type]++; - #endif - ctr_a[type]++; - talloc+= sz; - #endif -} -static inline void onFree(Value* x) { - #ifdef ALLOC_STAT - ctr_f[x->type]++; - #endif - #ifdef DEBUG - if (x->type==t_empty) err("double-free"); - // u32 undef; - // x->refc = undef; - x->refc = -1431655000; - #endif - // x->refc = 0x61616161; -} +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index 75ba68f3..a7f57eee 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,7 @@ #define rtLen 63 #include "h.h" +#include "stuff.c" #include "heap.c" #include "mm_buddy.c" #include "harr.c" diff --git a/src/sfns.c b/src/sfns.c index f8293dbe..af82242f 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -124,7 +124,10 @@ B eachm(B f, B x) { // complete F¨ x B eachd(B f, B w, B x) { // complete w F¨ x if (!isArr(w) & !isArr(x)) return m_unit(c2(f, w, x)); if (isFun(f)) return eachd_fn(c(Fun,f)->c2, f, w, x); - if (isArr(w) && isArr(x) && !eqShPrefix(a(w)->sh, a(x)->sh, minRank(w, x))) { decR(x); thrM("Mapping: Expected equal shape prefix"); } + if (isArr(w) && isArr(x)) { + ur mr = rnk(w); if(rnk(w)sh, a(x)->sh, mr)) { decR(x); thrM("Mapping: Expected equal shape prefix"); } + } if (isMd(f)) if ((isArr(w)&&a(w)->ia) || (isArr(x)&&a(x)->ia)) { decR(x); thrM("Calling a modifier"); } // case where both are scalars has already been taken care of HArr_p r = m_harrc(!isArr(w)? x : rnk(w)>rnk(x)? w : x); diff --git a/src/stuff.c b/src/stuff.c new file mode 100644 index 00000000..1d71f595 --- /dev/null +++ b/src/stuff.c @@ -0,0 +1,232 @@ +#include "h.h" +// a bunch of random things that don't really belong in any other file + +void arr_print(B x) { // should accept refc=0 arguments for debugging purposes + usz r = rnk(x); + BS2B xgetU = TI(x).getU; + usz ia = a(x)->ia; + if (r!=1) { + if (r==0) { + printf("<"); + print(xgetU(x,0)); + return; + } + usz* sh = a(x)->sh; + for (i32 i = 0; i < r; i++) { + if(i==0)printf("%d",sh[i]); + else printf("‿%d",sh[i]); + } + printf("⥊"); + } else if (ia>0) { + for (usz i = 0; i < ia; i++) { + B c = xgetU(x,i); + if (!isC32(c) || (u32)c.u=='\n') goto reg; + } + printf("\""); + for (usz i = 0; i < ia; i++) printUTF8((u32)xgetU(x,i).u); // c32, no need to decrement + printf("\""); + return; + } + reg:; + printf("⟨"); + for (usz i = 0; i < ia; i++) { + if (i!=0) printf(", "); + print(xgetU(x,i)); + } + printf("⟩"); +} + +void print(B x) { + if (isF64(x)) { + printf("%g", x.f); + } else if (isC32(x)) { + if ((u32)x.u>=32) { printf("'"); printUTF8((u32)x.u); printf("'"); } + else if((u32)x.u>15) printf("\\x%x", (u32)x.u); + else printf("\\x0%x", (u32)x.u); + } else if (isI32(x)) { + printf("%d", (i32)x.u); + } else if (isVal(x)) { + #ifdef DEBUG + if (isVal(x) && (v(x)->type==t_freed || v(x)->type==t_empty)) { + u8 t = v(x)->type; + v(x)->type = v(x)->flags; + printf(t==t_freed?"FREED:":"EMPTY:"); + TI(x).print(x); + v(x)->type = t; + return; + } + #endif + TI(x).print(x); + } + else if (isVar(x)) printf("(var d=%d i=%d)", (u16)(x.u>>32), (i32)x.u); + else if (x.u==bi_N.u) printf("·"); + else if (x.u==bi_optOut.u) printf("(value optimized out)"); + else if (x.u==bi_noVar.u) printf("(unset variable placeholder)"); + else if (x.u==bi_badHdr.u) printf("(bad header note)"); + else if (x.u==bi_noFill.u) printf("(no fill placeholder)"); + else printf("(todo tag %lx)", x.u>>48); +} + +void printRaw(B x) { + if (isAtm(x)) { + if (isF64(x)) printf("%g", x.f); + else if (isC32(x)) printUTF8((u32)x.u); + else err("bad printRaw argument: atom arguments should be either numerical or characters"); + } else { + usz ia = a(x)->ia; + BS2B xget = TI(x).get; + for (usz i = 0; i < ia; i++) { + B c = xget(x,i); + if (c.u==0 || noFill(c)) { printf(" "); continue; } + if (!isC32(c)) err("bad printRaw argument: expected all character items"); + printUTF8((u32)c.u); + } + } +} + +B eq_c2(B t, B w, B x); +bool equal(B w, B x) { // doesn't consume + bool wa = isArr(w); + bool xa = isArr(x); + if (wa!=xa) return false; + if (!wa) return o2iu(eq_c2(bi_N, inc(w), inc(x)))?1:0; + if (!eqShape(w,x)) return false; + usz ia = a(x)->ia; + BS2B xget = TI(x).get; + BS2B wget = TI(w).get; + for (usz i = 0; i < ia; i++) { + B wc=wget(w,i); B xc=xget(x,i); // getdec + bool eq=equal(wc,xc); + decR(wc); decR(xc); + if(!eq) return false; + } + return true; +} + +bool eqShPrefix(usz* w, usz* x, ur len) { + return memcmp(w, x, len*sizeof(usz))==0; +} +bool eqShape(B w, B x) { assert(isArr(w)); assert(isArr(x)); + ur wr = rnk(w); usz* wsh = a(w)->sh; + ur xr = rnk(x); usz* xsh = a(x)->sh; + if (wr!=xr) return false; + if (wsh==xsh) return true; + return eqShPrefix(wsh, xsh, wr); +} + +usz arr_csz(B x) { + ur xr = rnk(x); + if (xr<=1) return 1; + usz* sh = a(x)->sh; + usz r = 1; + for (i32 i = 1; i < xr; i++) r*= sh[i]; + return r; +} + + + +#ifdef DEBUG + Value* VALIDATEP(Value* x) { + if (x->refc<=0 || (x->refc>>28) == 'a' || x->type==t_empty) { + printf("bad refcount for type %d: %d\nattempting to print: ", x->type, x->refc); fflush(stdout); + print(tag(x,OBJ_TAG)); puts(""); fflush(stdout); + err(""); + } + if (ti[x->type].isArr) { + Arr* a = (Arr*)x; + if (rnk(tag(x,ARR_TAG))<=1) assert(a->sh == &a->ia); + else VALIDATE(tag(shObj(tag(x,ARR_TAG)),OBJ_TAG)); + } + return x; + } + B VALIDATE(B x) { + if (!isVal(x)) return x; + VALIDATEP(v(x)); + if(isArr(x)!=TI(x).isArr && v(x)->type!=t_freed) { + printf("wat %d %p\n", v(x)->type, (void*)x.u); + print(x); + err("\nk"); + } + return x; + } +#endif + +#ifdef USE_VALGRIND + #include + #include + void pst(char* msg) { + VALGRIND_PRINTF_BACKTRACE("%s", msg); + } +#endif + +static inline void hdr_init() { + for (i32 i = 0; i < t_COUNT; i++) { + ti[i].free = do_nothing; + ti[i].visit = def_visit; + ti[i].get = def_get; + ti[i].getU = def_getU; + ti[i].print = def_print; + ti[i].m1_d = def_m1_d; + ti[i].m2_d = def_m2_d; + ti[i].isArr = false; + ti[i].arrD1 = false; + ti[i].identity = def_identity; + ti[i].decompose = def_decompose; + ti[i].slice = def_slice; + ti[i].canStore = def_canStore; + } + ti[t_empty].free = empty_free; + ti[t_freed].free = do_nothing; + ti[t_freed].visit = freed_visit; + ti[t_shape].visit = do_nothing; + ti[t_funBI].visit = ti[t_md1BI].visit = ti[t_md2BI].visit = do_nothing; + ti[t_funBI].free = ti[t_md1BI].free = ti[t_md2BI].free = builtin_free; + bi_N = tag(0, TAG_TAG); + bi_noVar = tag(1, TAG_TAG); + bi_badHdr = tag(2, TAG_TAG); + bi_optOut = tag(3, TAG_TAG); + bi_noFill = tag(5, TAG_TAG); + assert((MD1_TAG>>1) == (MD2_TAG>>1)); // just to be sure it isn't changed incorrectly, `isMd` depends on this +} + + +#ifdef ALLOC_STAT + u64* ctr_a = 0; + u64* ctr_f = 0; + u64 actrc = 21000; + u64 talloc = 0; + #ifdef ALLOC_SIZES + u32** actrs; + #endif +#endif + +static inline void onAlloc(usz sz, u8 type) { + #ifdef ALLOC_STAT + if (!ctr_a) { + #ifdef ALLOC_SIZES + actrs = malloc(sizeof(u32*)*actrc); + for (i32 i = 0; i < actrc; i++) actrs[i] = calloc(t_COUNT, sizeof(u32)); + #endif + ctr_a = calloc(t_COUNT, sizeof(u64)); + ctr_f = calloc(t_COUNT, sizeof(u64)); + } + assert(type=actrc? actrc-1 : (sz+3)/4][type]++; + #endif + ctr_a[type]++; + talloc+= sz; + #endif +} +static inline void onFree(Value* x) { + #ifdef ALLOC_STAT + ctr_f[x->type]++; + #endif + #ifdef DEBUG + if (x->type==t_empty) err("double-free"); + // u32 undef; + // x->refc = undef; + x->refc = -1431655000; + #endif + // x->refc = 0x61616161; +}