urbit/include/f/loom.h
2014-04-08 09:25:49 -07:00

958 lines
24 KiB
C

/* include/loom.h
**
** This file is in the public domain.
*/
/** Global variables and definitions.
**/
# define Loom ((c3_w *)U2_OS_LoomBase)
# define LoomBits U2_OS_LoomBits
# define LoomSize (1 << LoomBits)
# define HalfBits (U2_OS_LoomBits - 1)
# define HalfSize (1 << HalfBits)
# define HalfEnd (HalfSize - 1)
# define LoomPageWords 12 // 16K pages
# define LoomAllPages (1 << 16) // 65536 pages
# define LoomHalfPages (1 << 15) // 32768 pages
# define LoomVersion 0xdeafbee
/** Data structures.
**/
/* u2_life: page state.
*/
typedef enum {
u2_page_none = 0, // page is not mapped
u2_page_slow = 1, // page not yet loaded (not used)
u2_page_neat = 2, // page is unmodified
u2_page_tref = 3 // page is dirty
} u2_page_life;
typedef struct {
u2_page_life lif_e: 2; // page state
c3_w mug_e: 30; // 30-bit mug
} u2_chit;
/* u2_chef: memory control, per whole, on disk.
*/
typedef struct _u2_chef { // control image
c3_d ent_d; // event number
c3_w ven_w; // version
c3_w bot_w; // offset in loom
c3_w pgs_w; // pages saved
} u2_chef;
/* u2_cheg: mapped segment. always grows upward for now.
*/
typedef struct _u2_cheg {
c3_c* nam_c; // name as a file
struct _u2_cheg* nex_u; // linked in list
c3_w bot_w; // beginning page
c3_w len_w; // length in pages
c3_w pgs_w; // pages in used prefix
c3_i ctl_i; // control file
c3_i dat_i; // data file
} u2_cheg;
# ifdef U2_GLOBAL
/* Memory control structures.
*/
volatile u2_chit LoomChem[LoomAllPages]; // memory
/* Direct segment pointers.
*/
u2_cheg LoomSegmentD = { "d" };
u2_cheg LoomSegmentC = { "c", &LoomSegmentD };
u2_cheg LoomSegmentB = { "b", &LoomSegmentC };
u2_cheg LoomSegmentA = { "a", &LoomSegmentB };
/* Critical-section bit, for signal handlers.
*/
volatile uint32_t u2_Critical;
# else
extern uint32_t LoomFrame;
extern volatile sig_atomic_t LoomStop;
extern volatile sig_atomic_t LoomIntr;
extern volatile uint32_t u2_Critical;
extern volatile u2_chit LoomChem[LoomAllPages];
extern u2_cheg LoomSegmentA, LoomSegmentB, LoomSegmentC, LoomSegmentD;
# endif
# define LoomFrameMax 8192
# define LoomSink \
(LoomFrame == LoomFrameMax ? (LoomStop = 1) : LoomFrame++)
# define LoomRise \
(LoomFrame--)
// # define LoomFold
/** Data types.
**/
/** Bitfields. Assumes HalfBits == 28 (the maximum).
***
*** u2_nit - word offset in loom
*** &&&&:28a
*** a: offset from loom
***
*** u2_ray - word offset on beam
*** &&&:1a:28b
*** a: beam (& = low = west, | = high = east)
*** b: offset on beam
***
*** u2_noun - noun
*** ?(u2_cat, u2_dog)
*** 1a:31b
*** a: cat if 0, dog if 1
***
*** u2_weak - noun
*** ?(noun, u2_none)
***
*** u2_dog - indirect atom or cell
*** ?(u2_pom, u2_pug)
*** |:29a:1b:1c
*** a: ray to data
*** b: boxed bit
***
*** u2_cat - direct atom
*** &:31a
*** a: unsigned integer
***
*** u2_pom - indirect cell
*** |:29a:1b:&
*** a: ray to struct u2_cell
*** b: allocated bit (0 == fixed, 1 == allocated)
***
*** u2_pug - indirect atom
*** |:29a:1b:|
*** a: ray to struct u2_atom
*** b: allocated bit (0 == fixed, 1 == allocated)
**/
typedef c3_w u2_nit;
typedef c3_w u2_ray;
typedef c3_w u2_fly;
typedef c3_w u2_dog;
typedef c3_w u2_cat;
typedef c3_w u2_pug;
/** Structures.
***
**/
/* u2_atom, u2_cell: logical atom and cell structures.
**
** Not referenced as such, since in ray space.
*/
typedef struct _u2_loom_atom {
c3_w mug_w;
c3_w len_w;
c3_w buf_w[0];
} u2_loom_atom;
typedef struct _u2_loom_cell {
c3_w mug_w;
u2_ray hed_r;
u2_ray tel_r;
} u2_loom_cell;
/** Basic macros.
**/
/** Bitfield unpacking. See above.
**/
# define u2_ray_a(ray) ( (ray) >> HalfBits )
# define u2_ray_b(ray) ( (ray) & ((1 << HalfBits) - 1) )
# define u2_fly_a(fly) ( (fly) >> 31 )
# define u2_dog_a(dog) ( ((dog) &~ (1 << 31)) >> 2 )
# define u2_dog_b(dog) ( 1 & ((dog) >> 1) )
# define u2_dog_c(dog) ( 1 & (dog) )
# define u2_pom_a(pom) u2_dog_a(pom)
# define u2_pom_b(pom) u2_dog_b(pom)
# define u2_pug_a(pug) u2_dog_a(pug)
# define u2_pug_b(pug) u2_dog_b(pug)
# define u2_fly_is_cat(fly) ( !u2_fly_a(fly) )
# define u2_fly_is_dog(fly) ( u2_fly_a(fly) )
# define u2_dog_is_pom(dog) ( !u2_dog_c(dog) )
# define u2_dog_is_pug(dog) ( u2_dog_c(dog) )
# define u2_dog_is_all(dog) ( u2_dog_b(dog) )
# define u2_fly_is_atom(a) \
(u2_fly_is_cat(a) || u2_dog_is_pug(a))
/** Bitfield packing. See above.
**/
# define u2_ray_of(a, b) ( ((a) << HalfBits) | (b) )
# define u2_dog_of(a, b, c) \
( (1 << 31) | ((a) << 2) | ((b) << 1) | (c) )
# define u2_pom_of(a, b) u2_dog_of(a, b, 0)
# define u2_pug_of(a, b) u2_dog_of(a, b, 1)
/** Cage reference and geometry.
***
*** Formally, we are always folded.
**/
# define u2_ray_fnit(ray) \
( u2_ray_a(ray) ? (HalfEnd - u2_ray_b(ray)) : (ray) )
# ifdef LoomFold
# define u2_ray_nit(ray) u2_ray_fnit(ray)
# else
# define u2_ray_nit(ray) (ray)
# endif
# define u2_ray_open(tid, tat, das) \
( (0 == u2_ray_a(tid)) \
? ( (u2_ray_fnit(tid) + (das)) < u2_ray_fnit(tat) ) \
: ( (u2_ray_fnit(tat) + (das)) < u2_ray_fnit(tid) ) )
# define u2_ray_gap(tid, tat) \
( (HalfSize - (u2_ray_b(tid) + u2_ray_b(tat))) )
/* last word of opposite is first word of other. so, in a 4-word loom:
**
** 0 1 2 3
** | | | |
** ## ## ## ##
** | | | |
** 3 2 1 0
*/
# define u2_ray_over(ray, siz_w) \
u2_ray_of(!u2_ray_a(ray), (HalfSize - (u2_ray_b(ray) + (siz_w))))
# define u2_at_nit(nit) (Loom + nit)
# define u2_at_ray(ray) u2_at_nit(u2_ray_nit(ray))
# define u2_nit_at(ptr_v) (((c3_w *)(ptr_v)) - Loom)
# ifdef LoomFold
# define u2_at_cord(ray, siz) \
(u2_ray_a(ray) ? (u2_at_ray(ray) - ((siz) - 1)) : u2_at_ray(ray))
# else
# define u2_at_cord(ray, siz) u2_at_ray(ray)
# endif
# define u2_aftr(ray, type, field) \
((ray) + \
( ((c3_w *)&((type *)0)->field) - \
((c3_w *)0) ) \
)
# define u2_fore(ray, type, field) \
((ray - 1) - \
( ((c3_w *)&((type *)0)->field) - \
((c3_w *)0) ) \
)
# define u2_at(ray, type, field) \
u2_at_ray(u2_aftr(ray, type, field))
# define u2_by(ray, type, field) \
u2_at_ray(u2_fore(ray, type, field))
# define u2_be(ray, type, item, field) \
( (item *)(void *)u2_at_ray(u2_aftr(ray, type, field)) )
# define u2_ray_beam(ray) u2_ray_a(ray)
# define u2_ray_point(ray) u2_ray_b(ray)
# define u2_dog_ray(dog) u2_dog_a(dog)
# define u2_dog_beam(dog) u2_ray_beam(u2_dog_ray(dog))
/*** Noun structure access.
***/
# define u2_at_dog_mug(a) u2_at_ray(u2_dog_a(a))
# define u2_at_pom_hed(a) u2_at_ray((1 + u2_pom_a(a)))
# define u2_at_pom_tel(a) u2_at_ray((2 + u2_pom_a(a)))
# define u2_at_pug_len(a) u2_at_ray((1 + u2_pug_a(a)))
# define u2_at_pug_buf(a, b) \
u2_at_ray((2 + (b) + u2_pug_a(a)))
# define u2_atom_word(a, b) \
( u2_fly_is_cat(a) ? (b ? 0 : (a)) : *u2_at_pug_buf(a, b) )
/*** Word axis macros.
****
**** Use these on axes known to be in 31-bit range.
***/
/* u2_ax_dep(): number of axis bits.
*/
# define u2_ax_dep(a_w) (c3_bits_word(a_w) - 1)
/* u2_ax_cap(): root axis, 2 or 3.
*/
# define u2_ax_cap(a_w) (0x2 | (a_w >> (u2_ax_dep(a_w) - 1)))
/* u2_ax_mas(): remainder after cap.
*/
# define u2_ax_mas(a_w) \
( (a_w & ~(1 << u2_ax_dep(a_w))) | (1 << (u2_ax_dep(a_w) - 1)) )
/* u2_ax_peg(): connect two axes.
*/
# define u2_ax_peg(a_w, b_w) \
( (a_w << u2_ax_dep(b_w)) | (b_w &~ (1 << u2_ax_dep(b_w))) )
/** Constants and macros.
**/
/* u2_none:
**
** An exceptional value, comparable to NaN for floats.
*/
# define u2_none u2_dog_of(u2_ray_of(0, 0), 0, 0)
/* Small atoms.
*/
# define _0 0
# define _1 1
# define _2 2
# define _3 3
# define _4 4
# define _5 5
# define _6 6
# define _7 7
# define _8 8
# define _9 9
# define _10 10
# define _11 11
# define _12 12
# define _13 13
# define _14 14
# define _15 15
/* Nock operators.
*/
# define u2_nock_frag 0
# define u2_nock_bone 1
# define u2_nock_sail 2
# define u2_nock_dust 3
# define u2_nock_vint 4
# define u2_nock_sing 5
# define u2_nock_trol 6
# define u2_nock_flac 7
# define u2_nock_gant 8
# define u2_nock_kick 9
# define u2_nock_hint 10
# define u2_nock_0 0
# define u2_nock_1 1
# define u2_nock_2 2
# define u2_nock_3 3
# define u2_nock_4 4
# define u2_nock_5 5
# define u2_nock_6 6
# define u2_nock_7 7
# define u2_nock_8 8
# define u2_nock_9 9
# define u2_nock_10 10
/* New (Nock 5) conventional axes for gate call.
*/
#if 1
# define u2_cv_pay 3 // payload
# define u2_cv_sam 6 // sample
# define u2_cv_sam_1 6
# define u2_cv_sam_2 12
# define u2_cv_sam_3 13
# define u2_cv_sam_4 24
# define u2_cv_sam_5 25
# define u2_cv_sam_6 26
# define u2_cv_sam_12 52
# define u2_cv_sam_13 53
# define u2_cv_sam_7 27
# define u2_cv_con 7 // context
# define u2_cv_con_2 14 // context
# define u2_cv_con_3 15 // context
# define u2_cv_con_sam 30 // sample in gate context
# define u2_cv_noc 2 // deprecated
# define u2_cv_bat 2 // battery
#endif
/* u2_yes, u2_no, u2_nul;
**
** Our Martian booleans and list terminator; empty string.
*/
# define u2_yes 0
# define u2_no 1
# define u2_nul 0
# define u2_blip 0
/* Tools for Martian booleans.
*/
# define u2_so(x) (u2_yes == (x))
# define u2_say(x) ( (x) ? u2_yes : u2_no )
# define u2_not(x) ( (x == u2_yes) ? u2_no : u2_yes )
# define u2_and(x, y) ( (u2_so(x) && u2_so(y)) ? u2_yes : u2_no )
# define u2_or(x, y) ( (u2_so(x) || u2_so(y)) ? u2_yes : u2_no )
/** Typedefs.
***
*** Noun typedefs may reflect usage, structure, or both. Any noun
*** typedef is a noun - that is, it may not be (u2_none).
**/
/* u2_noun:
**
** A fly which is not u2_none.
*/
typedef u2_fly u2_noun;
/* u2_weak:
**
** A fly which may be (and must be tested for) u2_none.
*/
typedef u2_fly u2_weak;
/* u2_atom:
**
** A noun which is an atom.
*/
typedef u2_noun u2_atom;
/* u2_cell:
**
** A noun which is a cell.
*/
typedef u2_noun u2_cell;
/* u2_bean:
**
** A Martian boolean (0 = yes, 1 = no).
*/
typedef u2_noun u2_bean;
/* u2_axis:
**
** An atomic tree address.
*/
typedef u2_noun u2_axis;
/* u2_mote:
**
** An atom < (1 << 31).
*/
typedef u2_atom u2_mote;
/* u2_term:
**
** A Watt symbol.
*/
typedef u2_noun u2_term;
/* u2_list:
**
** A zero-terminated, tailward list.
*/
typedef u2_noun u2_list;
/* u2_tool:
**
** A valid or presumptive Nock formula.
*/
typedef u2_noun u2_tool;
/* u2_pool:
**
** A set, stored as binary treap by mug.
*/
typedef u2_noun u2_pool;
/* u2_book:
**
** An associative array, stored as binary treap by mug.
*/
typedef u2_noun u2_book;
/* u2_unit:
**
** A conditional (maybe), `[0 n]` or `0`.
*/
typedef u2_noun u2_unit;
/** Functions.
**/
/** Lifecycle.
**/
/* u2_loom_boot():
**
** Instantiate the loom as a new image.
*/
void
u2_loom_boot(void);
/* u2_loom_clip():
**
** Clip top and bottom.
*/
void
u2_loom_clip(c3_w bot_w, c3_w top_w);
/* u2_loom_load():
**
** Load the loom from a file.
*/
u2_bean
u2_loom_load(void);
/* u2_loom_exit():
**
** Quit out of the loom.
*/
void
u2_loom_exit(void);
/* u2_loom_save():
**
** Save the current loom at the current event number.
*/
u2_bean
u2_loom_save(c3_d ent_d);
/** General.
**/
/* u2_dust():
**
** Yes iff (a) is a cell.
*/
#if 0
u2_bean
u2_dust(u2_noun a)
#else
# define u2_dust(a) \
(u2_fly_is_atom(a) ? u2_no : u2_yes)
#endif
/* u2_frag():
**
** Return fragment (a) of (b), or u2_none if not applicable.
*/
u2_weak
u2_frag(u2_atom a,
u2_noun b);
/* u2_mean():
**
** Attempt to deconstruct `a` by axis, noun pairs; 0 terminates.
** Axes must be sorted in tree order.
*/
u2_bean
u2_mean(u2_noun a,
...);
/* u2_mug():
**
** Compute and/or recall the mug (31-bit hash) of (a).
*/
c3_w
u2_mug(u2_noun a);
/* u2_mug_string():
**
** Compute the mug of `a`, LSB first.
*/
c3_w
u2_mug_string(const c3_c *a_c);
/* u2_mug_words():
**
** Compute the mug of `buf`, `len`, LSW first.
*/
c3_w
u2_mug_words(const c3_w *buf_w,
c3_w len_w);
/* u2_mug_cell():
**
** Compute the mug of `[a b]`.
*/
c3_w
u2_mug_cell(u2_noun a,
u2_noun b);
/* u2_mug_trel():
**
** Compute the mug of `[a b c]`.
*/
c3_w
u2_mug_trel(u2_noun a,
u2_noun b,
u2_noun c);
/* u2_mug_qual():
**
** Compute the mug of `[a b c d]`.
*/
c3_w
u2_mug_qual(u2_noun a,
u2_noun b,
u2_noun c,
u2_noun d);
/* u2_mug_both():
**
** Join two mugs.
*/
c3_w
u2_mug_both(c3_w a_w,
c3_w b_w);
/* u2_fing():
**
** Yes iff (a) and (b) are the same copy of the same noun.
** (Ie, by pointer equality - u2_sing with false negatives.)
*/
u2_bean
u2_fing(u2_noun a,
u2_noun b);
/* u2_fing_c():
**
** Yes iff (b) is the same copy of the same noun as the C string [a].
*/
u2_bean
u2_fing_c(const c3_c* a_c,
u2_noun b);
/* u2_fing_cell():
**
** Yes iff `[p q]` and `b` are the same copy of the same noun.
*/
u2_bean
u2_fing_cell(u2_noun p,
u2_noun q,
u2_noun b);
/* u2_fing_mixt():
**
** Yes iff `[p q]` and `b` are the same copy of the same noun.
*/
u2_bean
u2_fing_mixt(const c3_c* p_c,
u2_noun q,
u2_noun b);
/* u2_fing_trel():
**
** Yes iff `[p q r]` and `b` are the same copy of the same noun.
*/
u2_bean
u2_fing_trel(u2_noun p,
u2_noun q,
u2_noun r,
u2_noun b);
/* u2_fing_qual():
**
** Yes iff `[p q r s]` and `b` are the same copy of the same noun.
*/
u2_bean
u2_fing_qual(u2_noun p,
u2_noun q,
u2_noun r,
u2_noun s,
u2_noun b);
/* u2_sing():
**
** Yes iff (a) and (b) are the same noun.
*/
u2_bean
u2_sing(u2_noun a,
u2_noun b);
/* u2_sing_c():
**
** Yes iff (b) is the same noun as the C string [a].
*/
u2_bean
u2_sing_c(const c3_c* a_c,
u2_noun b);
/* u2_sing_cell():
**
** Yes iff `[p q]` and `b` are the same noun.
*/
u2_bean
u2_sing_cell(u2_noun p,
u2_noun q,
u2_noun b);
/* u2_sing_mixt():
**
** Yes iff `[p q]` and `b` are the same noun.
*/
u2_bean
u2_sing_mixt(const c3_c* p_c,
u2_noun q,
u2_noun b);
/* u2_sing_trel():
**
** Yes iff `[p q r]` and `b` are the same noun.
*/
u2_bean
u2_sing_trel(u2_noun p,
u2_noun q,
u2_noun r,
u2_noun b);
/* u2_sing_qual():
**
** Yes iff `[p q r s]` and `b` are the same noun.
*/
u2_bean
u2_sing_qual(u2_noun p,
u2_noun q,
u2_noun r,
u2_noun s,
u2_noun b);
/* u2_nord():
**
** Return 0, 1 or 2 if `a` is below, equal to, or above `b`.
*/
u2_atom
u2_nord(u2_noun a,
u2_noun b);
/* u2_stud():
**
** Yes iff (a) is an atom.
*/
#if 0
u2_bean
u2_stud(u2_noun a)
#else
# define u2_stud(a) \
(u2_fly_is_atom(a) ? u2_yes : u2_no)
#endif
/** Cell access.
**/
/* u2_as_bush():
**
** Factor [a] as a bush [b.[p q] c].
*/
u2_bean
u2_as_bush(u2_noun a,
u2_noun* b,
u2_noun* c);
/* u2_as_cell():
**
** Factor (a) as a cell (b c).
*/
u2_bean
u2_as_cell(u2_noun a,
u2_noun* b,
u2_noun* c);
/* u2_as_hext():
**
** Factor (a) as a hext (b c d e f g)
*/
u2_bean
u2_as_hext(u2_noun a,
u2_noun* b,
u2_noun* c,
u2_noun* d,
u2_noun* e,
u2_noun* f,
u2_noun* g);
/* u2_as_p():
**
** & [0] if [a] is of the form [b *c].
*/
u2_bean
u2_as_p(u2_noun a,
u2_noun b,
u2_noun* c);
/* u2_as_pq():
**
** & [0] if [a] is of the form [b *c d].
*/
u2_bean
u2_as_pq(u2_noun a,
u2_noun b,
u2_noun* c,
u2_noun* d);
/* u2_as_pqr():
**
** & [0] if [a] is of the form [b *c *d *e].
*/
u2_bean
u2_as_pqr(u2_noun a,
u2_noun b,
u2_noun* c,
u2_noun* d,
u2_noun* e);
/* u2_as_pqrs():
**
** & [0] if [a] is of the form [b *c *d *e *f].
*/
u2_bean
u2_as_pqrs(u2_noun a,
u2_noun b,
u2_noun* c,
u2_noun* d,
u2_noun* e,
u2_noun* f);
/* u2_as_qual():
**
** Factor (a) as a qual (b c d e).
*/
u2_bean
u2_as_qual(u2_noun a,
u2_noun* b,
u2_noun* c,
u2_noun* d,
u2_noun* e);
/* u2_as_quil():
**
** Factor (a) as a quil (b c d e f).
*/
u2_bean
u2_as_quil(u2_noun a,
u2_noun* b,
u2_noun* c,
u2_noun* d,
u2_noun* e,
u2_noun* f);
/* u2_as_trel():
**
** Factor (a) as a trel (b c d).
*/
u2_bean
u2_as_trel(u2_noun a,
u2_noun *b,
u2_noun *c,
u2_noun *d);
/* u2_h(), u2_sh():
**
** Return the head of `a`, unsafely or safely.
*/
#if 0
u2_noun
u2_h(u2_noun a);
#else
# define u2_h(a) (*u2_at_pom_hed(a))
#endif
u2_noun
u2_sh(u2_noun a);
/* u2_t(), u2_st():
**
** Return the tail of `a`, unsafely or safely.
*/
#if 0
u2_noun
u2_t(u2_noun a);
#else
# define u2_t(a) (*u2_at_pom_tel(a))
#endif
u2_noun
u2_st(u2_noun a);
/** Atom access.
**/
/* u2_met():
**
** Return the size of (b) in bits, rounded up to
** (1 << a_y).
**
** For example, (a_y == 3) returns the size in bytes.
*/
c3_w
u2_met(c3_y a_y,
u2_atom b);
/* u2_bit():
**
** Return bit (a_w) of (b).
*/
c3_b
u2_bit(c3_w a_w,
u2_atom b);
/* u2_byte():
**
** Return byte (a_w) of (b).
*/
c3_y
u2_byte(c3_w a_w,
u2_atom b);
/* u2_bytes():
**
** Copy bytes (a_w) through (a_w + b_w - 1) from (d) to (c).
*/
void
u2_bytes(c3_w a_w,
c3_w b_w,
c3_y* c_y,
u2_atom d);
/* u2_chop():
**
** Into the bloq space of `met`, from position `fum` for a
** span of `wid`, to position `tou`, XOR from atom `src`
** into ray `dst`.
*/
void
u2_chop(c3_g met_g,
c3_w fum_w,
c3_w wid_w,
c3_w tou_w,
u2_ray dst_r,
u2_atom src);
/* u2_mp():
**
** Copy (b) into (a_mp).
*/
void
u2_mp(mpz_t a_mp,
u2_atom b);
/* u2_word():
**
** Return word (a_w) of (b).
*/
c3_w
u2_word(c3_w a_w,
u2_atom b);
/* u2_chub():
**
** Return double-word (a_w) of (b).
*/
c3_d
u2_chub(c3_w a_w,
u2_atom b);
/* u2_words():
**
** Copy words (a_w) through (a_w + b_w - 1) from (d) to (c).
*/
void
u2_words(c3_w a_w,
c3_w b_w,
c3_w* c_w,
u2_atom d);