Generic BigList Utilities #7

Parent #72Owner #29Flags readSource hellcore/hellcore.db

Aliases: ghblu, biglist_utils

26 verbs · 13 properties · 0 children

Verbs

VerbSpecFlagsDefinerLines
lengththis none thisrxd#72
find_nththis none thisrxd#72
find_ordthis none thisrxd#74
set_nththis none thisrxd#78
killthis none thisrxd#77
insert_after insert_beforethis none thisrxd#722
extract_rangethis none thisrxd#72
delete_rangethis none thisrxd#76
keep_rangethis none thisrxd#76
insert_lastthis none thisrxd#733
startthis none thisrxd#724
nextthis none thisrxd#720
_find_nththis none thisrxd#718
_find_ordthis none thisrxd#725
_set_nththis none thisrxd#717
_skillthis none thisrxd#721
_extractthis none thisrxd#732
_mergethis none thisrxd#716
_smergethis none thisrxd#747
_splitthis none thisrxd#767
_rmergethis none thisrxd#743
_scrunchthis none thisrxd#713
_listfind_nththis none thisrxd#710
_insertfirstthis none thisrxd#73
debugthis none thisrxd#71
_callthis none thisrxd#77

Properties

PropertyDefinerFlagsOwnerValue
about#7rc#29
list of 15{"Implementation notes", "--------------------", "Each biglist is actually a tree (a kind of B-tree, actually).", "The routines above pass around handles of the form", "", " {root_node, size, leftmost_ord}", "", "where root_node is the (string) name of a property that holds the root of the tree, size is the number of leaves in the tree, and leftmost_ord is the :_ord value of the leftmost element of the list (i.e., the leftmost leaf).", "Each node property has a value of the form ", "", " {height,list of subtrees}.", "", "where the each of the subtrees is itself a 3-element list as above unless", "the height is 0, in which case the subtrees are actually biglist elements of the arbitrary form determined by the home object.", "At every level, each node except the rightmost has between this.maxfanout/2 and this.maxfanout subtrees; the rightmost is allowed to have as few as 1 subtree."}
maxfanout#7rc#297
help_msg#72rc#29
list of 73{"Generic BigList Utilities", "----------------------------", "This is a package for maintaining huge persistent (sorted) lists in a format that is less likely to spam the server (which runs into a certain amount of trouble dealing with long ordinary lists --- btw we use `biglist' to refer to the huge data structure we're about to describe and `list' to refer to ordinary MOO lists {...}). The biglist in question lives on a particular object, to which we will refer in the discussion below as the `home' object, and its various elements appear as leaves of a tree whose nodes are kept in properties of the home object. It should be noted that the home object does not need to be (and in fact should *not* be) a descendant of this one; this object merely provides utilities for manipulating the properties on the home object that are used in a particular biglist manipulation. ", "", "All of the utilities below refer to `caller' to locate the home object. Thus verbs to manipulate a given biglist must be located on or inherited by its home object itself. The home object needs to define the following verbs", "", " :_make(@args) => new property on home object with value args", " :_kill(prop) delete a given property that was created by :_make", " :_get(prop) => home.prop", " :_put(prop,@args) set home.prop = args", " :_ord(element) given something that is of the form of a biglist element", " return the corresponding ordinal (for sorting purposes).", " If you never intend to use :find_ord, then this can be a ", " routine that always returns 0 or some other random value.", "", "See #5546 (Generic Biglist Resident) or $big_mail_recipient", "for examples.", "", "Those of the following routines that take a biglist argument are expecting", "either {} (empty biglist) or some biglist returned by one of the other routines", "", " :length(biglist) => length(biglist) (i.e., number of elements)", " :find_nth(biglist,n) => biglist[n]", " :find_ord(biglist,k,comp) => n where n is", " the largest such that home:(comp)(k,home:_ord(biglist[n])) is false, or", " the smallest such that home:(comp)(k,home:_ord(biglist[n+1])) is true.", " Always returns a value between 0 and length(biglist) inclusive.", " This assumes biglist to be sorted in order of increasing :_ord values ", " with respect to home:(comp)().", " Standard situation is :_ord returns a number and comp is a < verb.", "", " :start(biglist,s,e) => {biglist[s..?],@handle} or {}", " :next(@handle) => {biglist[?+1..??],@newhandle} or {}", " These two are used for iterating over a range of elements of a biglist", " The canonical incantation for doing", " for elt in (biglist[first..last])", " ...", " endfor", " is", " handle = :start(biglist,first,last);", " while(handle)", " for elt in (handle[1])", " ...", " endfor", " handle = :next(@listdelete(handle,1));", " endwhile", "", "The following all destructively modify their biglist argument(s) L (and M).", "", " :set_nth(L,n,value) => L[n] = value", " replaces the indicated element", "", " :insert_before(L,M,n) => {@L[1..n-1],@M,@L[n..length(L)]}", " :insert_after (L,M,n) => {@L[1..n], @M,@L[n+1..length(L)]}", " takes two distinct biglists, inserts one into the other at the given point", " returns the resulting consolidated biglist", "", " :extract_range(L,m,n) => {{@L[1..m-1],@L[n+1..]}, L[m..n]} ", " breaks the given biglist into two distinct biglists.", "", " :delete_range(L,m,n[,leafkiller]) => {@L[1..m-1],@L[n+1..]}", " :keep_range (L,m,n[,leafkiller]) => L[m..n]", " like extract_range only we destroy what we don't want.", "", " :insert_last(L,value) => {@L,value}", " inserts a new element at the end of biglist. ", " If find_ord is to continue to work properly, it is assumed that the ", " home:_ord(elt) is greater (comp-wise) than all of the :_ord values", " of elements currently in the biglist.", "", " :kill(L[,leafkiller]) ", " destroys all nodes used by biglist. ", " Calls home:leafkiller on each element."}
aliases#1r#29{"ghblu", "biglist_utils"}
description#1rc#29{"This is the Generic BigList Utilities utility package. See `help $biglist' for more details."}
object_size#1r#29{23044, 1298433815}
hidden_verbs#1rc#29<clear>
phelp_msg#1rc#29<clear>
weight#1rc#29<clear>
owner_verbs#1rc#29<clear>
plural_name#1rc#29<clear>
client_image#1rc#29<clear>
listening#1rc#29<clear>

Ancestry

Ancestors (nearest first): #72 Generic Utilities Package#1 root

Children: none

Call graph

calls n7_1 #7:find_nth n7_12 #7:_find_nth n7_1->n7_12 n7_12->n7_12 n7_2 #7:find_ord n7_13 #7:_find_ord n7_2->n7_13 n7_13->n7_13 n7_25 #7:_call n7_13->n7_25 n7_3 #7:set_nth n7_14 #7:_set_nth n7_3->n7_14 n7_14->n7_14 n7_22 #7:_listfind_nth n7_14->n7_22 n7_4 #7:kill n7_15 #7:_skill n7_4->n7_15 n7_15->n7_15 n7_15->n7_25 n7_5 #7:insert_after n7_17 #7:_merge n7_5->n7_17 n7_19 #7:_split n7_5->n7_19 n7_20 #7:_rmerge n7_17->n7_20 n7_18 #7:_smerge n7_17->n7_18 n7_19->n7_19 n7_19->n7_22 n7_6 #7:extract_range n7_16 #7:_extract n7_6->n7_16 n7_16->n7_17 n7_16->n7_19 n7_21 #7:_scrunch n7_16->n7_21 n7_7 #7:delete_range n7_7->n7_15 n7_7->n7_16 n7_8 #7:keep_range n7_8->n7_15 n7_8->n7_16 n7_10 #7:start n7_10->n7_22 n7_20->n7_18 n7_18->n7_18 n7_24 #7:debug n42_0 #42:controls n7_24->n42_0

Source

length

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":length(tree) => number of leaves in tree.";
2return args[1] ? args[1][2] | 0;

find_nth

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":find_nth(tree,n) => nth leaf of tree.  Assumes n in [1..tree[2]]";
2return this:_find_nth(caller, @args);

find_ord

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":_find_ord(tree,n,comp) ";
2" => index of rightmost leaf for which :(comp)(n,:_ord(leaf)) is false.";
3"returns 0 if true for all leaves.";
4return args[1] ? this:_find_ord(caller, @args) | 0;

set_nth

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":set_nth(tree,n,value) => tree";
2"modifies tree so that nth leaf == value";
3if (((n = args[2]) < 1) || ((!(tree = args[1])) || (tree[2] < n)))
4return E_RANGE;
5else
6this:_set_nth(caller, @args);
7return (n != 1) ? tree | listset(tree, caller:_ord(args[3]), 3);
8endif

kill

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":kill(tree[,leafverb]) deletes tree and _kills all of the nodes that it uses.";
2"if leafverb is given, caller:leafverb is called on all leaves in tree.";
3if (tree = args[1])
4lverb = {@args, ""}[2];
5this:_skill(caller, (typeof(tree) == LIST) ? tree[1] | tree, lverb);
6endif
7"... otherwise nothing to do...";

insert_after insert_before

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":insert_after(tree,subtree,n)";
2":insert_before(tree,subtree,n)";
3"  inserts subtree after (before) the nth leaf of tree,";
4"  returning the resulting tree.";
5subtree = args[2];
6if (tree = args[1])
7if (subtree)
8where = args[3] - (verb == "insert_before");
9if (where <= 0)
10return this:_merge(caller, subtree, tree);
11elseif (where >= tree[2])
12return this:_merge(caller, tree, subtree);
13else
14s = this:_split(caller, caller:_get(tree[1])[1], where, tree);
15return this:_merge(caller, this:_merge(caller, s[1], subtree), s[2]);
16endif
17else
18return tree;
19endif
20else
21return subtree;
22endif

extract_range

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":extract_range(tree,first,last) => {newtree,extraction}";
2return this:_extract(caller, @args);

delete_range

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":delete_range(tree,first,last[,leafkill]) => newtree";
2extract = this:_extract(caller, @args);
3if (die = extract[2])
4this:_skill(caller, die[1], {@args, ""}[4]);
5endif
6return extract[1];

keep_range

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":keep_range(tree,first,last[,leafkill]) => range";
2extract = this:_extract(caller, @args);
3if (die = extract[1])
4this:_skill(caller, die[1], {@args, ""}[4]);
5endif
6return extract[2];

insert_last

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":insert_last(tree,insert) => newtree";
2"insert a new leaf to be inserted at the righthand end of the tree";
3tree = args[1];
4insert = args[2];
5if (!tree)
6return {caller:_make(0, {insert}), 1, caller:_ord(insert)};
7endif
8hgt = caller:_get(tree[1]);
9rspine = {{tree, plen = length(kids = hgt[2])}};
10for i in [1..hgt[1]]
11parent = kids[plen];
12kids = caller:_get(parent[1])[2];
13plen = length(kids);
14rspine = {{parent, plen}, @rspine};
15endfor
16iord = caller:_ord(insert);
17for h in [1..length(rspine)]
18"... tree is the plen'th (rightmost) child of parent...";
19if (rspine[h][2] < this.maxfanout)
20parent = rspine[h][1];
21hgp = caller:_get(parent[1]);
22caller:_put(parent[1], @listset(hgp, {@hgp[2], insert}, 2));
23for p in (rspine[h + 1..length(rspine)])
24rkid = listset(parent, parent[2] + 1, 2);
25parent = p[1];
26hgp = caller:_get(parent[1]);
27caller:_put(parent[1], @listset(hgp, listset(hgp[2], rkid, p[2]), 2));
28endfor
29return listset(tree, tree[2] + 1, 2);
30endif
31insert = {caller:_make(h - 1, {insert}), 1, iord};
32endfor
33return {caller:_make(length(rspine), {tree, insert}), tree[2] + 1, tree[3]};

start

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":start(tree,first,last) => {list of leaf nodes, @handle}";
2"handle is of the form {{node,next,size}...}";
3if (tree = args[1])
4before = max(0, args[2] - 1);
5howmany = min(args[3], tree[2]) - before;
6if (howmany <= 0)
7return {};
8else
9spine = {};
10for h in [1..caller:_get(tree[1])[1]]
11ik = this:_listfind_nth(kids = caller:_get(tree[1])[2], before);
12newh = kids[ik[1]][2] - ik[2];
13if (newh < howmany)
14spine = {{tree[1], ik[1] + 1, howmany - newh}, @spine};
15howmany = newh;
16endif
17tree = kids[ik[1]];
18before = ik[2];
19endfor
20return {caller:_get(tree[1])[2][before + 1..before + howmany], @spine};
21endif
22else
23return {};
24endif

next

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1":next(@handle) => {list of more leaf nodes, @newhandle}";
2if (args)
3spine = listdelete(args, 1);
4node = args[1][1];
5n = args[1][2];
6size = args[1][3];
7for h in [1..caller:_get(node)[1]]
8nnode = caller:_get(node)[2][n];
9if (size > nnode[2])
10spine = {{node, n + 1, size - nnode[2]}, @spine};
11size = nnode[2];
12endif
13n = 1;
14node = nnode[1];
15endfor
16test = caller:_get(node);
17return {test[2][n..size], @spine};
18else
19return {};
20endif

_find_nth

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1":_find_nth(home,tree,n) => nth leaf of tree.";
2"...Assumes n in [1..tree[2]]";
3if (caller != this)
4return E_PERM;
5endif
6{home, tree, n} = args;
7if ((p = home:_get(tree[1]))[1])
8for k in (p[2])
9if (n > k[2])
10n = n - k[2];
11else
12return this:_find_nth(home, k, n);
13endif
14endfor
15return E_RANGE;
16else
17return p[2][n];
18endif

_find_ord

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1":_find_ord(home,tree,n,less_than) ";
2" => index of rightmost leaf for which :(less_than)(n,:_ord(leaf)) is false.";
3"returns 0 if true for all leaves.";
4if (caller != this)
5return E_PERM;
6endif
7{home, tree, n, less_than} = args;
8if ((p = home:_get(tree[1]))[1])
9sz = tree[2];
10for i in [-length(p[2])..-1]
11k = p[2][-i];
12sz = sz - k[2];
13if (!this:_call(home, less_than, n, k[3]))
14return sz + this:_find_ord(home, k, n, less_than);
15endif
16endfor
17return 0;
18else
19for i in [1..r = length(p[2])]
20if (this:_call(home, less_than, n, home:_ord(p[2][i])))
21return i - 1;
22endif
23endfor
24return r;
25endif

_set_nth

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1":_set_nth(home,tree,n,value) => tree[n] = value";
2"Assumes n in [1..tree[2]]";
3if (caller != this)
4return E_PERM;
5endif
6{home, tree, n, value} = args;
7if ((p = home:_get(tree[1]))[1])
8ik = this:_listfind_nth(p[2], n - 1);
9this:_set_nth(home, p[2][ik[1]], ik[2] + 1, value);
10if (!ik[2])
11p[2][ik[1]][3] = home:_ord(value);
12home:_put(tree[1], @p);
13endif
14else
15p[2][n] = value;
16home:_put(tree[1], @p);
17endif

_skill

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1":_skill(home,node,kill_leaf)";
2"home:_kill's node and all descendants, home:(kill_leaf)'s all leaves";
3if (caller != this)
4return E_PERM;
5endif
6{home, node, kill_leaf} = args;
7try
8{height, subtrees} = home:_get(node) || {0, {}};
9except (E_PROPNF)
10return;
11endtry
12if (height)
13for kid in (subtrees)
14this:_skill(home, kid[1], kill_leaf);
15endfor
16elseif (kill_leaf)
17for kid in (subtrees)
18this:_call(home, kill_leaf, kid);
19endfor
20endif
21home:_kill(node);

_extract

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1":_extract(home,tree,first,last) => {newtree,extraction}";
2if (caller != this)
3return E_PERM;
4endif
5home = args[1];
6if (!(tree = args[2]))
7return {{}, {}};
8endif
9before = max(0, args[3] - 1);
10end = min(tree[2], args[4]);
11if ((end <= 0) || (before >= end))
12return {tree, {}};
13endif
14height = home:_get(tree[1])[1];
15if (end < tree[2])
16r = this:_split(home, height, end, tree);
17if (before)
18l = this:_split(home, height, before, r[1]);
19extract = l[2];
20newtree = this:_merge(home, l[1], r[2]);
21else
22extract = r[1];
23newtree = r[2];
24endif
25elseif (before)
26l = this:_split(home, height, before, tree);
27extract = l[2];
28newtree = l[1];
29else
30return {{}, tree};
31endif
32return {this:_scrunch(home, newtree), this:_scrunch(home, extract)};

_merge

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1"_merge(home,ltree,rtree) => newtree";
2"assumes ltree and rtree to be nonempty.";
3if (caller != this)
4return E_PERM;
5endif
6{home, lnode, rnode} = args;
7lh = home:_get(lnode[1])[1];
8rh = home:_get(rnode[1])[1];
9if (lh > rh)
10return this:_rmerge(home, lnode, rnode);
11endif
12for h in [lh + 1..rh]
13lnode[1] = home:_make(h, {lnode});
14endfor
15m = this:_smerge(home, rh, lnode, rnode);
16return (length(m) <= 1) ? m[1] | {home:_make(rh + 1, m), m[1][2] + m[2][2], m[1][3]};

_smerge

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1"_smerge(home, height, ltree, rtree) =>{ltree[,rtree]}";
2"assumes ltree and rtree are at the given height.";
3"merges the trees if the combined number of children is <= maxfanout";
4"otherwise returns two trees where ltree is guaranteed minfanout children and rtree is guaranteed the minimum of minfanout and however many children it started with.";
5if (caller != this)
6return E_PERM;
7endif
8{home, height, ltree, rtree} = args;
9llen = length(lkids = home:_get(ltree[1])[2]);
10rlen = length(rkids = home:_get(rtree[1])[2]);
11if (height)
12m = this:_smerge(home, height - 1, lkids[llen], rkids[1]);
13mlen = length(mkids = {@listdelete(lkids, llen), @m, @listdelete(rkids, 1)});
14if (mlen <= this.maxfanout)
15home:_put(ltree[1], height, mkids);
16home:_kill(rtree[1]);
17ltree[2] = ltree[2] + rtree[2];
18return {ltree};
19else
20S = max(llen - 1, (mlen + 1) / 2);
21home:_put(ltree[1], height, mkids[1..S]);
22home:_put(rtree[1], height, mkids[S + 1..$]);
23xfer = -lkids[llen][2];
24for k in (mkids[llen..S])
25xfer = xfer + k[2];
26endfor
27ltree[2] = ltree[2] + xfer;
28rtree[2] = rtree[2] - xfer;
29rtree[3] = mkids[S + 1][3];
30return {ltree, rtree};
31endif
32elseif ((llen * 2) >= this.maxfanout)
33return {ltree, rtree};
34elseif (this.maxfanout < (llen + rlen))
35T = ((rlen - llen) + 1) / 2;
36home:_put(ltree[1], 0, {@lkids, @rkids[1..T]});
37home:_put(rtree[1], 0, rkids[T + 1..rlen]);
38ltree[2] = ltree[2] + T;
39rtree[2] = rtree[2] - T;
40rtree[3] = home:_ord(rkids[T + 1]);
41return {ltree, rtree};
42else
43home:_put(ltree[1], 0, {@lkids, @rkids});
44home:_kill(rtree[1]);
45ltree[2] = ltree[2] + rtree[2];
46return {ltree};
47endif

_split

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1"_split(home, height,lmax,ltree[,@rtrees]}) => {ltree,[mtree,]@rtrees}";
2"ltree is split after the lmax'th leaf, the righthand portion grafted onto the leftmost of the rtrees, if possible.  Otherwise we create a new tree mtree, stealing from rtrees[1] if necessary.";
3"Assumes 1<=lmax<ltree[2]";
4if (caller != this)
5return E_PERM;
6endif
7{home, height, lmax, ltree, @rtrees} = args;
8llen = length(lkids = home:_get(ltree[1])[2]);
9rlen = length(rkids = rtrees ? home:_get(rtrees[1][1])[2] | {});
10if (height)
11ik = this:_listfind_nth(lkids, lmax);
12if (ik[2])
13llast = ik[1];
14m = this:_split(home, height - 1, ik[2], lkids[llast], @lkids[llast + 1..llen], @rkids);
15lkids[llast] = m[1];
16mkids = listdelete(m, 1);
17else
18llast = ik[1] - 1;
19mkids = {@lkids[ik[1]..llen], @rkids};
20endif
21home:_put(ltree[1], height, lkids[1..llast]);
22mlen = length(mkids);
23if ((((mlen - rlen) * 2) >= this.maxfanout) || (!rtrees))
24"...residue left over from splitting ltree can stand by itself...";
25return {listset(ltree, lmax, 2), {home:_make(height, mkids[1..mlen - rlen]), ltree[2] - lmax, mkids[1][3]}, @rtrees};
26elseif (mlen <= this.maxfanout)
27"...residue left over from splitting ltree fits in rtrees[1]...";
28home:_put(rtrees[1][1], height, mkids);
29rtrees[1][2] = (ltree[2] - lmax) + rtrees[1][2];
30rtrees[1][3] = mkids[1][3];
31return {listset(ltree, lmax, 2), @rtrees};
32else
33"...need to steal from rtrees[1]...";
34if (llast < llen)
35msize = ltree[2] - lmax;
36R = (mlen - rlen) + 1;
37else
38msize = 0;
39R = 1;
40endif
41for k in (mkids[R..mlen / 2])
42msize = msize + k[2];
43endfor
44home:_put(rtrees[1][1], height, mkids[(mlen / 2) + 1..mlen]);
45rtrees[1][2] = (rtrees[1][2] + ltree[2]) - (lmax + msize);
46rtrees[1][3] = mkids[(mlen / 2) + 1][3];
47return {listset(ltree, lmax, 2), {home:_make(height, mkids[1..mlen / 2]), msize, mkids[1][3]}, @rtrees};
48endif
49else
50home:_put(ltree[1], 0, lkids[1..lmax]);
51if ((((llen - lmax) * 2) >= this.maxfanout) || (!rtrees))
52"...residue left over from splitting ltree can stand by itself...";
53return {listset(ltree, lmax, 2), {home:_make(0, lkids[lmax + 1..llen]), llen - lmax, home:_ord(lkids[lmax + 1])}, @rtrees};
54elseif ((mlen = (rlen + llen) - lmax) <= this.maxfanout)
55"...residue left over from splitting ltree fits in rtrees[1]...";
56home:_put(rtrees[1][1], 0, {@lkids[lmax + 1..llen], @rkids});
57rtrees[1][2] = mlen;
58rtrees[1][3] = home:_ord(lkids[lmax + 1]);
59return {listset(ltree, lmax, 2), @rtrees};
60else
61"...need to steal from rtrees[1]...";
62home:_put(rtrees[1][1], 0, rkids[(R = ((rlen - llen) + lmax) / 2) + 1..rlen]);
63rtrees[1][2] = (mlen + 1) / 2;
64rtrees[1][3] = home:_ord(rkids[R + 1]);
65return {listset(ltree, lmax, 2), {home:_make(0, {@lkids[lmax + 1..llen], @rkids[1..R]}), mlen / 2, home:_ord(lkids[lmax + 1])}, @rtrees};
66endif
67endif

_rmerge

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1":_rmerge(home, tree, insertree) => newtree ";
2"(newtree is tree with insertree appended to the right)";
3"insertree is assumed to be of height < tree";
4if (caller != this)
5return E_PERM;
6endif
7{home, tree, insert} = args;
8if (!tree)
9return insert;
10elseif (!insert)
11return tree;
12endif
13iheight = home:_get(insert[1])[1];
14rspine = {};
15for i in [iheight + 1..home:_get(tree[1])[1]]
16kids = home:_get(tree[1])[2];
17tlen = length(kids);
18rspine = {{tree, tlen}, @rspine};
19tree = kids[tlen];
20endfor
21isize = insert[2];
22m = this:_smerge(home, iheight, tree, insert);
23for h in [1..length(rspine)]
24plen = rspine[h][2];
25parent = rspine[h][1];
26hgp = home:_get(parent[1]);
27if (((length(m) - 1) + plen) > this.maxfanout)
28home:_put(parent[1], @listset(hgp, listset(hgp[2], m[1], plen), 2));
29parent[2] = (parent[2] + isize) - m[2][2];
30m = {parent, listset(m[2], home:_make(h + iheight, {m[2]}), 1)};
31else
32home:_put(parent[1], @listset(hgp, {@hgp[2][1..plen - 1], @m}, 2));
33for p in (rspine[h + 1..length(rspine)])
34parent[2] = parent[2] + isize;
35tree = parent;
36parent = p[1];
37hgp = home:_get(parent[1]);
38home:_put(parent[1], @listset(hgp, listset(hgp[2], tree, p[2]), 2));
39endfor
40return listset(parent, parent[2] + isize, 2);
41endif
42endfor
43return {home:_make((length(rspine) + iheight) + 1, m), m[1][2] + m[2][2], m[1][3]};

_scrunch

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1":_scrunch(home,tree) => newtree";
2"decapitates single-child nodes from the top of the tree, returns new root.";
3if (caller != this)
4return E_PERM;
5endif
6if (tree = args[2])
7home = args[1];
8while ((n = home:_get(tree[1]))[1] && (length(n[2]) == 1))
9home:_kill(tree[1]);
10tree = n[2][1];
11endwhile
12endif
13return tree;

_listfind_nth

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

Source

1"_listfind_nth(nodelist,key) => {i,k} where i is the smallest i such that the sum of the first i elements of intlist is > key, and k==key - sum(first i-1 elements).";
2"1 <= i <= length(intlist)+1";
3{lst, key} = args;
4for i in [1..length(lst)]
5key = key - lst[i][2];
6if (0 > key)
7return {i, key + lst[i][2]};
8endif
9endfor
10return {length(lst) + 1, key};

_insertfirst

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1if (caller != this)
2return E_PERM;
3endif

debug

Spec this none thisFlags rxdOwner #29Definer #7

Referenced by

none

Source

1return $perm_utils:controls(caller_perms(), this) ? this:(args[1])(@listdelete(args, 1)) | E_PERM;

_call

Spec this none thisFlags rxdOwner #361Definer #7

Referenced by

Source

1":_call(home,verb,@vargs) calls home:verb(@vargs) with $no_one's perms";
2set_task_perms($no_one);
3if (caller != this)
4raise(E_PERM);
5endif
6{home, vb, @vargs} = args;
7return home:(vb)(@vargs);