diff --git a/include/f/liar.h b/include/f/liar.h new file mode 100644 index 0000000000..06f8bf3344 --- /dev/null +++ b/include/f/liar.h @@ -0,0 +1,673 @@ +/* include/rail.h +** +** This file is in the public domain. +*/ + /** Configurations. + **/ +# undef U2_LEAK_DEBUG + +# ifdef U2_LEAK_DEBUG +# define u2_leak_on(x) (COD_w = x) + extern c3_w COD_w; +# define u2_leak_off (COD_w = 0) +# endif + + /** Data types. + **/ + /** Ray types. + **/ + /* u2_rail: an allocation control frame. + */ + typedef u2_ray u2_rail; + + /* u2_wire: an execution context, inheriting rail + */ + typedef u2_ray u2_wire; + + /** Structures - in loom space. + **/ + /* Base rail. + */ + typedef struct _u2_loom_rail { + u2_ray cap_r; // top of transient region + u2_ray hat_r; // top of new durable region + u2_ray mat_r; // bottom of transient region + u2_ray rut_r; // bottom of new durable region + c3_m hip_m; // memory model in durable; c3__rock, c3__sand + } u2_loom_rail; + +# define u2_rail_cap_r(ral_r) *u2_at(ral_r, u2_loom_rail, cap_r) +# define u2_rail_hat_r(ral_r) *u2_at(ral_r, u2_loom_rail, hat_r) +# define u2_rail_mat_r(ral_r) *u2_at(ral_r, u2_loom_rail, mat_r) +# define u2_rail_rut_r(ral_r) *u2_at(ral_r, u2_loom_rail, rut_r) +# define u2_rail_hip_m(ral_r) *u2_at(ral_r, u2_loom_rail, hip_m) + + /* Pork - base of frame. + */ + typedef struct { + u2_ray mut_r; // parent mat + u2_ray rit_r; // parent rut + c3_m hap_m; // parent hip + } u2_loom_pork; +# define u2_pork_mut_r(pik_r) *u2_at(pik_r, u2_loom_pork, mut_r) +# define u2_pork_rit_r(pik_r) *u2_at(pik_r, u2_loom_pork, rit_r) +# define u2_pork_hap_m(pik_r) *u2_at(pik_r, u2_loom_pork, hap_m) + + /* Floe - a solid rail allocator. Implied by `hip_m == c3__sand`. + */ + typedef struct { + } u2_loom_floe; + + /* Soup - a liquid rail allocator. + */ +# define u2_soup_free_no 28 + + typedef struct { + u2_ray fre_r[u2_soup_free_no]; // doubly-linked free lists + u2_cash_slot lot_s; // modern memo cache +#ifdef U2_PROFILE_MEMORY + c3_w liv_w; // number of words live +#endif + } u2_loom_soup; +# define u2_soup_fre_r(sop_r, x) *u2_at(sop_r, u2_loom_soup, fre_r[x]) +# define u2_soup_lot_r(sop_r) u2_aftr(sop_r, u2_loom_soup, lot_s) +# define u2_soup_liv_w(sop_r) *u2_at(sop_r, u2_loom_soup, liv_w) + + /* A noun box, for liquid hats. Behind pointer, addressed fwd. + ** + ** The box size is also stored at the end of the box in classic + ** bad ass malloc style. Hence a box is: + ** + ** --- + ** siz_w + ** use_w + ** user data + ** siz_w + ** --- + ** + ** Do not attempt to adjust this structure! + */ + typedef struct _u2_loom_rail_box { + c3_w siz_w; // size of this box + c3_w use_w; // reference count; free if 0 +#ifdef U2_LEAK_DEBUG + c3_w cod_w; // allocation code +#endif + } u2_loom_rail_box; + +# define u2_rail_box_siz(box) *u2_at(box, u2_loom_rail_box, siz_w) +# define u2_rail_box_use(box) *u2_at(box, u2_loom_rail_box, use_w) +# define u2_rail_box_cod(box) *u2_at(box, u2_loom_rail_box, cod_w) + + /* A free node. Addressed from the box. + */ + typedef struct _u2_loom_rail_hut { + u2_loom_rail_box b; + u2_ray pre_r; // next on free list + u2_ray nex_r; // next on free list + } u2_loom_rail_hut; + +# define u2_rail_hut_siz(hut) *u2_at(hut, u2_loom_rail_hut, b.siz_w) +# define u2_rail_hut_use(hut) *u2_at(hut, u2_loom_rail_hut, b.use_w) +# define u2_rail_hut_pre(hut) *u2_at(hut, u2_loom_rail_hut, pre_r) +# define u2_rail_hut_nex(hut) *u2_at(hut, u2_loom_rail_hut, nex_r) + +# define u2_rail_box(som) \ + ( u2_fly_is_cat(som) \ + ? 0 \ + : (u2_dog_a(som) - c3_wiseof(u2_loom_rail_box)) ) + + /** Abbreviations. + **/ +# define u2_rc(ral_r, a, b) u2_rl_cell(ral_r, a, b) +# define u2_rt(ral_r, a, b, c) u2_rl_trel(ral_r, a, b, c) +# define u2_rq(ral_r, a, b, c, d) u2_rl_qual(ral_r, a, b, c, d) +# define u2_ri(ral_r, a, b, c, d, e) u2_rl_quil(ral_r, a, b, c, d, e) +# define u2_ro(ral_r, a) u2_rl_lone(ral_r, a) +# define u2_ru(ral_r, a) u2_rl_unit(ral_r, a) +# define u2_rx(ral_r, a) u2_rl_take(ral_r, a) +# define u2_rz(ral_r, a) u2_rl_lose(ral_r, a) +# define u2_rl u2_rl_list +# define u2_rk u2_rl_rack + + + /** Functions. + **/ + /** Miscellaneous and interesting. + **/ + /* u2_rl_boot(): + ** + ** Create an empty rail in an empty loom, with memory model `hip`. + ** See u2_rl_leap() for storage policies. + */ + u2_ray + u2_rl_boot(c3_m hip_m); + + /* u2_rl_clear(): + ** + ** Yes iff [lef] does not point to any word >= [net] + ** and < [bat]. + */ + u2_bean + u2_rl_clear(u2_noun lef, + u2_ray net_r, + u2_ray bat_r); + + /* u2_rl_init(): + ** + ** Install an empty rail within `hat_r` and `mat_r` in the loom, + ** with memory model `hip`. + ** + ** Returns ray to rail, which always equalls the passed `mat_r`. + */ + u2_ray + u2_rl_init(c3_m hip_m, + u2_ray hat_r, + u2_ray mat_r); + + /* u2_rl_dump(): + ** + ** Print memory structure for benefit of archeologists. + */ + void + u2_rl_dump(u2_ray ral_r); + + /* u2_rl_drain(): + ** + ** Clear the memo cache (soup). + */ + void + u2_rl_drain(u2_ray ral_r); + + /* u2_rl_fall(): + ** + ** Reverse the beams backward, restoring the old frame. + */ + void + u2_rl_fall(u2_ray ral_r); + + /* u2_rl_fall_part(): + ** + ** Fall on `ral`, also releasing the partition `aux`. + */ + void + u2_rl_fall_part(u2_ray ral_r, + u2_ray aux_r); + + /* u2_rl_flog(): + ** + ** Release the can, setting cap to mat. + */ + void + u2_rl_flog(u2_ray ral_r); + + /* u2_rl_gain(): + ** + ** Gain a reference to `som`, returning it. + */ + u2_weak // transfer + u2_rl_gain(u2_ray ral_r, + u2_weak som); // retain + + /* u2_rl_free(): + ** + ** Free storage allocated by u2_rl_malloc(). + */ + void + u2_rl_free(u2_ray ral_r, + void* lag_v); + + /* u2_rl_ok(): + ** + ** Ensure that all reference counts are valid in `som`. + */ + void + u2_rl_ok(u2_ray ral_r, + u2_noun som); // retain + + /* u2_rl_junior(): + ** + ** Yes iff `dus` is junior in `ral` - ie, must be copied + ** to be referenced on the hat. + */ + u2_bean + u2_rl_junior(u2_ray ral_r, + u2_noun dus); // retain + + /* u2_rl_leap(): + ** + ** Reverse the beams forward, with memory model `hip`. + ** Memory models at present: + ** + ** c3__sand solid, no boxes or reference counts + ** c3__rock liquid, boxes, reference-counted heap + ** + ** Returns u2_yes on success. + */ + u2_bean + u2_rl_leap(u2_ray ral_r, + c3_m hip_m); + + /* u2_rl_leap_part(): + ** + ** Reverse and split rail, inserting partition of size `num/dem` + ** plus `tip`. + ** + ** Returns partition rail, `aux_r`. + */ + u2_ray + u2_rl_leap_part(u2_ray ral_r, + c3_m hop_m, + c3_w num_w, + c3_w dem_w, + c3_w tip_w); + + /* u2_rl_lose(): + ** + ** Lose a reference to `som`. Free it if refcount == 0. + */ + void + u2_rl_lose(u2_ray ral_r, + u2_weak som); // transfer + + /* u2_rl_gc_mark_noun(): + ** + ** Mark a noun for gc. Return allocated words. + */ + c3_w + u2_rl_gc_mark_noun(u2_ray ral_r, + u2_noun som); + + /* u2_rl_gc_mark_ptr(): + ** + ** Mark a pointer allocated with ralloc. Return allocated words. + */ + c3_w + u2_rl_gc_mark_ptr(u2_ray ral_r, + u2_ray ptr_r); + + /* u2_rl_gc_mark(): + ** + ** Mark a rail (mainly memo cache). Return allocated words. + */ + c3_w + u2_rl_gc_mark(u2_ray ral_r); + + /* u2_rl_gc_sweep(): + ** + ** Sweep memory, freeing unused blocks. Match live, save leaked. + */ + c3_w + u2_rl_gc_sweep(u2_ray ral_r, c3_w sav_w); + + /* u2_rl_malloc(): + ** + ** Allocate `sib_w` *bytes* of raw C storage. + */ + void* + u2_rl_malloc(u2_ray ral_r, + c3_w sib_w); + + /* u2_rl_malt(): + ** + ** Initialize slab `sal` as an atom, internally measured. + */ + u2_atom // transfer + u2_rl_malt(u2_rail ral_r, + u2_ray sal_r); + + /* u2_rl_mint(): + ** + ** Initialize slab `sal` as an atom, externally measured. + */ + u2_atom // transfer + u2_rl_mint(u2_rail ral_r, + u2_ray sal_r, + c3_w len_w); + + /* u2_rl_moot(): + ** + ** Initialize slab `sal` as an atom, originally measured. + */ + u2_atom // transfer + u2_rl_moot(u2_rail ral_r, + u2_ray sal_r); + + /* u2_rl_open(): + ** + ** Yes iff [a] more words remain in the pad. + */ + u2_bean + u2_rl_open(u2_ray ral_r, + c3_w a_w); + + /* u2_rl_ralloc(): + ** + ** Allocate `siz_w` words of raw ray storage. + */ + u2_ray + u2_rl_ralloc(u2_ray ral_r, + c3_w siz_w); + + /* u2_rl_rfree(): + ** + ** Free raw ray storage allocated by `u2_rl_ralloc()`. + */ + void + u2_rl_rfree(u2_ray ral_r, + u2_ray nov_r); + + /* u2_rl_senior(): + ** + ** Yes iff `dus` is senior in `ral` - ie, does not + ** require reference counting. + */ + u2_bean + u2_rl_senior(u2_ray ral_r, + u2_noun dus); // retain + + /* u2_rl_slab(): + ** + ** Create a blank atomic slab of `len` words. + */ + u2_ray + u2_rl_slab(u2_rail ral_r, + c3_w len_w); + + /* u2_rl_slaq(): + ** + ** Create a blank atomic slab of `len` bloqs of size `met`. + */ + u2_ray + u2_rl_slaq(u2_wire wir_r, + c3_g met_g, + c3_w len_w); + + /* u2_rl_refs(): + ** + ** Return the reference count of (som). For debugging, etc. + */ + c3_w + u2_rl_refs(u2_ray ral_r, + u2_noun som); + + /* u2_rl_copy(): + ** + ** Copy indirect noun `fiz` into main storage, preserving dags. + ** Must be followed by `rl_wash(fiz)` if `fiz` is to be preserved. + */ + u2_weak // transfer + u2_rl_copy(u2_ray ral_r, + u2_dog fiz); // retain + + /* u2_rl_take(): + ** + ** Produce `a`, as eligible result. Copy juniors; reference peers. + */ + u2_weak // transfer + u2_rl_take(u2_ray ral_r, + u2_weak a); // retain +# define u2_rl_ice(ral_r, a) \ + u2_rl_take(ral_r, a) + + /* u2_rl_tamp(): + ** + ** Tamp, eliding the segment from `net` up to `bat`, + ** preserving the root `lef`. + ** + ** Assumes u2_rl_clear() with the same arguments. + */ + u2_noun + u2_rl_tamp(u2_ray ral_r, + u2_noun lef, + u2_ray net_r, + u2_ray bat_r); + + /* u2_rl_valid(): + ** + ** Validate rail for memory bugs. + */ + void + u2_rl_valid(u2_ray ral_r); + + /* u2_rl_water(): + ** + ** Return east and west watermarks, respectively. + */ + void + u2_rl_water(u2_ray ral_r, + c3_w* maz_w, + c3_w* buc_w); + + /** Basic noun fabrication. + **/ + /* u2_rl_bytes(): + ** + ** Copy `a` bytes from `b` to an LSB first atom. + */ + u2_weak // transfer + u2_rl_bytes(u2_ray ral_r, + c3_w a_w, + const c3_y* b_y); + + /* u2_rl_cell(): + ** + ** Produce the cell `[a b]`. + */ + u2_weak // transfer + u2_rl_cell(u2_ray ral_r, + u2_weak a, // transfer + u2_weak b); // transfer + + /* u2_rl_list(): + ** + ** Produce a null-terminated list, terminating `...` with `u2_none`. + */ + u2_weak // transfer + u2_rl_list(u2_rail ral_r, + ...); // transfer + + /* u2_rl_lone(): + ** + ** Create the unit `[0 a]`. + */ +#if 0 + u2_weak // transfer + u2_rl_lone(u2_rail ral_r, + u2_weak a); // transfer +#else +# define u2_rl_lone(ral_r, a) \ + u2_rc(ral_r, a, u2_nul) +#endif + + /* u2_rl_molt(): + ** + ** Mutate `som` with a 0-terminated list of axis, noun pairs. + ** Axes must be cats (31 bit). + */ + u2_weak // transfer + u2_rl_molt(u2_rail ral_r, + u2_weak som, // retain + ...); // transfer + + /* u2_rl_molv(): + ** + ** As u2_rl_molt(), by argument pointer. + */ + u2_weak // transfer + u2_rl_molv(u2_rail ral_r, + u2_weak som, // retain + va_list vap); // transfer + + /* u2_rl_mp(): + ** + ** Copy the GMP integer [a] into an atom. + */ + u2_weak // transfer + u2_rl_mp(u2_ray ral_r, + mpz_t a_mp); // transfer + + /* u2_rl_qual(): + ** + ** Produce the triple `[a b c d]`. + */ +#if 0 + u2_weak // transfer + u2_rl_qual(u2_rail ral_r, + u2_weak a, // transfer + u2_weak b, // transfer + u2_weak c, // transfer + u2_weak d); // transfer +#else +# define u2_rl_qual(ral_r, a, b, c, d) \ + u2_rc(ral_r, a, u2_rt(ral_r, b, c, d)) +#endif + + /* u2_rl_rack(): + ** + ** Produce an n-tuple, terminating `...` with `u2_none`. + */ + u2_weak // transfer + u2_rl_rack(u2_rail ral_r, + ...); // transfer + + /* u2_rl_string(): + ** + ** Produce an LSB-first atom from the C string `a`. + */ + u2_weak // transfer + u2_rl_string(u2_ray ral_r, + const c3_c* a_c); + + /* u2_rl_trel(): + ** + ** Create the triple `[a b c]`. + */ +#if 0 + u2_weak // transfer + u2_rl_trel(u2_rail ral_r, + u2_weak a, // transfer + u2_weak b, // transfer + u2_weak c); // transfer +#else +# define u2_rl_trel(ral_r, a, b, c) \ + u2_rc(ral_r, a, u2_rc(ral_r, b, c)) +#endif + + /* u2_rl_unit(): + ** + ** Create the unit `[0 a]`. + */ +#if 0 + u2_weak // transfer + u2_rl_unit(u2_rail ral_r, + u2_weak a); // transfer +#else +# define u2_rl_unit(ral_r, a) \ + u2_rc(ral_r, u2_nul, a) +#endif + + /* u2_rl_vint(): + ** + ** Create `a + 1`. + */ + u2_weak // transfer + u2_rl_vint(u2_rail ral_r, + u2_weak a); // transfer + + /* u2_rl_words(): + ** + ** Copy [a] words from [b] into an atom. + */ + u2_weak // transfer + u2_rl_words(u2_ray ral_r, + c3_w a_w, + const c3_w* b_w); + + /** Caching. + **/ + /* u2_rl_find(): + ** + ** Cache search for function (0 means nock) and sample. + */ + u2_weak // transfer + u2_rl_find(u2_ray ral_r, + u2_mote fun_m, + u2_noun sam); // retain + + /* u2_rl_save(): + ** + ** Cache store for function (0 means nock), sample and product. + */ + u2_weak // transfer + u2_rl_save(u2_ray ral_r, + u2_mote fun_m, // retain + u2_noun sam, // retain + u2_noun pro); // transfer + + /* u2_rl_uniq(): + ** + ** Use cache to render object unique. + */ + u2_noun // produce + u2_rl_uniq(u2_ray ral_r, + u2_noun som); // submit + + /* u2_rl_find_cell(): as u2_rl_find(), for `sam=[a b]`. + ** u2_rl_find_trel(): as u2_rl_find(), for `sam=[a b c]`. + ** u2_rl_find_qual(): as u2_rl_find(), for `sam=[a b d]`. + ** u2_rl_find_quil(): as u2_rl_find(), for `sam=[a b c d e]`. + ** + ** Extend as needed... + */ + u2_weak // transfer + u2_rl_find_cell(u2_ray, u2_mote, u2_noun, // retain + u2_noun); // retain + u2_weak // transfer + u2_rl_find_trel(u2_ray, u2_mote, u2_noun, // retain + u2_noun, // retain + u2_noun); // retain + u2_weak // transfer + u2_rl_find_qual(u2_ray, u2_mote, u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun); // retain + u2_weak // transfer + u2_rl_find_quil(u2_ray, u2_mote, u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun); // retain + + /* u2_rl_save_cell(): as u2_rl_save(), for `sam=[a b]`. + ** u2_rl_save_trel(): as u2_rl_save(), for `sam=[a b c]`. + ** u2_rl_save_qual(): as u2_rl_save(), for `sam=[a b c d]`. + ** u2_rl_save_quil(): as u2_rl_save(), for `sam=[a b c d e]`. + ** + ** Extended + */ + u2_weak // transfer + u2_rl_save_cell(u2_ray, u2_mote, u2_noun, // retain + u2_noun, // retain + u2_noun); // transfer + + u2_weak // transfer + u2_rl_save_trel(u2_ray, u2_mote, u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun); // transfer + + u2_weak // transfer + u2_rl_save_qual(u2_ray, u2_mote, u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun); // transfer + + u2_weak // transfer + u2_rl_save_quil(u2_ray, u2_mote, u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun, // retain + u2_noun); // transfer