u3: refactors "retreat" block of u3a_take in to do/while loop

This commit is contained in:
Joe Bryan 2020-09-14 16:03:13 -07:00
parent c591eb220d
commit fae8980660

View File

@ -1094,25 +1094,11 @@ _ca_take_cell(u3a_cell* old_u, u3_noun hed, u3_noun tel)
return new;
}
#define TAKE_ROOT 0
#define TAKE_HEAD 1
#define TAKE_TAIL 2
// stack frame for recording head vs tail iteration
//
// In Hoon, this structure would be as follows:
//
// $% [%root ~]
// [%head old=^]
// [%tail old=^ hed=*]
// ==
//
typedef struct takeframe
typedef struct _ca_take
{
c3_y tag_y;
u3_cell old;
u3_weak hed;
} takeframe;
u3_weak hed; // taken head
u3_cell old; // old cell
} _ca_take;
static inline u3_noun
_ca_take_next(u3a_pile* pil_u, u3_noun veb)
@ -1176,12 +1162,11 @@ _ca_take_next(u3a_pile* pil_u, u3_noun veb)
u3a_cell* old_u = (u3a_cell*)veb_u;
{
takeframe* fam_u = u3a_push(pil_u);
_ca_take* fam_u = u3a_push(pil_u);
u3a_pile_sane(pil_u);
fam_u->tag_y = TAKE_HEAD;
fam_u->old = veb;
fam_u->hed = u3_none;
fam_u->hed = u3_none;
fam_u->old = veb;
}
veb = old_u->hed;
@ -1196,78 +1181,45 @@ _ca_take_next(u3a_pile* pil_u, u3_noun veb)
u3_noun
u3a_take(u3_noun veb)
{
u3a_pile pil_u;
u3_noun pro;
c3_o nor_o = u3a_is_north(u3R);
u3a_pile pil_u;
_ca_take* fam_u;
u3_noun pro;
c3_o nor_o = u3a_is_north(u3R);
u3t_on(coy_o);
c3_assert(u3_none != veb);
u3a_pile_prep(&pil_u, sizeof(takeframe));
u3a_pile_prep(&pil_u, sizeof(*fam_u));
// push the ROOT stack frame (our termination condition)
//
{
takeframe* fam_u = u3a_push(&pil_u);
fam_u->tag_y = TAKE_ROOT;
}
// read from the current noun .veb
// commence taking
//
pro = _ca_take_next(&pil_u, veb);
// consume: popped stack frame, and .pro from above
// process cell results
//
retreat: {
takeframe* fam_u = u3a_peek(&pil_u);
if ( c3n == u3a_pile_done(&pil_u) ) {
fam_u = u3a_peek(&pil_u);
switch ( fam_u->tag_y ) {
default: {
c3_assert(0);
}
// .fam_u is our stack root, we're done.
do {
// fam_u is a head-frame: stash copy and continue into the tail
//
case TAKE_ROOT: {
u3a_pop(&pil_u);
break;
}
// .pro is the copied head of a cell; save a pointer to it in .new_u
// and advance to copy the tail
//
case TAKE_HEAD: {
if ( u3_none == fam_u->hed ) {
u3a_cell* old_u = u3a_to_ptr(fam_u->old);
c3_assert( u3_none == fam_u->hed );
fam_u->tag_y = TAKE_TAIL;
fam_u->hed = pro;
// veb = old_u->tel;
// goto advance;
pro = _ca_take_next(&pil_u, old_u->tel);
goto retreat;
fam_u->hed = pro;
pro = _ca_take_next(&pil_u, old_u->tel);
fam_u = u3a_peek(&pil_u);
}
// .pro is the copied tail of a cell; save a pointer to it in .new_u,
// and produce the whole copied cell (as if it were a read from above).
// fam_u is a tail-frame: copy cell and pop the stack
//
case TAKE_TAIL: {
else {
u3a_cell* old_u = u3a_to_ptr(fam_u->old);
c3_assert( u3_none != fam_u->hed );
pro = _ca_take_cell(old_u, fam_u->hed, pro);
u3a_pop(&pil_u);
goto retreat;
pro = _ca_take_cell(old_u, fam_u->hed, pro);
fam_u = u3a_pop(&pil_u);
}
}
} while ( c3n == u3a_pile_done(&pil_u) );
}
// sanity check
//
c3_assert( c3y == u3a_pile_done(&pil_u) );
u3t_off(coy_o);
return pro;