mutating edit

This commit is contained in:
Paul Driver 2018-06-26 11:49:15 -07:00
parent 6ce5fb681e
commit 7dcc2303d1
4 changed files with 162 additions and 25 deletions

View File

@ -256,6 +256,15 @@
? u3a_north_is_senior(r, som) \
: u3a_south_is_senior(r, som) )
# define u3a_is_mutable(r, som) \
( _(u3a_is_atom(som)) \
? c3n \
: _(u3a_is_senior(r, som)) \
? c3n \
: _(u3a_is_junior(r, som)) \
? c3n \
: (u3a_botox(u3a_to_ptr(som))->use_w == 1) \
? c3y : c3n )
/** Globals.
**/

View File

@ -55,6 +55,14 @@
u3_noun
u3i_qual(u3_noun a, u3_noun b, u3_noun c, u3_noun d);
/* u3i_edit():
**
** Mutate `big` at axis `axe` with new value `som`
** `axe` is RETAINED.
*/
u3_noun
u3i_edit(u3_noun big, u3_noun axe, u3_noun som);
/* u3i_string():
**
** Produce an LSB-first atom from the C string `a`.

View File

@ -262,6 +262,150 @@ u3i_qual(u3_noun a, u3_noun b, u3_noun c, u3_noun d)
return u3i_cell(a, u3i_trel(b, c, d));
}
static u3_noun
_edit_cat(u3_noun big, c3_l axe_l, u3_noun som)
{
if ( c3n == u3du(big) ) {
return u3m_bail(c3__exit);
}
else {
u3_noun pro;
switch ( axe_l ) {
case 2:
pro = u3nc(som, u3k(u3t(big)));
break;
case 3:
pro = u3nc(u3k(u3h(big)), som);
break;
default: {
c3_l mor_l = u3x_mas(axe_l);
pro = ( 2 == u3x_cap(axe_l) )
? u3nc(_edit_cat(u3k(u3h(big)), mor_l, som), u3k(u3t(big)))
: u3nc(u3k(u3h(big)), _edit_cat(u3k(u3t(big)), mor_l, som));
break;
}
}
u3z(big);
return pro;
}
}
static u3_noun
_edit(u3_noun big, u3_noun axe, u3_noun som)
{
if ( c3y == u3a_is_cat(axe) ) {
return _edit_cat(big, (c3_l) axe, som);
}
else if ( c3n == u3du(big) ) {
return u3m_bail(c3__exit);
}
else {
u3_noun mor = u3qc_mas(axe),
pro = ( 2 == u3qc_cap(axe) )
? u3nc(_edit(u3k(u3h(big)), mor, som), u3k(u3t(big)))
: u3nc(u3k(u3h(big)), _edit(u3k(u3t(big)), mor, som));
u3z(mor);
u3z(big);
return pro;
}
}
static u3_noun _edit_or_mutate_cat(u3_noun, c3_l, u3_noun);
static u3_noun _edit_or_mutate(u3_noun, u3_noun, u3_noun);
static void
_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som)
{
if ( c3n == u3du(big) ) {
u3m_bail(c3__exit);
}
else {
u3a_cell* cel_u = (void*) u3a_to_ptr(big);
switch ( axe_l ) {
case 2:
u3z(cel_u->hed);
cel_u->hed = som;
break;
case 3:
u3z(cel_u->tel);
cel_u->tel = som;
break;
default: {
u3_noun* tar = ( 2 == u3x_cap(axe_l) )
? &(cel_u->hed)
: &(cel_u->tel);
*tar = _edit_or_mutate_cat(*tar, u3x_mas(axe_l), som);
}
}
}
}
static void
_mutate(u3_noun big, u3_noun axe, u3_noun som)
{
if ( c3y == u3a_is_cat(axe) ) {
_mutate_cat(big, (c3_l) axe, som);
}
else if ( c3n == u3du(big) ) {
u3m_bail(c3__exit);
}
else {
u3a_cell* cel_u = (void*) u3a_to_ptr(big);
u3_noun mor = u3qc_mas(axe);
u3_noun* tar = ( 2 == u3qc_cap(axe) )
? &(cel_u->hed)
: &(cel_u->tel);
*tar = _edit_or_mutate(*tar, mor, som);
u3z(mor);
}
}
static u3_noun
_edit_or_mutate_cat(u3_noun big, c3_l axe_l, u3_noun som)
{
if ( c3y == u3a_is_mutable(u3R, big) ) {
_mutate_cat(big, axe_l, som);
return big;
}
else {
return _edit_cat(big, axe_l, som);
}
}
static u3_noun
_edit_or_mutate(u3_noun big, u3_noun axe, u3_noun som)
{
if ( c3y == u3a_is_cat(axe) ) {
return _edit_or_mutate_cat(big, (c3_l) axe, som);
}
else if ( c3y == u3a_is_mutable(u3R, big) ) {
_mutate(big, axe, som);
return big;
}
else {
return _edit(big, axe, som);
}
}
/* u3i_edit():
**
** Mutate `big` at axis `axe` with new value `som`.
** `axe` is RETAINED.
*/
u3_noun
u3i_edit(u3_noun big, u3_noun axe, u3_noun som)
{
switch ( axe ) {
case 0:
return u3m_bail(c3__exit);
case 1:
u3z(big);
return som;
default:
return _edit_or_mutate(big, axe, som);
}
}
/* u3i_string():
**
** Produce an LSB-first atom from the C string `a`.

View File

@ -1591,30 +1591,6 @@ _n_kale(u3_noun a)
return a;
}
/* _n_edit(): PRODUCE a modified big with its axe axis
* changed to som. axe is RETAINED.
*/
static u3_noun
_n_edit(u3_noun big, u3_noun axe, u3_noun som)
{
if ( c3y == u3a_is_cat(axe) ) {
return u3i_molt(big, axe, som, 0);
}
else {
u3_noun mor = u3qc_mas(axe);
if ( c3n == u3du(big) ) {
u3m_bail(c3__exit);
}
u3_noun pro = ( 2 == u3qc_cap(axe) )
? u3nc(_n_edit(u3k(u3h(big)), mor, som), u3k(u3t(big)))
: u3nc(u3k(u3h(big)), _n_edit(u3k(u3t(big)), mor, som));
u3z(mor);
u3z(big);
return pro;
}
}
typedef struct {
u3n_prog* pog_u;
c3_w ip_w;
@ -2325,7 +2301,7 @@ _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off)
_n_toss(mov, off);
top = _n_peek(off);
edit_in:
*top = _n_edit(*top, x, o);
*top = u3i_edit(*top, x, o);
BURN();
}
}