diff --git a/cc.bqn b/cc.bqn index 032c7aea..3b78612f 100755 --- a/cc.bqn +++ b/cc.bqn @@ -29,7 +29,7 @@ useInd ← "-i"≡⊑args ⋄ args↓˜↩useInd Comp ← (3+useInd) ↑ ((<"inc(runtime["∾⍕∾"])"˙)¨↕62)⊸Compile J ← ∾∾⟜\n¨ Fconst ← ≡◶⟨@⊸≤◶Num‿Char, Str, ⊑⟩ -prov ← {"inc("∾𝕩∾")"}¨"bi_type"‿"bi_fill"‿"bi_log"‿"bi_grLen"‿"bi_grOrd"‿"bi_asrt"‿"bi_add"‿"bi_sub"‿"bi_mul"‿"bi_div"‿"bi_pow"‿"bi_floor"‿"bi_eq"‿"bi_le"‿"bi_fne"‿"bi_shape"‿"bi_pick"‿"bi_ud"‿"bi_tbl"‿"bi_scan"‿"bi_fillBy"‿"bi_val" +prov ← {"inc("∾𝕩∾")"}¨"bi_type"‿"bi_fill"‿"bi_log"‿"bi_grLen"‿"bi_grOrd"‿"bi_asrt"‿"bi_add"‿"bi_sub"‿"bi_mul"‿"bi_div"‿"bi_pow"‿"bi_floor"‿"bi_eq"‿"bi_le"‿"bi_fne"‿"bi_shape"‿"bi_pick"‿"bi_ud"‿"bi_tbl"‿"bi_scan"‿"bi_fillBy"‿"bi_val"‿"bi_catch" Fout ← {((≠𝕩)↑⟨LI F¨,L ·prov⊸∾⍟(𝕨⊣0) Fconst¨,L (LI F¨)¨,L (L F¨)¨⟩) {𝕎𝕩}¨ 𝕩} Frun ← 1⊸Fout Long ← {¯2↓∾𝕩∾¨<","∾\n} diff --git a/src/c32arr.c b/src/c32arr.c index a056fc8b..bef8589f 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; } -B m_str32(u32* s) { // meant to be used as m_str32(U"{𝕨‿𝕩}") +NOINLINE B m_str32(u32* s) { // meant to be used as m_str32(U"{𝕨‿𝕩}") 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/fillarr.c b/src/fillarr.c index 7e4e5732..ebedfe66 100644 --- a/src/fillarr.c +++ b/src/fillarr.c @@ -22,7 +22,7 @@ B asFill(B x) { // consumes dec(x); return bi_noFill; } -B getFill(B x) { // consumes +B getFill(B x) { // consumes; can return bi_noFill if (isArr(x)) { u8 t = v(x)->type; if (t==t_fillarr ) { B r = inc(c(FillArr,x )->fill); dec(x); return r; } @@ -30,13 +30,15 @@ B getFill(B x) { // consumes 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); + return bi_noFill; } - if (isC32(x)) return m_c32(' '); if (isF64(x)|isI32(x)) return m_i32(0); + if (isC32(x)) return m_c32(' '); dec(x); - return m_f64(0); + if (isMd(x) || isFun(x)) return bi_noFill; + return bi_noFill; } +bool noFill(B x) { return x.u == bi_noFill.u; } typedef struct FillSlice { struct Slice; @@ -85,6 +87,7 @@ void fillarr_init() { B withFill(B x, B fill) { // consumes both assert(isArr(x)); + if (noFill(fill) && v(x)->type!=t_fillarr && v(x)->type!=t_fillslice) return 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; diff --git a/src/h.h b/src/h.h index 763bf76e..1e14cc04 100644 --- a/src/h.h +++ b/src/h.h @@ -121,12 +121,12 @@ char* format_pm1(u8 u) { } enum PrimMd2 { pm2_none, - pm2_val, pm2_fillBy, // md2.c + pm2_val, pm2_fillBy, pm2_catch, // md2.c }; char* format_pm2(u8 u) { switch(u) { default: case pf_none: return"(unknown 1-modifier)"; - case pm2_val: return"⊘"; case pm2_fillBy: return"•_fillBy_"; + case pm2_val: return"⊘"; case pm2_fillBy: return"•_fillBy_"; case pm2_catch: return"⎊"; } } @@ -204,8 +204,8 @@ NORETURN void thr(B b); NORETURN void thrM(char* s); jmp_buf* prepareCatch(); #ifdef CATCH_ERRORS -#define CATCH setjmp(*prepareCatch()) // use as `if (CATCH) { /*handle error; dec(catchMessage);*/ } /*regular execution*/ popCatch();` -#else +#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 void popCatch(); @@ -252,6 +252,7 @@ bool isVal(B x) { return (x.u - (((u64)VAL_TAG<<51) + 1)) < ((1ull<<51) - 1); } bool isF64(B x) { return (x.u<<1) - ((0xFFEull<<52) + 2) >= (1ull<<52) - 2; } bool isAtm(B x) { return !isVal(x); } +bool noFill(B x); // shape mess typedef struct ShArr { @@ -313,9 +314,9 @@ B m_i32(i32 n) { return m_f64(n); } B m_error() { return tag(4, TAG_TAG); } B m_usz(usz n) { return n==(i32)n? m_i32(n) : m_f64(n); } -i32 o2i (B x) { if ((i32)x.f!=x.f) err("o2i"": expected integer"); return (i32)x.f; } -usz o2s (B x) { if ((usz)x.f!=x.f) err("o2s"": expected integer"); return (usz)x.f; } -i64 o2i64(B x) { if ((i64)x.f!=x.f) err("o2i64: expected integer"); return (i64)x.f; } +i32 o2i (B x) { if ((i32)x.f!=x.f) thrM("Expected integer"); return (i32)x.f; } +usz o2s (B x) { if ((usz)x.f!=x.f) thrM("Expected integer"); return (usz)x.f; } +i64 o2i64(B x) { if ((i64)x.f!=x.f) thrM("Expected integer"); return (i64)x.f; } i32 o2iu (B x) { return isI32(x)? (i32)(u32)x.u : (i32)x.f; } bool q_i32(B x) { return isI32(x) || isF64(x)&(x.f==(i32)x.f); } @@ -464,6 +465,7 @@ void print(B x) { 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) { @@ -476,7 +478,7 @@ void printRaw(B x) { BS2B xget = TI(x).get; for (usz i = 0; i < ia; i++) { B c = xget(x,i); - if (c.u==0 | c.u==bi_noFill.u) { printf(" "); continue; } + if (c.u==0 || noFill(c)) { printf(" "); continue; } if (!isC32(c)) err("bad printRaw argument: expected all character items"); printUTF8((u32)c.u); } @@ -655,4 +657,4 @@ static inline void onFree(Value* x) { x->refc = -1431655000; #endif // x->refc = 0x61616161; -} \ No newline at end of file +} diff --git a/src/main.c b/src/main.c index fcdbaf7d..c760e33c 100644 --- a/src/main.c +++ b/src/main.c @@ -16,6 +16,7 @@ // #define FORMATTER // use self-hosted formatter for output // #define TIME // output runtime of every expression +#define rtLen 63 #include "h.h" #include "heap.c" #include "mm_buddy.c" @@ -27,9 +28,9 @@ #include "derv.c" #include "arith.c" #include "sfns.c" +#include "sysfn.c" #include "md1.c" #include "md2.c" -#include "sysfn.c" #include "vm.c" void pr(char* a, B b) { @@ -97,10 +98,11 @@ int main() { /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ bi_N , bi_N , bi_N , bi_N , bi_N , bi_N , bi_pick , bi_N , bi_N, bi_N, /* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_N , bi_N , bi_asrt , bi_N , bi_N , bi_N , bi_N , bi_tbl, bi_N, bi_N, /* ˝`∘○⊸⟜⌾⊘◶⎉ */ bi_N , bi_scan, bi_N , bi_N , bi_N , bi_N , bi_N , bi_val, bi_N, bi_N, - /* ⚇⍟ */ bi_N , bi_fill + /* ⚇⍟⎊ */ bi_N , bi_fill, bi_catch }; - for (i32 i = 0; i < 62; i++) inc(fruntime[i]); - B frtObj = m_caB(62, fruntime); + assert(sizeof(fruntime)/sizeof(B) == rtLen); + for (i32 i = 0; i < rtLen; i++) inc(fruntime[i]); + B frtObj = m_caB(rtLen, fruntime); Block* runtime_b = compile( diff --git a/src/md1.c b/src/md1.c index 4dc72549..1af34858 100644 --- a/src/md1.c +++ b/src/md1.c @@ -96,6 +96,7 @@ 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) || rnk(x)==0) thrM("`: argument cannot have rank 0"); + B xf = getFill(inc(x)); ur xr = rnk(x); usz ia = a(x)->ia; if (ia==0) return x; @@ -111,7 +112,7 @@ B scan_c1(B d, B x) { B f = c(Md1D,d)->f; for (usz i = csz; i < ia; i++) r.a[i] = c2(f, inc(r.a[i-csz]), xget(x,i)); } dec(x); - return r.b; + return withFill(r.b, xf); } B scan_c2(B d, B w, B x) { B f = c(Md1D,d)->f; if (!isArr(x) || rnk(x)==0) thrM("`: 𝕩 cannot have rank 0"); diff --git a/src/md2.c b/src/md2.c index 7403c590..70a5a14f 100644 --- a/src/md2.c +++ b/src/md2.c @@ -5,8 +5,35 @@ B val_c1(B d, B x) { return c1(c(Md2D,d)->f, x); } B val_c2(B d, B w, B x) { return c2(c(Md2D,d)->g, w,x); } + +#ifdef CATCH_ERRORS +B fillBy_c1(B d, B x) { + B xf=getFill(inc(x)); + B r = c1(c(Md2D,d)->f, x); + if(!isArr(r) || noFill(xf)) { dec(xf); return r; } + if (CATCH) { dec(catchMessage); return r; } + B fill = asFill(c1(c(Md2D,d)->g, xf)); + popCatch(); + return withFill(r, fill); +} +B fillBy_c2(B d, B w, B x) { + B wf=getFill(inc(w)); B xf=getFill(inc(x)); + B r = c2(c(Md2D,d)->f, w,x); + if(!isArr(r) || noFill(xf)) { dec(xf); dec(wf); return r; } + if (CATCH) { dec(catchMessage); return r; } + if (noFill(wf)) wf = inc(bi_asrt); + B fill = asFill(c2(c(Md2D,d)->g, wf, xf)); + popCatch(); + return withFill(r, fill); +} +B catch_c1(B d, B x) { if(CATCH) return c1(c(Md2D,d)->g, x); B r = c1(c(Md2D,d)->f, x); popCatch(); return r; } +B catch_c2(B d, B w, B x) { if(CATCH) return c2(c(Md2D,d)->g, w,x); B r = c2(c(Md2D,d)->f, w,x); popCatch(); 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); } +B catch_c1 (B d, B x) { return c1(c(Md2D,d)->f, x); } +B catch_c2 (B d, B w, B x) { return c2(c(Md2D,d)->f, w,x); } +#endif #define ba(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2_def, ftag(MD2_TAG)); c(Md2,bi_##NAME)->c2 = NAME##_c2; c(Md2,bi_##NAME)->c1 = NAME##_c1; c(Md2,bi_##NAME)->extra=pm2_##NAME; gc_add(bi_##NAME); #define bd(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2_def, ftag(MD2_TAG)); c(Md2,bi_##NAME)->c2 = NAME##_c2; c(Md2,bi_##NAME)->c1 = c1_invalid; c(Md1,bi_##NAME)->extra=pm2_##NAME; gc_add(bi_##NAME); @@ -14,8 +41,8 @@ B fillBy_c2(B d, B w, B x) { return c2(c(Md2D,d)->f, w,x); } void print_md2_def(B x) { printf("%s", format_pm2(c(Md1,x)->extra)); } -B bi_val, bi_fillBy; -void md2_init() { ba(val) ba(fillBy) +B bi_val, bi_fillBy, bi_catch; +void md2_init() { ba(val) ba(fillBy) ba(catch) ti[t_md2_def].print = print_md2_def; } diff --git a/src/sfns.c b/src/sfns.c index 3201f3a7..b4bf42e7 100644 --- a/src/sfns.c +++ b/src/sfns.c @@ -1,39 +1,37 @@ #include "h.h" B shape_c1(B t, B x) { - if (isArr(x)) { - usz ia = a(x)->ia; - if (reusable(x)) { - decSh(x); - arr_shVec(x, ia); - return x; - } - B r = TI(x).slice(x, 0); - arr_shVec(r, ia); - return r; - } else return err("reshaping non-array"); + if (!isArr(x)) thrM("reshaping non-array"); + usz ia = a(x)->ia; + if (reusable(x)) { + decSh(x); + arr_shVec(x, ia); + return x; + } + B r = TI(x).slice(x, 0); + arr_shVec(r, ia); + return r; } B shape_c2(B t, B w, B x) { - if (isArr(x)) { - if (!isArr(w)) return shape_c1(t, x); - BS2B wget = TI(w).get; - ur nr = a(w)->ia; - usz nia = a(x)->ia; - B r; - if (reusable(x)) { r = x; decSh(x); } - else r = TI(x).slice(x, 0); - usz* sh = arr_shAlloc(r, nia, nr); - if (sh) for (i32 i = 0; i < nr; i++) sh[i] = o2s(wget(w,i)); - dec(w); - return r; - } else return err("reshaping non-array"); + if (!isArr(x)) { dec(x); dec(w); thrM("reshaping non-array"); } + if (!isArr(w)) return shape_c1(t, x); + BS2B wget = TI(w).get; + ur nr = a(w)->ia; + usz nia = a(x)->ia; + B r; + if (reusable(x)) { r = x; decSh(x); } + else r = TI(x).slice(x, 0); + usz* sh = arr_shAlloc(r, nia, nr); + if (sh) for (i32 i = 0; i < nr; i++) sh[i] = o2s(wget(w,i)); + dec(w); + return r; } B pick_c1(B t, B x) { if (!isArr(x)) return x; if (a(x)->ia==0) { B r = getFill(x); - if (r.u==bi_noFill.u) return err("⊑: called on empty array without fill"); + if (noFill(r)) thrM("⊑: called on empty array without fill"); return r; } B r = TI(x).get(x, 0); @@ -42,13 +40,11 @@ B pick_c1(B t, B x) { } B pick_c2(B t, B w, B x) { usz wu = o2s(w); - if (isArr(x)) { - // if (wu >= a(x)->ia) err("⊑: 𝕨 is greater than length of 𝕩"); // no bounds check for now - B r = TI(x).get(x, wu); - dec(x); - return r; - } - dec(x); return err("n⊑atom"); + if (!isArr(x)) { dec(x); dec(w); thrM("⊑: 𝕩 wasn't an array"); } + // if (wu >= a(x)->ia) err("⊑: 𝕨 is greater than length of 𝕩"); // no bounds check for now + B r = TI(x).get(x, wu); + dec(x); + return r; } B ud_c1(B t, B x) { @@ -103,7 +99,7 @@ B fmtN_c1(B t, B x) { 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)"); + if (fl==0 || fl>=rtLen) 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 22afcc1c..0baef606 100644 --- a/src/sysfn.c +++ b/src/sysfn.c @@ -9,8 +9,8 @@ B type_c1(B t, B x) { else if (isFun(x)) r = 3; else if (isMd1(x)) r = 4; else if (isMd2(x)) r = 5; - decR(x); if (r==-1) return err("getting type"); + decR(x); return m_i32(r); } @@ -33,12 +33,14 @@ B glyph_c1(B t, B x) { } B fill_c1(B t, B x) { - return getFill(x); + B f = getFill(x); + if (noFill(f)) return m_f64(0); // thrM("No fill found"); + return f; } 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) { dec(fill); return x; } + if (noFill(fill)) return x; return withFill(x, fill); } dec(w); diff --git a/src/utf.c b/src/utf.c index c52e810f..80a7a9c0 100644 --- a/src/utf.c +++ b/src/utf.c @@ -20,10 +20,11 @@ B fromUTF8(char* s, u64 len) { u64 j; for (j = 0; j < len; j+= utf8_len(s[j])) sz++; if (j!=len) return err("invalid UTF-8"); - HArr_p r = m_harrv(sz); + B r = m_c32arrv(sz); + u32* rp = c32arr_ptr(r); u64 p = 0; - for (u64 i = 0; i < len; i+= utf8_len(s[i])) r.a[p++] = m_c32(utf8_p((u8*)s+i)); // may read after end, eh - return r.b; + for (u64 i = 0; i < len; i+= utf8_len(s[i])) rp[p++] = utf8_p((u8*)s+i); // may read after end, eh + return r; } void printUTF8(u32 c) { diff --git a/src/vm.c b/src/vm.c index e6b3982f..c6b92d2d 100644 --- a/src/vm.c +++ b/src/vm.c @@ -265,7 +265,7 @@ void allocStack(u64 am) { u64 left = gStackEnd-gStack; if (am>left) { u64 n = gStackEnd-gStackStart + am + 500; - u64 d = gStackStart-gStack; + u64 d = gStack-gStackStart; gStackStart = realloc(gStackStart, n*sizeof(B)); gStack = gStackStart+d; gStackEnd = gStackStart+n; @@ -534,7 +534,7 @@ jmp_buf* prepareCatch() { // in the case of returning false, must call popCatch( if (cf==cfEnd) { u64 n = cfEnd-cfStart; n = n<8? 8 : n*2; - u64 d = cfStart-cf; + u64 d = cf-cfStart; cfStart = realloc(cfStart, n*sizeof(CatchFrame)); cf = cfStart+d; cfEnd = cfStart+n; @@ -556,13 +556,12 @@ void thr(B msg) { cf--; B* gStackNew = gStackStart + cf->gStackDepth; - if (gStackNew>gStack) err("bad catch gStack"); + if (gStackNew>gStack) err("bad catch gStackDepth"); while (gStack!=gStackNew) dec(*--gStack); - // gStack = gStackNew; - cf = cfStart + cf->cfDepth; + if (cfStart+cf->cfDepth > cf) err("bad catch cfDepth"); + cf = cfStart+cf->cfDepth; longjmp(cf->jmp, 1); - printf("wat\n"); } assert(cf==cfStart); printf("Error: ");