uCBQN/src/core/fillarr.c
2021-07-03 00:27:20 +03:00

205 lines
6.0 KiB
C

#include "../core.h"
B asFill(B x) { // consumes
if (isArr(x)) {
u8 xe = TI(x).elType;
usz ia = a(x)->ia;
if (xe<=el_f64) {
i32* rp; B r = m_i32arrc(&rp, x);
for (usz i = 0; i < ia; i++) rp[i] = 0;
dec(x);
return r;
}
if (xe==el_c32) {
u32* rp; B r = m_c32arrc(&rp, x);
for (usz i = 0; i < ia; i++) rp[i] = ' ';
dec(x);
return r;
}
HArr_p r = m_harrUc(x);
BS2B xget = TI(x).get;
bool noFill = false;
for (usz i = 0; i < ia; i++) if ((r.a[i]=asFill(xget(x,i))).u == bi_noFill.u) noFill = true;
B xf = getFillQ(x);
dec(x);
if (noFill) { ptr_dec(r.c); return bi_noFill; }
return withFill(r.b, xf);
}
if (isF64(x)|isI32(x)) return m_i32(0);
if (isC32(x)) return m_c32(' ');
dec(x);
return bi_noFill;
}
static B fillarr_slice (B x, usz s) {return m_fillslice(x , c(FillArr ,x)->a+s); }
static B fillslice_slice(B x, usz s) { B r = m_fillslice(inc(c(Slice,x)->p), c(FillSlice,x)->a+s); dec(x); return r; }
static B fillarr_get (B x, usz n) { VTY(x,t_fillarr ); return inc(c(FillArr ,x)->a[n]); }
static B fillslice_get (B x, usz n) { VTY(x,t_fillslice); return inc(c(FillSlice,x)->a[n]); }
static B fillarr_getU (B x, usz n) { VTY(x,t_fillarr ); return c(FillArr ,x)->a[n] ; }
static B fillslice_getU(B x, usz n) { VTY(x,t_fillslice); return c(FillSlice,x)->a[n] ; }
static void fillarr_free(Value* x) {
decSh(x);
B* p = ((FillArr*)x)->a;
dec(((FillArr*)x)->fill);
usz ia = ((Arr*)x)->ia;
for (usz i = 0; i < ia; i++) dec(p[i]);
}
static void fillarr_visit(Value* x) { assert(x->type == t_fillarr);
usz ia = ((Arr*)x)->ia; B* p = ((FillArr*)x)->a;
mm_visit(((FillArr*)x)->fill);
for (usz i = 0; i < ia; i++) mm_visit(p[i]);
}
static bool fillarr_canStore(B x) { return true; }
void fillarr_init() {
ti[t_fillarr].get = fillarr_get; ti[t_fillslice].get = fillslice_get;
ti[t_fillarr].getU = fillarr_getU; ti[t_fillslice].getU = fillslice_getU;
ti[t_fillarr].slice = fillarr_slice; ti[t_fillslice].slice = fillslice_slice;
ti[t_fillarr].free = fillarr_free; ti[t_fillslice].free = slice_free;
ti[t_fillarr].visit = fillarr_visit; ti[t_fillslice].visit = slice_visit;
ti[t_fillarr].print = arr_print; ti[t_fillslice].print = arr_print;
ti[t_fillarr].isArr = true; ti[t_fillslice].isArr = true;
ti[t_fillarr].canStore = fillarr_canStore;
}
void validateFill(B x) {
if (isArr(x)) {
BS2B xgetU = TI(x).getU;
usz ia = a(x)->ia;
for (usz i = 0; i < ia; i++) validateFill(xgetU(x,i));
} else if (isF64(x)) {
assert(x.f==0);
} else if (isC32(x)) {
assert(' '==(u32)x.u);
}
}
NOINLINE bool fillEqualR(B w, B x) { // doesn't consume; both args must be arrays
if (!eqShape(w, x)) return false;
usz ia = a(w)->ia;
if (ia==0) return true;
u8 we = TI(w).elType;
u8 xe = TI(x).elType;
if (we!=el_B && xe!=el_B) {
if (we==el_c32 ^ xe==el_c32) return false;
assert(we==el_c32 & xe==el_c32 || we<=el_f64 & xe<=el_f64);
return true;
}
BS2B xgetU = TI(x).getU;
BS2B wgetU = TI(w).getU;
for (usz i = 0; i < ia; i++) if(!fillEqual(wgetU(w,i),xgetU(x,i))) return false;
return true;
}
B withFill(B x, B fill) { // consumes both
assert(isArr(x));
#ifdef DEBUG
validateFill(fill);
#endif
u8 xt = v(x)->type;
if (noFill(fill) && xt!=t_fillarr && xt!=t_fillslice) return x;
switch(xt) {
case t_f64arr : case t_f64slice:
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_fillslice: if (fillEqual(c(FillArr,c(Slice,x)->p)->fill, fill)) { dec(fill); return x; } break;
case t_fillarr: if (fillEqual(c(FillArr,x)->fill, fill)) { dec(fill); return x; }
if (reusable(x)) {
dec(c(FillArr, x)->fill);
c(FillArr, x)->fill = fill;
return x;
}
break;
}
usz ia = a(x)->ia;
if (isNum(fill)) {
if (xt==t_harr) {
B* xp = harr_ptr(x);
{
i32* rp; B r = m_i32arrc(&rp, x);
for (usz i = 0; i < ia; i++) {
B c = xp[i];
if (!q_i32(c)) { dec(r); goto h_f64; }
rp[i] = o2iu(c);
}
dec(x);
return r;
}
h_f64: {
f64* rp; B r = m_f64arrc(&rp, x);
for (usz i = 0; i < ia; i++) {
B c = xp[i];
if (!q_f64(c)) { dec(r); goto base; }
rp[i] = o2fu(c);
}
dec(x);
return r;
}
} else {
BS2B xgetU = TI(x).getU;
{
i32* rp; B r = m_i32arrc(&rp, x);
for (usz i = 0; i < ia; i++) {
B c = xgetU(x, i);
if (!q_i32(c)) { dec(r); goto g_f64; }
rp[i] = o2iu(c);
}
dec(x);
return r;
}
g_f64: {
f64* rp; B r = m_f64arrc(&rp, x);
for (usz i = 0; i < ia; i++) {
B c = xgetU(x, i);
if (!q_f64(c)) { dec(r); goto base; }
rp[i] = o2fu(c);
}
dec(x);
return r;
}
// bool ints = true;
// for (usz i = 0; i < ia; i++) {
// B c = xgetU(x, i);
// if (!isNum(c)) goto base;
// if (!q_i32(c)) ints = false;
// }
// if (ints) {
// B r = m_i32arrc(x); i32* rp = i32arr_ptr(r);
// for (usz i = 0; i < ia; i++) rp[i] = o2iu(xgetU(x, i));
// dec(x);
// return r;
// } else {
// B r = m_f64arrc(x); f64* rp = f64arr_ptr(r);
// for (usz i = 0; i < ia; i++) rp[i] = o2fu(xgetU(x, i));
// dec(x);
// return r;
// }
}
} else if (isC32(fill)) {
u32* rp; B r = m_c32arrc(&rp, x);
BS2B xgetU = TI(x).getU;
for (usz i = 0; i < ia; i++) {
B c = xgetU(x, i);
if (!isC32(c)) { dec(r); goto base; }
rp[i] = o2c(c);
}
dec(x);
return r;
}
base:;
FillArr* r = mm_alloc(fsizeof(FillArr,a,B,ia), t_fillarr);
arrP_shCopy((Arr*)r, x);
r->fill = fill;
B* a = r->a;
BS2B xget = TI(x).get;
for (usz i = 0; i < ia; i++) a[i] = xget(x,i);
dec(x);
return tag(r, ARR_TAG);
}