native », fill stuff

This commit is contained in:
dzaima 2021-04-30 20:58:43 +03:00
parent d7561d1fbd
commit 2828a05dfc
10 changed files with 185 additions and 36 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
main.s
BQN
src/runtime
src/runtime0
src/runtime1
src/compiler
src/interp

View File

@ -3,6 +3,7 @@ if [[ $# -ne 1 ]]; then
echo "Usage: ./genRuntime path/to/mlochbaum/BQN"
exit
fi
./cc.bqn $1 r0 > src/runtime0
./cc.bqn $1 r1 > src/runtime1
./cc.bqn $1 c > src/compiler
./cc.bqn $1 f > src/formatter

View File

@ -23,6 +23,10 @@ B asFill(B x) { // consumes
return bi_noFill;
}
B getFill(B x) { // consumes; can return bi_noFill
bool defZero = true;
#ifdef CATCH_ERRORS
defZero = false;
#endif
if (isArr(x)) {
u8 t = v(x)->type;
if (t==t_fillarr ) { B r = inc(c(FillArr,x )->fill); dec(x); return r; }
@ -31,13 +35,12 @@ B getFill(B x) { // consumes; can return bi_noFill
if (t==t_i32arr || t==t_i32slice) { dec(x); return m_f64(0 ); }
if (t==t_f64arr || t==t_f64slice) { dec(x); return m_f64(0 ); }
dec(x);
return bi_noFill;
return defZero? m_f64(0) : bi_noFill;
}
if (isF64(x)|isI32(x)) return m_i32(0);
if (isC32(x)) return m_c32(' ');
dec(x);
if (isMd(x) || isFun(x)) return bi_noFill;
return bi_noFill;
return defZero? m_f64(0) : bi_noFill;
}
bool noFill(B x) { return x.u == bi_noFill.u; }
@ -112,6 +115,19 @@ void validateFill(B x) {
assert(' '==(u32)x.u);
}
}
B fill_both(B w, B x) { // doesn't consume
B fw = getFill(inc(w));
if (noFill(fw)) return bi_noFill;
B fx = getFill(inc(x));
if (!equal(fw, fx)) {
dec(fw); dec(fx);
return bi_noFill;
}
dec(fw);
return fx;
}
B withFill(B x, B fill) { // consumes both
assert(isArr(x));
#ifdef DEBUG
@ -141,3 +157,7 @@ B withFill(B x, B fill) { // consumes both
dec(x);
return r;
}
B qWithFill(B x, B fill) { // consumes both
if (noFill(fill)) return x;
return withFill(x, fill);
}

View File

@ -101,7 +101,7 @@ char* format_type(u8 u) {
/*arith.c*/ F(add,"+") F(sub,"-") F(mul,"×") F(div,"÷") F(pow,"") F(floor,"") F(ceil,"") F(stile,"|") F(eq,"=") \
/*arith.c*/ F(ne,"") F(le,"") F(ge,"") F(lt,"<") F(gt,">") F(and,"") F(or,"") F(not,"¬") F(log,"⋆⁼") \
/*fns.c*/ F(ud,"") F(fne,"") F(feq,"") F(ltack,"") F(rtack,"") F(fmtF,"•FmtF") F(fmtN,"•FmtN") \
/*sfns.c*/ F(shape,"") F(pick,"") F(pair,"{𝕨‿𝕩}") F(select,"") F(slash,"/") F(join,"") F(take,"") F(drop,"") \
/*sfns.c*/ F(shape,"") F(pick,"") F(pair,"{𝕨‿𝕩}") F(select,"") F(slash,"/") F(join,"") F(shiftb,"»") F(take,"") F(drop,"") \
/*derv.c*/ F(fork,"(fork)") F(atop,"(atop)") F(md1d,"(derived 1-modifier)") F(md2d,"(derived 2-modifier)") \
/*sysfn.c*/ F(type,"•Type") F(decp,"•Decompose") F(primInd,"•PrimInd") F(glyph,"•Glyph") F(fill,"•FillFn") \
/*sysfn.c*/ F(grLen,"•GroupLen") F(grOrd,"•groupOrd") F(asrt,"!") F(sys,"•getsys") F(internal,"•Internal") F(show,"•Show") F(out,"•Out")
@ -216,7 +216,7 @@ bool equal(B w, B x); // doesn't consume
void arr_print(B x); // doesn't consume
u8 fillElType(B x); // doesn't consume
bool eqShape(B w, B x); // doesn't consume
usz arr_csz(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
@ -337,10 +337,11 @@ usz o2s (B x) { if (x.f!=(f64)(usz)x.f) thrM("Expected integer"); return (usz)
i64 o2i64 (B x) { if (x.f!=(f64)(i64)x.f) thrM("Expected integer"); return (i64)x.f; }
u64 o2u64 (B x) { if (x.f!=(f64)(u64)x.f) thrM("Expected integer"); return (u64)x.f; }
f64 o2f (B x) { if (!isNum(x)) thrM("Expected integer"); return x.f; }
i32 o2iu (B x) { return isI32(x)? (i32)(u32)x.u : (i32)x.f; }
u32 o2c (B x) { if (!isC32(x)) thrM("Expected character"); return (u32)x.u; }
i32 o2iu (B x) { return isI32(x)? (i32)(u32)x.u : (i32)x.f; }
i32 o2cu (B x) { return (u32)x.u; }
usz o2su (B x) { return (usz)x.f; }
i64 o2fu (B x) { return x.f; }
i64 o2i64u(B x) { return (i64)x.f; }
bool q_i32(B x) { return isI32(x) || isF64(x)&(x.f==(i32)x.f); }
bool q_f64(B x) { return isF64(x) || isI32(x); }

View File

@ -10,8 +10,9 @@
// #define USE_VALGRIND // whether to mark freed memory for valgrind
// #define DONT_FREE // don't actually ever free objects, such that they can be printed after being freed for debugging
// #define OBJ_COUNTER // store a unique allocation number with each object for easier analysis
// #define ALL_R0 // use all of r0.bqn for runtime_0
// #define ALL_R1 // use all of r1.bqn for runtime
#define FAKE_RUNTIME false // whether to disable the self-hosted runtime
// #define ALL_RUNTIME // don't use custom native runtime parts
// #define LOG_GC // log GC stats
// #define FORMATTER // use self-hosted formatter for output
@ -102,18 +103,18 @@ int main() {
// fake runtime
B fruntime[] = {
/* +-×÷⋆√⌊⌈|¬ */ bi_add , bi_sub , bi_mul , bi_div , bi_pow , bi_N , 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_N , bi_take , bi_drop , bi_ud , bi_N , bi_N,
/* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ bi_N , bi_N , bi_slash, bi_N , bi_N , bi_select, bi_pick , bi_N , bi_N , bi_N,
/* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_N , bi_N , bi_asrt , bi_const, bi_swap , bi_N , bi_each , bi_tbl , bi_N , bi_fold,
/* ˝`∘○⊸⟜⌾⊘◶⎉ */ bi_N , bi_scan , bi_atop , bi_over , bi_before, bi_after , bi_N , bi_val , bi_cond , bi_N,
/* +-×÷⋆√⌊⌈|¬ */ bi_add , bi_sub , bi_mul , bi_div , bi_pow , bi_N , 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_N , bi_take , bi_drop , bi_ud , bi_N , bi_shiftb,
/* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ bi_N , bi_N , bi_slash, bi_N , bi_N , bi_select, bi_pick , bi_N , bi_N , bi_N,
/* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_N , bi_N , bi_asrt , bi_const, bi_swap , bi_N , bi_each , bi_tbl , bi_N , bi_fold,
/* ˝`∘○⊸⟜⌾⊘◶⎉ */ bi_N , bi_scan , bi_atop , bi_over , bi_before, bi_after , bi_N , bi_val , bi_cond , bi_N,
/* ⚇⍟⎊ */ bi_N , bi_repeat, bi_catch
};
bool rtComplete[] = {
/* +-×÷⋆√⌊⌈|¬ */ 1,1,1,1,1,0,1,1,1,1,
/* ∧∨<>≠=≤≥≡≢ */ 1,1,1,1,1,1,1,1,1,1,
/* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,0,0,0,0,0,0,0,0,
/* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,0,1,0,0,0,0,0,1,
/* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ 0,0,1,0,0,1,0,0,0,0,
/* ⍷⊔!˙˜˘¨⌜⁼´ */ 0,0,1,1,1,0,1,1,0,1,
/* ˝`∘○⊸⟜⌾⊘◶⎉ */ 0,1,1,1,1,1,0,1,0,0,
@ -124,11 +125,25 @@ int main() {
B frtObj = m_caB(rtLen, fruntime);
B provide[] = {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};
B runtime_0[] = {bi_floor, bi_ceil, bi_stile, bi_lt, bi_gt, bi_ne, bi_ge, bi_rtack, bi_ltack, bi_join, bi_take, bi_drop, bi_select, bi_const, bi_swap, bi_each, bi_fold, bi_atop, bi_over, bi_before, bi_after, bi_cond, bi_repeat};
#ifndef ALL_R0
B runtime_0[] = {bi_floor,bi_ceil,bi_stile,bi_lt,bi_gt,bi_ne,bi_ge,bi_rtack,bi_ltack,bi_join,bi_take,bi_drop,bi_select,bi_const,bi_swap,bi_each,bi_fold,bi_atop,bi_over,bi_before,bi_after,bi_cond,bi_repeat};
#else
Block* runtime0_b = compile(
#include "runtime0"
);
B r0r = m_funBlock(runtime0_b, 0); ptr_dec(runtime0_b);
B* runtime_0 = toHArr(r0r)->a;
#endif
Block* runtime_b = compile(
#include "runtime1"
);
#ifdef ALL_R0
dec(r0r);
#endif
B rtRes = m_funBlock(runtime_b, 0); ptr_dec(runtime_b);
B rtObjRaw = TI(rtRes).get(rtRes,0);
B rtFinish = TI(rtRes).get(rtRes,1);
@ -144,9 +159,10 @@ int main() {
rt_undo = rtObjGet(rtObjRaw, 48); gc_add(rt_undo);
rt_select = rtObjGet(rtObjRaw, 35); gc_add(rt_select);
rt_slash = rtObjGet(rtObjRaw, 32); gc_add(rt_slash);
rt_join = rtObjGet(rtObjRaw, 23); gc_add(rt_join);
for (usz i = 0; i < runtimeLen; i++) {
#ifdef ALL_RUNTIME
#ifdef ALL_R1
B r = rtObjGet(rtObjRaw, i);
#else
B r = rtComplete[i]? inc(fruntime[i]) : rtObjGet(rtObjRaw, i);

View File

@ -1,7 +1,8 @@
#include "h.h"
B tbl_c1(B d, B x) { B f = c(Md1D,d)->f;
return eachm(f, x);
// return eachm(f, x);
return withFill(eachm(f, x), m_f64(0));
}
B tbl_c2(B d, B w, B x) { B f = c(Md1D,d)->f;
if (isAtm(w)) w = m_hunit(w);
@ -27,14 +28,17 @@ B tbl_c2(B d, B w, B x) { B f = c(Md1D,d)->f;
memcpy(rsh+wr, a(x)->sh, xr*sizeof(usz));
}
dec(w); dec(x);
return r.b;
// return r.b;
return withFill(r.b, m_f64(0));
}
B each_c1(B d, B x) { B f = c(Md1D,d)->f;
return eachm(f, x);
// return eachm(f, x);
return withFill(eachm(f, x), m_f64(0));
}
B each_c2(B d, B w, B x) { B f = c(Md1D,d)->f;
return eachd(f, w, x);
// return eachd(f, w, x);
return withFill(eachd(f, w, x), m_f64(0));
}
@ -63,7 +67,7 @@ B scan_c1(B d, B x) { B f = c(Md1D,d)->f;
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");
ur xr = rnk(x); usz* xsh = a(x)->sh; usz ia = a(x)->ia;
B wf = getFill(inc(w));
bool reuse = (v(x)->type==t_harr && reusable(x)) | !ia;
usz i = 0;
HArr_p r = reuse? harr_parts(x) : m_harrs(a(x)->ia, &i);
@ -84,7 +88,7 @@ B scan_c2(B d, B w, B x) { B f = c(Md1D,d)->f;
B pr = r.a[0] = c2(f, w, xget(x,0)); i++;
for (; i < ia; i++) r.a[i] = pr = c2(f, inc(pr), xget(x,i));
}
return reuse? x : harr_fcd(r, x);
return withFill(reuse? x : harr_fcd(r, x), wf);
}
B fold_c1(B d, B x) { B f = c(Md1D,d)->f;

View File

@ -27,17 +27,26 @@ void mut_to(Mut* m, u8 n) {
}
}
B mut_fv(Mut* m) {
assert(m->type!=el_MAX);
B mut_fv(Mut* m) { assert(m->type!=el_MAX);
m->val->sh = &m->val->ia;
B r = tag(m->val, ARR_TAG);
srnk(r, 1);
return r;
}
B mut_fp(Mut* m) {
assert(m->type!=el_MAX);
B mut_fp(Mut* m) { assert(m->type!=el_MAX);
return tag(m->val, ARR_TAG);
}
B mut_fc(Mut* m, B x) { assert(m->type!=el_MAX);
B r = tag(m->val, ARR_TAG);
arr_shCopy(r, x);
return r;
}
B mut_fcd(Mut* m, B x) { assert(m->type!=el_MAX);
B r = tag(m->val, ARR_TAG);
arr_shCopy(r, x);
dec(x);
return r;
}
u8 el_or(u8 a, u8 b) {
#define M(X) if(b==X) return b>X?b:X;
@ -57,6 +66,44 @@ void mut_pfree(Mut* m, usz n) { // free the first n elements
else mm_free((Value*) m->val);
}
// doesn't consume x; fills m[ms…ms+l] with x
void mut_fill(Mut* m, usz ms, B x, usz l) {
again:
#define AGAIN(T) { mut_to(m, T); goto again; }
switch(m->type) {
case el_MAX: AGAIN(isF64(x)? (q_i32(x)? el_i32 : el_f64) : (isC32(x)? el_c32 : el_B));
case el_i32: {
if (!q_i32(x)) AGAIN(isF64(x)? el_f64 : el_B);
i32* p = ((I32Arr*)m->val)->a+ms;
i32 v = o2iu(x);
for (usz i = 0; i < l; i++) p[i] = v;
return;
}
case el_c32: {
if (!isC32(x)) AGAIN(el_B);
u32* p = ((C32Arr*)m->val)->a+ms;
u32 v = o2cu(x);
for (usz i = 0; i < l; i++) p[i] = v;
return;
}
case el_f64: {
if (!isF64(x)) AGAIN(el_B);
f64* p = ((F64Arr*)m->val)->a+ms;
f64 v = o2fu(x);
for (usz i = 0; i < l; i++) p[i] = v;
return;
}
case el_B: {
B* p = ((HArr*)m->val)->a+ms;
for (usz i = 0; i < l; i++) p[i] = x;
if (isVal(x)) for (usz i = 0; i < l; i++) inc(x);
return;
}
}
#undef AGAIN
}
// expects x to be an array, each position must be written to precisely once
// doesn't consume x
void mut_copy(Mut* m, usz ms, B x, usz xs, usz l) {

View File

@ -365,24 +365,82 @@ B drop_c2(B t, B w, B x) {
i64 v = o2i64(w); usz ia = a(x)->ia;
return v<0? slicev(x, 0, v+ia) : slicev(x, v, ia-v);
}
B rt_join;
B join_c1(B t, B x) {
return c1(rt_join, x);
}
B join_c2(B t, B w, B x) {
if (!isArr(w)|!isArr(x) || rnk(w)!=1 | rnk(x)!=1) thrM("∾: NYI non-vector args");
usz wia = a(w)->ia;
usz xia = a(x)->ia;
B f = fill_both(w, x);
if (!isArr(w)) w = m_hunit(w); ur wr = rnk(w); usz wia = a(w)->ia; usz* wsh = a(w)->sh;
if (!isArr(x)) x = m_hunit(x); ur xr = rnk(x); usz xia = a(x)->ia; usz* xsh = a(x)->sh;
ur c = wr>xr?wr:xr;
if (c==0) {
HArr_p r = m_harrUv(2);
r.a[0] = TI(w).get(w,0); dec(w);
r.a[1] = TI(x).get(x,0); dec(x);
return r.b;
}
if (c-wr > 1 || c-xr > 1) thrM("∾: Argument ranks must differ by 1 or less");
MAKE_MUT(r, wia+xia);
mut_to(r, el_or(TI(w).elType, TI(x).elType));
mut_copy(r, 0, w, 0, wia);
mut_copy(r, wia, x, 0, xia);
dec(x); dec(w);
return mut_fv(r);
B rb = mut_fp(r);
usz* sh = arr_shAllocR(rb, c);
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"); }
sh[i] = s;
}
sh[0] = (wr==c? wsh[0] : 1) + (xr==c? xsh[0] : 1);
}
dec(w); dec(x);
return qWithFill(rb, f);
}
B shiftb_c1(B t, B x) {
if (!isArr(x) || rnk(x)==0) thrM("»: Argument cannot be a scalar");
usz ia = a(x)->ia;
if (ia==0) return x;
B xf = getFill(inc(x));
if (noFill(xf)) thrM("»: Argument didn't have a fill");
usz csz = arr_csz(x);
MAKE_MUT(r, ia);
mut_copy(r, csz, x, 0, ia-csz);
mut_fill(r, 0, xf, csz);
return qWithFill(mut_fcd(r, x), xf);
}
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");
}
B shiftb_c2(B t, B w, B x) {
// return c2(rt_shiftb, w, x);
if (!isArr(x) || rnk(x)==0) thrM("»: 𝕩 cannot be a scalar");
if (!isArr(w)) w = m_hunit(w); usz wia = a(w)->ia;
if (!isArr(x)) x = m_hunit(x); usz xia = a(x)->ia;
B f = fill_both(w, x);
shift_check(w, x);
MAKE_MUT(r, xia);
int mid = wia<xia? wia : xia;
mut_copy(r, 0 , w, 0, mid);
mut_copy(r, mid, x, 0, xia-mid);
dec(w);
return qWithFill(mut_fcd(r, x), f);
}
#define ba(N) bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); c(Fun,bi_##N)->c2 = N##_c2 ;c(Fun,bi_##N)->c1 = N##_c1 ; c(Fun,bi_##N)->extra=pf_##N; c(BFn,bi_##N)->ident=bi_N; gc_add(bi_##N);
#define bd(N) bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); c(Fun,bi_##N)->c2 = N##_c2 ;c(Fun,bi_##N)->c1 = c1_invalid; c(Fun,bi_##N)->extra=pf_##N; c(BFn,bi_##N)->ident=bi_N; gc_add(bi_##N);
#define bm(N) bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); c(Fun,bi_##N)->c2 = c2_invalid;c(Fun,bi_##N)->c1 = N##_c1 ; c(Fun,bi_##N)->extra=pf_##N; c(BFn,bi_##N)->ident=bi_N; gc_add(bi_##N);
B bi_shape, bi_pick, bi_pair, bi_select, bi_slash, bi_join, bi_take, bi_drop;
static inline void sfns_init() { ba(shape) ba(pick) ba(pair) ba(select) ba(slash) bd(join) bd(take) bd(drop)
B bi_shape, bi_pick, bi_pair, bi_select, bi_slash, bi_join, bi_shiftb, /*bi_shifta,*/ bi_take, bi_drop;
static inline void sfns_init() { ba(shape) ba(pick) ba(pair) ba(select) ba(slash) ba(join) ba(shiftb) /*ba(shifta)*/ bd(take) bd(drop)
}
#undef ba

View File

@ -34,7 +34,7 @@ B glyph_c1(B t, B x) {
B fill_c1(B t, B x) {
B f = getFill(x);
if (noFill(f)) return m_f64(0); // thrM("No fill found");
if (noFill(f)) thrM("No fill found");
return f;
}
B fill_c2(B t, B w, B x) { // TODO not set fill for typed arrays

View File

@ -332,8 +332,9 @@ B evalBC(Body* b, Scope* sc) { // doesn't consume
case ARRO: case ARRM: {
i32 sz = *bc++;
HArr_p r = m_harrUv(sz);
for (i32 i = 0; i < sz; i++) r.a[sz-i-1] = POP;
ADD(r.b);
bool allNum = true;
for (i32 i = 0; i < sz; i++) if (!isNum(r.a[sz-i-1] = POP)) allNum = false;
ADD(allNum && sz? withFill(r.b, m_f64(0)) : r.b);
break;
}
case DFND: {