-
Notifications
You must be signed in to change notification settings - Fork 0
/
Xanadu Hypertext Documents-20220906.xml
executable file
·3524 lines (3491 loc) · 237 KB
/
Xanadu Hypertext Documents-20220906.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version='1.0' encoding='utf-8'?>
<book xmlns="http://docbook.org/ns/docbook" version="5.1" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en">
<info>
<cover>
<link xlink:href="http://xanadu.com/" xlink:type="simple" xlink:show="new" xlink:actuate="onRequest"><inlinemediaobject><imageobject condition='web'><imagedata fileref='images/www.xanadu.com/FlamingX-transparent.png'/></imageobject><textobject><phrase>Xanadu Flaming-X</phrase></textobject></inlinemediaobject></link>
</cover>
<title>Xanadu Hypertext Documents</title>
<pubdate>1984-04-26</pubdate>
<author>Xanadu Operating Company <link xlink:href='http://aus.xanadu.com/people.html#XOC' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>http://aus.xanadu.com/people.html#XOC</link></author>
<author>Chip Morningstar <link xlink:href='http://www.fudco.com/chip/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>http://www.fudco.com/chip/</link></author>
<editor>Alberto González Palomo <link xlink:href='https://sentido-labs.com/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>https://sentido-labs.com/</link></editor>
<copyright>
<year>1984</year>
<holder>Xanadu Operating Company <link xlink:href='http://aus.xanadu.com/people.html#XOC' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>http://aus.xanadu.com/people.html#XOC</link></holder>
</copyright>
<copyright>
<year>2019</year>
<holder>Alberto González Palomo <link xlink:href='https://sentido-labs.com' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>https://sentido-labs.com</link></holder>
</copyright>
<legalnotice>
<para>“Xanadu<superscript>®</superscript>” and the Eternal-Flaming-X logo are registered trademarks of <link xlink:href='http://xanadu.com/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Project Xanadu</link>.</para>
<para><inlinemediaobject><imageobject condition='web'><imagedata fileref='images/licensebuttons.net/l/by-sa/4.0/88x31.png'/></imageobject><textobject><phrase>CC BY-SA badge</phrase></textobject></inlinemediaobject> This work is released under the <link xlink:href='https://creativecommons.org/licenses/by-sa/4.0/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Creative Commons Attribution-ShareAlike 4.0 International</link> (CC BY-SA 4.0) license.</para>
</legalnotice>
<abstract>
<section xml:id="about-2019-edition">
<title>2019 Edition (revised 2022)</title>
<para>This is a new edition by
<link xlink:href='https://sentido-labs.com/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Alberto González Palomo</link>
of the Xanadu System Proposal written by
<link xlink:href='http://www.fudco.com/chip/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Chip Morningstar</link>
in 1984, from
<link xlink:href='http://habitatchronicles.com/2019/03/a-lost-treasure-of-xanadu/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>the only known remaining copy</link>
which was printed on 1984-04-25 at 12:45
<link xlink:href='https://www.timeanddate.com/time/zones/pdt' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>PDT</link>.</para>
<para>It contains vector graphics instead of the original ASCII diagram,
and corrects small grammatical and print errors.</para>
<para>It features an instance of
<link xlink:href='https://archive.org/details/XD302_86ACM_Prese_AugKnowledgeWorkshopParts1and2?start=316' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Douglas Engelbart</link>’s
<link xlink:href='https://www.dougengelbart.org/content/view/138/#3b4c' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><emphasis>implicit links</emphasis></link>,
automatically linking all appearances of certain
terms to their definitions elsewhere in this
document<note><para>This automatic link shows the drawback of this method:
a naïve string match can not distinguish mentions of “document”
referring to the specific concept in Xanadu from this one
that instead refers to the document on which it is written.</para></note>.
This is done through a Javascript function that operates on the HTML
content from the web server.
It also shows his <link xlink:href='https://www.dougengelbart.org/content/view/148/#6b' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><emphasis>structural statement numbers</emphasis></link>,
those little labels to the right of each paragraph
that allow high resolution linking.</para>
<para>Please note that the dire curse on the original<note>
<blockquote>
<para>This document describes data structures,
designs and concepts which are the
proprietary intellectual property of Xanadu Operating Company, Inc.
The contents of this document are not for distribution or release
in whole or in part to any other party without the express permission
of Xanadu Operating Company, Inc.
All portions of this document are to be considered trade secrets
of Xanadu Operating Company, Inc. including the fact that
some previously published data structures may fall into the
classification of “enfilades”.</para>
<section xml:id="dire-curse">
<title>WARNING!</title>
<para>He who transgresses against the propriety of the Information
contained herein shall be Cursed!
Woe unto all who reveal the Secrets contained herein for they
shall be Hunted unto the Ends of the Universe.
They shall be afflicted unto the Tenth Generation with Lawyers.
Their Corporate Bodies shall be Broken and cast into the Pit.
Their Corporate Veil shall be Pierced, and Liability shall
attach to the Malefactors in personem.
They shall suffer Ulcers and Migraines and Agonies Unimagined.
Yea, Verily, for such shall come to pass against all who would
Dare to Test the Powers of Xanadu unto their Doom.</para>
</section>
<section xml:id="trade-secret-notice">
<title>Backend program copyright notice</title>
<para>Notice: This program belongs to Xanadu Operating Company, Inc.
It is an unpublished work fully protected by the United States
copyright laws. It is considered to be a trade secret and is
not to be divulged or used by parties who have not recieved
written authorization from the owner.</para>
</section>
</blockquote>
</note>
has been lifted,
and the Xanadu materials, including the original for this text,
are released under the
<link xlink:href='https://opensource.org/licenses/MIT' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>MIT license</link>.</para>
<para>This edition is relased under the
<link xlink:href='https://creativecommons.org/licenses/by-sa/4.0/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Creative Commons Attribution-ShareAlike</link> (CC BY-SA 4.0) license.</para>
</section>
</abstract>
<revisionhistory>
<revision><date>2019-04-24</date>
<revremark><para>First release, 35 years after the original.</para></revremark>
</revision>
<revision>
<date>2020-07-12</date>
<revremark><para>Corrected two more typos:
<itemizedlist>
<listitem>“Singe” → “<link xlink:href='#13c1e3a1' xlink:type='simple' xlink:actuate='onRequest'>Sing<emphasis role='strong'>l</emphasis>e</link>”, from the original printout. (Reported by a reader, M.A.)</listitem>
<listitem>“Phoebe <emphasis role='strong'>1</emphasis>s” → “<link xlink:href='#12bg2a' xlink:type='simple' xlink:actuate='onRequest'>Phoebe <emphasis role='strong'>i</emphasis>s</link>”, from the OCR.</listitem>
</itemizedlist>
Also fixed the chapter numbers in the table of contents by skipping the glossary which is not numbered in the original, and made most block-level elements addressable with synthetic identifiers like <link xlink:href='#13c1b1' xlink:type='simple' xlink:actuate='onRequest'>13c1b1</link>.</para>
</revremark>
</revision>
<revision>
<date>2022-03-30</date>
<revremark>
<para>More corrections by another reader (S.K.):</para>
<itemizedlist>
<listitem>“cumulative<emphasis role='strong'>l</emphasis>ndex” → “<link xlink:href='#algorithm-retrieve' xlink:type='simple' xlink:actuate='onRequest'>cumulative<emphasis role='strong'>I</emphasis>ndex</link>”, OCR.</listitem>
<listitem>“disp(ch<emphasis role='strong'>l</emphasis>ld)” → “<link xlink:href='#algorithm-retrieve' xlink:type='simple' xlink:actuate='onRequest'>… ch<emphasis role='strong'>i</emphasis>ld …</link>”, OCR.</listitem>
<listitem>“<link xlink:href='#4d5' xlink:type='simple' xlink:actuate='onRequest'>result</link>” and “<link xlink:href='#4d6' xlink:type='simple' xlink:actuate='onRequest'>cumulativeIndex</link>” are now marked up.</listitem>
<listitem>“disp(crum) <-- disp(crum) .+. (C<emphasis role='strong'>3</emphasis> .-. C2)” → “<link xlink:href='#algorithm-four-cut-rearrange' xlink:type='simple' xlink:actuate='onRequest'>… C<emphasis role='strong'>4</emphasis> …</link>”, my mistake as I typed this part. Did not copy the OCR text because it did not work well with those symbols.</listitem>
<listitem>“if (disp(child) .<. <emphasis role='strong'>t</emphasis>irstCut(cutSet)) and (lastCut(cutSet) .<=. (disp(child) .+. wid(child)))” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>f</emphasis>irstCut …</link>”, OCR.</listitem>
<listitem>“dontDiveDeeperFlag <-- <emphasis role='strong'>P</emphasis>ALSE” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>F</emphasis>ALSE</link>”, OCR.</listitem>
<listitem>“for each cut <emphasis role='strong'>1</emphasis>n cutSet” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>… cut <emphasis role='strong'>i</emphasis>n cutSet</link>”, OCR.</listitem>
<listitem>“ne<emphasis role='strong'>W</emphasis>ChildSet <-- split(cut, child)” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>ne<emphasis role='strong'>w</emphasis>ChildSet …</link>”, OCR.</listitem>
<listitem>“adopt (parentCrum, leftCh<emphasis role='strong'>l</emphasis>ld(newChildSet))” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>… leftCh<emphasis role='strong'>i</emphasis>ld …</link>”, OCR.</listitem>
<listitem>“disp(r<emphasis role='strong'>1</emphasis>ghtCrum) <-- cut” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>… r<emphasis role='strong'>i</emphasis>ghtCrum …</link>”, OCR.</listitem>
<listitem>“ne<emphasis role='strong'>W</emphasis>ChildSet <-- split(cut .-. disp(child), child)” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>… ne<emphasis role='strong'>w</emphasis>ChildSet …</link>”, OCR.</listitem>
<listitem>“<link xlink:href='#4d16' xlink:type='simple' xlink:actuate='onRequest'>child</link>” and “<link xlink:href='#4d16' xlink:type='simple' xlink:actuate='onRequest'>parent</link>” are now marked up.</listitem>
<listitem>“wid(newCrum) <-- naturalWid(newTh<emphasis role='strong'>1</emphasis>ng)” → “<link xlink:href='#algorithm-append' xlink:type='simple' xlink:actuate='onRequest'>… newTh<emphasis role='strong'>i</emphasis>ng …</link>”, OCR.</listitem>
<listitem>“if (notNull(potentia<emphasis role='strong'>I</emphasis>NewCrum))” → “<link xlink:href='#algorithm-append' xlink:type='simple' xlink:actuate='onRequest'>… potentia<emphasis role='strong'>l</emphasis>NewCrum …</link>”, OCR.</listitem>
<listitem>“wid (newCrum) <-- wid(potent<emphasis role='strong'>l</emphasis>alNewCrum)” → “<link xlink:href='#algorithm-cut' xlink:type='simple' xlink:actuate='onRequest'>… potent<emphasis role='strong'>i</emphasis>alNewCrum …</link>”, OCR.</listitem>
<listitem>“wid(new<emphasis role='strong'>P</emphasis>ulcrum) <-- enwidify(fulcrum, newCrum)” → “<link xlink:href='#algorithm-level-push' xlink:type='simple' xlink:actuate='onRequest'>… new<emphasis role='strong'>F</emphasis>ulcrum …</link>”, OCR.</listitem>
<listitem>“The algorithm to merge two <emphasis role='strong'>S</emphasis>iblings is:” → “<link xlink:href='#4d23' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>s</emphasis>iblings …</link>”, OCR.</listitem>
<listitem>“disp(newFulcrum) <-- disp(newFulcrum)” → “<link xlink:href='#algorithm-level-pop' xlink:type='simple' xlink:actuate='onRequest'>… disp(newFulcrum)<emphasis role='strong'> .+. disp(fulcrum)</emphasis></link>”, my mistake as I didn’t notice that, due to the OCR text structure, selecting this area for copying missed that part.</listitem>
<listitem>“TUMBLERS AND <emphasis role='strong'>B</emphasis>UMBERS” → “<link xlink:href='#5e1' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>H</emphasis>UMBERS</link>”, OCR.</listitem>
</itemizedlist>
<para>Changed structural statement format from “1.2.3.4” to the more compact “1b3d”. NLS could switch between them at will, and <link xlink:href='https://www.dougengelbart.org/content/view/148/#6b2' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Engelbart reports that the compact alphanumeric variant was most often preferred</link>. It is also the notation used in the <link xlink:href='https://dougengelbart.org/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>website of the Doug Engelbart Institute</link>.</para>
<para>Updated <link xlink:href='#13c1a3a3b2a' xlink:type='simple' xlink:actuate='onRequest'>link for the Interlisp-D documentation</link>, that no longer worked. It now uses the Internet Archive. There is also the <link xlink:href='#13c1a3a3b2a' xlink:type='simple' xlink:actuate='onRequest'>description of the I/O and virtual memory system</link>.</para>
</revremark>
</revision>
<revision>
<date>2022-04-05</date>
<revremark>
<itemizedlist>
<listitem>“for a s<emphasis role='strong'>l</emphasis>ngle transformation” → “<link xlink:href='#5k4' xlink:type='simple' xlink:actuate='onRequest'>… s<emphasis role='strong'>i</emphasis>ngle …</link>”, OCR.</listitem>
<listitem>“units of <emphasis role='strong'>S</emphasis>ingle edit operations” → “<link xlink:href='#5k6' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>s</emphasis>ingle …</link>”, OCR.</listitem>
<listitem>“regions <emphasis role='strong'>b</emphasis>as a s<emphasis role='strong'>l</emphasis>ngle entrance” → “<link xlink:href='#5k7' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>h</emphasis>as a s<emphasis role='strong'>i</emphasis>ngle …</link>”, OCR.</listitem>
<listitem>“the current<emphasis role='strong'>l</emphasis> implementation” → “<link xlink:href='#6d3' xlink:type='simple' xlink:actuate='onRequest'>… current …</link>”, OCR.</listitem>
</itemizedlist>
</revremark>
</revision>
<revision>
<date>2022-08-01</date>
<revremark>
<para>More corrections by S.K.:</para>
<itemizedlist>
<listitem>“berts which currently re<emphasis role='strong'>t</emphasis>er to” → “<link xlink:href='#3t' xlink:type='simple' xlink:actuate='onRequest'>… re<emphasis role='strong'>f</emphasis>er …</link>”, OCR.</listitem>
<listitem>“the old orgl<emphasis role='strong'>l</emphasis>s reference” → “<link xlink:href='#3t' xlink:type='simple' xlink:actuate='onRequest'>… orgl<emphasis role='strong'>’</emphasis>s …</link>”, OCR.</listitem>
<listitem>“I<emphasis role='strong'>t</emphasis> one wishes to” → “<link xlink:href='#3w' xlink:type='simple' xlink:actuate='onRequest'>I<emphasis role='strong'>f</emphasis> …</link>”, OCR.</listitem>
<listitem>“the system supports rearrange” → “<link xlink:href='#5k3' xlink:type='simple' xlink:actuate='onRequest'>the system supports <emphasis role='strong'>—</emphasis> rearrange</link>”, OCR.</listitem>
<listitem>“linear series <emphasis role='strong'>or</emphasis> operations” → “<link xlink:href='#5k5' xlink:type='simple' xlink:actuate='onRequest'>linear series <emphasis role='strong'>of</emphasis> operations</link>”, OCR.</listitem>
<listitem>“the data structure itself” → “the data structure itself <link xlink:href='#5k5' xlink:type='simple' xlink:actuate='onRequest'><emphasis role='strong'>—</emphasis></link>”, OCR.</listitem>
<listitem>“aspects of the <emphasis role='strong'>xanadu</emphasis> system” → “<link xlink:href='#6b' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis><link xlink:href='http://xanadu.com/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><productname>Xanadu</productname></link></emphasis> …</link>”, OCR.</listitem>
<listitem>“organizational functions and <emphasis role='strong'>tbe</emphasis>” → “<link xlink:href='#6d2' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>the</emphasis></link>”, OCR.</listitem>
<listitem>“data <emphasis role='strong'>formating</emphasis>” → “<link xlink:href='#6d2' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>formatting</emphasis></link>”, in the original.</listitem>
<listitem>“provided by unconstra<emphasis role='strong'>l</emphasis>ned use” → “<link xlink:href='#8f2' xlink:type='simple' xlink:actuate='onRequest'>… unconstra<emphasis role='strong'>i</emphasis>ned …</link>”, OCR.</listitem>
<listitem>“as a result of <emphasis role='strong'>S</emphasis>ubstantial” → “<link xlink:href='#8i2' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>s</emphasis>ubstantial …</link>”, OCR.</listitem>
<listitem>“such fragmentation <emphasis role='strong'>ist</emphasis> make” → “<link xlink:href='#8i2' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>is to</emphasis> …</link>”, in the original.</listitem>
<listitem>“previous example<emphasis role='strong'>.</emphasis> there” → “<link xlink:href='#8l3b1' xlink:type='simple' xlink:actuate='onRequest'>…<emphasis role='strong'>,</emphasis> …</link>”, OCR.</listitem>
<listitem>“that we can do<emphasis role='strong'>.</emphasis> but they” → “<link xlink:href='#8l3b1' xlink:type='simple' xlink:actuate='onRequest'>…<emphasis role='strong'>,</emphasis> …</link>”, OCR.</listitem>
<listitem>“spends a signicant fraction” → “<link xlink:href='#9f2' xlink:type='simple' xlink:actuate='onRequest'>… signi<emphasis role='strong'>fi</emphasis>cant …</link>”, in the original.</listitem>
<listitem>“its time” → “<link xlink:href='#9f2' xlink:type='simple' xlink:actuate='onRequest'>its <emphasis role='strong'>CPU</emphasis> time</link>”, OCR.</listitem>
<listitem>“as in our system<emphasis role='strong'>.</emphasis> very large” → “<link xlink:href='#9f3' xlink:type='simple' xlink:actuate='onRequest'>…<emphasis role='strong'>,</emphasis> …</link>”, OCR.</listitem>
<listitem>“invariant <emphasis role='strong'>ergl</emphasis>” → “<link xlink:href='#10k' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>orgl</emphasis></link>”, OCR.</listitem>
<listitem>“CREATENEWVERSION ::= <createversionrequest>” → “<link xlink:href='#grammar-create-new-version' xlink:type='simple' xlink:actuate='onRequest'>CREATENEWVERSION ::= <createversionrequest> <emphasis role='strong'><doc id></emphasis></link>”, my mistake when typing it.</listitem>
<listitem>“in document 〈doc <emphasis role='strong'>I</emphasis>d〉” → “<link xlink:href='#10x' xlink:type='simple' xlink:actuate='onRequest'>in document 〈doc <emphasis role='strong'>i</emphasis>d〉</link>”, OCR.</listitem>
<listitem>“past the link given by <<emphasis role='strong'>linkisa</emphasis>> on that list” → “<link xlink:href='#10at' xlink:type='simple' xlink:actuate='onRequest'>… <<emphasis role='strong'>link id</emphasis>> …</link>”, OCR.</listitem>
<listitem>“and only the first <emphasis role='strong'>l</emphasis>seven” → “<link xlink:href='#11c4' xlink:type='simple' xlink:actuate='onRequest'>… seven</link>”, my mistake when typing it.</listitem>
<listitem>“whic<emphasis role='strong'>b</emphasis>nobodycandeny();” → “<link xlink:href='#src-format-control-structures' xlink:type='simple' xlink:actuate='onRequest'>whic<emphasis role='strong'>h</emphasis>nobodycandeny();</link>”, OCR.</listitem>
<listitem>“typeo<emphasis role='strong'>r</emphasis>secondargument” → “<link xlink:href='#src-format-functions' xlink:type='simple' xlink:actuate='onRequest'>typeo<emphasis role='strong'>f</emphasis>secondargument</link>”, OCR.</listitem>
<listitem>“large numbers of cr<emphasis role='strong'>a</emphasis>ms” → “<link xlink:href='#12k2a' xlink:type='simple' xlink:actuate='onRequest'>… cr<emphasis role='strong'>u</emphasis>ms</link>”, OCR.</listitem>
<listitem>“made <emphasis role='strong'>toa</emphasis> phylum over time” → “<link xlink:href='#12ah2a' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>to a</emphasis> …</link>”, my mistake when typing it.</listitem>
<listitem>“group of sibling crum<emphasis role='strong'>e</emphasis>” → “<link xlink:href='#12bb2a' xlink:type='simple' xlink:actuate='onRequest'>… crum<emphasis role='strong'>s</emphasis></link>”, OCR.</listitem>
<listitem>“some other crum. <emphasis role='strong'>(</emphasis>A loaf is” → “<link xlink:href='#12bb2a' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>[</emphasis>…</link>”, OCR.</listitem>
<listitem>“data protection<emphasis role='strong'>.</emphasis> security and” → “<link xlink:href='#13c1a3g2a' xlink:type='simple' xlink:actuate='onRequest'>…<emphasis role='strong'>,</emphasis> …</link>”, OCR.</listitem>
<listitem>“Design test-FE <emphasis role='strong'>V</emphasis>irtuality” → “<link xlink:href='#13c1a3j3b1' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'>v</emphasis>irtuality</link>”, OCR.</listitem>
<listitem>“Kubla<emphasis role='strong'>i</emphasis> Khan <emphasis role='strong'>忽必烈</emphasis>” → “<link xlink:href='#12cu2a' xlink:type='simple' xlink:actuate='onRequest'>Kubla Khan</link>”, it was pedantic of me to correct the antiquated but valid spelling. Coleridge himself used the spellings “Xannadù” and “Cubla Kahn” in <link xlink:href='https://www.bl.uk/works/kubla-khan' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>his manuscript</link>.</listitem>
</itemizedlist>
</revremark>
<revremark>
<para>Other corrections:</para>
<itemizedlist>
<listitem>“returns <retrieveendsetsrequest> <emphasis role='strong'><spec set></emphasis>” → “<link xlink:href='#grammar-retrieveendsets' xlink:type='simple' xlink:actuate='onRequest'>… <emphasis role='strong'><from spec set> <to spec set></emphasis></link>”, my mistake when typing it, also missed the last two lines “from spec set” and “to spec set”.</listitem>
</itemizedlist>
</revremark>
</revision>
</revisionhistory>
</info>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.1" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en" xml:id="proposal">
<title>Proposal for the Implementation by <link xlink:href='http://aus.xanadu.com/people.html#XOC' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><orgname>Xanadu Operating Company</orgname></link> of a
Full-scale Semi-distributed Multi-user Hypertext System</title>
<para><link xlink:href='http://aus.xanadu.com/people.html#XOC' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><orgname>Xanadu Operating Company</orgname></link> (<link xlink:href='http://aus.xanadu.com/people.html#XOC' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><acronym>XOC</acronym></link>) is developing a hypertext information
storage management system called “<link xlink:href='http://xanadu.com/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><productname>Xanadu</productname></link>”. Hypertext is text or data which
exhibits patterns of structure or interconnectedness which are not necessarily
very regular and which may change over time. Project Xanadu, the informal
group that became <link xlink:href='http://aus.xanadu.com/people.html#XOC' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><acronym>XOC</acronym></link>, has developed a family of data structures which in
combination appear to meet the requirements of such a system. A working
prototype exists implementing the rudiments of the design.
Since its computational complexity and storage overhead are
essentially logarithmic with the volume of stored information,
it should be able to efficiently handle very
large amounts of material.</para>
<para><link xlink:href='http://aus.xanadu.com/people.html#XOC' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><acronym>XOC</acronym></link> intends to develop hypertext system software beyond the present
prototype stage, producing a fully operational and usable system.
Specifically, we propose to transport the current software to the <link xlink:href='https://en.wikipedia.org/wiki/Interlisp' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><productname>Interlisp</productname></link>
environment, extend the design, and complete its implementation. The system
will then be tuned and optimized to increase its speed and compactness. The
end product of this effort will be a complete “semi-distributed” multi-user
<link xlink:href='http://xanadu.com/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><productname>Xanadu</productname></link> “backend” integrated with the <link xlink:href='https://en.wikipedia.org/wiki/Interlisp' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><productname>Interlisp</productname></link> environment and able to
serve as an <link xlink:href='https://en.wikipedia.org/wiki/Ethernet' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'><productname>Ethernet</productname></link>-based resource for a wide variety of applications.
Details of the development plan, including a complete schedule and budget,
are included in the attached documents.</para>
<para>We believe the benefits of our system will be longer-term than is typical
with commercial ventures. An instantiation of these ideas in a working
database manager will be of immediate benefit to researchers in many fields.
<link xlink:href='https://oac.cdlib.org/view?docId=tf429003m4;query=;style=oac4;view=admin' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>SDF</link>’s<note><para><blockquote><para>The System Development Corporation was a nonprofit software company in Santa Mónica, California, that did contract work for the U.S. military. When the company was disbanded, they liquidated their buildings and ended up with a large profit, which is not allowed for a nonprofit. The System Development Foundation, based in Palo Alto, California, was formed in 1969 to distribute proceeds from selling buildings through a grant-making program from 1980 to 1988.</para></blockquote> “The Deep Learning Revolution” <link xlink:href='https://books.google.de/books?id=9xZxDwAAQBAJ&pg=PA293&lpg=PA293&hl=en' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>p.293</link>,
<link xlink:href='https://papers.cnl.salk.edu/' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>Terrence J. Sejnowski</link>,
<link xlink:href='https://mitpress.mit.edu/books/deep-learning-revolution' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>The MIT Press</link> 2018,
<link xlink:href='https://lccn.loc.gov/2017044863' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>LCC Q325.5.S45 2018 | DDC 006.3/1--dc23 LC</link></para></note>
clients appear most likely to be able to perceive and utilize the
potential in these ideas and their instantiation. Not only do these people
have a present need for this sort of tool, but they also will provide an
excellent community of critics to stimulate the refinement and generalization
of both the design and the implementation.</para>
</chapter>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.1" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en" xml:id="architecture">
<title>The Xanadu Hypertext System Architecture</title>
<para>The Xanadu Hypertext System manages the storage, retrieval and
manipulation of character strings and <emphasis>orgls</emphasis>.
<termdef>An <firstterm>orgl</firstterm> is a structure which
represents the organization of a collection of
<termdef><termdef>address spaces
(called <emphasis>virtual spaces</emphasis> or <firstterm>V-spaces</firstterm> for short)</termdef>,
each containing an editable stream of <emphasis>atoms</emphasis>.
This stream is referred to as the <emphasis>virtual stream</emphasis> or
the <emphasis>variant stream</emphasis> (or <firstterm>V-stream</firstterm> for short).</termdef></termdef></para>
<para><termdef>An <firstterm>atom</firstterm> is the primitive element
that the Xanadu System deals with.</termdef>
There are two types of atoms in the present system: orgls, representing
structural and organizational information, and characters (8-bit bytes),
representing actual data.
Other types of atoms are conceivable, such as
videodisk frames or other kinds of (non-orgl) organizational structures,
but these are not present in the current design.</para>
<para>Any atom contained in the system may be referenced by specifying its
virtual stream address. This is recursively defined as the virtual stream
address of the orgl containing the atom, combined with the number of the
V-space which holds the atom within that orgl and the position of the atom
itself within that V-space. Orgls that are not contained within other orgls
are addressed by a special sort of V-stream address called an invariant orgl
identifier, terminating the recursion. Thus, a virtual stream address
contains a variant part and an invariant part which are syntactically
separable.</para>
<para>The contents of the V-spaces within an orgl may be edited. This in turn
means that the V-stream addresses of atoms within an orgl may change, as
implied by the adjective “variant”. The contents of an orgl may be added to
or deleted from at any point in a V-space.
In addition, sections of a V-space
may be rearranged (i.e., a section may be moved or two sections transposed).
These operations — insert, delete and rearrange — can cause
the position and relative ordering, the V-stream order,
of atoms to shift,
thus altering those atoms’ V-stream addresses as well.</para>
<para><termdef>Atoms are stored internally in an
invariant stream (or <firstterm>I-stream</firstterm> for short).</termdef>
They appear, and are addressed, in I-stream order. As the adjective
“invariant” suggests, the I-stream address of an atom never changes. The
function performed by an orgl is the mapping back and forth between I-stream
addresses and V-stream addresses. When the contents of a V-space are edited,
the orgl mapping that V-space is changed,
and thus so are the virtual positions of the atoms.</para>
<para>The I-stream addresses of atoms are not generally visible externally. The
only exceptions are invariant orgl identifiers
which are in fact the I-stream
addresses of “top level” orgls.</para>
<para>The above discussion refers to mappings to and from particular I-stream
and V-stream addresses.
In practice, we work with spans rather than point addresses.
<termdef>A <firstterm>span</firstterm> is an abbreviated way of referring to
a group of contiguous addresses. A span consists of a starting address
together with a length.</termdef>
<termdef>A <firstterm>V-span</firstterm> is a span of V-stream addresses,
and <termdef>an <firstterm>I-span</firstterm> is similarly a span on
the I-stream</termdef>.</termdef>
An orgl maps from one V-span to a set of I-spans, and from an
I-span to a set of sets of V-spans.</para>
<para>The actual atoms located in a particular I-span may be found using another
structure called the <emphasis>grandmap</emphasis>.
<termdef>The <firstterm>grandmap</firstterm> is a tree of pointers to all the
atoms currently stored in the system, indexed by I-stream address.</termdef>
The grandmap provides a mapping between I-stream addresses
and the locations of the actual underlying physical storage
used to hold the atoms.</para>
<para>There are thus three levels of addressing used in this system:</para>
<itemizedlist>
<listitem><para>V-stream addresses identify atoms to the outside world.
The V-stream address of an atom may change and,
as will be explained below,
an atom may have more than one V-stream address.</para></listitem>
<listitem><para>I-stream addresses identify atoms internally
in a consistent and implementation independent fashion.
The I-stream address of an atom in the Xanadu system
is analogous to the accession number of a document in a library.
An atom has but one I-stream address and this address never changes.</para></listitem>
<listitem><para>Physical storage addresses identify the locations
of the actual bits and bytes of atoms themselves.
An atom’s physical address is both variable
and highly implementation dependent.
For example, it may change
due to reorganization of the underlying storage
for purposes of efficiency or convenience,
or due to changes in the types of storage devices used.</para></listitem>
</itemizedlist>
<para>To retrieve the atom located at a particular V-stream address Vq,
the invariant part of Vq’s V-stream address specification is extracted.
This will be an invariant orgl identifier for the orgl which maps Vq
to some I-stream address.
Since this invariant orgl identifier is itself an I-stream address,
it may be (and is) used as an index into the grandmap
to retrieve the relevant orgl.
Vq (the full V-stream address, not just the variant part)
is then mapped through this orgl to its corresponding I-stream address.
This second I-stream address in turn
is used for a second lookup in the grandmap
to acquire the atom which Vq addresses.
The following diagram illustrates the data flow:
<figure><mediaobject>
<imageobject condition='web'><imagedata fileref='images/data-flow.svg'/></imageobject><textobject><phrase/></textobject>
</mediaobject></figure></para>
<para>An important consequence of the V-stream to I-stream mapping is that
several V-stream addresses may all map to the same I-stream address.
This means that an orgl may contain multiple <emphasis>virtual copies</emphasis>
of a given set of material.
Although the I-stream address of an atom is related to the orgl in
which it originally was inserted, the V-stream address(es) of that atom
are under no such constraint.
Therefore, virtual copies of material originating in
one orgl may appear in other orgls.</para>
<para>Another consequence of this structure is that multiple orgls may be used
to represent alternate <emphasis>V-to-I</emphasis> mappings for the same set of atoms, yielding
alternative <emphasis>versions</emphasis> of a given collection of material.
In practice, the data structures used to realize such orgls
can share their underlying components in those places
where the V-to-I mappings are similar and need only differ
in their structure where the versions are actually different.
(See the accompanying paper on the implementation
of the Xanadu internal data structures
for a detailed description of how this mechanism works).</para>
<para><termdef>The orgls which represent multiple versions of
the same family of material
are collectively called a <firstterm>phylum</firstterm>.</termdef>
All of the orgls in a phylum are “descended” from a single original orgl,
in the sense that they were created by applying some edit operations
to that orgl or to one of its later descendents.</para>
<para><termdef>Xanadu provides a facility called <firstterm>historical trace</firstterm>.
<termdef>The sequence of
edit operations that have been applied to the orgls of a phylum
can be seen to form an <firstterm>historical trace tree</firstterm>.</termdef></termdef>
This tree branches wherever a different version was created.
Such versions result when two or more processes modify
the same orgl through different berts or when a process backs an orgl
up to an earlier state and then makes edits.</para>
<para>Since each of the editing primitives which the system supports is a
reversible operation upon an orgl, the state of an orgl at any point
in its history conceivably might be obtained
by inverting each of the edits in an edit log.
However, a data structure is constructed which represents the edit
history of a phylum at varying levels of detail.
This data structure is a tree which at the bottom level represents
individual edit operations and at the higher level represents
compositions of these lower level edits —
“superedits” that are single transformations
that represent the end result of a series of more primitive operations.
This tree is indexed by position in the
phylum’s historical trace tree (note that there are two trees here: the
historical trace tree, representing the sequence of operations forming the
phylum’s history, and the data structure erected over this tree,
representing the operations themselves).
The end result of a retrieval operation on this
data structure is not a series of edit operations
but the actual V-to-I mapping that existed at the indicated point
in the phylum’s history.
The details of how this is accomplished are given
in the accompanying paper which describes the data structures themselves.</para>
<para>The system can retrieve any atom stored within it, given the atom’s
V-stream address.
In the case of a character atom, the retrieval operation
returns the character itself.
In the case of an orgl atom, an entity called a
<emphasis>bert</emphasis> is returned.
<termdef>A <firstterm>bert</firstterm> is an identifier for an orgl pointing to a
current access, as opposed to an established V-stream address.</termdef>
It grants the <emphasis>process</emphasis> to which the bert is given
exclusive access to a particular V-to-I mapping.</para>
<para><termdef>A <firstterm>process</firstterm>, in the Xanadu System,
means a particular external connection to the system
which may request the retrieval, creation and editing
of orgls and characters.</termdef>
An arbitrary (i.e., implementation dependent)
number of processes may access the system concurrently.</para>
<para>Separate processes which request the retrieval of the same orgl at the
same time are each given different berts which refer to the orgl.
Associated with each orgl is a count of the number of berts
which currently refer to it.
If one of these processes then makes an edit change to the orgl,
a new orgl will be created.
The process’s bert will be made to refer to the new orgl and
the old orgl’s reference count will be decremented.
By this means, the other processes will not “see” the change,
and their berts will still refer to the same V to I mapping as previously.
Any information about the orgl’s state
which the other processes might have been keeping externally
will not be invalidated by the one process’s edit operation.</para>
<para><termdef>A structure called the <firstterm>spanmap</firstterm> implements two mappings.
The first of these is from the I-stream addresses of atoms in general
to the I-stream addresses of orgls.
The second mapping is from the same original I-stream addresses
to berts.</termdef>
The spanmap is designed to answer querys about
which orgls reference which I-spans.
It quickly identifies the orgl or orgls that map some
V-stream address(es) onto a particular I-stream address.
This is the inverse of the set of mappings implemented
by the full collection of orgls stored in the system.</para>
<para>The spanmap, as its name suggests,
is fundamentally designed to deal with spans.
It enables the system to answer queries about which orgls refer to
particular pieces of material, given the V-stream addresses
of the atoms of interest.
The general form of such a query takes the form of the question,
“what are the V-stream addresses of all the orgls which refer to this
particular V-span?”
The V-span of interest is mapped to a set of I-spans
(call this set Q, for “query”),
using the procedure described above in the discussion of
the operation of orgls.
This I-span set, Q, is then used to initiate a lookup in
the spanmap which results in a set of one or more I-stream
addresses corresponding to the orgls which reference Q
(along with berts identifying orgls that reference Q but
may not yet have I-stream addresses).
These I-stream addresses are then looked up in the grandmap,
yielding the orgls themselves.
These orgls are in turn used to map Q to a set of V-spans
(keep in mind that the mapping implemented by an orgl is bidirectional)
which are then returned as the answer to the process
which initiated the query.</para>
<para>Since the number of orgls which might refer to a particular I-span is
potentially very large, the spanmap enables restricted retrievals.
A retrieval may be restricted to return only orgls from a particular set,
for example those which reference a particular I-span
in addition to the one of interest.
This is important, among other reasons,
because queries are generally expressed in terms of V-spans,
and a single V-span may map to a number of I-spans.
It one wishes to determine the set of orgls which reference
a particular V-span, what is desired is the intersection of
the sets of orgls that reference the I-spans that the
V-span of interest maps to.</para>
<para>The spanmap also enables queries that may be expressed in terms of the
overlap of spans, rather than simple reference.
Thus one may ask which orgls contain I-spans that
begin inside a particular span and end outside of it, for example.
The reader is again referred to the companion paper on the
implementation of the various data structures.</para>
<para>In summary then, the system consists of four primary components:</para>
<orderedlist>
<listitem><para>orgls, which map back and forth between V-stream and I-stream
addresses,</para></listitem>
<listitem><para>the grandmap, which maps from I-stream addresses to the physical
addresses of atoms (characters and orgls) themselves,</para></listitem>
<listitem><para>the spanmap, which maps from the I-stream addresses of atoms to the
I-stream addresses of orgls which reference those atoms, and</para></listitem>
<listitem><para>an historical trace, which enables the determination of the contents
of an orgl at any point in its history or the history of any of its other
versions.</para></listitem>
</orderedlist>
</chapter>
<chapter xmlns="http://docbook.org/ns/docbook" version="5.1" xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en" xml:id="enfilade">
<title>Enfilade Theory</title>
<para>The underlying data abstraction of the Xanadu System is the <emphasis>enfilade</emphasis>.
The grandmap, spanmap and orgls are all implemented using different types of
enfilades. We shall first discuss enfilades generally and then show how the
theory is adapted to specific implementation.</para>
<section xml:id="enfilade-definitions">
<title>DEFINITIONS</title>
<para><termdef>An <firstterm>enfilade</firstterm> is a data structure
in which the positions of data items in index space
(i.e., the retrieval keys associated with those data items)
are stored indirectly, as local positions relative to
the data items’ neighborhoods in the data structure,
rather than being stored directly, as absolute positions.</termdef></para>
<para><termdef>Enfilades have traditionally been implemented as trees.
Each node of the tree is called a <firstterm>crum</firstterm></termdef>
(in order to disambiguate the term “node” — see footnote
<note><para>In the Xanadu nomenclature, the term node refers to
a computer system which is a member of a distributed data storage
and communications network.
The term crum is preferred for reference to a node in an enfiladic
data structure. The extra term is introduced to avoid confusion,
since the full-scale Xanadu design involves both enfilades and
computer networks.</para></note>).
Each crum contains, either explicitly or implicitly,
two components of indexing information, called the wid and the disp.
In addition, a crum may contain other structural information,
such as pointers to descendent or sibling crums.</para>
<para><termdef>A <firstterm>disp</firstterm> represents the relative offset, in index space,
of its crum from its crum’s parent.</termdef>
The “sum” of a crum’s disp with those of all of its ancestors
determines the crum’s absolute position in index space.
A change in a crum’s disp therefore causes a corresponding change
not only in the crum’s absolute position but
in those of all of its descendents.</para>
<para><termdef>A <firstterm>wid</firstterm> represents the extent, in index space,
of its crum’s collective descendants,
relative to its crum’s position
(which is in turn derived from its crum’s disp).</termdef>
A change in a crum’s wid may result if the wid or disp of one of
the crum’s children changes.</para>
<para>An enfilade’s disps are interpreted in a top-down fashion, telling the
relationship of crums to their ancestors,
while the wids are interpreted from the bottom-up,
indicating the relationship of crums to their descendents.</para>
<para><termdef>A group of sibling crums, all descended from the same parent crum,
is collectively referred to as a <firstterm>loaf</firstterm> or crum-block.</termdef>
<termdef>The single crum which forms the root of the tree and
from which all other crums are descended is called the <firstterm>fulcrum</firstterm>.</termdef>
The disp of the fulcrum is offset relative to the origin
of the index space.
<termdef>The crums which form the leaves of the tree are called
<firstterm>bottom crums</firstterm>.</termdef>
The tree is maintained at a constant depth, so all bottom
crums
are the same number of levels below the fulcrum.
Bottom crums may contain actual data in addition to structural and
indexing information and
therefore may have a different structure or
form than their ancestors do.
<termdef>Non-bottom crums are referred to as <firstterm>upper crums</firstterm>.</termdef>
When enumerating the levels of an enfilade,
it is conventional to number from the bottom up so that
the level number of a crum will not change
as the enfilade grows or shrinks
(levels are added or deleted at the top).</para>
<para>An index space may be multi-dimensional, and not all dimensions need
participate in enfiladic operations, as described below.</para>
<para>An enfilade is similar in many ways to a conventional
<link xlink:href='https://en.wikipedia.org/wiki/B-tree' xlink:type='simple' xlink:show='new' xlink:actuate='onRequest'>B-tree</link>.
This is especially so when considering the
set of primitive operations that are defined.
However, an <emphasis>enfilade is not a B-tree</emphasis>.
Enfilades possess two properties that distinguish them from B-trees
(properties that were, in fact,
the motivation for the invention of the first enfilades).
These properties are rearrangability and the capacity for sub-tree sharing.
These derive from the nature of wids and disps as local abstractions
independent of the overall frame of reference of the full data structure.</para>
<para>While enfilades have traditionally been implemented as trees, we do not
feel that this is essential.
Generalization of the theory of enfilades to
other types of data structures, for example hash tables,
has been considered but not yet examined in depth.</para>
</section>
<section xml:id="enfilade-operations">
<title>OPERATIONS</title>
<para>The fundamental operations on an enfilade are
retrieve, rearrange and append.
These are augmented by the useful, though not strictly necessary,
operations insert and delete.
All of these are supported by the “housekeeping” operations
cut, recombine, level push and level pop.</para>
<para><termdef>The <firstterm>retrieve</firstterm> operation obtains a data item associated
with a particular location in index space.</termdef>
Such a data item may be stored in an enfilade
either directly, by actually storing it in the bottom crum
associated with the desired position in index space,
or indirectly, as a function of the wids and disps of the crums
traversed while descending the tree to that bottom crum.
The latter alternative is fairly unusual and deserves elaboration.
For example, enfilades in index spaces with
multiple independent dimensions could
store data by indexing with some dimensions and
not others and then return the
positions of bottom crums along the other dimensions.
A single enfilade may contain several collections of data at once,
some stored one way and some another.</para>
<para>The general algorithm for retrieve is:
<figure xml:id="algorithm-retrieve">
<programlisting>retrieve (indexSpacePosition)
<emphasis>result</emphasis> ← recursiveRetrieve (indexSpacePosition, fulcrum, .O.)
<emphasis>end</emphasis> retrieve
recursiveRetrieve (index, aCrum, cumulativeIndex)
<emphasis>if</emphasis> (index .==. cumulativelndex)
<emphasis>result</emphasis> ← data (aCrum)
<emphasis>else</emphasis>
<emphasis>for</emphasis> each child <emphasis>of</emphasis> aCrum
<emphasis>if</emphasis> (disp(child) .<=. index) <emphasis>and</emphasis> (index .<. (disp(child) .+. wid(child)))
<emphasis>result</emphasis> ← recursiveRetrieve (index, child, cumulativeIndex .+. disp(chlld))
<emphasis>end</emphasis> if
<emphasis>end</emphasis> for
<emphasis>end</emphasis> if
<emphasis>end</emphasis> recursiveRetrieve</programlisting>
</figure></para>
<para>where <code>disp(crum)</code> extracts a crum’s disp, <code>wid(crum)</code> extracts its wid, and
<code>data(crum)</code> extracts the datum from a bottom crum.
The symbols <code>.==.</code>, <code>.<.</code> and <code>.<=.</code> represent
comparison operators in index space.
The symbol <code>.+.</code> represents “addition” in index space.
The symbol <code>.O.</code> represents the origin of the index space.
If less than the full number of possible dimensions is
being used for indexing, the index space operators must be specified to take
this into account.
The symbol <code>←</code> is an assignment operator.
<code>result</code> is assigned to return a value.
The control constructs are what they appear to be.</para>
<para>Note that this algorithm retrieves exactly one data item stored directly
in a bottom crum.
If data are stored indirectly in the wids and disps, as
described above, the algorithm must be modified accordingly.
To implement the case described previously
(where some dimensions are used for indexing and
others for indirect data storage),
the operators <code>.==.</code>, <code>.<.</code>, and <code>.<=.</code>
should be defined only to compare along the indexing dimensions,
while <code>.+.</code>
should be defined on all dimensions.
The result returned should not be the
extraction of data from the bottom crum but the
extraction of the data dimension components of <code>cumulativeIndex</code>.</para>
<termdef>Also note that it is possible for a single index space position
to map to more than one data item, although this algorithm would
only return the last of these.
The possibility of such <firstterm>multiple hit retrievals</firstterm> is a general property
of enfilades, although specific types of enfilades may by their nature
exclude it (multiple hit retrievals may occur, for example,
in the case of a multi-dimensional index space when data are retrieved
using indices with less than the full number of dimensions).
The obvious generalization of collecting aultiple data items into a set
was omitted for the sake of clarity.</termdef>
<para>This algorithm also does not take into account the possibility that the
desired data item might not be present at all.
Once again, the generalization of collecting the results in a set
would correct this (the result in such a case would be an empty set)
and the omission is for clarity.</para>
<para>In cases where multiple hits are excluded, retrieval time is logarithmic
with the number of data items stored. Where multiple hits are permitted,
non-logarithmic elements are introduced and the analysis is not so
straightforward, but depends upon the specific nature of the enfilade in
question.
In the case of multi-dimensional index spaces, retrieval times
depend on the splitting and regrouping algorithms used to balance the tree.
There are tradeoffs that depend on the number of dimensions that are typically
to be used to retrieve with and the performance in atypical retrievals.
If the enfilade is totally optimized along one dimension,
retrievals will be of logarithmic order along that dimension and
linear along the others.
If it is optimized along <inlineequation><mathphrase>D</mathphrase></inlineequation> dimensions collectively and
retrievals are performed along <inlineequation><mathphrase>K</mathphrase></inlineequation> of those dimensions,
the retrieval time will be on the order of
<inlineequation><mathphrase>N<superscript>(D-K)/D</superscript>·log(N)</mathphrase></inlineequation>, <inlineequation><mathphrase>K≤D</mathphrase></inlineequation>,
where <inlineequation><mathphrase>N</mathphrase></inlineequation> is the number of data items stored in the enfilade.</para>
<para><termdef>The <firstterm>rearrange</firstterm> operation alters the index space
positions of clusters of
data items by selective alteration or transposition
of disps.</termdef>
Rearrangability is one of the two essential properties of enfilades
which distinguish them from other sorts of data structures
(the other, sub-tree sharability, is discussed below).
Rearrange changes the relative ordering of crums in index space.</para>
<para>Rearrange operations are specified in terms of cuts.
There are two “flavors” of rearrange,
called three-cut rearrange and four-cut rearrange.
A cut delineates a boundary for the rearrange operation.
A cut is a separation between two regions of interest,
defined by a position in index space, <inlineequation><mathphrase>C</mathphrase></inlineequation>,
such that there exists a pair of sibling crums
(i.e., crums descended from the same parent),
<inlineequation><mathphrase>A1</mathphrase></inlineequation> and <inlineequation><mathphrase>A2</mathphrase></inlineequation>, such that:
<figure xml:id="algorithm-cut-condition-1">
<programlisting>indexSpacePosition(A1) .<=. C .<. indexSpacePosition(A2)
and
(indexSpacePosition(A1) .+. disp(A1)) .<=. C</programlisting>
</figure>
and, for any crum <inlineequation><mathphrase>Q</mathphrase></inlineequation> in the enfilade at a level lower than
that of <inlineequation><mathphrase>A1</mathphrase></inlineequation> and <inlineequation><mathphrase>A2</mathphrase></inlineequation>:
<figure xml:id="algorithm-cut-condition-2">
<programlisting>indexSpacePosition(Q) .<=. C implies that either
indexSpacePosition(Q) .<. indexSpacePosition(A1)
or
Q is a descendant <emphasis>of</emphasis> A1
and
C .<. indexSpacePosition(Q) implies that
indexSpacePosition(A2) .<=. indexspacePosition(Q)</programlisting>
</figure>
where, if the index space is multi-dimensional,
the comparison operations are limited to the
dimensions along which the cut is being performed
(cuts are often made along less than the full number of dimensions).</para>
<para>Cuts are generally used in groups
(in the case of rearrange, in groups of three or four).
When multiple cuts are used together they are constrained
to propagate upward until all cuts reach a common ancestor.
In other words, if cut <inlineequation><mathphrase>C1</mathphrase></inlineequation> is bounded by crums <inlineequation><mathphrase>A1</mathphrase></inlineequation> and <inlineequation><mathphrase>A2</mathphrase></inlineequation>,
as described above, and
cut <inlineequation><mathphrase>C2</mathphrase></inlineequation> is similarly bounded by crums <inlineequation><mathphrase>A3</mathphrase></inlineequation> and <inlineequation><mathphrase>A4</mathphrase></inlineequation>,
then crums <inlineequation><mathphrase>A1</mathphrase></inlineequation>, <inlineequation><mathphrase>A2</mathphrase></inlineequation>, <inlineequation><mathphrase>A3</mathphrase></inlineequation> and <inlineequation><mathphrase>A4</mathphrase></inlineequation> should all have the same parent.</para>
<para><termdef>A <firstterm>three-cut rearrange</firstterm> performed with cuts <inlineequation><mathphrase>C1</mathphrase></inlineequation>, <inlineequation><mathphrase>C2</mathphrase></inlineequation> and <inlineequation><mathphrase>C3</mathphrase></inlineequation>
moves the material between <inlineequation><mathphrase>C2</mathphrase></inlineequation> and <inlineequation><mathphrase>C3</mathphrase></inlineequation> to the position defined by <inlineequation><mathphrase>C1</mathphrase></inlineequation>
(or, equivalently, moves the material between <inlineequation><mathphrase>C1</mathphrase></inlineequation> and <inlineequation><mathphrase>C2</mathphrase></inlineequation> to the
position defined by <inlineequation><mathphrase>C3</mathphrase></inlineequation>).</termdef>
This is accomplished at the level of the sibling crums at the top of
the three cuts by adjusting some of the crums’ disps, as follows,
where P is the parent to all of the crums at the top of the cuts:
<figure xml:id="algorithm-three-cut-rearrange">
<programlisting>for <emphasis>each</emphasis> crum that is a child <emphasis>of</emphasis> P
pos ← indexSpacePosition(crum)
<emphasis>if</emphasis> (C1 .<. pos) <emphasis>and</emphasis> (pos .<=. C2)
disp(crum) ← disp(crum) .+. (C3 .-. C2)
<emphasis>else</emphasis> <emphasis>if</emphasis> (C2 .<. pos) <emphasis>and</emphasis> (pos .<=. C3)
disp(crum) ← disp(crum) .-. (C2 .-. C1)
<emphasis>end</emphasis> if
<emphasis>end</emphasis> for</programlisting>
</figure>
where the symbol <code>.-.</code> represents “subtraction” in index space.</para>
<para><termdef>A <firstterm>four-cut rearrange</firstterm> performed with
cuts <inlineequation><mathphrase>C1</mathphrase></inlineequation>, <inlineequation><mathphrase>C2</mathphrase></inlineequation>, <inlineequation><mathphrase>C3</mathphrase></inlineequation> and <inlineequation><mathphrase>C4</mathphrase></inlineequation> transposes the material between
cuts <inlineequation><mathphrase>C1</mathphrase></inlineequation> and <inlineequation><mathphrase>C2</mathphrase></inlineequation> and the material between cuts <inlineequation><mathphrase>C3</mathphrase></inlineequation> and <inlineequation><mathphrase>C4</mathphrase></inlineequation>.</termdef>
As with the three-cut rearrange, this is performed by manipulating the
disps of the crums at the top of the cuts:
<figure xml:id="algorithm-four-cut-rearrange">
<programlisting>for <emphasis>each</emphasis> crum that is a child <emphasis>of</emphasis> P
pos ← indexSpacePosition(crum)
<emphasis>if</emphasis> (C1 .<. pos) <emphasis>and</emphasis> (pos .<=. C2)
disp(crum) ← disp(crum) .+. (C4 .-. C2)
<emphasis>else</emphasis> <emphasis>if</emphasis> (C2 .<. pos) <emphasis>and</emphasis> (pos .<=. C3)
disp(crum) ← disp(crum) .-. (C2 .-. C1) .+. (C4 .-. C3)
<emphasis>else</emphasis> <emphasis>if</emphasis> (C3 .<. pos) <emphasis>and</emphasis> (pos .<=. C4)
disp(crum) ← disp(crum) .-. (C3 .-. C1)
<emphasis>end</emphasis> if
<emphasis>end</emphasis> for</programlisting>
</figure></para>
<para>It can be seen that the three-cut rearrange is equivalent to a
four-cut rearrange in which two adjacent cuts are identical.</para>
<para><termdef>The <firstterm>cut</firstterm> operation itself is accomplished by splitting crums which
straddle the cut location.
The two new crums correspond to the two sides of the cut.
The children of the old crum are assigned to the new crums according
to which side of the cut they fall on — any children which themselves
straddle the cut are split using the same procedure recursively.</termdef>
Cuts are usually made in groups, with the cutting process terminating
when a single crum spans all of the cut location
(this crum corresponds to the crum P in the algorithms above).
The following is the algorithm for cut:
<figure xml:id="algorithm-cut">
<programlisting>cut (cutSet)
recursiveCut (cutSet, fulcrum)
<emphasis>end</emphasis> cut
recursiveCut (cutSet, parentCrum)
dontDiveDeeperFlag ← TRUE
<emphasis>for</emphasis> each child <emphasis>of</emphasis> parentCrum
<emphasis>if</emphasis> (disp(child) .<. firstCut(cutSet)) <emphasis>and</emphasis> (lastCut(cutSet) .<=. (disp(child) .+. wid(child)))
dontDiveDeeperFlag ← FALSE
<emphasis>for</emphasis> each cut in cutSet
cut ← cut .-. disp(child)
<emphasis>end</emphasis> for
recursiveCut (cutSet, child)
<emphasis>end</emphasis> if
<emphasis>end</emphasis> for
<emphasis>if</emphasis> (dontDiveDeeperFlag)
chopUp (cutSet, parentCrum)
<emphasis>end</emphasis> if
<emphasis>end</emphasis> recursiveCut
chopOp (cutSet, parentCrum)
<emphasis>for</emphasis> each cut in cutSet
<emphasis>for</emphasis> each child <emphasis>of</emphasis> parentCrum
<emphasis>if</emphasis> (disp(child) .<. cut) <emphasis>and</emphasis> (cut .<=. (disp(child) .+. wid(child)))
neWChildSet ← split(cut, child)
disown(parentCrum, child)
adopt (parentCrum, leftChild(newChildSet))
adopt (parentCrum, rightChild(newChildSet))
break out <emphasis>of</emphasis> inner loop
<emphasis>end</emphasis> if
<emphasis>end</emphasis> for
<emphasis>end</emphasis> for
<emphasis>end</emphasis> chopUp
split (cut, crum)
leftCrum ← createNewCrum ()
rightCrum ← createNewCrum ()
disp(leftCrum) ← disp(crum)
wid(leftCrum) ← cut .-. disp(crum)
disp(rightCrum) ← cut
wid(rightCrum) ← wid(crum) .+. disp(crum) .-. cut
<emphasis>for</emphasis> each child <emphasis>of</emphasis> crum
<emphasis>if</emphasis> ((disp(child) .+. wid(child)) .<. cut)
adopt (leftCrum, child)
<emphasis>else</emphasis> <emphasis>if</emphasis> (cut .<=. disp(child))
adopt (rightCrum, child)
<emphasis>else</emphasis>
newChildSet ← split(cut .-. disp(child), child)
adopt (leftCrum, leftChild(newChildSet))
adopt (rightCrum, rightChild(newChildSet))
<emphasis>end</emphasis> if
<emphasis>end</emphasis> for
<emphasis>result</emphasis> ← makeChildSet(leftCrum, rightCrum)
<emphasis>end</emphasis> split</programlisting>
</figure>
where <code>makeChildSet(leftCrum, rightCrum)</code> takes two crums and
returns them in some sort of ordered collection,
<code>leftChild(childSet)</code> returns the first child in such a collection,
and <code>rightChild(childSet)</code> returns the other child;
<code>adopt(parent, child)</code> adds the crum <code>child</code>
to the set of children of <code>parent</code>
and <code>disown(parent, child)</code> removes it (discarding child);
<code>createNewCrum()</code> creates a new, uninitialized crum;
and <code>firstCut(cutSet)</code> returns the first (in index space) cut
in a set of cuts,
and <code>lastCut(cutSet)</code> similarly return the last one.</para>
<termdef>The <firstterm>append</firstterm> operation adds new elements to the data structure by
extending the range of index space covered by it and associating the new
elements with these extended index space positions.</termdef>
<para>The general algorithm to append a single new element to an enfilade is:
<figure xml:id="algorithm-append">
<programlisting>append (newThing, beyond, where)
potentialNewCrum ← recursiveAppend (newThing, fulcrum, beyond, where)
<emphasis>if</emphasis> (notNull(potentialNewCrum))
levelPush (potentialNewCrum)
<emphasis>end</emphasis> if
<emphasis>end</emphasis> append
recursiveAppend (newThing, parent, beyond, where)
<emphasis>if</emphasis> (where .==. .O.)
newCrum ← createNewBottomCrum ()
data(newCrum) ← newThing
wid(newCrum) ← naturalWid(newThing)
disp(newCrum) ← disp(parent) .+. beyond
<emphasis>result</emphasis> ← newCrum
<emphasis>else</emphasis>
<emphasis>for</emphasis> each child <emphasis>of</emphasis> parent
<emphasis>if</emphasis> (disp(child) .<=. where) <emphasis>and</emphasis> (where .<. (disp(child) .+. wid(child)))
potentialNewCrum ← recursiveAppend(newThing, child, beyond,
where .-. disp(child))
break
<emphasis>end</emphasis> if
<emphasis>end</emphasis> for
<emphasis>if</emphasis> (notNull(potentialNewCrum))
<emphasis>if</emphasis> (numberOfChildren(parent) >= MaximumNumberOfCrumsInALoaf)
newCrum ← createNewCrum ()
disp(newCrum) ← disp(potentialNewCrum)
disp(potentialNewCrum) ← .O.
wid (newCrum) ← wid(potentialNewCrum)
<emphasis>result</emphasis> ← newCrum
<emphasis>else</emphasis>
wid(parent) ← enwidify(children(parent), potentialNewCrum)
adopt(parent, potentialNewCrum)
<emphasis>result</emphasis> ← NULL
<emphasis>end</emphasis> if
<emphasis>else</emphasis>
<emphasis>result</emphasis> ← NULL
<emphasis>end</emphasis> if
<emphasis>end</emphasis> if
<emphasis>end</emphasis> recursiveAppend</programlisting>
</figure>
where
<termdef><code><firstterm>naturalWid</firstterm>(dataltem)</code> is a function that determines the
wid of a bottom crum associated with a particular data item</termdef>
and
<termdef><code><firstterm>enwidify</firstterm>(crum1, crum2, ...)</code> is the widdative function which
computes the wid of a parent crum from the wids and
disps of its children.</termdef>
The widdative function is one of the fundamental
operators that defines an enfilade, along with .+. and .-..
The location appended to is represented by the two arguments
<emphasis>where</emphasis> and <emphasis>beyond</emphasis> which
indicate the position in the enfilade to which the new data element
is to be appended and the distance beyond that position that
will define the new data element’s own position.
<termdef>The value <firstterm><code>MaximumNumberOfCrumsInALoaf</code></firstterm> sets a limit
to the amount of “fanout” at each level of the tree.</termdef></para>
<para>Enfiladic trees are generally balanced by maintaining the requirement that
the number of children of anyone crum (i.e., the number of crums in a loaf)
may not exceed a given threshold.
In practice, since the structure of bottom crums and upper crums
may differ, it is often the case that this threshold will
differ between bottom loaves and upper loaves.
The actual values chosen for these thresholds depend upon the
actual enfilade in question, and are typically
selected to optimize retrieval speed, disk space efficiency, or
some other empirically determined, implementation dependent criteria.</para>
<para><termdef>The <firstterm>level push</firstterm> operation adds an additional level to the
tree when an append or insert operation causes the
number of children of the fulcrum to grow too large.
It simply creates a new fulcrum from which is descended the
old one.</termdef>
The algorithm is:
<figure xml:id="algorithm-level-push">
<programlisting>levelPush (newCrum)
newFulcrum ← createNewCrum ()
disp(newFulcrum) ← .O.
wid(newFulcrum) ← enwidify(fulcrum, newCrum)
adopt (newFulcrum, fulcrum)
adopt (newFulcrum, newCrum)
fulcrum ← newFulcrum
<emphasis>end</emphasis> levelPush</programlisting>
</figure></para>
<para>where <termdef>the argument <firstterm>newCrum</firstterm> represents the new sibling
to the old fulcrum
from which is descended the branch of the tree which caused the
old fulcrum to overflow.</termdef></para>
<para><termdef>The <firstterm>insert</firstterm> operation adds a new data element at a
random position in the enfilade.</termdef>
Insert is not a strictly necessary operation, since it is
functionally equivalent to an append operation followed by a rearrange
operation.
The append adds the new item to the data structure and then the
rearrange relocates it to the desired location.
In practice, insert is often implemented as a separate operation,
for reasons of efficiency or convenience.
An insertion is accomplished by making a cut at the
desired insertion point,
extending this cut upwards to a crum whose wid is large enough
to encompass the data to be inserted,
and then plugging the new material in.
The disps of crums .>. the new material at this level are then
incremented accordingly.
The algorithm to accomplish this is left as an exercise for the reader
in order not to overly extend this paper.
<termdef>The <firstterm>delete</firstterm> operation removes things from an enfilade.</termdef>
Delete, like insert, is also not strictly necessary,
since undesired material can be relocated to any arbitrary “purgatory”
by the rearrange operation.
In actual use, however, it often desirable to actually delete things
in order to be able to reclaim the storage that they occupy.
The delete operation is quite simple:
two cuts are made on the boundaries of the unwanted region
of index space and propagated up to a common ancestor.
The child crums of this ancestor which lie between the
cuts are then disowned and
the disps of greater siblings reduced accordingly.
The disowned crums and all of their descendants may then
be deallocated or left for garbage collection.</para>
<para>Deletes and rearranges can result in an enfilade that is a badly
fragmented, unbalanced tree and in which many crums have fewer than the
optimum number of children.
This in turn can result in a tree which has more levels than necessary,
with a potentially adverse affect upon performance.
<termdef>The <firstterm>recombine</firstterm> operation is used to tidy things up by
merging sibling crums.</termdef>
The algorithm to merge two siblings is:
<figure xml:id="algorithm-primitive-recombine">
<programlisting>primitiveRecombine (parent, sibling1, sibling2)
newCrum ← createNewCrum ()
disp(newCrum) ← disp(sibling1)
<emphasis>for</emphasis> each child <emphasis>of</emphasis> sibling1
disown(sibling1, child)
adopt (newCrum, child)
<emphasis>end</emphasis> for
dispCorrection ← disp(sibling2) .-. disp(sibling1)
<emphasis>for</emphasis> each child <emphasis>of</emphasis> sibling2
disown(sibling2, child)
disp(child) ← disp(child) .+. dispCorrection
adopt (newCrum, child)
<emphasis>end</emphasis> for
wid(newCrum) ← enwidify(children(newCrum))
disown(parent, sibling1)
disown(parent, sibling2)
adopt(parent, newCrum)
<emphasis>end</emphasis> primitiveRecombine</programlisting>
</figure></para>
<para>The term recombine is commonly used to refer to the process of climbing
around the enfiladic tree and selectively applying the above operation
in order to perform some general housecleaning.
Such a process may also include cut operations to
split up recombined crums which have too many children, perhaps
interleaving cuts with primitiveRecombines in order to “shuffle”
crums around in the tree.
The methods for doing this are heuristic rather than algorithmic,
and depend both on the nature of the particular enfilade
in question and the data with which it is being used.
Certain applications may not, in fact,
require any recombines to be performed at all.
A recombine may also invoke a level pop operation to remove an
excess level from the tree.
This can be performed when the fulcrum has but a single child.
The algorithm is simply:
<figure xml:id="algorithm-level-pop">
<programlisting>levelPop ()
newFulcrum ← theOneChildOf(fulcrum)