diff --git a/Spec/nock/4.txt b/Spec/nock/4.txt index b6dafee9d9..3457d6bf65 100644 --- a/Spec/nock/4.txt +++ b/Spec/nock/4.txt @@ -1,5 +1,7 @@ A noun is an atom or a cell. An atom is a natural number. A cell is an ordered pair of nouns. +Reduce by the first matching pattern; variables match any noun. + nock(a) *a [a b c] [a [b c]] @@ -9,7 +11,6 @@ nock(a) *a +a 1 + a =[a a] 0 =[a b] 1 -=a =a /[1 a] a /[2 a b] a @@ -30,15 +31,15 @@ nock(a) *a *[a 2 b c] *[*[a b] *[a c]] *[a 3 b] ?*[a b] *[a 4 b] +*[a b] -*[a 5 b] =*[a b] +*[a 5 b c] =[*[a b] *[a c]] -*[a 6 b c d] *[a 2 [0 1] 2 [1 c d] [1 0] 2 [1 2 3] [1 0] 4 4 b] -*[a 7 b c] *[a 2 b 1 c] -*[a 8 b c] *[a 7 [[7 [0 1] b] 0 1] c] -*[a 9 b c] *[a 7 c 2 [0 1] 0 b] -*[a 10 [b c] d] *[a 8 c 7 [0 3] d] -*[a 10 b c] *[a c] -*[a 12 [b c] d] #[b *[a c] *[a d]] +*[a 6 b c d] *[a *[[c d] 0 *[[2 3] 0 *[a 4 4 b]]]] +*[a 7 b c] *[*[a b] c] +*[a 8 b c] *[[*[a b] a] c] +*[a 9 b c] *[*[a c] 2 [0 1] 0 b] +*[a 10 [b c] d] #[b *[a c] *[a d]] + +*[a 11 [b c] d] *[[*[a c] *[a d]] 0 3] +*[a 11 b c] *[a c] *a *a - diff --git a/include/noun/allocate.h b/include/noun/allocate.h index 23fd558917..11199014d1 100644 --- a/include/noun/allocate.h +++ b/include/noun/allocate.h @@ -250,6 +250,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. **/ diff --git a/include/noun/imprison.h b/include/noun/imprison.h index efda35fab3..f552c87f5e 100644 --- a/include/noun/imprison.h +++ b/include/noun/imprison.h @@ -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`. diff --git a/jets/f/hike.c b/jets/f/hike.c index 567b1ca0d5..6b1bb5b369 100644 --- a/jets/f/hike.c +++ b/jets/f/hike.c @@ -89,6 +89,7 @@ u3qf_hike(u3_noun axe, u3_noun pac) { + c3_assert(0); if ( (u3_nul == pac) ) { return u3nc(0, u3k(axe)); } diff --git a/jets/f/ut_mint.c b/jets/f/ut_mint.c index 7dd189300b..117c9c0d16 100644 --- a/jets/f/ut_mint.c +++ b/jets/f/ut_mint.c @@ -148,16 +148,16 @@ } static u3_noun - _mint_coke(u3_noun nug) + _mint_cove(u3_noun nug) { if ( 0 == u3h(nug) ) { return u3k(u3t(nug)); } - else if ( 10 == u3h(nug) ) { - return _mint_coke(u3t(u3t(nug))); + else if ( 11 == u3h(nug) ) { + return _mint_cove(u3t(u3t(nug))); } else { - return u3m_error("mint-coke"); + return u3m_error("mint-cove"); } } @@ -370,7 +370,7 @@ u3_noun wam = u3qfu_play(van, sut, p_gen); u3_noun dok = u3nc(c3__wing, u3k(q_gen)); u3_noun vol = _mint_corn(van, sut, dok); - u3_noun axe = _mint_coke(vol); + u3_noun axe = _mint_cove(vol); ret = u3nc(_mint_nice(van, gol, _mint_bean()), u3qfu_fish(van, wam, axe)); @@ -471,7 +471,7 @@ u3_noun viz = _mint_in(van, sut, c3__noun, q_gen); ret = u3nc(u3k(u3h(nef)), - u3nt(11, u3nc(1, u3nc(151, u3k(u3h(nef)))), u3k(u3t(viz)))); + u3nt(12, u3nc(1, u3nc(151, u3k(u3h(nef)))), u3k(u3t(viz)))); u3z(viz); u3z(nef); @@ -683,7 +683,7 @@ _mint_corn(van, sut, u3t(p_gen))); } ret = u3nc(u3k(u3h(hum)), - u3nt(10, bez, u3k(u3t(hum)))); + u3nt(11, bez, u3k(u3t(hum)))); u3z(hum); return ret; @@ -786,7 +786,7 @@ u3_noun hum = _mint_in(van, sut, gol, q_gen); u3_noun bez = u3nt(c3__spot, 1, u3k(p_gen)); - ret = u3nc(u3k(u3h(hum)), u3nt(10, bez, u3k(u3t(hum)))); + ret = u3nc(u3k(u3h(hum)), u3nt(11, bez, u3k(u3t(hum)))); u3z(hum); } u3t_drop(); diff --git a/jets/f/ut_mull.c b/jets/f/ut_mull.c index e078407433..760ebbf1f1 100644 --- a/jets/f/ut_mull.c +++ b/jets/f/ut_mull.c @@ -63,16 +63,16 @@ } } static u3_noun - _mull_coke(u3_noun nug) + _mull_cove(u3_noun nug) { if ( 0 == u3h(nug) ) { return u3k(u3t(nug)); } - else if ( 10 == u3h(nug) ) { - return _mull_coke(u3t(u3t(nug))); + else if ( 11 == u3h(nug) ) { + return _mull_cove(u3t(u3t(nug))); } else { - return u3m_error("mull-coke"); + return u3m_error("mull-cove"); } } @@ -109,7 +109,7 @@ u3_noun gen) { u3_noun fug = u3qfu_mint(van, sut, c3__noun, gen); - u3_noun axe = _mull_coke(u3t(fug)); + u3_noun axe = _mull_cove(u3t(fug)); u3z(fug); return axe; diff --git a/noun/imprison.c b/noun/imprison.c index 09126c14ff..daf59a1d37 100644 --- a/noun/imprison.c +++ b/noun/imprison.c @@ -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`. diff --git a/noun/jets.c b/noun/jets.c index f2c4759605..40405b543e 100644 --- a/noun/jets.c +++ b/noun/jets.c @@ -249,7 +249,7 @@ _cj_axis(u3_noun fol) { u3_noun p_fol, q_fol, r_fol; - while ( _(u3du(fol)) && (10 == u3h(fol)) ) + while ( _(u3du(fol)) && (11 == u3h(fol)) ) { fol = u3t(u3t(fol)); } if ( !_(u3r_trel(fol, &p_fol, &q_fol, &r_fol)) ) { @@ -436,7 +436,7 @@ _cj_je_fsck(u3_noun clu) if ( 0 == (nam_c = _cj_chum(p_clu)) ) { u3z(clu); return u3_none; } - while ( _(u3du(q_clu)) && (10 == u3h(q_clu)) ) { + while ( _(u3du(q_clu)) && (11 == u3h(q_clu)) ) { q_clu = u3t(u3t(q_clu)); } if ( !_(u3du(q_clu)) ) { diff --git a/noun/nock.c b/noun/nock.c index c784d87ab4..adc1cf015e 100644 --- a/noun/nock.c +++ b/noun/nock.c @@ -526,6 +526,22 @@ _n_nock_on(u3_noun bus, u3_noun fol) #define SLIB 70 #define SLIS 71 #define SAVE 72 +// nock 10 +#define MUTH 73 +#define KUTH 74 +#define MUTT 75 +#define KUTT 76 +#define MUSM 77 +#define KUSM 78 +#define MUTB 79 +#define MUTS 80 +#define MITB 81 +#define MITS 82 +#define KUTB 83 +#define KUTS 84 +#define KITB 85 +#define KITS 86 +#define LAST 87 /* _n_arg(): return the size (in bytes) of an opcode's argument */ @@ -538,6 +554,7 @@ _n_arg(c3_y cod_y) case SAMB: case SANB: case SBIP: case SBIN: case SLIB: case SKIB: case KICB: case TICB: case BUSH: case BAST: case BALT: + case MUTB: case KUTB: case MITB: case KITB: return sizeof(c3_y); case FASK: case FASL: case FISL: case FISK: @@ -545,13 +562,14 @@ _n_arg(c3_y cod_y) case SAMS: case SANS: case SIPS: case SINS: case SLIS: case SKIS: case KICS: case TICS: case SUSH: case SAST: case SALT: + case MUTS: case KUTS: case MITS: case KITS: return sizeof(c3_s); case SWIP: case SWIN: return sizeof(c3_l); default: - c3_assert( cod_y <= SAVE ); + c3_assert( cod_y < LAST ); return 0; } } @@ -657,6 +675,7 @@ _n_melt(u3_noun ops, c3_w* byc_w, c3_w* cal_w, case BUSH: case FIBK: case FIBL: case SANB: case LIBL: case LIBK: + case KITB: case MITB: a_w = (*lit_w)++; if ( a_w <= 0xFF ) { siz_y[i_w] = 2; @@ -854,6 +873,7 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) /* 8-bit direct args */ case FABK: case FABL: case LITB: case LILB: + case MUTB: case KUTB: case SAMB: buf_y[i_w--] = (c3_y) u3t(op); buf_y[i_w] = (c3_y) cod; @@ -862,6 +882,7 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) /* 16-bit direct args */ case FASK: case FASL: case LILS: case LITS: + case MUTS: case KUTS: case SAMS: case SIPS: case SINS: { c3_s off_s = u3t(op); buf_y[i_w--] = (c3_y) (off_s >> 8); @@ -885,6 +906,7 @@ _n_prog_asm(u3_noun ops, u3n_prog* pog_u, u3_noun sip) case FIBK: case FIBL: case LIBK: case LIBL: case BUSH: case SANB: + case KITB: case MITB: _n_prog_asm_inx(buf_y, &i_w, lit_s, cod); pog_u->lit_u.non[lit_s++] = u3k(u3t(op)); break; @@ -992,6 +1014,10 @@ static char* opcode_names[] = { "balt", "salt", "skib", "skis", "slib", "slis", "save", + "muth", "kuth", "mutt", "kutt", + "musm", "kusm", + "mutb", "muts", "mitb", "mits", + "kutb", "kuts", "kitb", "kits", }; #endif @@ -1185,8 +1211,8 @@ _n_comp(u3_noun* ops, u3_noun fol, c3_o los_o, c3_o tel_o) u3x_cell(arg, &hed, &tel); if ( c3n == u3du(hed) ) { - tot_w += _n_comp(ops, arg, los_o, c3n); - ++tot_w; _n_emit(ops, SAMC); + u3m_bail(c3__exit); + return 0; } else { c3_t hec_t, tec_t; @@ -1276,12 +1302,44 @@ _n_comp(u3_noun* ops, u3_noun fol, c3_o los_o, c3_o tel_o) } break; - case 10: + case 10: { + u3_noun axe, nef; + u3x_cell(arg, &hed, &tel); + u3x_cell(hed, &axe, &nef); + tot_w += _n_comp(ops, tel, c3n, c3n); + ++tot_w; _n_emit(ops, SWAP); + tot_w += _n_comp(ops, nef, c3n, c3n); + + ++tot_w; + switch ( axe ) { + case 2: + _n_emit(ops, (c3y == los_o) ? MUTH : KUTH); + break; + + case 3: + _n_emit(ops, (c3y == los_o) ? MUTT : KUTT); + break; + + case u3x_sam: + _n_emit(ops, (c3y == los_o) ? MUSM : KUSM); + break; + + default: + op_y = (c3y == los_o) + ? (axe <= 0xFF) ? MUTB : (axe <= 0xFFFF) ? MUTS : MITB // overflows to MITS + : (axe <= 0xFF) ? KUTB : (axe <= 0xFFFF) ? KUTS : KITB; // overflows to KITS + _n_emit(ops, u3nc(op_y, u3k(axe))); + break; + } + break; + } + + case 11: u3x_cell(arg, &hed, &tel); tot_w += _n_bint(ops, hed, tel, los_o, tel_o); break; - case 11: + case 12: u3x_cell(arg, &hed, &tel); tot_w += _n_comp(ops, hed, c3n, c3n); ++tot_w; _n_emit(ops, SWAP); @@ -1573,6 +1631,10 @@ _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) &&do_balt, &&do_salt, &&do_skib, &&do_skis, &&do_slib, &&do_slis, &&do_save, + &&do_muth, &&do_kuth, &&do_mutt, &&do_kutt, + &&do_musm, &&do_kusm, + &&do_mutb, &&do_muts, &&do_mitb, &&do_mits, + &&do_kutb, &&do_kuts, &&do_kitb, &&do_kits, }; u3j_site* sit_u; @@ -2158,6 +2220,89 @@ _n_burn(u3n_prog* pog_u, u3_noun bus, c3_ys mov, c3_ys off) *top = x; u3z(o); BURN(); + + do_kuth: + x = _n_pep(mov, off); + top = _n_swap(mov, off); + goto muth_in; + do_muth: + x = _n_pep(mov, off); + _n_toss(mov, off); + top = _n_peek(off); + muth_in: + o = *top; + *top = u3nc(x, u3k(u3t(o))); + u3z(o); + BURN(); + + do_kutt: + x = _n_pep(mov, off); + top = _n_swap(mov, off); + goto mutt_in; + do_mutt: + x = _n_pep(mov, off); + _n_toss(mov, off); + top = _n_peek(off); + mutt_in: + o = *top; + *top = u3nc(u3k(u3h(o)), x); + u3z(o); + BURN(); + + do_kusm: + x = _n_pep(mov, off); + top = _n_swap(mov, off); + goto musm_in; + do_musm: + x = _n_pep(mov, off); + _n_toss(mov, off); + top = _n_peek(off); + musm_in: + o = *top; + *top = u3nt(u3k(u3h(o)), x, u3k(u3t(u3t(o)))); + u3z(o); + BURN(); + + do_kitb: + x = pog_u->lit_u.non[pog[ip_w++]]; + goto kut_in; + + do_kits: + x = pog_u->lit_u.non[_n_resh(pog, &ip_w)]; + goto kut_in; + + do_kuts: + x = _n_resh(pog, &ip_w); + goto kut_in; + + do_kutb: + x = pog[ip_w++]; + kut_in: + o = _n_pep(mov, off); + top = _n_swap(mov, off); + goto edit_in; + + do_mitb: + x = pog_u->lit_u.non[pog[ip_w++]]; + goto mut_in; + + do_mits: + x = pog_u->lit_u.non[_n_resh(pog, &ip_w)]; + goto mut_in; + + do_muts: + x = _n_resh(pog, &ip_w); + goto mut_in; + + do_mutb: + x = pog[ip_w++]; + mut_in: + o = _n_pep(mov, off); + _n_toss(mov, off); + top = _n_peek(off); + edit_in: + *top = u3i_edit(*top, x, o); + BURN(); } }