/* g/j.c ** */ #include "all.h" /* _cj_count(): count and link dashboard entries. */ static c3_w _cj_count(u3j_core* par_u, u3j_core* dev_u) { c3_w len_l = 0; c3_w i_w; if ( dev_u ) { for ( i_w = 0; 0 != dev_u[i_w].cos_c; i_w++ ) { u3j_core* kid_u = &dev_u[i_w]; kid_u->par_u = par_u; len_l += _cj_count(kid_u, kid_u->dev_u); } } return 1 + len_l; } /* _cj_install(): install dashboard entries. */ static c3_w _cj_install(u3j_core* ray_u, c3_w jax_l, u3j_core* dev_u) { c3_w i_w; if ( dev_u ) { for ( i_w = 0; 0 != dev_u[i_w].cos_c; i_w++ ) { u3j_core* kid_u = &dev_u[i_w]; kid_u->jax_l = jax_l; ray_u[jax_l++] = *kid_u; jax_l = _cj_install(ray_u, jax_l, kid_u->dev_u); } } return jax_l; } /* _cj_axis(): axis from formula, or 0. `fol` is RETAINED. */ static c3_l _cj_axis(u3_noun fol) { u3_noun p_fol, q_fol, r_fol; while ( _(u3du(fol)) && (10 == u3h(fol)) ) { fol = u3t(u3t(fol)); } if ( !_(u3r_trel(fol, &p_fol, &q_fol, &r_fol)) ) { if ( !_(u3r_cell(fol, &p_fol, &q_fol)) || (0 != p_fol) || (!_(u3a_is_cat(q_fol))) ) { fprintf(stderr, "axis: bad a\r\n"); return 0; } return q_fol; } else { if ( 9 != p_fol ) { fprintf(stderr, "axis: bad b\r\n"); return 0; } if ( !_(u3a_is_cat(q_fol)) ) { fprintf(stderr, "axis: bad c\r\n"); return 0; } if ( !_(u3du(r_fol)) || (0 != u3h(r_fol)) || (1 != u3t(r_fol)) ) { fprintf(stderr, "axis: bad d\r\n"); return 0; } return q_fol; } } #if 0 /* _cj_by_gut(): (~(get by a) b), unifying; RETAINS a, b, AND result. */ static u3_weak _cj_by_gut(u3_noun a, u3_noun b) { if ( u3_nul == a ) { return u3_none; } else { u3_noun l_a, n_a, r_a; u3_noun pn_a, qn_a; u3x_trel(a, &n_a, &l_a, &r_a); u3x_cell(n_a, &pn_a, &qn_a); { if ( (c3y == u3r_sing(b, pn_a)) ) { return qn_a; } else { if ( c3y == u3qc_gor(b, pn_a) ) { return _cj_by_gut(l_a, b); } else return _cj_by_gut(r_a, b); } } } } #endif /* _cj_chum(): decode chum as string. */ static c3_c* _cj_chum(u3_noun chu) { if ( _(u3ud(chu)) ) { return u3r_string(chu); } else { u3_noun h_chu = u3h(chu); u3_noun t_chu = u3t(chu); if ( !_(u3a_is_cat(t_chu)) ) { return 0; } else { c3_c* h_chu_c = u3r_string(h_chu); c3_c buf[33]; memset(buf, 0, 33); snprintf(buf, 32, "%s%d", h_chu_c, t_chu); free(h_chu_c); return strdup(buf); } } } /* _cj_je_fsck: fsck:je, or none. */ static u3_noun _cj_je_fsck(u3_noun clu) { u3_noun p_clu, q_clu, r_clu; u3_noun huk; c3_c* nam_c; c3_l axe_l; if ( c3n == u3r_trel(clu, &p_clu, &q_clu, &r_clu) ) { u3z(clu); return u3_none; } if ( 0 == (nam_c = _cj_chum(p_clu)) ) { u3z(clu); return u3_none; } while ( _(u3du(q_clu)) && (10 == u3h(q_clu)) ) { q_clu = u3t(u3t(q_clu)); } if ( !_(u3du(q_clu)) ) { u3z(clu); free(nam_c); return u3_none; } if ( (1 == u3h(q_clu)) && (0 == u3t(q_clu)) ) { axe_l = 0; } else { if ( (0 != u3h(q_clu)) || !_(u3a_is_cat(axe_l = u3t(q_clu))) ) { u3z(clu); free(nam_c); return u3_none; } } { huk = 0; while ( _(u3du(r_clu)) ) { u3_noun ir_clu, tr_clu, pir_clu, qir_clu; if ( (c3n == u3r_cell(r_clu, &ir_clu, &tr_clu)) || (c3n == u3r_cell(ir_clu, &pir_clu, &qir_clu)) || (c3n == u3ud(pir_clu)) ) { u3z(huk); u3z(clu); free(nam_c); return u3_none; } huk = u3kdb_put(huk, u3k(pir_clu), u3k(qir_clu)); r_clu = tr_clu; } } u3z(clu); return u3nt(u3i_string(nam_c), axe_l, huk); } /* _cj_find_cold(): search cold state for `bat`s registry. * RETAIN. */ static u3_weak _cj_find_cold(u3_noun bat) { u3a_road* rod_u = u3R; while ( 1 ) { u3_weak reg = u3h_gut(rod_u->jed.cod_p, bat); if ( u3_none != reg ) { return reg; } if ( rod_u->par_p ) { rod_u = u3to(u3_road, rod_u->par_p); } else return u3_none; } } /* _cj_find_warm(): search warm state for `loc`s activation. * RETAIN. */ static u3_weak _cj_find_warm(u3_noun loc) { u3a_road* rod_u = u3R; while ( 1 ) { u3_weak ank = u3h_gut(rod_u->jed.war_p, loc); if ( u3_none != ank ) { return ank; } if ( rod_u->par_p ) { rod_u = u3to(u3_road, rod_u->par_p); } else return u3_none; } } /* u3j_spot(): identify `cor`s location. RETAIN. */ u3_weak u3j_spot(u3_noun cor) { u3_weak reg = _cj_find_cold(u3h(cor)); if ( u3_none == reg ) { return u3_none; } else { u3_noun rut = u3h(reg), pas = u3t(reg), rum = u3qdb_get(rut, u3t(cor)); if ( u3_nul != rum ) { u3_noun loc = u3k(u3t(rum)); u3z(rum); u3z(reg); return loc; } else { while ( u3_nul != pas ) { u3_noun pap = u3h(pas), axe = u3h(pap), lol = u3t(pap); u3_weak par = u3r_at(axe, cor), pel; if ( u3_none != par ) { pel = u3j_spot(par); if ( u3_none != pel ) { u3_noun nit = u3qdb_get(lol, pel); u3z(pel); if ( u3_nul != nit ) { u3_noun loc = u3k(u3t(nit)); u3z(nit); u3z(reg); return loc; } } } pas = u3t(pas); } u3z(reg); return u3_none; } } } static u3j_fink* _cj_cast(u3_noun cor, u3_noun loc) { c3_w i_w = 0; u3_noun j, par, bat, dyn, pax, rev = u3_nul, pat = u3h(loc); u3j_fink* fin_u; while ( c3n == u3h(pat) ) { bat = u3h(cor); dyn = u3t(pat); pax = u3h(dyn); loc = u3t(dyn); pat = u3h(loc); rev = u3nc(u3nc(u3k(bat), u3k(pax)), rev); cor = u3r_at(pax, cor); ++i_w; } fin_u = u3a_walloc(c3_wiseof(u3j_fink) + (i_w * c3_wiseof(u3j_fist))); fin_u->len_w = i_w; fin_u->sat = u3k(cor); for ( j = rev; i_w-- > 0; j = u3t(j) ) { u3j_fist* fis_u = &(fin_u->fis_u[i_w]); par = u3h(j); fis_u->bat = u3k(u3h(par)); fis_u->pax = u3k(u3t(par)); } u3z(rev); c3_assert( u3_nul == j ); return fin_u; } /* u3j_cast(): create u3j_fink from core and location. */ u3j_fink* u3j_cast(u3_noun cor, u3_noun loc) { u3j_fink* fin_u; u3t_on(glu_o); fin_u = _cj_cast(cor, loc); u3t_off(glu_o); return fin_u; } static c3_o _cj_fine(u3_noun cor, u3j_fink* fin_u) { c3_w i_w; for ( i_w = 0; i_w < fin_u->len_w; ++i_w ) { u3j_fist* fis_u = &(fin_u->fis_u[i_w]); if ( c3n == u3r_sing(fis_u->bat, u3h(cor)) ) { return c3n; } else { cor = u3r_at(fis_u->pax, cor); } } return u3r_sing(fin_u->sat, cor); } /* u3j_fine(): check core against u3j_fink. */ c3_o u3j_fine(u3_noun cor, u3j_fink* fin_u) { c3_o ret_o; u3t_on(glu_o); ret_o = _cj_fine(cor, fin_u); u3t_off(glu_o); return ret_o; } /* u3j_nail(): resolve hot state for location and axis. RETAIN. ** return value indicates presence of driver. **/ c3_o u3j_nail(u3_noun loc, u3_noun axe, u3_noun* lab, u3j_core** cop_u, u3j_harm** ham_u) { c3_o ret_o; u3_noun jax, hap, bal, jit; u3_weak act; u3t_on(glu_o); act = _cj_find_warm(loc); c3_assert(u3_none != act); u3x_qual(act, &jax, &hap, &bal, &jit); *lab = u3k(bal); if ( 0 == jax ) { ret_o = c3n; } else { u3_weak inx = u3kdb_get(u3k(hap), u3k(axe)); if ( u3_none == inx ) { ret_o = c3n; } else { c3_l jax_l = jax, inx_l = inx; *cop_u = &(u3D.ray_u[jax_l]); *ham_u = &((*cop_u)->arm_u[inx_l]); ret_o = c3y; } } u3z(act); u3t_off(glu_o); return ret_o; } /* _cj_scan(): has this core been registered? */ static c3_o _cj_scan(u3_noun cor) { u3_weak loc = u3j_spot(cor); c3_o reg_o = (u3_none == loc) ? c3n : c3y; u3z(loc); return reg_o; } /* _cj_warm_hump(): generate axis-to-arm map. RETAIN. */ static u3_noun _cj_warm_hump(c3_l jax_l, u3_noun huc) { u3_noun hap = u3_nul; u3j_core* cop_u; /* Compute axes of all correctly declared arms. */ if ( jax_l && (cop_u = &u3D.ray_u[jax_l])->arm_u ) { u3j_harm* jet_u; c3_l i_l; for ( i_l = 0; (jet_u = &cop_u->arm_u[i_l])->fcs_c; i_l++ ) { c3_l axe_l = 0; if ( '.' == *(jet_u->fcs_c) ) { c3_d axe_d = 0; if ( (1 != sscanf(jet_u->fcs_c+1, "%" SCNu64, &axe_d)) || axe_d >> 32ULL || ((1 << 31) & (axe_l = (c3_w)axe_d)) || (axe_l < 2) ) { fprintf(stderr, "jets: activate: bad fcs %s\r\n", jet_u->fcs_c); } } else { u3_noun nam = u3i_string(jet_u->fcs_c); u3_noun fol = u3kdb_get(u3k(huc), nam); if ( u3_none == fol ) { fprintf(stderr, "jets: activate: bad fcs %s\r\n", jet_u->fcs_c); } else { axe_l = _cj_axis(fol); u3z(fol); } } if ( 0 != axe_l ) { hap = u3kdb_put(hap, axe_l, i_l); } } } return hap; } /* _cj_hot_mean(): in parent, declare a core. RETAINS. */ static c3_l _cj_hot_mean(c3_l par_l, u3_noun nam) { u3j_core* par_u; u3j_core* dev_u; if ( 0 != par_l ) { par_u = &u3D.ray_u[par_l]; dev_u = par_u->dev_u; } else { par_u = 0; dev_u = u3D.dev_u; } { c3_w i_l = 0; u3j_core* cop_u; while ( (cop_u = &dev_u[i_l])->cos_c ) { if ( _(u3r_sing_c(cop_u->cos_c, nam)) ) { #if 0 fprintf(stderr, "hot: bound jet %d/%s/%s/\r\n", cop_u->jax_l, cop_u->cos_c, par_u ? par_u->cos_c : "~"); #endif return cop_u->jax_l; } i_l++; } } return 0; } /* u3j_boot(): initialize jet system. */ void u3j_boot(void) { c3_w jax_l; u3D.len_l =_cj_count(0, u3D.dev_u); u3D.all_l = (2 * u3D.len_l) + 1024; // horrid heuristic u3D.ray_u = (u3j_core*) malloc(u3D.all_l * sizeof(u3j_core)); memset(u3D.ray_u, 0, (u3D.all_l * sizeof(u3j_core))); jax_l = _cj_install(u3D.ray_u, 1, u3D.dev_u); fprintf(stderr, "boot: installed %d jets\n", jax_l); } /* _cj_soft(): kick softly by arm axis. */ static u3_noun _cj_soft(u3_noun cor, u3_noun axe) { u3_noun arm = u3x_at(axe, cor); return u3n_nock_on(cor, u3k(arm)); } void find_error(u3_noun cor, u3_noun old, u3_noun new); /* _cj_kick_z(): try to kick by jet. If no kick, produce u3_none. ** ** `cor` is RETAINED iff there is no kick, TRANSFERRED if one. ** `axe` is RETAINED. */ static u3_weak _cj_kick_z(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) { if ( 0 == ham_u->fun_f ) { return u3_none; } if ( !_(ham_u->liv) ) { return u3_none; } else { #ifdef U3_MEMORY_DEBUG c3_w cod_w; { char soc_c[6]; memset(soc_c, 0, 6); strncpy(soc_c, cop_u->cos_c, 5); soc_c[5] = 0; cod_w = u3i_string(soc_c); cod_w = u3a_lush(cod_w); } #endif if ( _(ham_u->ice) ) { u3_weak pro = ham_u->fun_f(cor); #ifdef U3_MEMORY_DEBUG u3a_lop(cod_w); #endif if ( u3_none != pro ) { u3z(cor); return pro; } } else { u3_weak pro, ame; ham_u->ice = c3y; pro = ham_u->fun_f(u3k(cor)); ham_u->ice = c3n; #ifdef U3_MEMORY_DEBUG u3a_lop(cod_w); #endif if ( u3_none == pro ) { u3z(cor); return pro; } ham_u->liv = c3n; ame = _cj_soft(cor, axe); ham_u->liv = c3y; if ( c3n == u3r_sing(ame, pro) ) { fprintf(stderr, "test: %s %s: mismatch: good %x, bad %x\r\n", cop_u->cos_c, (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c, u3r_mug(ame), u3r_mug(pro)); ham_u->liv = c3n; c3_assert(0); return u3m_bail(c3__fail); } else { #if 0 fprintf(stderr, "test: %s %s\r\n", cop_u->cos_c, (!strcmp(".2", ham_u->fcs_c)) ? "$" : ham_u->fcs_c); #endif u3z(ame); return pro; } } return u3_none; } } /* u3j_hock(): Try to kick by jet with resolved hot state. ** If no kick, produce u3_none. ** ** `cor` is RETAINED iff there is no kick, TRANSFERRED if one. ** `axe` is RETAINED. */ u3_weak u3j_hock(u3_noun cor, u3j_core* cop_u, u3j_harm* ham_u, u3_atom axe) { // this is where you would trace, if we traced this return _cj_kick_z(cor, cop_u, ham_u, axe); } /* _cj_hook_in(): execute hook from core, or fail. */ static u3_noun _cj_hook_in(u3_noun cor, const c3_c* tam_c, c3_o jet_o) { u3_weak loc, col; u3_noun roc, tem, got, pat, nam, huc; if ( c3n == u3du(cor) ) { return u3m_bail(c3__fail); } loc = u3j_spot(cor); if ( u3_none == loc ) { return u3m_bail(c3__fail); } tem = u3i_string(tam_c); while ( 1 ) { u3x_trel(loc, &pat, &nam, &huc); got = u3qdb_get(huc, tem); if ( u3_nul != got ) { c3_l axe_l; u3_noun pro, fol; u3j_core* cop_u; u3z(tem); fol = u3k(u3t(got)); u3z(got); axe_l = _cj_axis(fol); if ( 0 == axe_l ) { pro = u3n_nock_on(cor, fol); } else { c3_l jax_l, inx_l; u3_noun hap, act; u3z(fol); act = _cj_find_warm(loc); jax_l = u3h(act); hap = u3h(u3t(act)); cop_u = &u3D.ray_u[jax_l]; // Tricky: the above case would work here too, but would // disable jet_o and create some infinite recursions. // if ( (c3n == jet_o) || (u3_none == (inx_l = u3kdb_get(u3k(hap), axe_l))) || (u3_none == (pro = _cj_kick_z(cor, cop_u, &cop_u->arm_u[inx_l], axe_l))) ) { pro = u3n_nock_on(cor, u3k(u3x_at(axe_l, cor))); } u3z(act); } u3z(loc); return pro; } else if ( c3n == u3h(pat) ) { u3_noun dyn = u3t(pat), axe = u3h(dyn), pel = u3t(dyn); roc = u3k(u3r_at(axe, cor)); u3z(cor); cor = roc; col = u3k(pel); u3z(loc); loc = col; } else { u3_noun sat = u3t(pat); if ( c3y == u3h(sat) ) { return u3m_bail(c3__fail); } else { col = u3k(u3t(sat)); u3z(loc); loc = col; roc = u3k(u3t(cor)); u3z(cor); cor = roc; } } } } /* u3j_soft(): execute soft hook. */ u3_noun u3j_soft(u3_noun cor, const c3_c* tam_c) { u3_noun pro; pro = _cj_hook_in(cor, tam_c, c3n); return pro; } /* u3j_hook(): execute hook from core, or fail. */ u3_noun u3j_hook(u3_noun cor, const c3_c* tam_c) { u3_noun pro; pro = _cj_hook_in(cor, tam_c, c3y); return pro; } /* u3j_kick(): new kick. ** ** `axe` is RETAINED by the caller; `cor` is RETAINED iff there ** is no kick, TRANSFERRED if one. */ u3_weak u3j_kick(u3_noun cor, u3_noun axe) { u3t_on(glu_o); u3_weak loc = u3j_spot(cor); if ( u3_none == loc ) { u3t_off(glu_o); return u3_none; } else { u3_weak act = _cj_find_warm(loc); u3z(loc); if ( u3_none == act ) { u3t_off(glu_o); return u3_none; } else { c3_l jax_l; u3_noun hap, bal, jit, inx; u3x_qual(act, &jax_l, &hap, &bal, &jit); if ( u3_none == (inx = u3kdb_get(u3k(hap), u3k(axe))) ) { u3t_off(glu_o); { c3_o pof_o = __(u3C.wag_w & u3o_debug_cpu); if ( _(pof_o) ) { pof_o = u3t_come(bal); } u3z(act); if ( _(pof_o) ) { u3_noun pro = u3n_nock_on(cor, u3nq(9, u3k(axe), 0, 1)); u3t_flee(); return pro; } else { return u3_none; } } } else { u3j_core* cop_u = &u3D.ray_u[jax_l]; c3_l inx_l = inx; u3j_harm* ham_u = &cop_u->arm_u[inx_l]; c3_o pof_o = __(u3C.wag_w & u3o_debug_cpu); u3_noun pro; if ( _(pof_o) ) { pof_o = u3t_come(bal); } u3z(act); u3t_off(glu_o); pro = _cj_kick_z(cor, cop_u, ham_u, axe); if ( u3_none == pro ) { if ( _(pof_o) ) { pro = u3n_nock_on(cor, u3nq(9, u3k(axe), 0, 1)); u3t_flee(); return pro; } else return u3_none; } else { if ( _(pof_o) ) { u3t_flee(); } return pro; } } } } } /* u3j_kink(): kick either by jet or by nock. */ u3_noun u3j_kink(u3_noun cor, u3_noun axe) { u3_weak pro = u3j_kick(cor, axe); if ( u3_none != pro ) { return pro; } else { return u3n_nock_on(cor, u3nq(9, axe, 0, 1)); } } /* _cj_jit(): generate arbitrary warm jet-associated data. RETAIN. */ static u3_noun _cj_jit(c3_l jax_l, u3_noun bat) { return u3_nul; } /* _cj_mine_par_old(): register hooks and parent location within existing * axis in ancestor list or u3_none. RETAIN. */ static u3_weak _cj_mine_par_old(u3_noun lan, u3_noun axe, u3_noun pel, u3_noun loc) { u3_noun par; if ( u3_nul == lan ) { return u3_none; } else if ( c3y == u3r_sing(axe, u3h(par = u3h(lan))) ) { u3_noun lol = u3qdb_put(u3t(par), pel, loc), rap = u3nc(u3k(axe), lol); return u3nc(rap, u3k(u3t(lan))); } else { u3_weak nex = _cj_mine_par_old(u3t(lan), axe, pel, loc); if ( u3_none == nex ) { return u3_none; } else { return u3nc(u3k(par), nex); } } } /* _cj_mine_par_new(): insert ancestor within lan at sorted index. RETAIN. */ static u3_noun _cj_mine_par_new(u3_noun lan, u3_noun axe, u3_noun pel, u3_noun loc) { u3_noun par; if ( (u3_nul == lan) || (c3y == u3qa_lth(axe, u3h(u3h(lan)))) ) { par = u3nc(u3k(axe), u3qdb_put(u3_nul, pel, loc)); return u3nc(par, u3k(lan)); } else { return u3nc(u3k(u3h(lan)), _cj_mine_par_new(u3t(lan), axe, pel, loc)); } } /* _cj_mine_par(): register a location as an ancestor in a list of ancestors. * RETAIN. */ static u3_noun _cj_mine_par(u3_noun lan, u3_noun axe, u3_noun pel, u3_noun loc) { u3_weak old = _cj_mine_par_old(lan, axe, pel, loc); if ( u3_none != old ) { return old; } else { return _cj_mine_par_new(lan, axe, pel, loc); } } /* _cj_mine(): declare a core and produce location. RETAIN. */ static u3_weak _cj_mine(u3_noun cey, u3_noun cor) { c3_l par_l, jax_l; u3_noun bat = u3h(cor), hap, reg, loc, bal, act, nam, axe, huc, ger; u3x_trel(cey, &nam, &axe, &huc); if ( 0 == axe ) { u3_noun pay = u3t(cor); reg = _cj_find_cold(bat); loc = u3nt(u3nt(c3y, c3y, u3k(pay)), u3k(nam), u3k(huc)); if ( u3_none == reg ) { reg = u3nc(u3_nul, u3_nul); } ger = u3nc(u3qdb_put(u3h(reg), pay, loc), u3k(u3t(reg))); u3z(reg); reg = ger; bal = u3nc(u3k(nam), u3_nul); par_l = 0; } else { u3_weak par, pel, pac; u3_noun pat; par = u3r_at(axe, cor); if ( u3_none == par || c3n == u3du(par) ) { fprintf(stderr, "fund: %s is bogus\r\n", u3r_string(nam)); return u3_none; } pel = u3j_spot(par); if ( u3_none == pel ) { fprintf(stderr, "fund: in %s, parent %x not found at %d\r\n", u3r_string(nam), u3r_mug(u3h(par)), axe); return u3_none; } pac = _cj_find_warm(pel); c3_assert(u3_none != pac); par_l = u3h(pac); bal = u3nc(u3k(nam), u3k(u3h(u3t(u3t(pac))))); u3z(pac); pat = ( ( 3 == axe ) && (c3y == u3h(u3h(pel))) ) ? u3nt(c3y, c3n, u3k(pel)) : u3nt(c3n, u3k(axe), u3k(pel)); loc = u3nt(pat, u3k(nam), u3k(huc)); reg = _cj_find_cold(bat); if ( u3_none == reg ) { reg = u3nc(u3_nul, u3_nul); } ger = u3nc(u3k(u3h(reg)), _cj_mine_par(u3t(reg), axe, pel, loc)); u3z(pel); u3z(reg); reg = ger; } jax_l = _cj_hot_mean(par_l, nam); #if 0 u3m_p("new jet", bal); fprintf(stderr, " bat %x, jax %d\r\n", u3r_mug(bat), jax_l); #endif hap = _cj_warm_hump(jax_l, huc); act = u3nq(jax_l, hap, bal, _cj_jit(jax_l, bat)); u3h_put(u3R->jed.cod_p, bat, reg); u3h_put(u3R->jed.war_p, loc, act); return loc; } /* _cj_moan(): register core known to be unregistered, returning * location. */ static u3_weak _cj_moan(u3_noun clu, u3_noun cor) { u3_weak cey = _cj_je_fsck(clu); u3_weak loc = u3_none; if ( u3_none != cey ) { loc = _cj_mine(cey, cor); u3z(cey); } u3z(cor); return loc; } /* u3j_mile(): register core for jets, returning location. */ u3_weak u3j_mile(u3_noun clu, u3_noun cor) { u3t_on(glu_o); u3_weak loc = u3_none; if ( c3n == u3du(cor) ) { u3z(clu); u3z(cor); } else { loc = u3j_spot(cor); if ( u3_none == loc ) { loc = _cj_moan(clu, cor); } else { u3z(clu); u3z(cor); } } u3t_off(glu_o); return loc; } /* u3j_mine(): register core for jets. */ void u3j_mine(u3_noun clu, u3_noun cor) { u3t_on(glu_o); if ( (c3n == u3du(cor)) || (c3y == _cj_scan(cor)) ) { u3z(clu); u3z(cor); } else { u3_weak loc = _cj_moan(clu, cor); if ( u3_none != loc ) { u3z(loc); } } u3t_off(glu_o); } /* _cj_warm_reap(): reap key and value from warm table. */ static void _cj_warm_reap(u3_noun kev) { u3_noun loc = u3a_take(u3h(kev)); u3_noun act = u3a_take(u3t(kev)); u3h_put(u3R->jed.war_p, loc, act); u3z(loc); } /* _cj_uni_jun(): merge junior map into senior map. * sem is TRANSFERRED. * jum is RETAINED. */ static u3_noun _cj_uni_jun(u3_noun sem, u3_noun jum) { if ( u3_nul == jum ) { return sem; } else { u3_noun n, l, r; u3x_trel(jum, &n, &l, &r); sem = _cj_uni_jun(sem, l); sem = _cj_uni_jun(sem, r); return u3kdb_put(sem, u3a_take(u3h(n)), u3a_take(u3t(n))); } } /* _cj_remarry(): merge parent lists. * sel is TRANSFERRED. * jul is RETAINED. */ static u3_noun _cj_remarry(u3_noun sel, u3_noun jul) { if ( u3_nul == sel ) { return u3a_take(jul); } else if ( u3_nul == jul ) { return sel; } else { u3_noun sap = u3h(sel), jup = u3h(jul), sax = u3h(sap), jux = u3h(jup); if ( c3y == u3r_sing(sax, jux) ) { u3_noun lol = _cj_uni_jun(u3k(u3t(sap)), u3t(jup)), par = u3nc(u3k(u3h(sap)), lol), nex = _cj_remarry(u3k(u3t(sel)), u3t(jul)), pro = u3nc(par, nex); u3z(sel); return pro; } else if ( c3y == u3qa_lth(sax, jux) ) { u3_noun nex = _cj_remarry(u3k(u3t(sel)), jul), pro = u3nc(u3k(sap), nex); u3z(sel); return pro; } else { return u3nc(u3a_take(jup), _cj_remarry(sel, u3t(jul))); } } } /* _cj_cold_reap(): reap cold dashboard entries. */ static void _cj_cold_reap(u3_noun kev) { u3_noun jur = u3t(kev); u3_noun bat = u3a_take(u3h(kev)); u3_weak ser = _cj_find_cold(bat); u3_noun reg = ( u3_none == ser ) ? u3a_take(jur) : u3nc(_cj_uni_jun(u3k(u3h(ser)), u3h(jur)), _cj_remarry(u3k(u3t(ser)), u3t(jur))); u3h_put(u3R->jed.cod_p, bat, reg); u3z(ser); u3z(bat); } /* u3j_reap(): promote jet state. */ void u3j_reap(u3p(u3h_root) cod_p, u3p(u3h_root) war_p) { u3h_walk(cod_p, _cj_cold_reap); u3h_walk(war_p, _cj_warm_reap); } /* _cj_ream(): ream list of battery registry pairs. RETAIN. */ static void _cj_ream(u3_noun all) { c3_l par_l, jax_l; u3_noun i, j, k, rul, loc, bal, act, lop, kev, rut, hap, pat, reg, pol, rem, rec, bat, pel, nam, huc; u3_weak pac; for ( i = all, lop = u3_nul; i != u3_nul; i = u3t(i) ) { kev = u3h(i); bat = u3h(kev); reg = u3t(kev); rut = u3h(reg); // register roots rul = u3qdb_tap(rut); for ( j = rul; j != u3_nul; j = u3t(j) ) { loc = u3t(u3h(j)); u3x_trel(loc, &pat, &nam, &huc); bal = u3nc(u3k(nam), u3_nul); jax_l = _cj_hot_mean(0, nam); hap = _cj_warm_hump(jax_l, huc); act = u3nq(jax_l, hap, bal, _cj_jit(jax_l, bat)); #if 0 u3m_p("old jet", bal); fprintf(stderr, " bat %x, jax %d\r\n", u3r_mug(bat), jax_l); #endif u3h_put(u3R->jed.war_p, loc, act); } u3z(rul); // put ancestors in lop (list [battery=^ parent=location this=location]) for ( j = u3t(reg); j != u3_nul; j = u3t(j) ) { pol = lop; lop = u3qdb_tap(u3t(u3h(j))); for ( k = lop; u3_nul != k; k = u3t(k) ) { pol = u3nc(u3nc(u3k(bat), u3k(u3h(k))), pol); } u3z(lop); lop = pol; } } // ordering is random so we need to push onto rem when parent // isn't yet present in the warm state while ( u3_nul != lop ) { rem = u3_nul; for ( i = lop; u3_nul != i; i = u3t(i) ) { rec = u3h(i); u3x_trel(rec, &bat, &pel, &loc); pac = _cj_find_warm(pel); if ( u3_none == pac ) { rem = u3nc(u3k(rec), rem); } else { u3x_trel(loc, &pat, &nam, &huc); par_l = u3h(pac); jax_l = _cj_hot_mean(par_l, nam); bal = u3nc(u3k(nam), u3k(u3h(u3t(u3t(pac))))); hap = _cj_warm_hump(jax_l, huc), u3z(pac); act = u3nq(jax_l, hap, bal, _cj_jit(jax_l, bat)); #if 0 u3m_p("old jet", bal); fprintf(stderr, " bat %x, jax %d\r\n", u3r_mug(bat), jax_l); #endif u3h_put(u3R->jed.war_p, loc, act); } } u3z(lop); lop = rem; } } /* _cj_warm_tap(): tap war_p to rel */ static void _cj_warm_tap(u3_noun kev, void* wit) { u3_noun* rel = wit; *rel = u3nc(u3k(kev), *rel); } /* u3j_ream(): rebuild warm state */ void u3j_ream(void) { u3_noun rel = u3_nul; u3h_free(u3R->jed.war_p); u3R->jed.war_p = u3h_new(); c3_assert(u3R == &(u3H->rod_u)); u3h_walk_with(u3R->jed.cod_p, _cj_warm_tap, &rel); _cj_ream(rel); u3z(rel); } static c3_w _cj_fink_mark(u3j_fink* fin_u) { c3_w i_w, tot_w = u3a_mark_noun(fin_u->sat); for ( i_w = 0; i_w < fin_u->len_w; ++i_w ) { u3j_fist* fis_u = &(fin_u->fis_u[i_w]); tot_w += u3a_mark_noun(fis_u->bat); tot_w += u3a_mark_noun(fis_u->pax); } tot_w += u3a_mark_ptr(fin_u); return tot_w; } /* u3j_rite_mark(): mark u3j_rite for gc. */ c3_w u3j_rite_mark(u3j_rite* rit_u) { c3_w tot_w = 0; if ( (c3y == rit_u->own_o) && u3_none != rit_u->clu ) { tot_w += u3a_mark_noun(rit_u->clu); tot_w += _cj_fink_mark(rit_u->fin_u); } return tot_w; } /* u3j_site_mark(): mark u3j_site for gc. */ c3_w u3j_site_mark(u3j_site* sit_u) { c3_w tot_w = u3a_mark_noun(sit_u->axe); if ( u3_none != sit_u->bat ) { tot_w += u3a_mark_noun(sit_u->bat); } if ( u3_none != sit_u->loc ) { tot_w += u3a_mark_noun(sit_u->loc); tot_w += u3a_mark_noun(sit_u->lab); if ( c3y == sit_u->fon_o ) { tot_w += _cj_fink_mark(sit_u->fin_u); } } return tot_w; } /* XX FIXME: move to u3.md |% += location $: pattern=(each static dynamic) name=term hooks=(map term axis) == += static (each payload=* parent=location) += dynamic [where=axis parent=location] :: += registry [roots=(map * location) parents=(list parent)] += parent (pair axis (map location location)) :: += activation $: hot-index=@ud drivers=(map axis @ud) label=path jit=* == :: += cold (map battery=^ registry) += warm (map location activation) -- */