native ⌾(a⊸/) and ⌾⊑

This commit is contained in:
dzaima 2021-05-16 18:16:09 +03:00
parent 1bdb0b1968
commit 45207372f6
9 changed files with 192 additions and 22 deletions

View File

@ -71,11 +71,18 @@ B m1_d(B m, B f ) { if(isMd1(m)) return TI(m).m1_d(m, f ); thrM("Interpret
B m2_d(B m, B f, B g) { if(isMd2(m)) return TI(m).m2_d(m, f, g); thrM("Interpreting non-2-modifier as 2-modifier"); } B m2_d(B m, B f, B g) { if(isMd2(m)) return TI(m).m2_d(m, f, g); thrM("Interpreting non-2-modifier as 2-modifier"); }
B m2_h(B m, B g) { return m_md2H(m, g); } B m2_h(B m, B g) { return m_md2H(m, g); }
B md2D_uc1(B t, B o, B x) {
B m = c(Md2D, t)->m2;
B f = c(Md2D, t)->f;
B g = c(Md2D, t)->g;
if (v(t)->flags || !isMd2(m)) return def_fn_uc1(t, o, x); // flags check to not deconstruct builtins
return TI(m).m2_uc1(m, o, f, g, x);
}
static inline void derv_init() { static inline void derv_init() {
ti[t_md1D].free = md1D_free; ti[t_md1D].visit = md1D_visit; ti[t_md1D].print = md1D_print; ti[t_md1D].decompose = md1D_decompose; ti[t_md1D].free = md1D_free; ti[t_md1D].visit = md1D_visit; ti[t_md1D].print = md1D_print; ti[t_md1D].decompose = md1D_decompose;
ti[t_md2D].free = md2D_free; ti[t_md2D].visit = md2D_visit; ti[t_md2D].print = md2D_print; ti[t_md2D].decompose = md2D_decompose; ti[t_md2D].free = md2D_free; ti[t_md2D].visit = md2D_visit; ti[t_md2D].print = md2D_print; ti[t_md2D].decompose = md2D_decompose; ti[t_md2D].fn_uc1 = md2D_uc1;
ti[t_md2H].free = md2H_free; ti[t_md2H].visit = md2H_visit; ti[t_md2H].print = md2H_print; ti[t_md2H].decompose = md2H_decompose; ti[t_md2H].free = md2H_free; ti[t_md2H].visit = md2H_visit; ti[t_md2H].print = md2H_print; ti[t_md2H].decompose = md2H_decompose;
ti[t_fork].free = fork_free; ti[t_fork].visit = fork_visit; ti[t_fork].print = fork_print; ti[t_fork].decompose = fork_decompose; ti[t_fork].free = fork_free; ti[t_fork].visit = fork_visit; ti[t_fork].print = fork_print; ti[t_fork].decompose = fork_decompose;
ti[t_atop].free = atop_free; ti[t_atop].visit = atop_visit; ti[t_atop].print = atop_print; ti[t_atop].decompose = atop_decompose; ti[t_atop].free = atop_free; ti[t_atop].visit = atop_visit; ti[t_atop].print = atop_print; ti[t_atop].decompose = atop_decompose;

View File

@ -3,9 +3,13 @@
typedef struct BFn { typedef struct BFn {
struct Fun; struct Fun;
B ident; B ident;
BBB2B uc1;
BBBB2B ucw;
} BFn; } BFn;
void print_funBI(B x) { printf("%s", format_pf(c(Fun,x)->extra)); } void print_funBI(B x) { printf("%s", format_pf(c(Fun,x)->extra)); }
B funBI_uc1(B t, B o, B x) { return c(BFn,t)->uc1(t, o, x); }
B funBI_ucw(B t, B o, B w, B x) { return c(BFn,t)->ucw(t, o, w, x); }
B funBI_identity(B x) { return inc(c(BFn,x)->ident); } B funBI_identity(B x) { return inc(c(BFn,x)->ident); }
@ -165,9 +169,9 @@ B fne_c2(B t, B w, B x) {
} }
#define BI_A(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; gc_add(t); } #define BI_A(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); }
#define BI_D(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=c1_invalid; f->extra=pf_##N; f->ident=bi_N; gc_add(t); } #define BI_D(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=N##_c2 ; f->c1=c1_invalid; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); }
#define BI_M(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=c2_invalid; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; gc_add(t); } #define BI_M(N) { B t=bi_##N = mm_alloc(sizeof(BFn), t_funBI, ftag(FUN_TAG)); BFn*f=c(BFn,t); f->c2=c2_invalid; f->c1=N##_c1 ; f->extra=pf_##N; f->ident=bi_N; f->uc1=def_fn_uc1; f->ucw=def_fn_ucw; gc_add(t); }
#define BI_VAR(N) B bi_##N; #define BI_VAR(N) B bi_##N;
#define BI_FNS0(F) F(BI_VAR,BI_VAR,BI_VAR) #define BI_FNS0(F) F(BI_VAR,BI_VAR,BI_VAR)
#define BI_FNS1(F) F(BI_A,BI_M,BI_D) #define BI_FNS1(F) F(BI_A,BI_M,BI_D)
@ -178,5 +182,7 @@ BI_FNS0(F);
static inline void fns_init() { BI_FNS1(F) static inline void fns_init() { BI_FNS1(F)
ti[t_funBI].print = print_funBI; ti[t_funBI].print = print_funBI;
ti[t_funBI].identity = funBI_identity; ti[t_funBI].identity = funBI_identity;
ti[t_funBI].fn_uc1 = funBI_uc1;
ti[t_funBI].fn_ucw = funBI_ucw;
} }
#undef F #undef F

25
src/h.h
View File

@ -156,13 +156,13 @@ char* format_pm1(u8 u) {
} }
enum PrimMd2 { enum PrimMd2 {
pm2_none, pm2_none,
pm2_val, pm2_atop, pm2_over, pm2_before, pm2_after, pm2_cond, pm2_repeat, pm2_fillBy, pm2_catch, // md2.c pm2_val, pm2_atop, pm2_over, pm2_before, pm2_after, pm2_cond, pm2_repeat, pm2_fillBy, pm2_catch, pm2_under, // md2.c
}; };
char* format_pm2(u8 u) { char* format_pm2(u8 u) {
switch(u) { switch(u) {
default: case pf_none: return"(unknown 1-modifier)"; default: case pf_none: return"(unknown 1-modifier)";
case pm2_val:return""; case pm2_repeat:return""; case pm2_fillBy:return"•_fillBy_"; case pm2_catch:return""; case pm2_val:return""; case pm2_repeat:return""; case pm2_fillBy:return"•_fillBy_"; case pm2_catch:return"";
case pm2_atop:return""; case pm2_over:return""; case pm2_before:return""; case pm2_after:return""; case pm2_cond:return""; case pm2_atop:return""; case pm2_over:return""; case pm2_before:return""; case pm2_after:return""; case pm2_cond:return""; case pm2_under:return"";
} }
} }
@ -411,11 +411,12 @@ B* harr_ptr(B x);
typedef void (*B2v)(B); typedef void (*B2v)(B);
typedef B (* BS2B)(B, usz); typedef B (* BS2B)(B, usz);
typedef B (*BSS2B)(B, usz, usz); typedef B (*BSS2B)(B, usz, usz);
typedef B (* B2B)(B); typedef B (* B2B)(B);
typedef B (* BB2B)(B, B); typedef B (* BB2B)(B, B);
typedef B (* BBB2B)(B, B, B); typedef B (* BBB2B)(B, B, B);
typedef B (* BBBB2B)(B, B, B, B); typedef B (* BBBB2B)(B, B, B, B);
typedef B (*BBBBB2B)(B, B, B, B, B); typedef B (* BBBBB2B)(B, B, B, B, B);
typedef B (*BBBBBB2B)(B, B, B, B, B, B);
typedef bool (*B2b)(B); typedef bool (*B2b)(B);
typedef struct TypeInfo { typedef struct TypeInfo {
@ -427,6 +428,13 @@ typedef struct TypeInfo {
BS2B slice; // consumes; create slice from given starting position; add ia, rank, shape yourself; may not actually be a Slice object BS2B slice; // consumes; create slice from given starting position; add ia, rank, shape yourself; may not actually be a Slice object
B2B identity; // return identity element of this function; doesn't consume B2B identity; // return identity element of this function; doesn't consume
BBB2B fn_uc1; // t,o, x→r; r≡O⌾( T ) x; consumes x
BBBB2B fn_ucw; // t,o, w,x→r; r≡O⌾(w⊸ T ) x; consumes w,x
BBBB2B m1_uc1; // t,o,f, x→r; r≡O⌾( F _T ) x; consumes x
BBBBB2B m1_ucw; // t,o,f, w,x→r; r≡O⌾(w⊸(F _T )) x; consumes w,x
BBBBB2B m2_uc1; // t,o,f,g, x→r; r≡O⌾( F _T_ G ) x; consumes x
BBBBBB2B m2_ucw; // t,o,f,g,w,x→r; r≡O⌾(w⊸(F _T_ G)) x; consumes w,x
B2b canStore; // doesn't consume B2b canStore; // doesn't consume
u8 elType; u8 elType;
@ -496,6 +504,9 @@ B c2(B f, B w, B x) { // BQN-call f dyadically; consumes w,x
if (isFun(f)) return VALIDATE(c(Fun,f)->c2(f, w, x)); if (isFun(f)) return VALIDATE(c(Fun,f)->c2(f, w, x));
return c2_rare(f, w, x); return c2_rare(f, w, x);
} }
B m1_d(B m, B f );
B m2_d(B m, B f, B g);
B m2_h(B m, B g);
typedef struct Md1 { typedef struct Md1 {

View File

@ -64,7 +64,7 @@ static inline void load_init() {
/* ⊣⊢⥊∾≍↑↓↕«» */ 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_N , bi_N , bi_slash, bi_gradeUp, bi_N , bi_select, bi_pick , bi_N , bi_N , bi_N, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ bi_N , bi_N , bi_slash, bi_gradeUp, bi_N , bi_select, bi_pick , bi_N , bi_N , bi_N,
/* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_N , bi_group , bi_asrt , bi_const , bi_swap , bi_N , bi_each , bi_tbl , bi_N , bi_fold, /* ⍷⊔!˙˜˘¨⌜⁼´ */ bi_N , bi_group , 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_scan , bi_atop , bi_over , bi_before, bi_after , bi_under, bi_val , bi_cond , bi_N,
/* ⚇⍟⎊ */ bi_N , bi_repeat, bi_catch /* ⚇⍟⎊ */ bi_N , bi_repeat, bi_catch
}; };
bool rtComplete[] = { bool rtComplete[] = {
@ -73,7 +73,7 @@ static inline void load_init() {
/* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,0,1,1,1,1,1,1,1, /* ⊣⊢⥊∾≍↑↓↕«» */ 1,1,0,1,1,1,1,1,1,1,
/* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ 0,0,1,1,0,1,1,0,0,0, /* ⌽⍉/⍋⍒⊏⊑⊐⊒∊ */ 0,0,1,1,0,1,1,0,0,0,
/* ⍷⊔!˙˜˘¨⌜⁼´ */ 0,1,1,1,1,0,1,1,0,1, /* ⍷⊔!˙˜˘¨⌜⁼´ */ 0,1,1,1,1,0,1,1,0,1,
/* ˝`∘○⊸⟜⌾⊘◶⎉ */ 0,1,1,1,1,1,0,1,0,0, /* ˝`∘○⊸⟜⌾⊘◶⎉ */ 0,1,1,1,1,1,1,1,0,0,
/* ⚇⍟⎊ */ 0,1,1 /* ⚇⍟⎊ */ 0,1,1
}; };
assert(sizeof(fruntime)/sizeof(B) == rtLen); assert(sizeof(fruntime)/sizeof(B) == rtLen);
@ -122,6 +122,7 @@ static inline void load_init() {
rt_take = rtObjGet(rtObjRaw, 25); gc_add(rt_take); rt_take = rtObjGet(rtObjRaw, 25); gc_add(rt_take);
rt_drop = rtObjGet(rtObjRaw, 26); gc_add(rt_drop); rt_drop = rtObjGet(rtObjRaw, 26); gc_add(rt_drop);
rt_group = rtObjGet(rtObjRaw, 41); gc_add(rt_group); rt_group = rtObjGet(rtObjRaw, 41); gc_add(rt_group);
rt_under = rtObjGet(rtObjRaw, 56); gc_add(rt_under);
for (usz i = 0; i < runtimeLen; i++) { for (usz i = 0; i < runtimeLen; i++) {
#ifdef ALL_R1 #ifdef ALL_R1

View File

@ -13,8 +13,9 @@
// #define OBJ_COUNTER // store a unique allocation number with each object for easier analysis // #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_R0 // use all of r0.bqn for runtime_0
// #define ALL_R1 // use all of r1.bqn for runtime // #define ALL_R1 // use all of r1.bqn for runtime
// #define RT_SRC // whether ./genRuntimeSrc was used to generate precompiled sources
#define VM_POS false // whether to store detailed execution position information for stacktraces #define VM_POS false // whether to store detailed execution position information for stacktraces
#define CHECK_VALID true // whether to check for valid arguments in places where that would be detrimental to performance (e.g. left argument sortedness of ⍋/⍒) #define CHECK_VALID true // whether to check for valid arguments in places where that would be detrimental to performance (e.g. left argument sortedness of ⍋/⍒, incompatible changes in ⌾, etc)
#define EACH_FILLS false // whether to try to squeeze out fills for ¨ and ⌜ #define EACH_FILLS false // whether to try to squeeze out fills for ¨ and ⌜
#define SFNS_FILLS true // whether to insert fills for structural functions (∾, ≍, etc) #define SFNS_FILLS true // whether to insert fills for structural functions (∾, ≍, etc)
#define FAKE_RUNTIME false // whether to disable the self-hosted runtime #define FAKE_RUNTIME false // whether to disable the self-hosted runtime

View File

@ -1,5 +1,14 @@
#include "h.h" #include "h.h"
typedef struct BMd2 {
struct Md1;
BBBBB2B uc1;
BBBBBB2B ucw;
} BMd2;
void print_md2BI(B x) { printf("%s", format_pm2(c(Md1,x)->extra)); }
B md2BI_uc1(B t, B o, B f, B g, B x) { return c(BMd2,t)->uc1(t, o, f, g, x); }
B md2BI_ucw(B t, B o, B f, B g, B w, B x) { return c(BMd2,t)->ucw(t, o, f, g, w, x); }
B val_c1(B d, B x) { return c1(c(Md2D,d)->f, x); } B val_c1(B d, B x) { return c1(c(Md2D,d)->f, x); }
@ -118,15 +127,46 @@ B cond_c2(B d, B w, B x) { B g=c(Md2D,d)->g;
return c2(TI(g).getU(g, fr), w, x); return c2(TI(g).getU(g, fr), w, x);
} }
#define ba(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2BI, 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); B rt_under, bi_before;
#define bd(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2BI, 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); B under_c1(B d, B x) { B f=c(Md2D,d)->f; B g=c(Md2D,d)->g;
#define bm(NAME) bi_##NAME = mm_alloc(sizeof(Md2), t_md2BI, ftag(MD2_TAG)); c(Md2,bi_##NAME)->c2 = c2_invalid;c(Md2,bi_##NAME)->c1 = NAME##_c1; c(Md1,bi_##NAME)->extra=pm2_##NAME; gc_add(bi_##NAME); if (!isVal(g)) { // ugh idk
B fn = m2_d(inc(rt_under), inc(f), inc(g));
B r = c1(fn, x);
dec(fn);
return r;
}
return TI(g).fn_uc1(g, f, x);
}
B under_c2(B d, B w, B x) { B f=c(Md2D,d)->f; B g=c(Md2D,d)->g;
if (!isVal(g)) {
B fn = m2_d(inc(rt_under), inc(f), inc(g));
B r = c2(fn, w, x);
dec(fn);
return r;
}
B f2 = m2_d(inc(bi_before), c1(g, w), inc(f));
B r = TI(g).fn_uc1(g, f2, x);
dec(f2);
return r;
}
void print_md2BI(B x) { printf("%s", format_pm2(c(Md1,x)->extra)); } B before_uc1(B t, B o, B f, B g, B x) {
if (!isFun(g)) return def_m2_uc1(t, o, f, g, x);
return TI(g).fn_ucw(g, o, inc(f), x);
}
B bi_val, bi_repeat, bi_atop, bi_over, bi_before, bi_after, bi_cond, bi_fillBy, bi_catch;
static inline void md2_init() { ba(val) ba(repeat) ba(atop) ba(over) ba(before) ba(after) ba(cond) ba(fillBy) ba(catch) #define ba(N) { B t=bi_##N=mm_alloc(sizeof(BMd2), t_md2BI, ftag(MD2_TAG)); BMd2*m=c(BMd2,t); m->c2 = N##_c2 ; m->c1 = N##_c1; m->extra=pm2_##N; m->uc1=def_m2_uc1; m->ucw=def_m2_ucw; gc_add(t); }
#define bd(N) { B t=bi_##N=mm_alloc(sizeof(BMd2), t_md2BI, ftag(MD2_TAG)); BMd2*m=c(BMd2,t); m->c2 = N##_c2 ; m->c1 = c1_invalid; m->extra=pm2_##N; m->uc1=def_m2_uc1; m->ucw=def_m2_ucw; gc_add(t); }
#define bm(N) { B t=bi_##N=mm_alloc(sizeof(BMd2), t_md2BI, ftag(MD2_TAG)); BMd2*m=c(BMd2,t); m->c2 = c2_invalid; m->c1 = N##_c1; m->extra=pm2_##N; m->uc1=def_m2_uc1; m->ucw=def_m2_ucw; gc_add(t); }
B bi_val, bi_repeat, bi_atop, bi_over, bi_before, bi_after, bi_cond, bi_fillBy, bi_under, bi_catch;
static inline void md2_init() { ba(val) ba(repeat) ba(atop) ba(over) ba(before) ba(after) ba(cond) ba(fillBy) ba(under) ba(catch)
ti[t_md2BI].print = print_md2BI; ti[t_md2BI].print = print_md2BI;
ti[t_md2BI].m2_uc1 = md2BI_uc1;
ti[t_md2BI].m2_ucw = md2BI_ucw;
c(BMd2,bi_before)->uc1 = before_uc1;
} }
#undef ba #undef ba

View File

@ -78,11 +78,40 @@ u8 el_or(u8 a, u8 b) {
#undef M #undef M
} }
void mut_pfree(Mut* m, usz n) { // free the first n elements void mut_pfree(Mut* m, usz n) { // free the first n-1 elements
if (m->type==el_B) harr_pfree(tag(m->val,ARR_TAG), n); if (m->type==el_B) harr_pfree(tag(m->val,ARR_TAG), n);
else mm_free((Value*) m->val); else mm_free((Value*) m->val);
} }
void mut_set(Mut* m, usz ms, B x) { // consumes; sets m[ms] to x
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);
m->ai32[ms] = o2iu(x);
return;
}
case el_c32: {
if (!isC32(x)) AGAIN(el_B);
m->ac32[ms] = o2cu(x);
return;
}
case el_f64: {
if (!isF64(x)) AGAIN(el_B);
m->af64[ms] = o2fu(x);
return;
}
case el_B: {
m->aB[ms] = x;
return;
}
}
#undef AGAIN
}
// doesn't consume; fills m[ms…ms+l] with x // doesn't consume; fills m[ms…ms+l] with x
void mut_fill(Mut* m, usz ms, B x, usz l) { void mut_fill(Mut* m, usz ms, B x, usz l) {
again: again:

View File

@ -736,8 +736,49 @@ B group_c2(B t, B w, B x) {
return c2(rt_group, w, x); return c2(rt_group, w, x);
} }
B pick_uc1(B t, B o, B x) {
if (isAtm(x) || a(x)->ia==0) return def_fn_uc1(t, o, x);
usz ia = a(x)->ia;
B x0 = TI(x).get(x, 0);
B item = c1(o, x0);
MAKE_MUT(r, ia); mut_to(r, el_or(TI(x).elType, selfElType(item)));
mut_set(r, 0, item);
mut_copy(r, 1, x, 1, ia-1);
return mut_fcd(r, x);
}
B slash_ucw(B t, B o, B w, B x) {
if (isAtm(w) || rnk(w)!=1 || rnk(x)!=1 || a(w)->ia!=a(x)->ia) return def_fn_ucw(t, o, w, x);
usz ia = a(x)->ia;
BS2B wgetU = TI(w).getU;
for (usz i = 0; i < ia; i++) { B cw=wgetU(w,i); if (!q_i32(cw)) return def_fn_ucw(t, o, w, x); }
B arg = slash_c2(t, inc(w), inc(x));
usz argIA = a(arg)->ia;
B rep = c1(o, arg);
if (isAtm(rep) || rnk(rep)!=1 || a(rep)->ia != argIA) thrM("𝔽⌾(a⊸/)𝕩: Result of 𝔽 must have the same shape as a/𝕩");
MAKE_MUT(r, ia); mut_to(r, el_or(TI(x).elType, TI(rep).elType));
BS2B xget = TI(x).get;
BS2B rgetU = TI(rep).getU;
BS2B rget = TI(rep).get;
usz repI = 0;
for (usz i = 0; i < ia; i++) {
i32 cw = o2iu(wgetU(w, i));
if (cw) {
B cr = rget(rep,repI);
if (CHECK_VALID) for (i32 j = 1; j < cw; j++) if (!equal(rgetU(rep,repI+j), cr)) { mut_pfree(r,i); thrM("𝔽⌾(a⊸/): Incompatible result elements"); }
mut_set(r, i, cr);
repI+= cw;
} else mut_set(r, i, xget(x,i));
}
dec(w); dec(rep);
return mut_fcd(r, x);
}
#define F(A,M,D) A(shape) A(pick) A(pair) A(select) A(slash) A(join) A(couple) A(shiftb) A(shifta) A(take) A(drop) A(group) #define F(A,M,D) A(shape) A(pick) A(pair) A(select) A(slash) A(join) A(couple) A(shiftb) A(shifta) A(take) A(drop) A(group)
BI_FNS0(F); BI_FNS0(F);
static inline void sfns_init() { BI_FNS1(F) } static inline void sfns_init() { BI_FNS1(F)
c(BFn,bi_pick)->uc1 = pick_uc1;
c(BFn,bi_slash)->ucw = slash_ucw;
}
#undef F #undef F

View File

@ -29,6 +29,29 @@ B def_m2_d(B m, B f, B g) { thrM("cannot derive this"); }
B def_slice(B x, usz s) { thrM("cannot slice non-array!"); } B def_slice(B x, usz s) { thrM("cannot slice non-array!"); }
bool def_canStore(B x) { return false; } bool def_canStore(B x) { return false; }
B rt_under, bi_before;
B rtUnder_c1(B f, B g, B x) { // consumes x
B fn = m2_d(inc(rt_under), inc(f), inc(g));
B r = c1(fn, x);
dec(fn);
return r;
}
B rtUnder_cw(B f, B g, B w, B x) { // consumes w,x
B fn = m2_d(inc(rt_under), inc(f), m2_d(inc(bi_before), w, inc(g)));
B r = c1(fn, x);
dec(fn);
return r;
}
B bi_before;
B def_fn_uc1(B t, B o, B x) { return rtUnder_c1(o, t, x); }
B def_fn_ucw(B t, B o, B w, B x) { return rtUnder_cw(o, t, w, x); }
B def_m1_uc1(B t, B o, B f, B x) { B t2 = m1_d(inc(t),inc(f) ); B r = rtUnder_c1(o, t2, x); dec(t2); return r; }
B def_m1_ucw(B t, B o, B f, B w, B x) { B t2 = m1_d(inc(t),inc(f) ); B r = rtUnder_cw(o, t2, w, x); dec(t2); return r; }
B def_m2_uc1(B t, B o, B f, B g, B x) { B t2 = m2_d(inc(t),inc(f),inc(g)); B r = rtUnder_c1(o, t2, x); dec(t2); return r; }
B def_m2_ucw(B t, B o, B f, B g, B w, B x) { B t2 = m2_d(inc(t),inc(f),inc(g)); B r = rtUnder_cw(o, t2, w, x); dec(t2); return r; }
void arr_print(B x) { // should accept refc=0 arguments for debugging purposes void arr_print(B x) { // should accept refc=0 arguments for debugging purposes
ur r = rnk(x); ur r = rnk(x);
@ -208,6 +231,11 @@ u8 fillElType(B x) {
if (isC32(x)) return el_c32; if (isC32(x)) return el_c32;
return el_B; return el_B;
} }
u8 selfElType(B x) {
if (isF64(x)) return q_i32(x)? el_i32 : el_f64;
if (isC32(x)) return el_c32;
return el_B;
}
@ -261,6 +289,12 @@ static inline void hdr_init() {
ti[i].decompose = def_decompose; ti[i].decompose = def_decompose;
ti[i].slice = def_slice; ti[i].slice = def_slice;
ti[i].canStore = def_canStore; ti[i].canStore = def_canStore;
ti[i].fn_uc1 = def_fn_uc1;
ti[i].fn_ucw = def_fn_ucw;
ti[i].m1_uc1 = def_m1_uc1;
ti[i].m1_ucw = def_m1_ucw;
ti[i].m2_uc1 = def_m2_uc1;
ti[i].m2_ucw = def_m2_ucw;
} }
ti[t_empty].free = empty_free; ti[t_empty].free = empty_free;
ti[t_freed].free = def_free; ti[t_freed].free = def_free;