urbit/noun/nock.c

1611 lines
35 KiB
C
Raw Normal View History

2014-09-11 04:01:32 +04:00
/* g/n.c
2014-09-05 23:55:16 +04:00
**
*/
#include "all.h"
2014-12-03 00:53:35 +03:00
static u3_noun _n_nock_on(u3_noun bus, u3_noun fol);
2014-10-28 20:36:22 +03:00
/* u3_term_io_hija(): hijack console for cooked print.
*/
FILE*
u3_term_io_hija(void);
/* u3_term_io_loja(): release console from cooked print.
*/
void
u3_term_io_loja(int x);
/* uL, uH: wrap hijack/lojack around fprintf.
**
** uL(fprintf(uH, ...));
*/
# define uH u3_term_io_hija()
# define uL(x) u3_term_io_loja(x)
2014-12-03 00:53:35 +03:00
/* _n_hint(): process hint.
2014-09-05 23:55:16 +04:00
*/
2014-09-06 00:13:24 +04:00
static u3_noun
2014-12-03 00:53:35 +03:00
_n_hint(u3_noun zep,
u3_noun hod,
u3_noun bus,
u3_noun nex)
2014-09-05 23:55:16 +04:00
{
switch ( zep ) {
default: {
2014-11-06 03:20:01 +03:00
// u3m_p("weird zep", zep);
u3a_lose(zep);
u3a_lose(hod);
2014-09-05 23:55:16 +04:00
2014-12-03 00:53:35 +03:00
return _n_nock_on(bus, nex);
2014-09-05 23:55:16 +04:00
}
case c3__hunk:
case c3__lose:
case c3__mean:
case c3__spot: {
2014-09-06 00:13:24 +04:00
u3_noun tac = u3nc(zep, hod);
u3_noun pro;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3t_push(tac);
2014-09-05 23:55:16 +04:00
#if 0
{
static int low_i;
if ( !low_i ) {
low_i = 1;
if ( 0 == (u3R->pro.nox_d % 65536ULL) ) {
if ( c3__spot == zep ) {
uL(fprintf(uH, "spot %d/%d : %d/%d\r\n",
u3h(u3h(u3t(hod))),
u3t(u3h(u3t(hod))),
u3h(u3t(u3t(hod))),
u3t(u3t(u3t(hod)))));
}
}
low_i = 0;
}
2014-09-05 23:55:16 +04:00
}
#endif
2014-12-03 00:53:35 +03:00
pro = _n_nock_on(bus, nex);
2014-11-06 03:20:01 +03:00
u3t_drop();
2014-09-05 23:55:16 +04:00
return pro;
}
2016-02-23 21:57:34 +03:00
case c3__live: {
if ( c3y == u3ud(hod) ) {
2016-02-23 22:18:14 +03:00
u3t_off(noc_o);
2016-02-23 21:57:34 +03:00
u3t_heck(hod);
2016-02-23 22:18:14 +03:00
u3t_on(noc_o);
2016-02-23 21:57:34 +03:00
} else {
u3z(hod);
}
return _n_nock_on(bus, nex);
}
2014-09-05 23:55:16 +04:00
case c3__slog: {
2015-05-20 03:04:08 +03:00
if ( !(u3C.wag_w & u3o_quiet) ) {
u3t_off(noc_o);
u3t_slog(hod);
u3t_on(noc_o);
}
2014-12-03 00:53:35 +03:00
return _n_nock_on(bus, nex);
2014-09-05 23:55:16 +04:00
}
case c3__germ: {
2014-12-03 00:53:35 +03:00
u3_noun pro = _n_nock_on(bus, nex);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( c3y == u3r_sing(pro, hod) ) {
2014-09-06 00:13:24 +04:00
u3z(pro); return hod;
2014-09-05 23:55:16 +04:00
} else {
2014-09-06 00:13:24 +04:00
u3z(hod); return pro;
2014-09-05 23:55:16 +04:00
}
}
case c3__fast: {
2014-12-03 00:53:35 +03:00
u3_noun pro = _n_nock_on(bus, nex);
2014-09-05 23:55:16 +04:00
2014-12-03 00:53:35 +03:00
u3t_off(noc_o);
2014-11-06 03:20:01 +03:00
u3j_mine(hod, u3k(pro));
2014-12-03 00:53:35 +03:00
u3t_on(noc_o);
2014-10-25 01:04:44 +04:00
return pro;
2014-09-05 23:55:16 +04:00
}
case c3__memo: {
2014-09-06 00:13:24 +04:00
u3z(hod);
2014-09-17 04:29:12 +04:00
#if 0
2014-12-03 00:53:35 +03:00
return _n_nock_on(bus, nex);
2014-09-17 04:29:12 +04:00
#else
2014-09-05 23:55:16 +04:00
{
2017-11-09 01:19:48 +03:00
u3_noun pro = u3z_find_2(144 + c3__nock, bus, nex);
2014-09-05 23:55:16 +04:00
2014-11-06 02:36:30 +03:00
if ( pro != u3_none ) {
2014-10-11 09:32:58 +04:00
u3z(bus); u3z(nex);
2014-09-05 23:55:16 +04:00
return pro;
}
2014-12-03 00:53:35 +03:00
pro = _n_nock_on(u3k(bus), u3k(nex));
2014-09-05 23:55:16 +04:00
2015-07-02 01:28:55 +03:00
if ( &(u3H->rod_u) != u3R ) {
2017-11-09 01:19:48 +03:00
u3z_save_2(144 + c3__nock, bus, nex, pro);
2015-05-14 01:23:20 +03:00
}
2014-09-06 00:13:24 +04:00
u3z(bus); u3z(nex);
2014-10-10 05:27:02 +04:00
return pro;
2014-09-05 23:55:16 +04:00
}
2014-09-17 04:29:12 +04:00
#endif
2014-09-05 23:55:16 +04:00
}
case c3__sole: {
2014-09-06 00:13:24 +04:00
u3z(hod);
2014-09-05 23:55:16 +04:00
{
2014-12-03 00:53:35 +03:00
u3_noun pro = _n_nock_on(bus, nex);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
// return u3z_uniq(pro);
2014-09-17 04:29:12 +04:00
return pro;
2014-09-05 23:55:16 +04:00
}
}
}
}
/* _n_mush_in(): see _n_mush().
*/
static u3_noun
_n_mush_in(u3_noun val)
{
if ( c3n == u3du(val) ) {
return u3_nul;
}
else {
u3_noun h_val = u3h(val);
u3_noun ite;
if ( c3n == u3ud(h_val) ) {
ite = u3nc(c3__leaf, u3_nul);
} else {
ite = u3nc(c3__leaf, u3qe_trip(h_val));
}
return u3nc(ite, _n_mush_in(u3t(val)));
}
}
/* _n_mush(): tank from failed path request.
*/
static u3_noun
_n_mush(u3_noun val)
{
u3_noun pro;
pro = u3nt(c3__rose,
u3nt(u3nc('/', u3_nul), u3nc('/', u3_nul), u3_nul),
_n_mush_in(val));
u3z(val);
return pro;
}
2014-12-03 00:53:35 +03:00
/* _n_nock_on(): produce .*(bus fol). Do not virtualize.
2014-09-05 23:55:16 +04:00
*/
static u3_noun
2014-12-03 00:53:35 +03:00
_n_nock_on(u3_noun bus, u3_noun fol)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun hib, gal;
2014-09-05 23:55:16 +04:00
while ( 1 ) {
2014-09-06 00:13:24 +04:00
hib = u3h(fol);
gal = u3t(fol);
2014-09-05 23:55:16 +04:00
#ifdef U3_CPU_DEBUG
2014-09-27 06:14:24 +04:00
u3R->pro.nox_d += 1;
#endif
2014-09-16 03:56:37 +04:00
2014-11-06 03:20:01 +03:00
if ( c3y == u3r_du(hib) ) {
2014-09-06 00:13:24 +04:00
u3_noun poz, riv;
2014-09-05 23:55:16 +04:00
2014-12-03 00:53:35 +03:00
poz = _n_nock_on(u3k(bus), u3k(hib));
riv = _n_nock_on(bus, u3k(gal));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
return u3i_cell(poz, riv);
2014-09-05 23:55:16 +04:00
}
else switch ( hib ) {
2014-11-06 03:20:01 +03:00
default: return u3m_bail(c3__exit);
2014-09-05 23:55:16 +04:00
case 0: {
2014-11-06 03:20:01 +03:00
if ( c3n == u3r_ud(gal) ) {
return u3m_bail(c3__exit);
2014-09-05 23:55:16 +04:00
}
else {
2014-09-06 00:13:24 +04:00
u3_noun pro = u3k(u3at(gal, bus));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(bus); u3a_lose(fol);
2014-09-05 23:55:16 +04:00
return pro;
}
}
c3_assert(!"not reached");
case 1: {
2014-09-06 00:13:24 +04:00
u3_noun pro = u3k(gal);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(bus); u3a_lose(fol);
2014-09-05 23:55:16 +04:00
return pro;
}
c3_assert(!"not reached");
case 2: {
2014-12-03 00:53:35 +03:00
u3_noun nex = _n_nock_on(u3k(bus), u3k(u3t(gal)));
u3_noun seb = _n_nock_on(bus, u3k(u3h(gal)));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-09-05 23:55:16 +04:00
bus = seb;
fol = nex;
continue;
}
c3_assert(!"not reached");
case 3: {
2014-09-06 00:13:24 +04:00
u3_noun gof, pro;
2014-09-05 23:55:16 +04:00
2014-12-03 00:53:35 +03:00
gof = _n_nock_on(bus, u3k(gal));
2014-11-06 03:20:01 +03:00
pro = u3r_du(gof);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(gof); u3a_lose(fol);
2014-09-05 23:55:16 +04:00
return pro;
}
c3_assert(!"not reached");
case 4: {
2014-09-06 00:13:24 +04:00
u3_noun gof, pro;
2014-09-05 23:55:16 +04:00
2014-12-03 00:53:35 +03:00
gof = _n_nock_on(bus, u3k(gal));
2014-11-06 03:20:01 +03:00
pro = u3i_vint(gof);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-09-05 23:55:16 +04:00
return pro;
}
c3_assert(!"not reached");
case 5: {
2014-12-03 00:53:35 +03:00
u3_noun wim = _n_nock_on(bus, u3k(gal));
2014-11-06 03:20:01 +03:00
u3_noun pro = u3r_sing(u3h(wim), u3t(wim));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(wim); u3a_lose(fol);
2014-09-05 23:55:16 +04:00
return pro;
}
c3_assert(!"not reached");
case 6: {
2014-09-06 00:13:24 +04:00
u3_noun b_gal, c_gal, d_gal;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3x_trel(gal, &b_gal, &c_gal, &d_gal);
2014-09-05 23:55:16 +04:00
{
2014-12-03 00:53:35 +03:00
u3_noun tys = _n_nock_on(u3k(bus), u3k(b_gal));
2014-09-06 00:13:24 +04:00
u3_noun nex;
2014-09-05 23:55:16 +04:00
if ( 0 == tys ) {
2014-09-06 00:13:24 +04:00
nex = u3k(c_gal);
2014-09-05 23:55:16 +04:00
} else if ( 1 == tys ) {
2014-09-06 00:13:24 +04:00
nex = u3k(d_gal);
2014-11-06 03:20:01 +03:00
} else return u3m_bail(c3__exit);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-09-05 23:55:16 +04:00
fol = nex;
continue;
}
}
c3_assert(!"not reached");
case 7: {
2014-09-06 00:13:24 +04:00
u3_noun b_gal, c_gal;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3x_cell(gal, &b_gal, &c_gal);
2014-09-05 23:55:16 +04:00
{
2014-12-03 00:53:35 +03:00
u3_noun bod = _n_nock_on(bus, u3k(b_gal));
2014-09-06 00:13:24 +04:00
u3_noun nex = u3k(c_gal);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-09-05 23:55:16 +04:00
bus = bod;
fol = nex;
continue;
}
}
c3_assert(!"not reached");
case 8: {
2014-09-06 00:13:24 +04:00
u3_noun b_gal, c_gal;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3x_cell(gal, &b_gal, &c_gal);
2014-09-05 23:55:16 +04:00
{
2014-12-03 00:53:35 +03:00
u3_noun heb = _n_nock_on(u3k(bus), u3k(b_gal));
2014-09-06 00:13:24 +04:00
u3_noun bod = u3nc(heb, bus);
u3_noun nex = u3k(c_gal);
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-09-05 23:55:16 +04:00
bus = bod;
fol = nex;
continue;
}
}
c3_assert(!"not reached");
case 9: {
2014-09-06 00:13:24 +04:00
u3_noun b_gal, c_gal;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3x_cell(gal, &b_gal, &c_gal);
2014-09-05 23:55:16 +04:00
{
2014-12-03 00:53:35 +03:00
u3_noun seb = _n_nock_on(bus, u3k(c_gal));
2014-12-03 03:26:30 +03:00
u3_noun pro;
u3t_off(noc_o);
pro = u3j_kick(seb, b_gal);
u3t_on(noc_o);
2014-09-05 23:55:16 +04:00
2014-11-06 02:36:30 +03:00
if ( u3_none != pro ) {
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-09-05 23:55:16 +04:00
return pro;
}
else {
2014-11-06 03:20:01 +03:00
if ( c3n == u3r_ud(b_gal) ) {
return u3m_bail(c3__exit);
2014-09-05 23:55:16 +04:00
}
else {
2014-09-06 00:13:24 +04:00
u3_noun nex = u3k(u3at(b_gal, seb));
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-09-05 23:55:16 +04:00
bus = seb;
fol = nex;
continue;
}
}
}
}
c3_assert(!"not reached");
case 10: {
2014-09-06 00:13:24 +04:00
u3_noun p_gal, q_gal;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
u3x_cell(gal, &p_gal, &q_gal);
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun zep, hod, nex;
2014-09-05 23:55:16 +04:00
2014-11-06 03:20:01 +03:00
if ( c3y == u3r_du(p_gal) ) {
2014-09-06 00:13:24 +04:00
u3_noun b_gal = u3h(p_gal);
u3_noun c_gal = u3t(p_gal);
u3_noun d_gal = q_gal;
2014-09-05 23:55:16 +04:00
2014-09-06 00:13:24 +04:00
zep = u3k(b_gal);
2014-12-03 00:53:35 +03:00
hod = _n_nock_on(u3k(bus), u3k(c_gal));
2014-09-06 00:13:24 +04:00
nex = u3k(d_gal);
2014-09-05 23:55:16 +04:00
}
else {
2014-09-06 00:13:24 +04:00
u3_noun b_gal = p_gal;
u3_noun c_gal = q_gal;
2014-09-05 23:55:16 +04:00
2014-09-06 00:13:24 +04:00
zep = u3k(b_gal);
hod = u3_nul;
nex = u3k(c_gal);
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
u3a_lose(fol);
2014-12-03 00:53:35 +03:00
return _n_hint(zep, hod, bus, nex);
2014-09-05 23:55:16 +04:00
}
}
case 11: {
2016-01-26 22:03:05 +03:00
u3_noun ref = _n_nock_on(u3k(bus), u3k(u3h(gal)));
u3_noun gof = _n_nock_on(bus, u3k(u3t(gal)));
2014-12-03 03:26:30 +03:00
u3_noun val;
u3t_off(noc_o);
2016-02-02 22:52:10 +03:00
val = u3m_soft_esc(ref, u3k(gof));
2014-12-03 03:26:30 +03:00
u3t_on(noc_o);
2014-10-31 00:40:05 +03:00
2014-11-05 04:18:47 +03:00
if ( !_(u3du(val)) ) {
2014-11-06 03:20:01 +03:00
u3m_bail(u3nt(1, gof, 0));
2014-10-01 10:34:30 +04:00
}
2016-02-04 00:33:43 +03:00
if ( !_(u3du(u3t(val))) ) {
//
// replace with proper error stack push
//
u3t_push(u3nc(c3__hunk, _n_mush(gof)));
2016-02-04 00:33:43 +03:00
return u3m_bail(c3__exit);
2014-10-01 10:34:30 +04:00
}
else {
u3_noun pro;
u3z(gof);
u3z(fol);
2016-02-04 00:33:43 +03:00
pro = u3k(u3t(u3t(val)));
u3z(val);
return pro;
}
}
2014-09-05 23:55:16 +04:00
c3_assert(!"not reached");
}
}
}
2014-12-03 00:53:35 +03:00
/* u3n_nock_on(): produce .*(bus fol). Do not virtualize.
*/
u3_noun
u3n_nock_on(u3_noun bus, u3_noun fol)
{
u3_noun pro;
u3t_on(noc_o);
pro = _n_nock_on(bus, fol);
u3t_off(noc_o);
return pro;
}
2014-11-06 03:20:01 +03:00
/* u3n_kick_on(): fire `gat` without changing the sample.
2014-09-05 23:55:16 +04:00
*/
2014-09-06 00:13:24 +04:00
u3_noun
2014-11-06 03:20:01 +03:00
u3n_kick_on(u3_noun gat)
2014-09-05 23:55:16 +04:00
{
2014-11-06 03:20:01 +03:00
return u3j_kink(gat, 2);
2014-09-05 23:55:16 +04:00
}
2014-11-02 01:13:18 +03:00
c3_w exc_w;
2014-11-06 03:20:01 +03:00
/* u3n_slam_on(): produce (gat sam).
2014-09-05 23:55:16 +04:00
*/
2014-09-06 00:13:24 +04:00
u3_noun
2014-11-06 03:20:01 +03:00
u3n_slam_on(u3_noun gat, u3_noun sam)
2014-09-05 23:55:16 +04:00
{
2014-09-06 00:13:24 +04:00
u3_noun cor = u3nc(u3k(u3h(gat)), u3nc(sam, u3k(u3t(u3t(gat)))));
2014-09-05 23:55:16 +04:00
2014-11-02 01:13:18 +03:00
#if 0
if ( &u3H->rod_u == u3R ) {
if ( exc_w == 1 ) {
c3_assert(0);
}
exc_w++;
}
#endif
2014-09-06 00:13:24 +04:00
u3z(gat);
2014-11-06 03:20:01 +03:00
return u3n_kick_on(cor);
2014-09-05 23:55:16 +04:00
}
2016-02-04 00:33:43 +03:00
/* u3n_nock_et(): produce .*(bus fol), as ++toon, in namespace.
*/
u3_noun
u3n_nock_et(u3_noun gul, u3_noun bus, u3_noun fol)
{
return u3m_soft_run(gul, u3n_nock_on, bus, fol);
2016-02-04 00:33:43 +03:00
}
/* u3n_slam_et(): produce (gat sam), as ++toon, in namespace.
*/
u3_noun
u3n_slam_et(u3_noun gul, u3_noun gat, u3_noun sam)
{
return u3m_soft_run(gul, u3n_slam_on, gat, sam);
2014-09-05 23:55:16 +04:00
}
2014-11-06 03:20:01 +03:00
/* u3n_nock_an(): as slam_in(), but with empty fly.
2014-09-05 23:55:16 +04:00
*/
2014-09-06 00:13:24 +04:00
u3_noun
2014-11-06 03:20:01 +03:00
u3n_nock_an(u3_noun bus, u3_noun fol)
2014-09-05 23:55:16 +04:00
{
u3_noun gul = u3nt(u3nt(1, 0, 0), 0, 0); // |=(a/{* *} ~)
2014-10-01 10:34:30 +04:00
return u3n_nock_et(gul, bus, fol);
2014-09-05 23:55:16 +04:00
}
2018-01-31 03:27:04 +03:00
/* These must match the order in the section marked OPCODE TABLE */
2018-02-01 20:04:47 +03:00
#define HALT 0 // stop executing, leaving the product on the top of stack
#define COPY 1 // copy TOS, keep, and push it
#define TOSS 2 // throw away and lose TOS
#define SWAP 3 // exchange TOS with item underneat
#define SWAT 4 // toss item under TOS (under)
#define SKIP 5 // skip N (c3_s) instructions
#define SKIN 6 // pop loob, skip N if it is no, bail if not yes
#define SBIP 7 // skip with byte argument
#define SBIN 8 // skin with byte argument
#define CONS 9 // makes a cell of [under, TOS]
#define SNOC 10 // makes a cell of [TOS, under]
#define HEAD 11 // replaces TOS with its head (old TOS lost)
#define TAIL 12 // as HEAD, but for the tail
#define FRAG 13 // as HEAD/TAIL but with arbitrary noun axis
#define FRAS 14 // frag with short
#define FRAB 15 // frag with byte axis
#define QUOT 16 // toss TOS, push literal noun argument
#define QUIP 17 // as QUOT, but without the toss
#define NOCK 18 // *(under, TOS)
#define NOCT 19 // as NOCK, but in tail position
#define DEEP 20 // pop TOS and push isCell loob
#define PEEP 21 // as DEEP, but doesn't pop
#define BUMP 22 // increment TOS
#define SAME 23 // pop two items and push equality loob
#define KICK 24 // pull noun axis from TOS
#define KICS 25 // kick with short axis
#define KICB 26 // kick with byte axis
#define TICK 27 // KICK, but in tail position
#define TICS 28 // tick with short axis
#define TICB 29 // tick with byte axis
#define WISH 30 // ref is under, gof is TOS, u3m_soft_esc
#define FAST 31 // u3j_mine TOS
#define CUSH 32 // u3t_push TOS
#define DROP 33 // u3t_drop
#define PUMO 34 // saves memo from tos->[pro key]
#define GEMO 35 // pushes (unit pro) of u3z_save with key=TOS
#define HECK 36 // u3t_heck TOS
#define SLOG 37 // u3t_slog TOS
#define BAIL 37 // bail %exit
2018-02-01 20:04:47 +03:00
/* _n_apen(): emit the instructions contained in src to dst
*/
static inline void
_n_apen(u3_noun* dst, u3_noun src)
{
*dst = u3qb_weld(src, *dst);
}
2018-02-01 20:04:47 +03:00
/* _n_emit(): emit a single instruction to ops, returning
* the size (in bytes) required to store that
* opcode.
*/
2018-01-31 03:27:04 +03:00
static inline c3_y
_n_emit(u3_noun *ops, u3_noun op)
{
*ops = u3nc(op, *ops);
if ( c3n == u3du(op) ) {
return sizeof(c3_y);
}
else switch ( u3h(op) ) {
case SBIP:
case SBIN:
2018-02-05 22:20:34 +03:00
case KICB:
case TICB:
case FRAB:
return sizeof(c3_y) + sizeof(c3_y);
case KICS:
case TICS:
case FRAS:
2018-01-31 03:27:04 +03:00
case SKIP:
case SKIN:
return sizeof(c3_y) + sizeof(c3_s);
2018-02-05 22:20:34 +03:00
case FRAG:
2018-01-31 03:27:04 +03:00
case QUOT:
case QUIP:
case TICK:
case KICK:
return sizeof(c3_y) + sizeof(u3_noun);
default:
c3_assert(0);
}
}
2018-02-07 21:26:06 +03:00
static c3_s _n_comp(u3_noun*, c3_o*, u3_noun, c3_o);
2018-01-31 03:27:04 +03:00
static u3_noun
_n_skip(c3_s len_s)
{
return u3nc((len_s < 0xFF ? SBIP : SKIP), len_s);
}
static u3_noun
_n_skin(c3_s len_s)
{
return u3nc((len_s < 0xFF ? SBIN : SKIN), len_s);
}
/* _n_one(): emit non-tail fol's ops with a leading copy if not constant */
static c3_s
_n_one(u3_noun* ops, c3_o* tos_o, u3_noun fol)
2018-02-06 04:04:41 +03:00
{
c3_assert(c3y == u3du(fol));
c3_s tot_s = 0;
u3_noun bok = u3_nul;
2018-02-07 21:26:06 +03:00
tot_s += _n_comp(&bok, tos_o, fol, c3n);
if ( c3n == *tos_o ) {
2018-02-06 04:04:41 +03:00
tot_s += _n_emit(ops, COPY);
}
_n_apen(ops, bok);
2018-02-06 04:04:41 +03:00
return tot_s;
}
2018-02-07 21:26:06 +03:00
/* _n_two(): _n_comp() helper for computing two products
* from a single subject
*/
static c3_s
2018-02-07 21:26:06 +03:00
_n_two(u3_noun* ops, c3_o* lev_o, u3_noun one, u3_noun two, c3_o cop_o)
2018-02-06 04:04:41 +03:00
{
u3_noun one_bok = u3_nul,
two_bok = u3_nul;
2018-02-07 21:26:06 +03:00
c3_s tot_s = 0;
c3_o one_o, two_o;
tot_s += _n_comp(&one_bok, &one_o, one, cop_o, c3n);
tot_s += _n_comp(&two_bok, &two_o, two, cop_o, c3n);
if ( c3y == one_o ) {
if ( c3y == two_o ) {
_n_apen(ops, one_bok);
_n_apen(ops, two_bok);
2018-02-07 21:26:06 +03:00
*lev_o = c3y;
2018-02-06 04:04:41 +03:00
}
else {
_n_apen(ops, one_bok);
2018-02-06 04:04:41 +03:00
tot_s += _n_emit(ops, SWAP);
_n_apen(ops, two_bok);
2018-02-07 21:26:06 +03:00
*lev_o = c3n;
2018-02-06 04:04:41 +03:00
}
}
else {
if ( c3y == two_o ) {
2018-02-07 21:26:06 +03:00
_n_apen(ops, one_bok);
_n_apen(ops, two_bok);
*lev_o = c3n;
}
else {
tot_s += _n_emit(ops, COPY);
2018-02-07 21:26:06 +03:00
_n_apen(ops, one_bok);
tot_s += _n_emit(ops, SWAP);
2018-02-07 21:26:06 +03:00
_n_apen(ops, two_bok);
*lev_o = c3n;
}
2018-02-06 04:04:41 +03:00
}
2018-02-06 04:04:41 +03:00
return tot_s;
}
2018-02-01 20:04:47 +03:00
/* _n_bint(): hint-processing helper for _n_comp.
* hif: hint-formula (first part of 10). RETAIN.
* nef: next-formula (second part of 10). RETAIN.
*/
static c3_s
_n_bint(u3_noun* ops, c3_o* tos_o, u3_noun hif, u3_noun nef, c3_o tel_o)
2018-01-31 03:27:04 +03:00
{
2018-02-07 21:26:06 +03:00
*tos_o = c3n;
// XX todo: hints don't currently participate in optimization because it's
// complicated and i want to test it without them.
2018-01-31 03:27:04 +03:00
if ( c3n == u3du(hif) ) {
// no currently recognized static hints
return _n_comp(ops, tos_o, nef, tel_o);
2018-01-31 03:27:04 +03:00
}
else {
2018-02-07 21:26:06 +03:00
c3_s tot_s = 0;
u3_noun zep, hod;
2018-01-31 03:27:04 +03:00
u3x_cell(hif, &zep, &hod);
switch ( zep ) {
default:
2018-02-07 21:26:06 +03:00
tot_s += _n_one(ops, tos_o, hod);
tot_s += _n_emit(ops, TOSS);
tot_s += _n_comp(ops, tos_o, nef, tel_o);
2018-01-31 03:27:04 +03:00
break;
case c3__hunk:
case c3__lose:
case c3__mean:
case c3__spot:
2018-02-07 21:26:06 +03:00
tot_s += _n_one(ops, tos_o, hod);
tot_s += _n_emit(ops, u3nc(QUIP, zep));
tot_s += _n_emit(ops, SNOC);
tot_s += _n_emit(ops, CUSH);
2018-02-07 21:26:06 +03:00
tot_s += _n_comp(ops, tos_o, nef, c3n);
tot_s += _n_emit(ops, DROP);
2018-01-31 03:27:04 +03:00
break;
case c3__live: {
u3_noun yep = u3_nul,
nop = u3_nul;
c3_s y_s = 0,
n_s = 0;
2018-02-07 21:26:06 +03:00
tot_s += _n_one(ops, tos_o, hod);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, PEEP);
n_s += _n_emit(&nop, HECK);
y_s += _n_emit(&yep, TOSS);
y_s += _n_emit(&yep, _n_skip(n_s));
tot_s += _n_emit(ops, _n_skin(y_s));
_n_apen(ops, yep); tot_s += y_s;
_n_apen(ops, nop); tot_s += n_s;
2018-02-07 21:26:06 +03:00
tot_s += _n_comp(ops, tos_o, nef, tel_o);
2018-01-31 03:27:04 +03:00
break;
}
2018-01-31 03:27:04 +03:00
case c3__slog:
2018-02-07 21:26:06 +03:00
tot_s += _n_one(ops, tos_o, hod);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, SLOG);
2018-02-07 21:26:06 +03:00
tot_s += _n_comp(ops, tos_o, nef, tel_o);
2018-01-31 03:27:04 +03:00
break;
// germ and sole are unused...
2018-01-31 03:27:04 +03:00
case c3__fast:
2018-02-07 21:26:06 +03:00
tot_s += _n_two(ops, tos_o, hod, nef);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, FAST);
break;
case c3__memo: {
u3_noun nop = u3_nul,
yep = u3_nul;
c3_s y_s = 0,
n_s = 0; // top->[bus]
tot_s += _n_emit(ops, COPY); // [bus bus]
2018-02-07 21:26:06 +03:00
tot_s += _n_one(ops, tos_o, hod); // [clue bus bus]
tot_s += _n_emit(ops, TOSS); // [bus bus]
tot_s += _n_emit(ops, u3nc(QUIP, u3k(nef))); // [fol bus bus]
2018-02-01 20:21:10 +03:00
tot_s += _n_emit(ops, SNOC); // [[bus fol] bus]
tot_s += _n_emit(ops, GEMO); // [u key bus]
tot_s += _n_emit(ops, PEEP); // [b u key bus]
// NO branch, i.e. gemo gave us ~
n_s += _n_emit(&nop, TOSS); // [key bus]
n_s += _n_emit(&nop, SWAP); // [bus key]
2018-02-07 21:26:06 +03:00
n_s += _n_comp(&nop, tos_o, nef, c3n); // [pro key]
n_s += _n_emit(&nop, PUMO);
// YES branch, i.e. gemo gave us [0 pro]
y_s += _n_emit(&yep, TAIL); // [pro key bus]
y_s += _n_emit(&yep, SWAT); // [pro bus]
y_s += _n_emit(&yep, _n_skip(n_s));
tot_s += _n_emit(ops, _n_skin(y_s));
2018-02-01 20:21:10 +03:00
_n_apen(ops, yep); tot_s += y_s;
_n_apen(ops, nop); tot_s += n_s;
// both branches leave an extra value under the top
tot_s += _n_emit(ops, SWAT);
2018-01-31 03:27:04 +03:00
break;
}
}
return tot_s;
}
}
2018-02-07 21:26:06 +03:00
/* _n_comp(): compile nock formula to reversed opcode list
* ops is a pointer to a list (to be emitted to)
* lev_o is written: c3y/n whether the operand is left on the stack
* fol is the nock formula to compile. RETAIN.
* cop_o indicates the subject/product stack position is a COPY
* if this is taken advantage of (lev_o), the caller should
* omit the COPY
* tel_o is yes if this formula is in tail position
* return: the number of bytes needed for this opcode list
2018-02-01 20:04:47 +03:00
*/
2018-01-31 03:27:04 +03:00
static c3_s
2018-02-07 21:26:06 +03:00
_n_comp(u3_noun* ops, c3_o* lev_o, u3_noun fol, c3_o cop_o, c3_o tel_o) {
2018-01-31 03:27:04 +03:00
c3_s tot_s = 0;
2018-02-07 21:26:06 +03:00
c3_y op_y;
2018-01-31 03:27:04 +03:00
u3_noun cod, arg, hed, tel;
u3x_cell(fol, &cod, &arg);
if ( c3y == u3du(cod) ) {
2018-02-07 21:26:06 +03:00
tot_s += _n_two(ops, lev_o, cod, arg, cop_o);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, CONS);
}
else switch ( cod ) {
case 0:
2018-02-07 21:26:06 +03:00
c3_assert( c3y == u3ud(arg) );
2018-01-31 03:27:04 +03:00
switch ( arg ) {
case 0:
tot_s += _n_emit(ops, BAIL);
break;
case 1:
break;
case 2:
2018-02-07 21:26:06 +03:00
tot_s += _n_emit(ops, (c3y == cop_o) ? HELD : HEAD);
2018-01-31 03:27:04 +03:00
break;
case 3:
2018-02-07 21:26:06 +03:00
tot_s += _n_emit(ops, (c3y == cop_o) ? TALL : TAIL);
2018-01-31 03:27:04 +03:00
break;
2018-02-07 21:26:06 +03:00
default:
op_y = (c3y == cop_o)
? (arg < 0xFF ? GRAB : arg < 0xFFFF ? GRAS : GRAN)
: (arg < 0xFF ? FRAG : arg < 0xFFFF ? FRAS : FRAG);
tot_s += _n_emit(ops, u3nc(op_y, arg));
2018-02-05 21:27:39 +03:00
break;
2018-01-31 03:27:04 +03:00
}
2018-02-07 21:26:06 +03:00
*lev_o = cop_o;
2018-01-31 03:27:04 +03:00
break;
case 1:
2018-02-07 21:26:06 +03:00
op_y = (c3y == cop_o) ? QUIP : QUOT;
tot_s += _n_emit(ops, u3nc(op_y, u3k(arg)));
*lev_o = cop_o;
2018-01-31 03:27:04 +03:00
break;
case 2:
u3x_cell(arg, &hed, &tel);
2018-02-07 21:26:06 +03:00
tot_s += _n_two(ops, lev_o, hed, tel, cop_o);
tot_s += _n_emit(ops, (c3y == tel_o)? NOCT : NOCK);
2018-01-31 03:27:04 +03:00
break;
case 3:
tot_s += _n_comp(ops, tos_o, arg, c3n);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, DEEP);
break;
case 4:
tot_s += _n_comp(ops, tos_o, arg, c3n);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, BUMP);
break;
case 5:
u3x_cell(arg, &hed, &tel);
tot_s += _n_two(ops, tos_o, hed, tel);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, SAME);
break;
case 6: {
u3_noun mid, tes, yep, nop;
2018-02-07 21:26:06 +03:00
c3_s yep_s, nop_s, tes_s;
c3_o ban_o, yep_o, nop_o;
2018-01-31 03:27:04 +03:00
u3x_trel(arg, &hed, &mid, &tel);
yep = u3_nul;
yep_o = *tos_o;
yep_s = _n_comp(&yep, &yep_o, mid, tel_o);
2018-01-31 03:27:04 +03:00
nop = u3_nul;
nop_o = yep_o;
nop_s = _n_comp(&nop, &nop_o, tel, tel_o);
2018-01-31 03:27:04 +03:00
if ( yep_o == nop_o ) {
ban_o = yep_o;
}
else {
if ( c3y == yep_o ) {
u3z(yep);
2018-02-07 21:26:06 +03:00
yep = u3_nul;
yep_s = _n_comp(&yep, &n_o, mid, tel_o);
}
else {
2018-02-07 21:26:06 +03:00
u3z(nop);
nop = u3_nul;
nop_s = _n_comp(&nop, &n_o, tel, tel_o);
}
ban_o = c3n;
}
tes = u3_nul;
tes_s = ( c3y == ban_o )
? _n_comp(&tes, tos_o, hed, c3n)
: _n_one(&tes, tos_o, hed);
tot_s += tes_s; _n_apen(ops, tes);
yep_s += _n_emit(&yep, _n_skip(nop_s));
tot_s += _n_emit(ops, _n_skin(yep_s));
tot_s += yep_s; _n_apen(ops, yep);
tot_s += nop_s; _n_apen(ops, nop);
2018-01-31 03:27:04 +03:00
break;
}
case 7:
2018-01-31 03:27:04 +03:00
u3x_cell(arg, &hed, &tel);
tot_s += _n_comp(ops, tos_o, hed, c3n);
tot_s += _n_comp(ops, &n_o, tel, tel_o);
2018-01-31 03:27:04 +03:00
break;
case 8: {
u3_noun aft;
c3_o aft_o;
2018-01-31 03:27:04 +03:00
u3x_cell(arg, &hed, &tel);
aft = u3_nul;
aft_o = *tos_o;
tot_s = _n_comp(&aft, &aft_o, tel, tel_o);
if ( c3y == aft_o ) {
tot_s += _n_comp(ops, tos_o, hed, c3n);
tot_s += _n_emit(ops, TOSS);
}
else {
tot_s += _n_one(ops, tos_o, hed);
tot_s += _n_emit(ops, SNOC);
*tos_o = c3n;
}
_n_apen(ops, aft);
2018-01-31 03:27:04 +03:00
break;
}
2018-01-31 03:27:04 +03:00
case 9:
u3x_cell(arg, &hed, &tel);
if ( 3 == u3qc_cap(hed) ) {
u3_noun mac = u3nq(7, u3k(tel), 2, u3nt(u3nc(0, 1), 0, u3k(hed)));
tot_s += _n_comp(ops, tos_o, mac, tel_o);
2018-01-31 03:27:04 +03:00
u3z(mac);
}
else {
tot_s += _n_comp(ops, tos_o, tel, c3n);
2018-02-05 22:20:34 +03:00
tot_s += _n_emit(ops, u3nc(
(c3y == tel_o)
? (hed < 0xFF ? TICB : hed < 0xFFFF ? TICS : TICK)
: (hed < 0xFF ? KICB : hed < 0xFFFF ? KICS : KICK),
u3k(hed)));
2018-01-31 03:27:04 +03:00
}
break;
case 10:
u3x_cell(arg, &hed, &tel);
tot_s += _n_bint(ops, tos_o, hed, tel, tel_o);
2018-01-31 03:27:04 +03:00
break;
case 11:
u3x_cell(arg, &hed, &tel);
tot_s += _n_two(ops, tos_o, hed, tel);
2018-01-31 03:27:04 +03:00
tot_s += _n_emit(ops, WISH);
break;
}
return tot_s;
}
static void _n_print_byc(c3_y* pog);
2018-02-01 20:04:47 +03:00
/* _n_asm(): assemble an accumulated list of instructions (i.e. from _n_comp)
*/
2018-01-31 03:27:04 +03:00
static c3_y*
_n_asm(u3_noun ops, c3_s len_s)
2018-01-31 03:27:04 +03:00
{
u3_noun top = ops;
c3_y* buf_y = u3a_malloc(sizeof(c3_y) * (len_s+1));
c3_s i_s = len_s;
2018-01-31 03:27:04 +03:00
buf_y[i_s] = HALT;
2018-02-01 20:21:10 +03:00
while ( i_s-- > 0 ) {
2018-01-31 03:27:04 +03:00
u3_noun op = u3h(ops);
if ( c3y == u3ud(op) ) {
buf_y[i_s] = (c3_y) u3h(ops);
}
else {
u3_noun cod = u3h(op);
switch ( cod ) {
case SBIP:
case SBIN:
2018-02-05 22:20:34 +03:00
case KICB:
case TICB:
case FRAB:
buf_y[i_s--] = (c3_y) u3t(op);
buf_y[i_s] = (c3_y) cod;
break;
case KICS:
case TICS:
case FRAS:
2018-01-31 03:27:04 +03:00
case SKIP:
case SKIN: {
2018-02-01 20:21:10 +03:00
c3_s off_s = u3t(op);
2018-01-31 03:27:04 +03:00
buf_y[i_s--] = (c3_y) (off_s >> 8);
buf_y[i_s--] = (c3_y) off_s;
buf_y[i_s] = (c3_y) cod;
break;
}
2018-02-05 22:20:34 +03:00
case FRAG:
2018-01-31 03:27:04 +03:00
case QUOT:
case QUIP:
case TICK:
case KICK: {
2018-02-01 20:21:10 +03:00
c3_w non_w = u3k(u3t(op));
2018-01-31 03:27:04 +03:00
buf_y[i_s--] = (c3_y) (non_w >> 24);
buf_y[i_s--] = (c3_y) (non_w >> 16);
buf_y[i_s--] = (c3_y) (non_w >> 8);
buf_y[i_s--] = (c3_y) non_w;
buf_y[i_s] = (c3_y) cod;
break;
}
default:
c3_assert(0);
}
}
ops = u3t(ops);
}
2018-02-01 20:21:10 +03:00
u3z(top);
2018-01-31 03:27:04 +03:00
return buf_y;
}
2018-02-01 20:04:47 +03:00
/* _n_push(): push a noun onto the stack. RETAIN
* mov: -1 north, 1 south
* off: 0 north, -1 south
2018-02-01 20:04:47 +03:00
*/
2018-01-31 03:27:04 +03:00
static inline void
_n_push(c3_ys mov, c3_ys off, u3_noun a)
2018-01-31 03:27:04 +03:00
{
u3R->cap_p += mov;
u3_noun* p = u3to(u3_noun, u3R->cap_p + off);
//u3_noun* p = (u3_noun*) u3a_push(sizeof(u3_noun));
2018-01-31 03:27:04 +03:00
*p = a;
}
/* _n_peek(): pointer to noun at top of stack
* off: 0 north, -1 south
2018-02-01 20:04:47 +03:00
*/
2018-01-31 03:27:04 +03:00
static inline u3_noun*
_n_peek(c3_ys off)
2018-01-31 03:27:04 +03:00
{
return u3to(u3_noun, u3R->cap_p + off);
//return (u3_noun*) u3a_peek(sizeof(u3_noun));
2018-01-31 03:27:04 +03:00
}
2018-02-01 20:04:47 +03:00
/* _n_peet(): address of the next-to-top of stack
* mov: -1 north, 1 south
* off: 0 north, -1 south
2018-02-01 20:04:47 +03:00
*/
static inline u3_noun*
_n_peet(c3_ys mov, c3_ys off)
{
return u3to(u3_noun, (u3R->cap_p - mov) + off);
// return u3to(u3_noun, u3R->cap_p + (_(u3a_is_north(u3R)) ? 1 : -2));
}
2018-02-01 20:04:47 +03:00
/* _n_pop(): pop a noun from the cap stack
* mov: -1 north, 1 south
*/
static inline void
_n_pop(c3_ys mov)
{
u3R->cap_p -= mov;
}
/* _n_pep(): pop and return noun from the cap stack
* mov: -1 north, 1 south
* off: 0 north, -1 south
2018-02-01 20:04:47 +03:00
*/
2018-01-31 03:27:04 +03:00
static inline u3_noun
_n_pep(c3_ys mov, c3_ys off)
2018-01-31 03:27:04 +03:00
{
u3_noun r = *(_n_peek(off));
_n_pop(mov);
2018-01-31 03:27:04 +03:00
return r;
}
/* _n_toss(): pep and lose
2018-02-01 20:04:47 +03:00
*/
2018-01-31 03:27:04 +03:00
static inline void
_n_toss(c3_ys mov, c3_ys off)
2018-01-31 03:27:04 +03:00
{
u3z(_n_pep(mov, off));
2018-01-31 03:27:04 +03:00
}
2018-02-01 20:04:47 +03:00
/* _n_rean(): read a c3_s from the bytecode stream
*/
2018-01-31 03:27:04 +03:00
static inline c3_s
_n_resh(c3_y* buf, c3_s* ip_s)
{
c3_y les = buf[(*ip_s)++];
c3_y mos = buf[(*ip_s)++];
return les | (mos << 8);
}
2018-02-01 20:04:47 +03:00
/* _n_rean(): read a noun from the bytecode stream
*/
2018-01-31 03:27:04 +03:00
static inline u3_noun
_n_rean(c3_y* buf, c3_s* ip_s)
{
c3_y one = buf[(*ip_s)++],
two = buf[(*ip_s)++],
tre = buf[(*ip_s)++],
qua = buf[(*ip_s)++];
return one | (two << 8) | (tre << 16) | (qua << 24);
}
2018-02-01 20:04:47 +03:00
/* _n_bite(): compile a nock formula to bytecode
*/
2018-01-31 03:27:04 +03:00
static inline c3_y*
_n_bite(u3_noun fol)
{
u3_noun bok = u3_nul;
2018-02-07 21:26:06 +03:00
c3_o tos_o = c3n;
c3_s len_s = _n_comp(&bok, &tos_o, fol, c3y);
c3_y* buf_y = _n_asm(bok, len_s);
2018-02-06 04:04:41 +03:00
u3m_p("fol", fol);
2018-02-05 21:27:39 +03:00
_n_print_byc(buf_y);
return buf_y;
2018-01-31 03:27:04 +03:00
}
2018-02-01 20:04:47 +03:00
/* _n_find(): return bytecode for given formula. fol is RETAINED.
*/
static inline c3_y*
2018-01-31 03:27:04 +03:00
_n_find(u3_noun fol)
{
u3_noun got = u3h_get(u3R->byc.har_p, fol);
if ( u3_none != got ) {
2018-02-01 20:21:10 +03:00
return u3a_into(got);
2018-01-31 03:27:04 +03:00
}
else {
c3_y* gop = _n_bite(fol);
2018-02-01 20:21:10 +03:00
got = u3a_outa(gop);
2018-01-31 03:27:04 +03:00
u3h_put(u3R->byc.har_p, fol, got);
return gop;
}
}
2018-02-06 02:26:17 +03:00
typedef struct {
c3_y* pog;
c3_s ip_s;
} burnframe;
/* _n_burn(): pog: program
* bus: subject
* mov: -1 north, 1 south
* off: 0 north, -1 south
*/
2018-02-06 02:26:17 +03:00
static u3_noun
_n_burn(c3_y* pog, u3_noun bus, c3_ys mov, c3_ys off)
2018-01-31 03:27:04 +03:00
{
/* OPCODE TABLE */
2018-01-31 03:27:04 +03:00
static void* lab[] = {
&&do_halt, &&do_copy, &&do_toss,
&&do_swap, &&do_swat,
&&do_skip, &&do_skin,
&&do_sbip, &&do_sbin,
&&do_cons, &&do_snoc,
2018-02-05 21:27:39 +03:00
&&do_head, &&do_tail,
2018-02-05 22:20:34 +03:00
&&do_frag, &&do_fras, &&do_frab,
2018-01-31 03:27:04 +03:00
&&do_quot, &&do_quip,
&&do_nock, &&do_noct,
&&do_deep, &&do_peep,
&&do_bump, &&do_same,
2018-02-05 22:20:34 +03:00
&&do_kick, &&do_kics, &&do_kicb,
&&do_tick, &&do_tics, &&do_ticb,
&&do_wish, &&do_fast,
&&do_cush, &&do_drop,
&&do_pumo, &&do_gemo,
2018-02-01 20:04:47 +03:00
&&do_heck, &&do_slog, &&do_bail
2018-01-31 03:27:04 +03:00
};
c3_s sip_s, ip_s = 0;
u3_noun* top;
u3_noun* up;
u3_noun x, o;
2018-02-06 02:26:17 +03:00
u3p(void) empty;
burnframe* fam;
2018-02-01 20:04:47 +03:00
2018-02-06 02:26:17 +03:00
empty = u3R->cap_p;
_n_push(mov, off, bus);
2018-01-31 03:27:04 +03:00
#define BURN() goto *lab[pog[ip_s++]]
2018-01-31 03:27:04 +03:00
BURN();
while ( 1 ) {
do_halt:
2018-02-06 02:26:17 +03:00
x = _n_pep(mov, off);
if ( empty == u3R->cap_p ) {
return x;
}
else {
fam = u3to(burnframe, u3R->cap_p) + off;
pog = fam->pog;
ip_s = fam->ip_s;
u3R->cap_p = u3of(burnframe, fam - mov);
_n_push(mov, off, x);
BURN();
}
2018-01-31 03:27:04 +03:00
do_copy:
top = _n_peek(off);
_n_push(mov, off, u3k(*top));
2018-01-31 03:27:04 +03:00
BURN();
do_toss:
_n_toss(mov, off);
BURN();
2018-01-31 03:27:04 +03:00
do_swap:
top = _n_peek(off);
up = _n_peet(mov, off);
2018-01-31 03:27:04 +03:00
x = *top;
*top = *up;
*up = x;
BURN();
do_swat:
top = _n_peek(off);
up = _n_peet(mov, off);
x = *top;
*top = *up;
*up = x;
_n_toss(mov, off);
2018-01-31 03:27:04 +03:00
BURN();
do_skip:
ip_s += _n_resh(pog, &ip_s);
BURN();
do_sbip:
ip_s += pog[ip_s] + 1;
BURN();
2018-01-31 03:27:04 +03:00
do_skin:
sip_s = _n_resh(pog, &ip_s);
goto skin_in;
do_sbin:
sip_s = pog[ip_s++];
skin_in:
x = _n_pep(mov, off);
2018-01-31 03:27:04 +03:00
if ( c3n == x ) {
ip_s += sip_s;
}
else if ( c3y != x ) {
2018-02-01 20:21:10 +03:00
u3m_bail(c3__exit);
2018-02-06 02:26:17 +03:00
return u3_none;
2018-01-31 03:27:04 +03:00
}
BURN();
do_cons:
x = _n_pep(mov, off);
top = _n_peek(off);
2018-01-31 03:27:04 +03:00
*top = u3nc(*top, x);
BURN();
do_snoc:
x = _n_pep(mov, off);
top = _n_peek(off);
2018-01-31 03:27:04 +03:00
*top = u3nc(x, *top);
BURN();
do_head:
top = _n_peek(off);
2018-01-31 03:27:04 +03:00
o = *top;
if ( c3n == u3du(o) ) {
2018-02-01 20:21:10 +03:00
u3m_bail(c3__exit);
2018-02-06 02:26:17 +03:00
return u3_none;
2018-01-31 03:27:04 +03:00
}
*top = u3k(u3h(o));
u3z(o);
BURN();
do_tail:
top = _n_peek(off);
2018-01-31 03:27:04 +03:00
o = *top;
if ( c3n == u3du(o) ) {
2018-02-01 20:21:10 +03:00
u3m_bail(c3__exit);
2018-02-06 02:26:17 +03:00
return u3_none;
2018-01-31 03:27:04 +03:00
}
*top = u3k(u3t(o));
u3z(o);
BURN();
2018-02-05 22:20:34 +03:00
do_fras:
x = _n_resh(pog, &ip_s);
goto frag_in;
2018-01-31 03:27:04 +03:00
2018-02-05 22:20:34 +03:00
do_frag:
x = _n_rean(pog, &ip_s);
goto frag_in;
2018-02-05 21:27:39 +03:00
2018-02-05 22:20:34 +03:00
do_frab:
x = pog[ip_s++];
frag_in:
top = _n_peek(off);
2018-02-05 22:20:34 +03:00
o = *top;
*top = u3k(u3r_at(x, o));
u3z(o);
2018-02-05 21:27:39 +03:00
BURN();
2018-01-31 03:27:04 +03:00
do_quot:
_n_toss(mov, off);
2018-01-31 03:27:04 +03:00
do_quip:
_n_push(mov, off, u3k(_n_rean(pog, &ip_s)));
2018-01-31 03:27:04 +03:00
BURN();
do_nock:
2018-02-06 02:26:17 +03:00
o = _n_pep(mov, off);
x = _n_pep(mov, off);
fam = u3to(burnframe, u3R->cap_p) + off + mov;
u3R->cap_p = u3of(burnframe, fam);
fam->ip_s = ip_s;
fam->pog = pog;
pog = _n_find(o);
ip_s = 0;
2018-02-01 20:04:47 +03:00
u3z(o);
2018-02-06 02:26:17 +03:00
_n_push(mov, off, x);
2018-01-31 03:27:04 +03:00
BURN();
do_noct:
o = _n_pep(mov, off);
2018-02-01 20:04:47 +03:00
pog = _n_find(o);
2018-01-31 03:27:04 +03:00
ip_s = 0;
2018-02-01 20:04:47 +03:00
u3z(o);
2018-01-31 03:27:04 +03:00
BURN();
do_deep:
top = _n_peek(off);
2018-01-31 03:27:04 +03:00
o = *top;
*top = u3du(o);
u3z(o);
BURN();
do_peep:
top = _n_peek(off);
_n_push(mov, off, u3du(*top));
2018-01-31 03:27:04 +03:00
BURN();
do_bump:
top = _n_peek(off);
2018-01-31 03:27:04 +03:00
o = *top;
*top = u3i_vint(o);
u3z(o);
BURN();
do_same:
x = _n_pep(mov, off);
top = _n_peek(off);
2018-01-31 03:27:04 +03:00
o = *top;
*top = u3r_sing(x, o);
u3z(x);
u3z(o);
BURN();
2018-01-31 05:14:37 +03:00
2018-02-05 22:20:34 +03:00
do_kics:
x = _n_resh(pog, &ip_s);
goto kick_in;
2018-01-31 05:14:37 +03:00
do_kick:
2018-02-05 22:20:34 +03:00
x = _n_rean(pog, &ip_s);
goto kick_in;
do_kicb:
x = pog[ip_s++];
kick_in:
top = _n_peek(off);
2018-01-31 05:14:37 +03:00
o = *top;
u3t_off(noc_o);
*top = u3j_kick(o, x);
u3t_on(noc_o);
if ( u3_none == *top ) {
u3_noun fol = u3r_at(x, o);
if ( u3_none == fol ) {
2018-02-01 20:21:10 +03:00
u3m_bail(c3__exit);
2018-02-06 02:26:17 +03:00
return u3_none;
2018-01-31 05:14:37 +03:00
}
2018-02-06 02:26:17 +03:00
_n_pop(mov);
fam = u3to(burnframe, u3R->cap_p) + off + mov;
u3R->cap_p = u3of(burnframe, fam);
fam->ip_s = ip_s;
fam->pog = pog;
pog = _n_find(fol);
ip_s = 0;
_n_push(mov, off, o);
2018-01-31 05:14:37 +03:00
}
BURN();
2018-02-05 22:20:34 +03:00
do_tics:
x = _n_resh(pog, &ip_s);
goto tick_in;
2018-01-31 05:14:37 +03:00
do_tick:
2018-02-05 22:20:34 +03:00
x = _n_rean(pog, &ip_s);
goto tick_in;
do_ticb:
x = pog[ip_s++];
tick_in:
top = _n_peek(off);
2018-01-31 05:14:37 +03:00
o = *top;
u3t_off(noc_o);
*top = u3j_kick(o, x);
u3t_on(noc_o);
if ( u3_none == *top ) {
u3_noun fol = u3r_at(x, o);
if ( u3_none == fol ) {
2018-02-01 20:21:10 +03:00
u3m_bail(c3__exit);
2018-02-06 02:26:17 +03:00
return u3_none;
2018-01-31 05:14:37 +03:00
}
*top = o;
pog = _n_find(fol);
ip_s = 0;
}
BURN();
do_fast: // top->[pro clu]
top = _n_peek(off);
up = _n_peet(mov, off);
u3t_off(noc_o);
u3j_mine(*up, u3k(*top));
u3t_on(noc_o);
*up = *top;
2018-02-06 02:26:17 +03:00
_n_pop(mov);
BURN();
do_wish:
top = _n_peek(off);
up = _n_peet(mov, off);
u3t_off(noc_o);
x = u3m_soft_esc(*up, u3k(*top));
u3t_on(noc_o);
if ( c3n == u3du(x) ) {
2018-02-01 20:21:10 +03:00
u3m_bail(u3nt(1, *top, 0));
2018-02-06 02:26:17 +03:00
return u3_none;
}
else if ( c3n == u3du(u3t(x)) ) {
// replace with proper error stack push
u3t_push(u3nc(c3__hunk, _n_mush(*top)));
2018-02-01 20:21:10 +03:00
u3m_bail(c3__exit);
2018-02-06 02:26:17 +03:00
return u3_none;
}
else {
u3z(*top);
*top = u3k(u3t(u3t(x)));
u3z(x);
BURN();
}
do_cush:
u3t_push(_n_pep(mov, off));
BURN();
do_drop:
u3t_drop();
BURN();
do_pumo: // top->[pro key]
if ( &(u3H->rod_u) != u3R ) {
top = _n_peek(off);
up = _n_peet(mov, off);
u3z_save(144 + c3__nock, *up, *top);
}
BURN();
do_gemo:
top = _n_peek(off);
x = u3z_find(144 + c3__nock, *top);
_n_push(mov, off, (u3_none == x ? 0 : u3nc(0, x)));
BURN();
do_heck:
u3t_off(noc_o);
u3t_heck(_n_pep(mov, off));
u3t_on(noc_o);
BURN();
do_slog:
x = _n_pep(mov, off);
2018-02-01 20:04:47 +03:00
if ( !(u3C.wag_w & u3o_quiet) ) {
u3t_off(noc_o);
u3t_slog(x);
u3t_on(noc_o);
}
else {
u3z(x);
}
BURN();
2018-02-01 20:04:47 +03:00
do_bail:
2018-02-01 20:21:10 +03:00
u3m_bail(c3__exit);
2018-02-06 02:26:17 +03:00
return u3_none;
2018-01-31 03:27:04 +03:00
}
}
2018-02-01 20:04:47 +03:00
static void
_n_print_byc(c3_y* pog)
{
static char* names[] = {
"halt", "copy", "toss",
"swap", "swat",
"skip", "skin",
"sbip", "sbin",
"cons", "snoc",
2018-02-05 21:27:39 +03:00
"head", "tail",
2018-02-05 22:20:34 +03:00
"frag", "fras", "frab",
"quot", "quip",
"nock", "noct",
"deep", "peep",
"bump", "same",
2018-02-05 22:20:34 +03:00
"kick", "kics", "kicb",
"tick", "tics", "ticb",
"wish", "fast",
"cush", "drop",
"pumo", "gemo",
"heck", "slog", "bail"
};
c3_s ip_s = 0;
printf("bytecode: {");
int first = 1;
while ( pog[ip_s] ) {
if ( first ) {
first = 0;
}
else {
printf(" ");
}
switch ( pog[ip_s] ) {
default:
printf("%s", names[pog[ip_s++]]);
break;
case SBIP:
case SBIN:
2018-02-05 22:20:34 +03:00
case KICB:
case TICB:
case FRAB:
printf("[%s ", names[pog[ip_s++]]);
printf("%d]", pog[ip_s++]);
break;
case KICS:
case TICS:
case FRAS:
case SKIP:
case SKIN:
printf("[%s ", names[pog[ip_s++]]);
printf("%d]", _n_resh(pog, &ip_s));
break;
case QUOT:
case QUIP:
case TICK:
2018-02-05 22:20:34 +03:00
case FRAG:
case KICK:
printf("[%s ", names[pog[ip_s++]]);
printf("%d]", _n_rean(pog, &ip_s));
break;
}
}
printf(" halt}\r\n");
}
static void _n_print_stack(u3p(u3_noun) empty) {
c3_w cur_p = u3R->cap_p;
printf("[");
int first = 1;
while ( cur_p != empty ) {
if ( first ) {
first = 0;
}
else {
printf(" ");
}
if ( c3y == u3a_is_north(u3R) ) {
printf("%d", *(u3to(u3_noun, cur_p)));
cur_p++;
}
else {
printf("%d", *(u3to(u3_noun, cur_p-1)));
cur_p--;
}
}
printf("]\r\n");
}
2018-02-01 20:04:47 +03:00
/* _n_burn_on(): produce .*(bus fol) with bytecode interpreter
*/
static u3_noun
_n_burn_on(u3_noun bus, u3_noun fol)
{
c3_y* pog = _n_find(fol);
c3_ys mov, off;
2018-02-01 20:04:47 +03:00
u3z(fol);
if ( c3y == u3a_is_north(u3R) ) {
mov = -1;
off = 0;
}
else {
mov = 1;
off = -1;
}
2018-02-06 02:26:17 +03:00
return _n_burn(pog, bus, mov, off);
2018-02-01 20:04:47 +03:00
}
u3_noun
u3n_burn_on(u3_noun bus, u3_noun fol)
{
u3_noun pro;
u3t_on(noc_o);
pro = _n_burn_on(bus, fol);
u3t_off(noc_o);
return pro;
}
2018-02-05 21:27:39 +03:00
/* u3n_beep(): promote bytecode state.
*/
void
u3n_beep(u3p(u3h_root) har_p)
{
u3m_p("beep", 0);
}