From b18157d86b4290532a825bd5dc3ca746c9cc029b Mon Sep 17 00:00:00 2001 From: dzaima Date: Tue, 27 Jul 2021 19:48:02 +0300 Subject: [PATCH] =?UTF-8?q?native=20=E2=A5=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit it's horrible but it appears to work --- cc.bqn | 2 +- src/builtins/sfns.c | 196 +++++++++++++++++++++++++++++++++++++++----- src/core/stuff.h | 5 ++ src/load.c | 4 +- test.bqn | 33 ++++---- 5 files changed, 199 insertions(+), 41 deletions(-) diff --git a/cc.bqn b/cc.bqn index d72d68ce..b24ebb57 100755 --- a/cc.bqn +++ b/cc.bqn @@ -22,7 +22,7 @@ Esc←{ ∾(i<≠in) /⟜"\"⊸∾¨ 𝕩 # Insert \ } -OStr ← "m_str32(U"""∾Esc∾""")"˙ # A BQN string +OStr ← "m_str32(U"""∾Esc∾""")"˙ # A BQN string OChr ← {"m_c32(U'"∾(Esc⥊𝕩)∾"')"} # A BQN character ONum ← {s←"-"/˜𝕩<0 ⋄ ∞⊸=∘|◶⟨"m_f64("∾")"∾˜s∾F∘| ⋄ "m_f64("∾s∾"1.0/0.0)"⟩𝕩} # Format number OAny ← ≡◶⟨@⊸≤◶ONum‿OChr, OStr, ⊑⟩ diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index 56cd9394..2a1691a2 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -6,32 +6,184 @@ B shape_c1(B t, B x) { - if (isAtm(x)) thrM("⥊: deshaping non-array"); - usz ia = a(x)->ia; - if (reusable(x)) { - decSh(v(x)); - arr_shVec(a(x), ia); - return x; + if (isAtm(x)) { + unit: + if (isF64(x)) { + i32 i = (i32)x.f; + if (i == x.f) { + i32* rp; B r = m_i32arrv(&rp, 1); + rp[0] = i; + return r; + } else { + f64* rp; B r = m_f64arrv(&rp, 1); + rp[0] = x.f; + return r; + } + } + if (isC32(x)) { + u32* rp; B r = m_c32arrv(&rp, 1); + rp[0] = o2cu(x); + return r; + } + Arr* ra = m_fillarrp(1); + arr_shVec(ra, 1); + fillarr_setFill(ra, asFill(inc(x))); + fillarr_ptr(ra)[0] = x; + return taga(ra); + } else { + usz ia = a(x)->ia; + if (ia==1 && TI(x,elType)ia; - if (wia>UR_MAX) thrM("⥊: Result rank too large"); - ur nr = (ur)wia; - usz nia = a(x)->ia; - B r; Arr* ra; - if (reusable(x)) { r = x; decSh(v(x)); ra = (Arr*)v(r); } - else { ra = TI(x,slice)(x, 0); r = taga(ra); } - usz* sh = arr_shAllocI(ra, nia, nr); - if (sh) for (u32 i = 0; i < nr; i++) sh[i] = o2s(wget(w,i)); + usz xia = isArr(x)? a(x)->ia : 1; + usz nia; + bool fill = false; + ur nr; + ShArr* sh; + if (isF64(w)) { + nia = o2s(w); + nr = 1; + sh = NULL; + } else { + if (isAtm(w)) w = m_atomUnit(w); + if (rnk(w)>1) thrM("⥊: 𝕨 must have rank at most 1"); + if (a(w)->ia>UR_MAX) thrM("⥊: Result rank too large"); + nr = a(w)->ia; + sh = nr<=1? NULL : m_shArr(nr); + if (TI(w,elType)==el_i32) { + i32* wi = i32any_ptr(w); + if (nr>1) for (i32 i = 0; i < nr; i++) sh->a[i] = wi[i]; + i64 tot = 1; + for (i32 i = 0; i < nr; i++) { + if (wi[i]<0) thrF("⥊: 𝕨 contained %i", wi[i]); + tot*= wi[i]; + if (tot > USZ_MAX) thrM("⥊: Result too large"); // TODO this (& below) doesn't detect overflows for usz==u64 + } + nia = (usz)tot; + } else { + BS2B getU = TI(w,getU); + i32 unkPos = -1; + i32 unkInd; + i64 tot = 1; + for (i32 i = 0; i < nr; i++) { + B c = getU(w, i); + if (isF64(c)) { + usz v = o2s(c); + if (sh) sh->a[i] = v; + tot*= v; + if (tot > USZ_MAX) thrM("⥊: Result too large"); + } else { + if (isArr(c) || !isVal(c)) thrM("⥊: 𝕨 must consist of natural numbers or ∘ ⌊ ⌽ ↑"); + if (unkPos!=-1) thrM("⥊: 𝕨 contained multiple computed axes"); + unkPos = i; + unkInd = ((i32)v(c)->flags) - 1; + } + } + if (unkPos!=-1) { + if (unkInd!=52 & unkInd!=6 & unkInd!=30 & unkInd!=25) thrM("⥊: 𝕨 must consist of natural numbers or ∘ ⌊ ⌽ ↑"); + if (tot==0) thrM("⥊: Can't compute axis when the rest of the shape is empty"); + i64 div = xia/tot; + i64 mod = xia%tot; + usz item; + if (unkInd == 52) { + if (mod!=0) thrM("⥊: Shape must be exact when reshaping with ∘"); + item = div; + } else if (unkInd == 6) { + item = div; + } else if (unkInd == 30) { + item = mod? div+1 : div; + } else if (unkInd == 25) { + item = mod? div+1 : div; + fill = true; + } else UD; + if (sh) sh->a[unkPos] = item; + tot*= item; + if (tot > USZ_MAX) thrM("⥊: Result too large"); + nia = tot; + } else nia = tot; + } + } dec(w); - return r; + + B xf; + if (isAtm(x)) { + xf = asFill(x); + // goes to unit + } else { + if (nia <= xia) { + B r; Arr* ra; + if (reusable(x) && xia==nia) { r = x; decSh(v(x)); ra = (Arr*)v(r); } + else { ra = TI(x,slice)(x, 0); ra->ia = nia; r = taga(ra); } + arr_shSetU(ra, nr, sh); + return r; + } else { + xf = getFillQ(x); + if (xia<=1) { + if (xia==0) { + if (xf.u == bi_noFill.u) thrM("⥊: No fill for empty array"); + dec(x); + x = inc(xf); + } else { + B n = TI(x,get)(x,0); + dec(x); + x = n; + } + goto unit; + } + + MAKE_MUT(m, nia); mut_init(m, TI(x,elType)); + i64 div = nia/xia; + i64 mod = nia%xia; + for (i64 i = 0; i < div; i++) mut_copyG(m, i*xia, x, 0, xia); + if (fill) mut_fill(m, div*xia, xf, mod); + else mut_copyG(m, div*xia, x, 0, mod); + dec(x); + Arr* ra = mut_fp(m); + arr_shSetU(ra, nr, sh); + return withFill(taga(ra), xf); + } + } + unit: + + if (isF64(x)) { decR(xf); + i32 n = (i32)x.f; + if (n == x.f) { + i32* rp; Arr* r = m_i32arrp(&rp, nia); arr_shSetU(r, nr, sh); + for (u64 i = 0; i < nia; i++) rp[i] = n; + return taga(r); + } else { + f64* rp; Arr* r = m_f64arrp(&rp, nia); arr_shSetU(r, nr, sh); + for (u64 i = 0; i < nia; i++) rp[i] = x.f; + return taga(r); + } + } + if (isC32(x)) { decR(xf); + u32* rp; Arr* r = m_c32arrp(&rp, nia); arr_shSetU(r, nr, sh); + u32 c = o2cu(x); + for (u64 i = 0; i < nia; i++) rp[i] = c; + return taga(r); + } + Arr* r = m_fillarrp(nia); r->ia=nia; arr_shSetU(r, nr, sh); + B* rp = fillarr_ptr(r); + if (nia) incBy(x, nia-1); + else dec(x); + for (u64 i = 0; i < nia; i++) rp[i] = x; + fillarr_setFill(r, xf); + return taga(r); } extern B rt_pick; diff --git a/src/core/stuff.h b/src/core/stuff.h index 6fa3ec7b..1601986a 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -56,6 +56,11 @@ static void arr_shSetI(Arr* x, usz ia, ur r, ShArr* sh) { if (r>1) { x->sh = sh->a; ptr_inc(sh); } else { x->sh = &x->ia; } } +static void arr_shSetU(Arr* x, ur r, ShArr* sh) { + sprnk(x,r); + if (r>1) { x->sh = sh->a; } + else { x->sh = &x->ia; } +} static void arr_shCopy(Arr* n, B o) { // copy shape,rank,ia from o to n assert(isArr(o)); n->ia = a(o)->ia; diff --git a/src/load.c b/src/load.c index d3d2b850..3c764714 100644 --- a/src/load.c +++ b/src/load.c @@ -206,7 +206,7 @@ void load_init() { // very last init function B fruntime[] = { /* +-×÷⋆√⌊⌈|¬ */ bi_add , bi_sub , bi_mul , bi_div , bi_pow , bi_root , bi_floor, bi_ceil , bi_stile , bi_not, /* ∧∨<>≠=≤≥≡≢ */ bi_and , bi_or , bi_lt , bi_gt , bi_ne , bi_eq , bi_le , bi_ge , bi_feq , bi_fne, - /* ⊣⊢⥊∾≍↑↓↕«» */ bi_ltack , bi_rtack , bi_shape, bi_join , bi_couple , bi_take , bi_drop , bi_ud , bi_shifta, bi_shiftb, + /* ⊣⊢⥊∾≍↑↓↕«» */ bi_ltack , bi_rtack , bi_shape, bi_join , bi_couple , bi_take , bi_drop , bi_ud , bi_shifta, bi_shiftb, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ bi_reverse, bi_N , bi_slash, bi_gradeUp, bi_gradeDown, bi_select, bi_pick , bi_indexOf, bi_count , bi_memberOf, /* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_find , bi_group , bi_asrt , bi_const , bi_swap , bi_cell , bi_each , bi_tbl , bi_N , bi_fold, /* ˝`∘○⊸⟜⌾⊘◶⎉ */ bi_N , bi_scan , bi_atop , bi_over , bi_before , bi_after , bi_under, bi_val , bi_cond , bi_N, @@ -215,7 +215,7 @@ void load_init() { // very last init function bool rtComplete[] = { /* +-×÷⋆√⌊⌈|¬ */ 1,1,1,1,1,1,1,1,1,1, /* ∧∨<>≠=≤≥≡≢ */ 1,1,1,1,1,1,1,1,1,1, - /* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,0,1,1,1,1,1,1,1, + /* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,1,1,1,1,1,1,1,1, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ 1,0,1,1,1,1,1,1,1,1, /* ⍷⊔!˙˜˘¨⌜⁼´ */ 1,1,1,1,1,1,1,1,0,1, /* ˝`∘○⊸⟜⌾⊘◶⎉ */ 0,1,1,1,1,1,1,1,0,0, diff --git a/test.bqn b/test.bqn index f6d9a52c..be4ec4b6 100755 --- a/test.bqn +++ b/test.bqn @@ -5,22 +5,23 @@ args←1↓•args opt←"" {𝕊: opt↩𝕩 ⋄ args↓˜↩1}⍟('-'≡⊑) ⊑args -"Missing argument!"!1=≠args -case←⊑args -case∾↩".bqn" -tests ← •FLines path∾"/test/cases/"∾case -tests/˜↩ (('#'≢⊑)∧0<≠)¨tests -{𝕊: tests/˜↩'!'≠⊑¨tests}⍟⊑ 's'∊opt -{𝕊: tests/˜↩'!'=⊑¨tests}⍟⊑ 'e'∊opt -verify ← ⊑'v'∊opt -RMC ← ⊐⟜'#'⊑⊸↑⊢ # doesn't work for token.bqn but whatever -Q ← { - i←⊑𝕩⊐'%' - ((1+'!'≠⊑𝕩)×verify)◶⟨(1+i)⊸↓ ⋄ {∾ ⟨"""should've errored!""∘•BQN⎊1 """ ⋄ {𝕩/˜1+𝕩='"'}𝕩↓˜1+⊑𝕩⊐'%' ⋄ """"⟩} ⋄ {∾⟨"""incorrect!""‿1⊑˜(" ⋄ i↑𝕩 ⋄ ") ≡ {" ⋄ (1+i)↓𝕩 ⋄ " }"⟩}⟩ RMC 𝕩 -} -Out ← {•Out'%'⊸∊◶(verify◶⊢‿{∾⟨"""incorrect!""‿1⊑˜1≡{" ⋄ RMC 𝕩 ⋄ " }"⟩})‿Q𝕩} +"Missing argument!"!0<≠args +{ + case ← 𝕩∾".bqn" + tests ← •FLines path∾"/test/cases/"∾case + tests/˜↩ (('#'≢⊑)∧0<≠)¨tests + {𝕊: tests/˜↩'!'≠⊑¨tests}⍟⊑ 's'∊opt + {𝕊: tests/˜↩'!'=⊑¨tests}⍟⊑ 'e'∊opt + verify ← ⊑'v'∊opt + RMC ← ⊐⟜'#'⊑⊸↑⊢ # doesn't work for token.bqn but whatever + Q ← { + i←⊑𝕩⊐'%' + ((1+'!'≠⊑𝕩)×verify)◶⟨(1+i)⊸↓ ⋄ {∾ ⟨"""should've errored!""∘•BQN⎊1 """ ⋄ {𝕩/˜1+𝕩='"'}𝕩↓˜1+⊑𝕩⊐'%' ⋄ """"⟩} ⋄ {∾⟨"""incorrect!""‿1⊑˜(" ⋄ i↑𝕩 ⋄ ") ≡ {" ⋄ (1+i)↓𝕩 ⋄ " }"⟩}⟩ RMC 𝕩 + } + Out ← {•Out'%'⊸∊◶(verify◶⊢‿{∾⟨"""incorrect!""‿1⊑˜1≡{" ⋄ RMC 𝕩 ⋄ " }"⟩})‿Q𝕩} -((⊑'m'∊opt)⊑Out‿{•Show𝕩⋄Out𝕩})¨tests -# ('%'⊸∊∨ '#'= ·⊑ ∾⟜"#")◶•Out‿@¨tests + ((⊑'m'∊opt)⊑Out‿{•Show𝕩⋄Out𝕩})¨tests + # ('%'⊸∊∨ '#'= ·⊑ ∾⟜"#")◶•Out‿@¨tests +}¨args •Out⍟(¬⊑'q'∊opt) """finished""" •Out⍟(¬⊑'q'∊opt) "" \ No newline at end of file