init commit

This commit is contained in:
divorce committed 2026-09-30 19:27:45 -04:00
commit 6300e42bb2
28 files changed
+104005

No files matched your search

+367
View File
@@ -0,0 +1,367 @@
ENSIFER ENFILADE — BEGINNER'S GUIDE
===================================
This guide assumes you have never worked with an enfilade before.
The shortest description is:
A tumbler is an address.
An enfilade is the tree that stores things at those addresses.
For example:
1.2.3
is one tumbler address.
If we store:
1.2.3 -> 42
the enfilade creates this path automatically:
root
|
+-- 1
|
+-- 2
|
+-- 3 -> 42
You do not construct those intermediate nodes yourself.
1. BUILD AND RUN IT
-------------------
From the Ensifer directory, configure and build:
./configure
make
Then start the REPL:
./build/bin/logan
To load the module into a different S7 host:
(load "./build/lib/enfilade.so" (inlet 'init_func 'init_enfilade_s7))
2. CREATE ONE
-------------
(define e (make-enfilade))
`e` is now the enfilade.
3. PUT SOMETHING IN IT
----------------------
(enfilade-put-data e "1.2.3" 42)
There is now a datum at address `1.2.3`.
4. GET IT BACK
--------------
(enfilade-get-by-tumbler e "1.2.3")
Result:
(42)
The result is a Scheme list because a tumbler lookup can produce more than one
datum.
5. PUT MORE IN
--------------
(enfilade-put-data e "1.2.4" 43)
(enfilade-put-data e "1.3.1" 99)
Now:
(enfilade-get-by-tumbler e "1.2.3")
; => (42)
(enfilade-get-by-tumbler e "1.2")
; => (42 43)
The second lookup stops at key `2` inside the `1` branch and returns the data
at that key followed by the data beneath its child enfilade.
6. A KEY MAY HAVE BOTH A DATUM AND CHILDREN
--------------------------------------------
This is important.
(enfilade-put-data e "1.2" 99)
(enfilade-put-data e "1.2.5" 50)
Now key `1.2` has both:
datum = 99
child = 5 -> 50
So:
(enfilade-get-by-tumbler e "1.2")
; => (99 42 43 50)
The datum at the exact key comes first. The child is then flattened in numeric
key order.
7. REPLACE A DATUM
------------------
A final key contains one datum. Putting another datum at the same final key
replaces the old one:
(enfilade-put-data e "1.2.3" 500)
(enfilade-get-by-tumbler e "1.2.3")
; => (500)
8. REMOVE A DATUM
-----------------
(enfilade-remove e "1.2.3")
; => #t
That removes only the datum stored exactly at `1.2.3`.
It does not delete an unrelated child at that key.
Removing a nonexistent final datum returns `#f`:
(enfilade-remove e "1.2.3")
; => #f
If an intermediate child does not exist, the operation reports a
`TumblerAddressException` instead.
9. RANGE
--------
Keep this distinction in mind:
tumbler lookup = dotted address
range = numeric keys at one enfilade level
For example:
(enfilade-get-range e 1 3)
means “visit numeric keys 1, 2, and 3 at this level, inclusive, and flatten
their contents.”
A negative end means “through the end”:
(enfilade-get-range e 2 -1)
The `range` interface is intentionally kept exactly as the existing API.
10. TUMBLERS ARE MORE THAN STRINGS
-----------------------------------
The external notation is a string:
"1.2.3"
but the package now has a real C tumbler primitive underneath it.
The S7 side exposes the useful basic operations too.
Compare:
(tumbler-compare "1" "1.1")
; => -1
(tumbler-compare "1.1" "1.1.1")
; => -1
(tumbler-compare "1.2" "1.1.9")
; => 1
Add:
(tumbler-add "3" "2.16.3")
; => "5.16.3"
(tumbler-add "25.6.46.93" "0.0.3.1.21")
; => "25.6.49.1.21"
Subtract / difference:
(tumbler-subtract "1.4.3" "1.1.1")
; => "0.3.3"
These are the historical tumbler operations, not ordinary decimal-number
addition and subtraction.
11. WHY THIS MATTERS FOR ZIGZAG
-------------------------------
An enfilade does not need to understand what a datum means.
That is useful when the datum is a ZigZag cell pointer.
Conceptually:
cell ID
|
v
tumbler
|
v
enfilade
|
v
cell
The catalogue can therefore answer:
“What cell is stored at this ID?”
without embedding ZigZag cell structure into the indexing mechanism.
12. THE C VERSION
-----------------
Include:
#include "enfilade.h"
Create:
enfilade_t *e = create_enfilade();
Store a pointer:
int value = 42;
put_enfilade(e, "1.2.3", &value);
Use it while the pointed-to object is alive:
int *found = getXtumbler_enfilade(e, "1.2.3");
printf("%d\n", *found);
Destroy the index before destroying the object it points to:
destroy_enfilade(e);
The enfilade never frees `value`.
The important rule is therefore:
the enfilade owns its tree;
the caller owns its datum.
13. TUMBLER C API
-----------------
Include:
#include "tumbler.h"
Parse a tumbler string:
tumbler_t t = {0};
tumbler_result_t r = tumbler_parse("1.2.3", &t);
Use it:
int cmp = tumbler_compare(&t, &t);
Release it:
tumbler_free(&t);
Arithmetic produces another heap-owned tumbler whose storage the caller must
also release:
tumbler_t a = {0}, b = {0}, out = {0};
tumbler_parse("25.6.46.93", &a);
tumbler_parse("0.0.3.1.21", &b);
tumbler_add(&a, &b, &out);
tumbler_free(&a);
tumbler_free(&b);
tumbler_free(&out);
14. VALID TUMBLERS
------------------
The current C representation accepts one or more unsigned decimal fields:
1
1.2
1.2.3
0
1.0.3
100.0.7
Malformed examples:
.1
1.
1..2
1.a.2
-1.2
The zero field is legal. Historical Xanadu addressing uses zero fields as
delimiters in some larger address formats; this small enfilade does not assign
zero any additional structural meaning.
15. ERRORS
----------
Malformed tumbler text:
TumblerAddressException
Missing intermediate child during lookup/removal:
TumblerAddressException
Valid final key with no datum or descendants:
()
Allocation failure:
memory-error
16. WHAT YOU DO NOT NEED TO LEARN YET
--------------------------------------
You do not need CRUM, POOM, Granfilade, Spanfilade, WID, DISP, orgl, loaf, or
Green's virtual-memory machinery to use this object.
Those names describe the larger historical system and specialized data
structures built around enfilades. They are important when implementing those
higher layers, but they are not prerequisites for understanding this small
primitive.
The right mental model for this package is simply:
tumbler -> path through an enfilade -> datum(s)
17. REFERENCES
--------------
Immediate behavioral reference:
https://raw.githubusercontent.com/enkiv2/ds-lib/refs/heads/master/Enfilade.py
Historical Xanadu technical material:
https://sentido-labs.com/en/library/201904240732/Xanadu%20Hypertext%20Documents.html
Udanax Green / Xanalogical Structure:
https://www.mprove.de/visionreality/media/xuDation.html
Jeff Rush's tumbler implementation:
https://pypi.org/project/xanalogica.tumbler/
+128
View File
@@ -0,0 +1,128 @@
.Dd September 24, 2026
.Dt ENFILADE-S7 7
.Os
.Sh NAME
.Nm enfilade-s7
.Nd S7 Scheme bindings for the small enfilade
.Sh SYNOPSIS
.Bd -literal -offset indent
(load "./build/lib/enfilade.so" (inlet 'init_func 'init_enfilade_s7))
(define e (make-enfilade))
(enfilade-put-data e "1.2.3" 42)
(enfilade-get-by-tumbler e "1.2.3")
.Ed
.Sh DESCRIPTION
The module wraps the C
.Vt enfilade_t
in an S7 c-object of type
.Ql <enfilade> .
The Scheme datum passed to
.Fn enfilade-put-data
is retained in the C tree as an S7 pointer.
The c-object mark callback marks every stored datum during garbage collection.
.Sh LOADING
Configure and build the S7 module:
.Bd -literal -offset indent
./configure
make
.Ed
.Pp
Load it into an S7 host with:
.Bd -literal -offset indent
(load "./build/lib/enfilade.so" (inlet 'init_func 'init_enfilade_s7))
.Ed
.Sh FUNCTIONS
.Bl -tag -width enfilade-get-by-tumbler
.It Fn make-enfilade
Returns a new
.Ql <enfilade>
object.
.It Fn enfilade-put-data enfilade tumbler datum
Stores
.Fa datum
at
.Fa tumbler .
The tumbler is a string of unsigned decimal fields separated by periods.
Missing intermediate child enfilades are created automatically.
The return value is unspecified.
.It Fn enfilade-remove enfilade tumbler
Removes the datum at the exact final key.
Returns
.Ql #t
when a datum was removed and
.Ql #f
when the exact final datum was not present.
A child subtree at that key is retained.
.It Fn enfilade-get-by-tumbler enfilade tumbler
Returns a Scheme list containing the datum at the exact final key, followed by
the flattened contents of a child subtree at that key, if present.
Missing intermediate children and malformed tumblers raise
.Ql TumblerAddressException .
A valid final key with nothing stored there returns
.Ql () .
.It Fn enfilade-get-range enfilade start end
Visits numeric keys from
.Fa start
through
.Fa end ,
inclusive, and flattens their contents.
A negative end means through the end.
This is a one-level numeric range, not a dotted tumbler interval.
.It Fn tumbler-compare a b
Returns a negative integer, zero, or a positive integer according to the
whole-tumbler ordering of the two strings.
.It Fn tumbler-add position offset
Returns the dotted-string result of Xanadu tumbler addition.
.It Fn tumbler-subtract a b
Returns the generalized non-negative tumbler difference.
.El
.Sh EXAMPLE
.Bd -literal -offset indent
(define e (make-enfilade))
(enfilade-put-data e "1.2.3" 42)
(enfilade-put-data e "1.2.4" 43)
(enfilade-put-data e "1.3.1" 99)
(enfilade-get-by-tumbler e "1.2.3")
; => (42)
(enfilade-get-by-tumbler e "1.2")
; => (42 43)
(enfilade-get-range e 1 3)
; => (42 43 99)
(enfilade-remove e "1.2.3")
; => #t
.Ed
.Sh DATUM LIFETIME
The C tree does not copy or free Scheme datums.
The S7 c-object retains them by marking them during garbage collection.
When the c-object is finally freed, the C tree is destroyed.
Do not call
.Fn destroy_enfilade
on the pointer owned by a live S7 c-object.
.Sh ERRORS
Malformed tumbler strings and missing intermediate children raise
.Ql TumblerAddressException .
Allocation failures raise
.Ql memory-error .
Wrong Scheme argument types use S7's normal wrong-type condition.
.Sh FILES
.Bl -tag -width src/enfilade_s7.c
.It Pa src/enfilade_s7.c
S7 binding implementation.
.It Pa src/logan.c
Direct minimal REPL for the module.
.It Pa test/enfload.c
Non-interactive S7 smoke test.
.El
.Sh SEE ALSO
.Xr tumbler-s7 7 ,
.Xr enfilade 3 ,
.Xr tumbler 3 ,
.Xr ensifer 7
.Sh REFERENCES
.Lk https://raw.githubusercontent.com/enkiv2/ds-lib/refs/heads/master/Enfilade.py
+155
View File
@@ -0,0 +1,155 @@
.Dd September 24, 2026
.Dt ENFILADE 3
.Os
.Sh NAME
.Nm enfilade
.Nd small Model-T-style tumbler-addressed enfilade
.Sh SYNOPSIS
.In enfilade.h
.Ft enfilade_t *
.Fn create_enfilade void
.Ft void
.Fn destroy_enfilade "enfilade_t *enf"
.Ft enf_result_t
.Fn put_enfilade "enfilade_t *enf" "const char *tumbler" "void *datum"
.Ft enf_result_t
.Fn remove_enfilade "enfilade_t *enf" "const char *tumbler"
.Ft void *
.Fn getXtumbler_enfilade "enfilade_t *enf" "const char *tumbler"
.Ft enf_result_t
.Fn getXtumbler_values_enfilade "enfilade_t *enf" "const char *tumbler" "void ***items" "size_t *count"
.Ft enf_result_t
.Fn getXrange_values_enfilade "enfilade_t *enf" "int64_t start" "int64_t end" "void ***items" "size_t *count"
.Ft void
.Fn enfilade_visit_data "enfilade_t *enf" "enfilade_datum_visitor visitor" "void *context"
.Sh DESCRIPTION
An
.Nm
is a tree whose local keys are unsigned integer tumbler fields.
Each node can contain terminal datum values and child enfilades at the same
numeric keys.
.Pp
Putting
.Ql 1.2.3
creates the path through keys 1, 2, and 3. The datum is stored at the final
key.
.Pp
The interface is intentionally small and follows the behavior of the
Model-T-style Python reference implementation used by this project.
.Sh CREATION AND LIFETIME
.Fn create_enfilade
returns an empty enfilade or NULL on allocation failure.
.Fn destroy_enfilade
recursively frees the enfilade tree.
.Pp
The enfilade owns its tree nodes but does not own datum pointers supplied by
the caller. The caller must keep every datum alive for as long as it may be
returned by a lookup and must destroy the enfilade before those datum objects
are destroyed.
.Sh INSERTION
.Fn put_enfilade
stores
.Fa datum
at the exact final field of
.Fa tumbler .
Missing intermediate child enfilades are created automatically.
.Pp
A second insertion at the same final key replaces the existing datum.
.Pp
If a final key already contains a datum and a child subtree, insertion replaces
only the datum.
.Sh REMOVAL
.Fn remove_enfilade
removes only the datum stored at the exact final key.
.Pp
A child subtree at that same key is retained.
Empty intermediate child enfilades are pruned after successful removal.
The datum pointer itself is never freed.
.Pp
A missing exact datum returns
.Dv ENF_ERR_NOT_FOUND .
.Sh EXACT LOOKUP
.Fn getXtumbler_enfilade
returns only the datum stored at the exact final key, or NULL if none exists or
the path is invalid.
.Pp
For callers that need reference-style flattened lookup,
.Fn getXtumbler_values_enfilade
walks every component except the last as a child path, then returns a newly
allocated array containing the datum at the final key followed by all data in
its child subtree.
.Pp
The caller owns the returned array and releases it with
.Xr free 3 .
The datum pointers remain owned by the caller.
.Sh RANGE
.Fn getXrange_values_enfilade
walks numeric keys at the current enfilade level from
.Fa start
through
.Fa end ,
inclusive, and recursively flattens their contents.
A negative
.Fa end
means there is no upper bound.
.Pp
This operation deliberately remains the existing
.Dq range
interface. It is not a parser for dotted tumbler intervals.
.Sh TRAVERSAL
.Fn enfilade_visit_data
visits every stored datum. The visitor callback is not retained after the
call.
The callback must not be assumed to outlive the traversal call.
.Sh EXAMPLE
.Bd -literal -offset indent
#include "enfilade.h"
#include <stdio.h>
int main(void)
{
enfilade_t *e = create_enfilade();
int value = 42;
void *found;
if (!e) return 1;
if (put_enfilade(e, "1.2.3", &value).code != ENF_OK)
return 1;
found = getXtumbler_enfilade(e, "1.2.3");
if (found)
printf("%d\\n", *(int *)found);
destroy_enfilade(e);
return 0;
}
.Ed
.Sh ERRORS
.Bl -tag -width ENF_ERR_NOT_FOUND
.It Dv ENF_OK
Success.
.It Dv ENF_ERR_NULL
A required pointer was null.
.It Dv ENF_ERR_ADDR
The tumbler text is malformed.
.It Dv ENF_ERR_NOT_FOUND
A requested datum or intermediate child was absent.
.It Dv ENF_ERR_NOMEM
An allocation failed.
.El
.Sh THREADING
The enfilade structure does not provide internal locking.
External synchronization is required if multiple threads may access the same
instance concurrently.
.Sh SCOPE
This package implements the small tumbler-keyed tree only. It does not
implement the broader Green machinery such as WIDs, DISPs, orgls, POOMs,
Spanfilades, persistent CRUM storage, rearrangement, or version management.
.Sh SEE ALSO
.Xr tumbler 3 ,
.Xr enfilade-s7 7 ,
.Xr ensifer 7
.Sh REFERENCES
.Lk https://raw.githubusercontent.com/enkiv2/ds-lib/refs/heads/master/Enfilade.py
.Pp
.Lk https://sentido-labs.com/en/library/201904240732/Xanadu%20Hypertext%20Documents.html
+212
View File
@@ -0,0 +1,212 @@
.Dd September 24, 2026
.Dt ENSIFER 7
.Os
.ds V 0.1.20
.Sh NAME
.Nm ensifer
.Nd small Model-T-style enfilade for C and S7 Scheme
.Sh SYNOPSIS
.Bd -literal -offset indent
./build/bin/logan
(define e (make-enfilade))
(enfilade-put-data e "1.2.3" 42)
(enfilade-get-by-tumbler e "1.2.3")
.Ed
.Sh DESCRIPTION
.Nm ensifer
is a small, working enfilade layer intended to be understandable and reusable
without requiring the larger Xanadu/Green architecture to be introduced first.
.Pp
The central idea is simple: a dotted tumbler is a path through an indexed tree.
Storing:
.Bd -literal -offset indent
1.2.3 -> 42
.Ed
.Pp
conceptually produces:
.Bd -literal -offset indent
root
|
+-- 1
|
+-- 2
|
+-- 3 -> 42
.Ed
.Pp
A node can contain a datum and a child at the same numeric key. Lookup returns
the exact-key datum first and then recursively flattens the child.
.Sh FIRST USE
Configure and build the complete package:
.Bd -literal -offset indent
./configure
make
.Ed
.Pp
Run the REPL, which initializes the enfilade bindings automatically:
.Bd -literal -offset indent
./build/bin/logan
.Ed
.Pp
Install with
.Cm make install .
Use
.Cm ./configure --prefix=PATH
for a non-default prefix, or set
.Ev DESTDIR
when staging an install.
.Sh CORE OPERATIONS
The small reference consists of:
.Bl -tag -width tumbler-subtract
.It Fn make-enfilade
Create an empty enfilade.
.It Fn enfilade-put-data
Insert or replace a datum at a tumbler.
.It Fn enfilade-remove
Remove the datum at an exact tumbler key.
.It Fn enfilade-get-by-tumbler
Resolve a dotted tumbler and flatten the matching subtree.
.It Fn enfilade-get-range
Range over numeric keys at one enfilade level.
.It Fn tumbler-compare
Compare complete tumbler addresses.
.It Fn tumbler-add
Perform Xanadu tumbler addition.
.It Fn tumbler-subtract
Perform the generalized tumbler difference.
.El
.Sh TUMBLERS
Tumblers are unsigned integer fields separated by periods:
.Bd -literal -offset indent
1
1.2
1.2.3
1.0.7
.Ed
.Pp
The package stores each field as
.Vt uint64_t .
It does not implement the historical arbitrary-precision Humber encoding.
.Pp
Whole-tumbler comparison uses the infinitesimal-style order represented by the
small Udanax-derived implementations:
.Bd -literal -offset indent
1 < 1.1 < 1.1.1 < 1.2 < 2
.Ed
.Pp
The C tumbler module also implements Xanadu's non-commutative addition and
strong, weak, and generalized subtraction. See
.Xr tumbler 3 .
.Sh RANGE
The name
.Dq range
is intentionally retained.
.Pp
.Fn enfilade-get-range
operates on the numeric keys of the current enfilade level, with inclusive
bounds. A negative upper bound means through the end.
.Pp
It is not a dotted tumbler interval expression.
.Sh REMOVAL
.Fn enfilade-remove
removes only the datum at the exact final key.
If a child subtree exists at that key, it remains.
Empty intermediate children are pruned.
.Pp
In Scheme the operation returns
.Ql #t
on removal and
.Ql #f
when there was no datum at the exact key.
.Sh DATUM OWNERSHIP
C callers own the objects pointed to by datum entries.
The enfilade owns only its index nodes and never frees a datum pointer.
.Pp
In S7, datums are Scheme objects. The c-object mark callback visits every
stored datum, making them reachable to the garbage collector while the
enfilade remains live.
.Sh WHAT THIS IS
This is a small tumbler-addressed Model-T-style enfilade.
It is intended as a primitive that other structures can use directly.
.Pp
It is not a complete implementation of Udanax Green.
The broader historical system includes specialized enfilades and additional
machinery for WIDs, DISPs, rearrangement, versioning, spans, virtual copies,
and persistence.
.Pp
Those concepts are intentionally outside this layer so that the fundamental
indexing mechanism remains visible.
.Sh REFERENCE IMPLEMENTATION
The immediate behavioral reference is the `Enfilade.py` implementation in
.Dq ds-lib .
.Pp
Its `putValue`, `getByTumbler`, `get`, and `getRange` behavior correspond to the
operations in this package.
.Pp
The C `range` implementation deliberately merges a node's value keys and child
keys rather than traversing a duplicated combined-key list. Thus a key shared
by a datum and child is visited once during a range traversal; the Python
reference can visit it twice in that particular case. Exact tumbler lookup
retains the reference's datum-then-child result order.
.Sh ZIGZAG USE
A simple catalogue can use the enfilade without teaching the enfilade anything
about cells:
.Bd -literal -offset indent
cell ID (tumbler)
|
v
enfilade
|
v
cell pointer
.Ed
.Pp
This makes the enfilade a general index beneath a cell store rather than a
second representation of the cell itself.
.Sh FILES
.Bl -tag -width src/enfilade_s7.c
.It Pa src/enfilade.c
Enfilade tree implementation.
.It Pa inc/enfilade.h
Public C API.
.It Pa src/tumbler.c
Tumbler parser, comparison, and arithmetic.
.It Pa inc/tumbler.h
Public tumbler API.
.It Pa src/enfilade_s7.c
S7 bindings and c-object type.
.It Pa src/logan.c
Direct REPL.
.It Pa test/enfload.c
S7 smoke test.
.It Pa scheme/enf.scm
Scheme smoke-test procedure.
.It Pa test/tumbler-test.c
Tumbler regression tests.
.It Pa test/enfilade-test.c
Enfilade regression tests.
.El
.Sh VERSION
The package version is available as
.Dv ENSIFER_VERSION
from
.Pa inc/enfilade.h
and from
.Nm logan --version .
The current version is 0.1.20.
.Sh TRIVIA
Ensifer is called after the greatest frost mage on Zuluhed. He would duel glads naked & win.
.Sh SEE ALSO
.Xr enfilade 3 ,
.Xr tumbler 3 ,
.Xr enfilade-s7 7 ,
.Xr tumbler-s7 7
.Sh REFERENCES
.Lk https://raw.githubusercontent.com/enkiv2/ds-lib/refs/heads/master/Enfilade.py
.Pp
.Lk https://sentido-labs.com/en/library/201904240732/Xanadu%20Hypertext%20Documents.html
.Pp
.Lk https://www.mprove.de/visionreality/media/xuDation.html
.Pp
.Lk https://pypi.org/project/xanalogica.tumbler/
+55
View File
@@ -0,0 +1,55 @@
.Dd September 24, 2026
.Dt TUMBLER-S7 7
.Os
.Sh NAME
.Nm tumbler-s7
.Nd S7 Scheme interface to the tumbler primitive
.Sh SYNOPSIS
Bd -literal -offset indent
(load "./build/lib/enfilade.so" (inlet 'init_func 'init_enfilade_s7))
(tumbler-compare "1" "1.1")
(tumbler-add "3" "2.16.3")
(tumbler-subtract "1.4.3" "1.1.1")
.Ed
.Sh DESCRIPTION
The module exposes the small C tumbler implementation to S7 without requiring
a separate Scheme tumbler object type. Tumblers cross the FFI as dotted
unsigned-integer strings.
.Sh FUNCTIONS
.Bl -tag -width tumbler-subtract
.It Fn tumbler-compare a b
Returns a negative integer, zero, or a positive integer according to the
whole-tumbler ordering of
.Fa a
and
.Fa b .
.It Fn tumbler-add position offset
Returns a new tumbler string containing Xanadu tumbler addition.
.It Fn tumbler-subtract a b
Returns the generalized non-negative tumbler difference.
.El
.Sh EXAMPLES
.Bd -literal
(tumbler-compare "1" "1.1")
; => -1
(tumbler-add "3" "2.16.3")
; => "5.16.3"
(tumbler-add "25.6.46.93" "0.0.3.1.21")
; => "25.6.49.1.21"
(tumbler-subtract "1.4.3" "1.1.1")
; => "0.3.3"
.Ed
.Sh ERRORS
Malformed tumbler strings raise
.Ql TumblerAddressException .
Allocation failures raise
.Ql memory-error .
.Sh SEE ALSO
.Xr tumbler 3 ,
.Xr enfilade-s7 7
.Sh REFERENCES
.Lk https://sentido-labs.com/en/library/201904240732/Xanadu%20Hypertext%20Documents.html
+179
View File
@@ -0,0 +1,179 @@
.Dd September 24, 2026
.Dt TUMBLER 3
.Os
.Sh NAME
.Nm tumbler
.Nd dotted integer coordinates and Xanadu tumbler arithmetic
.Sh SYNOPSIS
.In tumbler.h
.Ft tumbler_result_t
.Fn tumbler_parse "const char *text" "tumbler_t *out"
.Ft void
.Fn tumbler_free "tumbler_t *t"
.Ft tumbler_result_t
.Fn tumbler_to_string "const tumbler_t *t" "char **out"
.Ft int
.Fn tumbler_compare "const tumbler_t *a" "const tumbler_t *b"
.Ft tumbler_result_t
.Fn tumbler_add "const tumbler_t *position" "const tumbler_t *offset" "tumbler_t *out"
.Ft tumbler_result_t
.Fn tumbler_subtract_strong "const tumbler_t *position" "const tumbler_t *offset" "tumbler_t *out"
.Ft tumbler_result_t
.Fn tumbler_subtract_weak "const tumbler_t *position" "const tumbler_t *offset" "tumbler_t *out"
.Ft tumbler_result_t
.Fn tumbler_subtract "const tumbler_t *a" "const tumbler_t *b" "tumbler_t *out"
.Sh DESCRIPTION
The
.Nm
module provides the small tumbler primitive used by the enfilade.
A tumbler is a finite sequence of unsigned integer fields written in dotted
form, such as
.Ql 1.2.3 .
.Pp
The implementation stores each field as a
.Vt uint64_t .
The historical Xanadu system used arbitrary-precision Humbers; this package
intentionally does not implement that representation.
.Sh PARSING
.Fn tumbler_parse
parses one or more unsigned decimal fields separated by periods.
On success it allocates the field array in
.Vt tumbler_t .
The caller must release it with
.Fn tumbler_free .
.Pp
Examples:
.Bd -literal -offset indent
1
1.2
1.2.3
0.1.0.7
.Ed
.Pp
Malformed input includes an empty string, a leading or trailing period, two
periods in succession, non-decimal characters, and negative fields.
.Sh COMPARISON
.Fn tumbler_compare
returns a negative value, zero, or a positive value according as
.Fa a
is less than, equal to, or greater than
.Fa b .
.Pp
Comparison is performed from the most significant field toward the least
significant. A missing field is treated as zero for comparison. Thus:
.Bd -literal -offset indent
1 < 1.1 < 1.1.1 < 1.2 < 2
.Ed
.Pp
This is the infinitesimal-style tumbler ordering used by the small Udanax-derived
tumbler implementations. In this implementation, trailing zero fields do not
change comparison order.
.Sh ADDITION
.Fn tumbler_add
implements Xanadu tumbler addition. The operands have different roles:
.Fa position
is a position and
.Fa offset
is a distance to move forward.
.Pp
The procedure is:
.Bl -enum
.It
Copy fields from the position while the corresponding offset fields are zero.
.It
At the first non-zero offset field, add it to the corresponding position field.
.It
Copy the remaining offset fields into the result.
.El
.Pp
For example:
.Bd -literal -offset indent
3 + 2.16.3
= 5.16.3
25.6.46.93 + 0.0.3.1.21
= 25.6.49.1.21
.Ed
.Pp
Addition is non-commutative.
.Sh SUBTRACTION
The historical system distinguishes strong and weak subtraction.
.Fn tumbler_subtract_strong
implements strong subtraction and
.Fn tumbler_subtract_weak
implements weak subtraction.
.Pp
Strong subtraction preserves matching leading fields as zero until the first
difference, subtracts there, then copies the remaining fields from the
position. It requires
.Fa position
not be less than
.Fa offset .
.Pp
For example:
.Bd -literal -offset indent
1.4.3 s- 1.1.1
= 0.3.3
0.1.2.3.4.5.6 s- 0.1.2.3.3.3.3
= 0.0.0.0.1.5.6
.Ed
.Pp
Weak subtraction preserves the position through leading zero offset fields,
then subtracts the first non-zero offset field and stops.
For example:
.Bd -literal -offset indent
1.4.3 w- 1.1.1
= 0
0.3.3.3.4.5.6 w- 0.1.1.3.3.3.3
= 0.2
.Ed
.Pp
.Fn tumbler_subtract
is the generalized difference operation used by the Xanadu system. If
.Fa a
is greater than
.Fa b ,
strong subtraction computes
.Ql a - b .
Otherwise weak subtraction computes
.Ql b - a .
The result is therefore never negative.
.Sh MEMORY
All parsed and arithmetic result tumblers own heap storage for their digit
arrays. The caller is responsible for calling
.Fn tumbler_free .
.Pp
Strings returned by
.Fn tumbler_to_string
are allocated with
.Xr malloc 3
and are released with
.Xr free 3 .
.Sh ERRORS
The result structure uses these codes:
.Bl -tag -width TUMBLER_ERR_UNDERFLOW
.It Dv TUMBLER_OK
Success.
.It Dv TUMBLER_ERR_NULL
A required pointer was null.
.It Dv TUMBLER_ERR_INVALID
The tumbler representation is malformed.
.It Dv TUMBLER_ERR_NOMEM
Memory allocation failed.
.It Dv TUMBLER_ERR_OVERFLOW
An integer field or arithmetic result exceeded
.Vt uint64_t .
.It Dv TUMBLER_ERR_UNDERFLOW
A subtraction would require a negative field.
.El
.Sh SEE ALSO
.Xr enfilade 3 ,
.Xr tumbler-s7 7 ,
.Xr enfilade-s7 7
.Sh REFERENCES
.Pp
.Lk https://sentido-labs.com/en/library/201904240732/Xanadu%20Hypertext%20Documents.html
.Pp
.Lk https://pypi.org/project/xanalogica.tumbler/