diff --git a/src/arith.c b/src/arith.c index b3ea59d3..1ce55f1c 100644 --- a/src/arith.c +++ b/src/arith.c @@ -33,6 +33,7 @@ B decp_c1(B t, B x); B eq_c2(B t, B w, B x) { if(isF64(w)&isF64(x)) return m_i32(w.f==x.f); if (w.u==x.u) return m_i32(1); + // doesn't handle int=float if (!isVal(w) | !isVal(x)) { dec(w);dec(x); return m_i32(0); } if (v(w)->type!=v(x)->type) { dec(w);dec(x); return m_i32(0); } B2B dcf = TI(w).decompose; diff --git a/src/fillarr.c b/src/fillarr.c index 497fca30..eed3a043 100644 --- a/src/fillarr.c +++ b/src/fillarr.c @@ -6,7 +6,7 @@ typedef struct FillArr { B a[]; } FillArr; -B asFill(B x) { +B asFill(B x) { // consumes if (isArr(x)) { HArr_p r = m_harrc(x); usz ia = r.c->ia; @@ -14,20 +14,22 @@ B asFill(B x) { bool noFill = false; for (usz i = 0; i < ia; i++) if ((r.a[i]=asFill(xget(x,i))).u == bi_noFill.u) noFill = true; dec(x); - if (noFill) { dec(r.b); return bi_noFill; } + if (noFill) { ptr_dec(r.c); return bi_noFill; } return r.b; } if (isF64(x)|isI32(x)) return m_i32(0); if (isC32(x)) return m_c32(' '); + dec(x); return bi_noFill; } -B withFill(B x, B fill) { +B withFill(B x, B fill) { // consumes both assert(isArr(x)); switch(v(x)->type) { case t_i32arr : case t_i32slice : if(fill.u == m_i32(0 ).u) return x; break; case t_c32arr : case t_c32slice : if(fill.u == m_c32(' ').u) return x; break; - case t_fillarr: case t_fillslice: if (equal(c(FillArr,x)->fill, fill)) return x; + case t_fillarr: case t_fillslice: if (equal(c(FillArr,x)->fill, fill)) { dec(fill); return x; } if (reusable(x)) { + dec(c(FillArr, x)->fill); c(FillArr, x)->fill = fill; return x; } @@ -43,14 +45,19 @@ B withFill(B x, B fill) { dec(x); return r; } -B getFill(B x) { +B getFill(B x) { // consumes if (isArr(x)) { u8 t = v(x)->type; if (t==t_fillarr ) { B r = inc(c(FillArr,x )->fill); dec(x); return r; } if (t==t_fillslice) { B r = inc(c(FillArr,c(Slice,x)->p)->fill); dec(x); return r; } - if (t==t_c32arr || t==t_c32slice) return m_c32(' '); + if (t==t_c32arr || t==t_c32slice) { dec(x); return m_c32(' '); } + if (t==t_i32arr || t==t_i32slice) { dec(x); return m_f64(0 ); } + dec(x); + return m_f64(0); } if (isC32(x)) return m_c32(' '); + if (isF64(x)|isI32(x)) return m_i32(0); + dec(x); return m_f64(0); } diff --git a/src/h.h b/src/h.h index 3f998c77..a3cb6347 100644 --- a/src/h.h +++ b/src/h.h @@ -551,19 +551,25 @@ u64* ctr_a = 0; u64* ctr_f = 0; u64 actrc = 21000; u64 talloc = 0; +#ifdef ALLOC_SIZES u32** actrs; #endif +#endif static void onAlloc(usz sz, u8 type) { #ifdef ALLOC_STAT - if (!actrs) { - actrs = malloc(sizeof(u32*)*actrc); + if (!ctr_a) { + #ifdef ALLOC_SIZES + actrs = malloc(sizeof(u32*)*actrc); + for (i32 i = 0; i < actrc; i++) actrs[i] = calloc(Type_MAX, sizeof(u32)); + #endif ctr_a = calloc(Type_MAX, sizeof(u64)); ctr_f = calloc(Type_MAX, sizeof(u64)); - for (i32 i = 0; i < actrc; i++) actrs[i] = calloc(Type_MAX, sizeof(u32)); } assert(type=actrc? actrc-1 : (sz+3)/4][type]++; + #ifdef ALLOC_SIZES + actrs[(sz+3)/4>=actrc? actrc-1 : (sz+3)/4][type]++; + #endif ctr_a[type]++; talloc+= sz; #endif diff --git a/src/main.c b/src/main.c index e75d097e..de6838b0 100644 --- a/src/main.c +++ b/src/main.c @@ -3,6 +3,7 @@ // #define DEBUG_VM #endif // #define ALLOC_STAT +// #define ALLOC_SIZES // #define FORMATTER // #define TIME #define FAKE_RUNTIME false @@ -166,7 +167,7 @@ int main() { #else pr("", res); #endif - + ptr_dec(cbc_b); } dec(rtRes); @@ -180,15 +181,20 @@ int main() { printf("leaked heap size: %ld\n", heapUsed()); printf("ctrA←"); for (i64 i = 0; i < Type_MAX; i++) { if(i)printf("‿"); printf("%lu", ctr_a[i]); } printf("\n"); printf("ctrF←"); for (i64 i = 0; i < Type_MAX; i++) { if(i)printf("‿"); printf("%lu", ctr_f[i]); } printf("\n"); - for(i64 i = 0; i < actrc; i++) { - u32* c = actrs[i]; - bool any = false; - for (i64 j = 0; j < Type_MAX; j++) if (c[j]) any=true; - if (any) { - printf("%ld", i*4); - for (i64 k = 0; k < Type_MAX; k++) printf("‿%u", c[k]); - printf("\n"); + u64 leakedCount = 0; + for (i64 i = 0; i < Type_MAX; i++) leakedCount+= ctr_a[i]-ctr_f[i]; + printf("leaked object count: %ld\n", leakedCount); + #ifdef ALLOC_SIZES + for(i64 i = 0; i < actrc; i++) { + u32* c = actrs[i]; + bool any = false; + for (i64 j = 0; j < Type_MAX; j++) if (c[j]) any=true; + if (any) { + printf("%ld", i*4); + for (i64 k = 0; k < Type_MAX; k++) printf("‿%u", c[k]); + printf("\n"); + } } - } + #endif #endif } diff --git a/src/md1.c b/src/md1.c index d7c0b722..3af1399b 100644 --- a/src/md1.c +++ b/src/md1.c @@ -13,7 +13,7 @@ B tbl_c1(B d, B x) { B f = c(Md1D,d)->f; if (v(x)->type==t_harr) { B* xp = harr_ptr(x); if (reuse) { - xp[i++] = cr; + dec(xp[i]); xp[i++] = cr; for (; i < ia; i++) xp[i] = c1(f, xp[i]); return x; } else { @@ -43,8 +43,9 @@ B tbl_c1(B d, B x) { B f = c(Md1D,d)->f; } else if (v(x)->type==t_fillarr) { B* xp = fillarr_ptr(x); if (reuse) { + dec(c(FillArr,x)->fill); c(FillArr,x)->fill = bi_noFill; - xp[i++] = cr; + dec(xp[i]); xp[i++] = cr; for (; i < ia; i++) xp[i] = c1(f, xp[i]); return x; } else { @@ -54,8 +55,10 @@ B tbl_c1(B d, B x) { B f = c(Md1D,d)->f; dec(x); return rp.b; } - } else rH = m_harrc(x); - } else rH = m_harrc(x); + } else + rH = m_harrc(x); + } else + rH = m_harrc(x); fallback: rH.a[i++] = cr; for (; i < ia; i++) rH.a[i] = c1(f, xget(x,i)); @@ -94,10 +97,10 @@ B tbl_c2(B d, B w, B x) { B f = c(Md1D,d)->f; B scan_c1(B d, B x) { B f = c(Md1D,d)->f; if (!isArr(x)) return err("`: argument cannot be a scalar"); ur xr = rnk(x); + usz ia = a(x)->ia; if (xr==0) return err("`: argument cannot be a scalar"); + if (ia==0) return x; HArr_p r = (v(x)->type==t_harr && reusable(x))? harr_parts(inc(x)) : m_harrc(x); - usz ia = r.c->ia; - if (ia==0) { dec(x); return r.b; } BS2B xget = TI(x).get; if (xr==1) { r.a[0] = xget(x,0); @@ -119,14 +122,14 @@ B scan_c2(B d, B w, B x) { B f = c(Md1D,d)->f; if (xr==0) return err("`: 𝕩 cannot be a scalar"); if (wr+1 != xr) return err("`: shape of 𝕨 must match the cell of 𝕩"); if (memcmp(wsh, xsh+1, wr)) return err("`: shape of 𝕨 must match the cell of 𝕩"); - if (ia==0) { dec(x); return r.b; } + if (ia==0) { ptr_dec(r.c); return x; } usz csz = arr_csz(x); for (usz i = 0; i < csz; i++) r.a[i] = c2(f, wget(w,i), xget(x,i)); for (usz i = csz; i < ia; i++) r.a[i] = c2(f, inc(r.a[i-csz]), xget(x,i)); dec(w); } else { if (xr!=1) return err("`: if 𝕨 is scalar, 𝕩 must be a vector"); - if (ia==0) { dec(x); return r.b; } + if (ia==0) { ptr_dec(r.c); return x; } B pr = r.a[0] = c2(f, w, xget(x,0)); for (usz i = 1; i < ia; i++) r.a[i] = pr = c2(f, inc(pr), xget(x,i)); } diff --git a/src/sfns.c b/src/sfns.c index f787c350..695585d1 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -59,7 +59,7 @@ B ud_c1(B t, B x) { for (usz i = 0; i < xu; i++) pr[i] = i; return r; } - HArr_p r = m_harrv(xu); + HArr_p r = m_harrv(xu); // TODO f64arr for (usz i = 0; i < xu; i++) r.a[i] = m_f64(i); return r.b; } @@ -104,6 +104,7 @@ B fmtF_c1(B t, B x) { if (!isVal(x)) return m_str32(U"(fmtF: not given a function)"); u8 fl = v(x)->flags; if (fl==0 || fl>=62) return m_str32(U"(fmtF: not given a runtime primitive)"); + dec(x); return m_c32(U"+-×÷⋆√⌊⌈|¬∧∨<>≠=≤≥≡≢⊣⊢⥊∾≍↑↓↕«»⌽⍉/⍋⍒⊏⊑⊐⊒∊⍷⊔!˙˜˘¨⌜⁼´˝`∘○⊸⟜⌾⊘◶⎉⚇⍟"[fl-1]); } diff --git a/src/sysfn.c b/src/sysfn.c index f0e47cd1..8ff4709b 100644 --- a/src/sysfn.c +++ b/src/sysfn.c @@ -23,7 +23,8 @@ B decp_c1(B t, B x) { usz runtimeLen; B primInd_c1(B t, B x) { if (!isVal(x)) return m_i32(runtimeLen); - if (v(x)->flags) return m_i32(v(x)->flags-1); + if (v(x)->flags) { B r = m_i32(v(x)->flags-1); dec(x); return r; } + dec(x); return m_i32(runtimeLen); } @@ -37,7 +38,7 @@ B fill_c1(B t, B x) { B fill_c2(B t, B w, B x) { // TODO not set fill for typed arrays if (isArr(x)) { B fill = asFill(w); - if (fill.u == bi_noFill.u) return x; + if (fill.u == bi_noFill.u) { dec(fill); return x; } return withFill(x, fill); } dec(w); @@ -84,8 +85,8 @@ B grLen_c2(B t, B w, B x) { B grOrd_c2(B t, B w, B x) { usz wia = a(w)->ia; usz xia = a(x)->ia; - if (wia==0) return c1(bi_ud, m_i32(0)); - if (xia==0) return x; + if (wia==0) { dec(w); dec(x); return c1(bi_ud, m_i32(0)); } + if (xia==0) { dec(w); dec(x); return x; } BS2B wget = TI(w).get; BS2B xget = TI(x).get; usz tmp[wia]; @@ -109,8 +110,8 @@ B asrt_c1(B t, B x) { return err("assertion error"); } B asrt_c2(B t, B w, B x) { - if (isI32(x) && 1==(i32)x.u) return x; - if (isF64(x) && 1==x.f) return x; + if (isI32(x) && 1==(u32)x.u) { dec(w); return x; } + if (isF64(x) && 1==x.f) { dec(w); return x; } dec(x); printf("Assertion error: "); fflush(stdout); print(w); printf("\n"); dec(w); diff --git a/test.bqn b/test.bqn index 0a1e45be..a1b76ede 100755 --- a/test.bqn +++ b/test.bqn @@ -5,9 +5,9 @@ envP←1⊑•args tests ← •FLines path∾"/test/cases/prim.bqn" # tests ← •FLines path∾"/test/cases/identity.bqn" +# tests ← •FLines path∾"/test/cases/undo.bqn" # tests ← •FLines path∾"/test/cases/under.bqn" # tests ← •FLines path∾"/test/cases/fill.bqn" -# tests ← •FLines "primLeft.bqn" {tests↩𝕩}⍟(×≠) 2↓•args ('#'≠ ·⊑ ∾⟜"#")◶@‿{