diff --git a/whitepaper/lumbda-whitepaper.html b/whitepaper/lumbda-whitepaper.html index 400f892..ab5417e 100644 --- a/whitepaper/lumbda-whitepaper.html +++ b/whitepaper/lumbda-whitepaper.html @@ -2153,6 +2153,19 @@ ALL EML THEOREMS VERIFIED IN LUMBDA

Hygienic macros: syntax-rules with ellipsis (...) support. Pattern matching, template instantiation, proper hygiene. Also define-macro for procedural macros.

Standard library (stdlib.lsp, 385 lines): Additional macros (swap!, fluid-let, while, dotimes), utility functions, simple object system, SRFI-2/8/64 test framework.

Test suite: 974 verified assertions covering lexing, parsing, special forms, bytecode compilation, macros (hygienic & procedural), continuations, generators, record types, modules, arithmetic, higher-order functions, error handling, portal serialization, cross-implementation portal exchange, file I/O parity, & graceful degradation on mismatched or corrupt input.

+
+

9.1 Integer Square Root (isqrt)

+

sqrt returns an inexact real. That is the right answer when the caller wants a distance or a norm, and the wrong answer when the caller wants a count: bucket indices, loop bounds, coordinates on a grid, bignum primality witnesses. Float sqrt drifts with FPU mode, with the libm in play, and across platforms — none of which a portal should let into a replay trace.

+

(isqrt n) → floor(sqrt(n)) ships in all three implementations. Contract matches Python 3.8+ math.isqrt and the integer half of R7RS exact-integer-sqrt: integer-in, integer-out, negative argument raises. No floats anywhere in the pipeline.

+
(isqrt 0)       ; => 0
+(isqrt 16)      ; => 4     ; exact
+(isqrt 17)      ; => 4     ; floor, not round
+(isqrt 1000000) ; => 1000
+(isqrt -1)      ; error: negative argument
+

Algorithm. Bit-by-bit digit-recurrence (Wikipedia "Methods of computing square roots"). O(log n) shifts, adds, and compares; no multiplies, no divides, no FPU. The C and asm implementations share the same loop skeleton — the asm version (bi_isqrt, asm/lumbda.s) runs it in three integer registers (%r8 radicand, %r9 bit, %r10 result) with no memory traffic per iteration. Python delegates to CPython's math.isqrt, which uses Karatsuba-square-root for bignums.

+

Domain limits. Python: unbounded — works on arbitrary-precision int. asm: 61-bit (three tag bits consumed at the bottom of the word). C: 48-bit (NaN-boxed doubles carry the integer payload in the mantissa). Portal round-trips remain bit-identical within the smaller of the two tiers on either end; a value that fits in the C tier's 48-bit window survives every Python ↔ C ↔ asm crossing in §7.2's 3×3 matrix.

+

MOAD-0001 note. Each call is O(log n) in the value, not in the heap or the symbol table. No hidden linear scan, no per-call allocation in C or asm. Safe to invoke inside a tight loop without inflating the overall complexity class.

+

10. Relationship to Companion Papers

diff --git a/whitepaper/lumbda-whitepaper.pdf b/whitepaper/lumbda-whitepaper.pdf index a8a6cd4..67f5c98 100644 --- a/whitepaper/lumbda-whitepaper.pdf +++ b/whitepaper/lumbda-whitepaper.pdf @@ -73,9 +73,9 @@ endobj endobj 12 0 obj << -/Annots [ 9 0 R 10 0 R 11 0 R ] /Contents 141 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Annots [ 9 0 R 10 0 R 11 0 R ] /Contents 142 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << -/FormXob.674d5febcf42b97eda58b30c4a10192f 4 0 R /FormXob.c9411fecc114c344e33ac82182b38f43 6 0 R +/FormXob.674d5febcf42b97eda58b30c4a10192f 4 0 R /FormXob.abf5431e047a12a84b98349be6f1e444 6 0 R >> >> /Rotate 0 /Trans << @@ -90,7 +90,7 @@ endobj endobj 14 0 obj << -/Contents 142 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 143 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -113,7 +113,7 @@ endobj endobj 17 0 obj << -/Contents 143 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 144 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << /FormXob.a2c922509fa3b1785bcd08461c0457b3 15 0 R >> @@ -125,7 +125,7 @@ endobj endobj 18 0 obj << -/Contents 144 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 145 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -135,7 +135,7 @@ endobj endobj 19 0 obj << -/Contents 145 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 146 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -145,7 +145,7 @@ endobj endobj 20 0 obj << -/Contents 146 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 147 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -155,7 +155,7 @@ endobj endobj 21 0 obj << -/Contents 147 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 148 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -165,7 +165,7 @@ endobj endobj 22 0 obj << -/Contents 148 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 149 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -175,7 +175,7 @@ endobj endobj 23 0 obj << -/Contents 149 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 150 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -217,7 +217,7 @@ Gb"0;!=8`+$j31%en endobj 28 0 obj << -/Contents 150 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 151 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << /FormXob.6378944cfcd9d967b8dea9d1fdf81282 24 0 R /FormXob.914f0cd152b732307eb1a2bfb0d863fa 26 0 R >> @@ -237,7 +237,7 @@ Gb",k#C$s7fsZT]046lMitTPd:;/]-NFO>2i\0\Wj8LDL[UU6bNbrSUOQ^!BhM$WE!!/fb#UHuBlDUB4 endobj 30 0 obj << -/Contents 151 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 152 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << /FormXob.ddff3fe796cb06f610a0e90e16a0db7d 29 0 R >> @@ -262,7 +262,7 @@ endobj endobj 33 0 obj << -/Contents 152 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 153 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << /FormXob.ac4d2a97676ca8c002b2001987b87b9d 31 0 R >> @@ -279,7 +279,7 @@ endobj endobj 35 0 obj << -/Contents 153 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 154 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -289,7 +289,7 @@ endobj endobj 36 0 obj << -/Contents 154 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 155 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -299,7 +299,7 @@ endobj endobj 37 0 obj << -/Contents 155 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 156 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -314,7 +314,7 @@ endobj endobj 39 0 obj << -/Contents 156 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 157 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -324,7 +324,7 @@ endobj endobj 40 0 obj << -/Contents 157 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 158 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -334,7 +334,7 @@ endobj endobj 41 0 obj << -/Contents 158 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 159 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -344,7 +344,7 @@ endobj endobj 42 0 obj << -/Contents 159 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 160 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -354,7 +354,7 @@ endobj endobj 43 0 obj << -/Contents 160 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 161 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -364,7 +364,7 @@ endobj endobj 44 0 obj << -/Contents 161 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 162 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -374,7 +374,7 @@ endobj endobj 45 0 obj << -/Contents 162 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 163 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -384,7 +384,7 @@ endobj endobj 46 0 obj << -/Contents 163 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 164 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -394,19 +394,19 @@ endobj endobj 47 0 obj << -/A << -/S /URI /Type /Action /URI (mailto:russell@unturf.com) ->> /Border [ 0 0 0 ] /Rect [ 248.0736 422.6236 334.3536 434.6236 ] /Subtype /Link /Type /Annot +/Contents 165 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << +/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] +>> /Rotate 0 /Trans << + +>> + /Type /Page >> endobj 48 0 obj << -/Annots [ 47 0 R ] /Contents 164 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << -/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] ->> /Rotate 0 - /Trans << - ->> /Type /Page +/A << +/S /URI /Type /Action /URI (mailto:russell@unturf.com) +>> /Border [ 0 0 0 ] /Rect [ 248.0736 753.0236 334.3536 765.0236 ] /Subtype /Link /Type /Annot >> endobj 49 0 obj @@ -435,19 +435,19 @@ Gb"-VGBahP*ld_dH@X@.673m]5Z!>/OUajVKd+rl%FU.GOCIDSUkBirLgj0l#UggK9*dsQ$&!I6Uj!Oc endobj 52 0 obj << -/Contents 165 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Annots [ 48 0 R ] /Contents 166 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << /FormXob.02a72be19fedaa76bd1061921e7cc82b 51 0 R /FormXob.baaa2211732baa0f94f6912a5b035550 49 0 R >> ->> /Rotate 0 /Trans << +>> /Rotate 0 + /Trans << ->> - /Type /Page +>> /Type /Page >> endobj 53 0 obj << -/Contents 166 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 167 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -457,7 +457,7 @@ endobj endobj 54 0 obj << -/Contents 167 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 168 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -475,7 +475,7 @@ Gb",k#?V^BhM4rA',+)6h&$gSeal+> @@ -487,7 +487,7 @@ endobj endobj 57 0 obj << -/Contents 169 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 170 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -497,7 +497,7 @@ endobj endobj 58 0 obj << -/Contents 170 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 171 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -509,19 +509,19 @@ endobj << /A << /S /URI /Type /Action /URI (https://undefect.com/moad-cheat-sheet/) ->> /Border [ 0 0 0 ] /Rect [ 505.5536 449.8236 538.0932 461.8236 ] /Subtype /Link /Type /Annot +>> /Border [ 0 0 0 ] /Rect [ 505.5536 401.8236 538.0932 413.8236 ] /Subtype /Link /Type /Annot >> endobj 60 0 obj << /A << /S /URI /Type /Action /URI (https://undefect.com/moad-cheat-sheet/) ->> /Border [ 0 0 0 ] /Rect [ 57.02362 437.8236 115.9985 449.8236 ] /Subtype /Link /Type /Annot +>> /Border [ 0 0 0 ] /Rect [ 57.02362 389.8236 115.9985 401.8236 ] /Subtype /Link /Type /Annot >> endobj 61 0 obj << -/Annots [ 59 0 R 60 0 R ] /Contents 171 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Annots [ 59 0 R 60 0 R ] /Contents 172 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -531,7 +531,7 @@ endobj endobj 62 0 obj << -/Contents 172 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 173 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -555,7 +555,7 @@ endobj endobj 65 0 obj << -/Annots [ 63 0 R 64 0 R ] /Contents 173 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Annots [ 63 0 R 64 0 R ] /Contents 174 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -579,7 +579,7 @@ endobj endobj 68 0 obj << -/Annots [ 66 0 R 67 0 R ] /Contents 174 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Annots [ 66 0 R 67 0 R ] /Contents 175 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -605,9 +605,9 @@ Gb"0;0`_7S!5bE.WFlYNTE"rlzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz endobj 71 0 obj << -/Contents 175 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 176 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << -/FormXob.c9411fecc114c344e33ac82182b38f43 6 0 R /FormXob.fc331aff86ff817ecac4c4ce4b2ecd3a 69 0 R +/FormXob.abf5431e047a12a84b98349be6f1e444 6 0 R /FormXob.fc331aff86ff817ecac4c4ce4b2ecd3a 69 0 R >> >> /Rotate 0 /Trans << @@ -617,7 +617,7 @@ endobj endobj 72 0 obj << -/Contents 176 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 140 0 R /Resources << +/Contents 177 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 141 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << @@ -627,18 +627,18 @@ endobj endobj 73 0 obj << -/Outlines 75 0 R /PageLabels 177 0 R /PageMode /UseNone /Pages 140 0 R /Type /Catalog +/Outlines 75 0 R /PageLabels 178 0 R /PageMode /UseNone /Pages 141 0 R /Type /Catalog >> endobj 74 0 obj << -/Author () /CreationDate (D:20260421135917-04'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260421135917-04'00') /Producer (ReportLab PDF Library - \(opensource\)) +/Author () /CreationDate (D:20260423201822-04'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260423201822-04'00') /Producer (ReportLab PDF Library - \(opensource\)) /Subject (\(unspecified\)) /Title (lumbda.) /Trapped /False >> endobj 75 0 obj << -/Count 75 /First 76 0 R /Last 139 0 R /Type /Outlines +/Count 77 /First 76 0 R /Last 140 0 R /Type /Outlines >> endobj 76 0 obj @@ -872,116 +872,122 @@ endobj endobj 120 0 obj << -/Dest [ 46 0 R /XYZ 57.02362 277.4236 0 ] /Next 121 0 R /Parent 75 0 R /Prev 113 0 R /Title (9. Language Coverage) +/Count 1 /Dest [ 46 0 R /XYZ 57.02362 277.4236 0 ] /First 121 0 R /Last 121 0 R /Next 122 0 R /Parent 75 0 R + /Prev 113 0 R /Title (9. Language Coverage) >> endobj 121 0 obj << -/Dest [ 48 0 R /XYZ 57.02362 721.0236 0 ] /Next 122 0 R /Parent 75 0 R /Prev 120 0 R /Title (10. Relationship to Companion Papers) +/Dest [ 47 0 R /XYZ 57.02362 723.0236 0 ] /Parent 120 0 R /Title (9.1 Integer Square Root \(isqrt\)) >> endobj 122 0 obj << -/Count 7 /Dest [ 48 0 R /XYZ 57.02362 465.8236 0 ] /First 123 0 R /Last 129 0 R /Next 130 0 R /Parent 75 0 R - /Prev 121 0 R /Title (11. Four Implementation Tiers, One Language) +/Dest [ 47 0 R /XYZ 57.02362 358.6236 0 ] /Next 123 0 R /Parent 75 0 R /Prev 120 0 R /Title (10. Relationship to Companion Papers) >> endobj 123 0 obj << -/Dest [ 53 0 R /XYZ 57.02362 273.0236 0 ] /Next 124 0 R /Parent 122 0 R /Title (11.1 Test Coverage) +/Count 7 /Dest [ 47 0 R /XYZ 57.02362 103.4236 0 ] /First 124 0 R /Last 130 0 R /Next 131 0 R /Parent 75 0 R + /Prev 122 0 R /Title (11. Four Implementation Tiers, One Language) >> endobj 124 0 obj << -/Dest [ 54 0 R /XYZ 57.02362 765.0236 0 ] /Next 125 0 R /Parent 122 0 R /Prev 123 0 R /Title (11.2 File I/O Parity) +/Dest [ 53 0 R /XYZ 57.02362 205.0236 0 ] /Next 125 0 R /Parent 123 0 R /Title (11.1 Test Coverage) >> endobj 125 0 obj << -/Dest [ 54 0 R /XYZ 57.02362 449.8236 0 ] /Next 126 0 R /Parent 122 0 R /Prev 124 0 R /Title (11.3 Sockets: One HTTP Server, Three Runtimes) +/Dest [ 54 0 R /XYZ 57.02362 681.0236 0 ] /Next 126 0 R /Parent 123 0 R /Prev 124 0 R /Title (11.2 File I/O Parity) >> endobj 126 0 obj << -/Dest [ 56 0 R /XYZ 57.02362 484.6988 0 ] /Next 127 0 R /Parent 122 0 R /Prev 125 0 R /Title (11.4 S-expressions over Sockets: RPC, REPL, and Chains) +/Dest [ 54 0 R /XYZ 57.02362 365.8236 0 ] /Next 127 0 R /Parent 123 0 R /Prev 125 0 R /Title (11.3 Sockets: One HTTP Server, Three Runtimes) >> endobj 127 0 obj << -/Dest [ 57 0 R /XYZ 57.02362 645.0236 0 ] /Next 128 0 R /Parent 122 0 R /Prev 126 0 R /Title (11.5 Portal over HTTP: State Transfer Between Machines) +/Dest [ 56 0 R /XYZ 57.02362 412.6988 0 ] /Next 128 0 R /Parent 123 0 R /Prev 126 0 R /Title (11.4 S-expressions over Sockets: RPC, REPL, and Chains) >> endobj 128 0 obj << -/Dest [ 58 0 R /XYZ 57.02362 765.0236 0 ] /Next 129 0 R /Parent 122 0 R /Prev 127 0 R /Title (11.6 heap-snapshot: The Arena Escape Hatch) +/Dest [ 57 0 R /XYZ 57.02362 567.0236 0 ] /Next 129 0 R /Parent 123 0 R /Prev 127 0 R /Title (11.5 Portal over HTTP: State Transfer Between Machines) >> endobj 129 0 obj << -/Dest [ 58 0 R /XYZ 57.02362 414.2236 0 ] /Parent 122 0 R /Prev 128 0 R /Title (11.7 Static File Serving: Cache, Sendfile, and Adaptive Preload) +/Dest [ 58 0 R /XYZ 57.02362 723.0236 0 ] /Next 130 0 R /Parent 123 0 R /Prev 128 0 R /Title (11.6 heap-snapshot: The Arena Escape Hatch) >> endobj 130 0 obj << -/Count 3 /Dest [ 61 0 R /XYZ 57.02362 487.0236 0 ] /First 131 0 R /Last 133 0 R /Next 134 0 R /Parent 75 0 R - /Prev 122 0 R /Title (12. MOAD Audit: Fixing What We Built) +/Dest [ 58 0 R /XYZ 57.02362 372.2236 0 ] /Parent 123 0 R /Prev 129 0 R /Title (11.7 Static File Serving: Cache, Sendfile, and Adaptive Preload) >> endobj 131 0 obj << -/Dest [ 61 0 R /XYZ 57.02362 191.8236 0 ] /Next 132 0 R /Parent 130 0 R /Title (12.1 MOAD-0001: The Sedimentary Defect in Our Own Code) +/Count 3 /Dest [ 61 0 R /XYZ 57.02362 439.0236 0 ] /First 132 0 R /Last 134 0 R /Next 135 0 R /Parent 75 0 R + /Prev 123 0 R /Title (12. MOAD Audit: Fixing What We Built) >> endobj 132 0 obj << -/Dest [ 62 0 R /XYZ 57.02362 273.0236 0 ] /Next 133 0 R /Parent 130 0 R /Prev 131 0 R /Title (12.2 MOAD-0002: The Intertangle in Our Own Design) +/Dest [ 61 0 R /XYZ 57.02362 143.8236 0 ] /Next 133 0 R /Parent 131 0 R /Title (12.1 MOAD-0001: The Sedimentary Defect in Our Own Code) >> endobj 133 0 obj << -/Dest [ 65 0 R /XYZ 57.02362 711.0236 0 ] /Parent 130 0 R /Prev 132 0 R /Title (12.3 Our Shared Infrastructure) +/Dest [ 62 0 R /XYZ 57.02362 244.2236 0 ] /Next 134 0 R /Parent 131 0 R /Prev 132 0 R /Title (12.2 MOAD-0002: The Intertangle in Our Own Design) >> endobj 134 0 obj << -/Dest [ 65 0 R /XYZ 57.02362 513.8236 0 ] /Next 135 0 R /Parent 75 0 R /Prev 130 0 R /Title (13. Future Work) +/Dest [ 65 0 R /XYZ 57.02362 711.0236 0 ] /Parent 131 0 R /Prev 133 0 R /Title (12.3 Our Shared Infrastructure) >> endobj 135 0 obj << -/Dest [ 65 0 R /XYZ 57.02362 162.6236 0 ] /Next 136 0 R /Parent 75 0 R /Prev 134 0 R /Title (14. The Defect in the Model) +/Dest [ 65 0 R /XYZ 57.02362 513.8236 0 ] /Next 136 0 R /Parent 75 0 R /Prev 131 0 R /Title (13. Future Work) >> endobj 136 0 obj << -/Dest [ 68 0 R /XYZ 57.02362 169.0236 0 ] /Next 137 0 R /Parent 75 0 R /Prev 135 0 R /Title (Acknowledgments) +/Dest [ 65 0 R /XYZ 57.02362 162.6236 0 ] /Next 137 0 R /Parent 75 0 R /Prev 135 0 R /Title (14. The Defect in the Model) >> endobj 137 0 obj << -/Dest [ 71 0 R /XYZ 57.02362 765.0236 0 ] /Next 138 0 R /Parent 75 0 R /Prev 136 0 R /Title (Citation) +/Dest [ 68 0 R /XYZ 57.02362 169.0236 0 ] /Next 138 0 R /Parent 75 0 R /Prev 136 0 R /Title (Acknowledgments) >> endobj 138 0 obj << -/Dest [ 71 0 R /XYZ 57.02362 675.8236 0 ] /Next 139 0 R /Parent 75 0 R /Prev 137 0 R /Title (References) +/Dest [ 71 0 R /XYZ 57.02362 765.0236 0 ] /Next 139 0 R /Parent 75 0 R /Prev 137 0 R /Title (Citation) >> endobj 139 0 obj << -/Dest [ 71 0 R /XYZ 57.02362 586.6236 0 ] /Parent 75 0 R /Prev 138 0 R /Title (License) +/Dest [ 71 0 R /XYZ 57.02362 675.8236 0 ] /Next 140 0 R /Parent 75 0 R /Prev 138 0 R /Title (References) >> endobj 140 0 obj << -/Count 36 /Kids [ 12 0 R 14 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 28 0 R - 30 0 R 33 0 R 35 0 R 36 0 R 37 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R - 44 0 R 45 0 R 46 0 R 48 0 R 52 0 R 53 0 R 54 0 R 56 0 R 57 0 R 58 0 R - 61 0 R 62 0 R 65 0 R 68 0 R 71 0 R 72 0 R ] /Type /Pages +/Dest [ 71 0 R /XYZ 57.02362 586.6236 0 ] /Parent 75 0 R /Prev 139 0 R /Title (License) >> endobj 141 0 obj << +/Count 36 /Kids [ 12 0 R 14 0 R 17 0 R 18 0 R 19 0 R 20 0 R 21 0 R 22 0 R 23 0 R 28 0 R + 30 0 R 33 0 R 35 0 R 36 0 R 37 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R + 44 0 R 45 0 R 46 0 R 47 0 R 52 0 R 53 0 R 54 0 R 56 0 R 57 0 R 58 0 R + 61 0 R 62 0 R 65 0 R 68 0 R 71 0 R 72 0 R ] /Type /Pages +>> +endobj +142 0 obj +<< /Length 3239 >> stream @@ -1027,7 +1033,7 @@ q 1 0 0 1 142.0762 3 cm q 197.0759 0 0 197.0759 0 0 cm -/FormXob.c9411fecc114c344e33ac82182b38f43 Do +/FormXob.abf5431e047a12a84b98349be6f1e444 Do Q Q q @@ -1096,7 +1102,7 @@ Q endstream endobj -142 0 obj +143 0 obj << /Length 8069 >> @@ -1266,7 +1272,7 @@ Q endstream endobj -143 0 obj +144 0 obj << /Length 3406 >> @@ -1341,7 +1347,7 @@ Q endstream endobj -144 0 obj +145 0 obj << /Length 7835 >> @@ -1637,7 +1643,7 @@ Q endstream endobj -145 0 obj +146 0 obj << /Length 7764 >> @@ -2045,7 +2051,7 @@ Q endstream endobj -146 0 obj +147 0 obj << /Length 8455 >> @@ -2515,7 +2521,7 @@ Q endstream endobj -147 0 obj +148 0 obj << /Length 9830 >> @@ -3001,7 +3007,7 @@ Q endstream endobj -148 0 obj +149 0 obj << /Length 12397 >> @@ -3669,7 +3675,7 @@ Q endstream endobj -149 0 obj +150 0 obj << /Length 11577 >> @@ -4276,7 +4282,7 @@ Q endstream endobj -150 0 obj +151 0 obj << /Length 8677 >> @@ -4533,7 +4539,7 @@ Q endstream endobj -151 0 obj +152 0 obj << /Length 8091 >> @@ -4773,7 +4779,7 @@ Q endstream endobj -152 0 obj +153 0 obj << /Length 11242 >> @@ -5207,7 +5213,7 @@ Q endstream endobj -153 0 obj +154 0 obj << /Length 11975 >> @@ -5738,7 +5744,7 @@ Q endstream endobj -154 0 obj +155 0 obj << /Length 11585 >> @@ -6236,7 +6242,7 @@ Q endstream endobj -155 0 obj +156 0 obj << /Length 7982 >> @@ -6352,7 +6358,7 @@ Q endstream endobj -156 0 obj +157 0 obj << /Length 11081 >> @@ -6888,7 +6894,7 @@ Q endstream endobj -157 0 obj +158 0 obj << /Length 7418 >> @@ -7161,7 +7167,7 @@ Q endstream endobj -158 0 obj +159 0 obj << /Length 8366 >> @@ -7306,7 +7312,7 @@ Q endstream endobj -159 0 obj +160 0 obj << /Length 14341 >> @@ -7717,7 +7723,7 @@ Q endstream endobj -160 0 obj +161 0 obj << /Length 8460 >> @@ -8105,7 +8111,7 @@ Q endstream endobj -161 0 obj +162 0 obj << /Length 8962 >> @@ -8510,7 +8516,7 @@ Q endstream endobj -162 0 obj +163 0 obj << /Length 9155 >> @@ -8775,7 +8781,7 @@ Q endstream endobj -163 0 obj +164 0 obj << /Length 10338 >> @@ -9062,9 +9068,9 @@ Q endstream endobj -164 0 obj +165 0 obj << -/Length 5017 +/Length 7728 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET @@ -9075,23 +9081,79 @@ BT 1 0 0 1 0 14 Tm 4.238031 Tw 12 TL /F1 10 Tf 0 0 0 rg (error handling, portal Q Q q -1 0 0 1 57.02362 701.8236 cm +1 0 0 1 57.02362 709.8236 cm +q +BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (9.1 Integer Square Root \() Tj /F5 11 Tf 0 0 0 rg (isqrt) Tj /F2 11 Tf .133333 .133333 .133333 rg (\)) Tj T* ET +Q +Q +q +1 0 0 1 57.02362 653.8236 cm +q +BT 1 0 0 1 0 38 Tm .712417 Tw 12 TL /F5 10 Tf 0 0 0 rg (sqrt) Tj /F1 10 Tf ( returns an inexact real. That is the right answer when the caller wants a distance or a norm, and the) Tj T* 0 Tw 1.139272 Tw (wrong answer when the caller wants a count: bucket indices, loop bounds, coordinates on a grid, bignum) Tj T* 0 Tw .078241 Tw (primality witnesses. Float ) Tj /F5 10 Tf (sqrt) Tj /F1 10 Tf ( drifts with FPU mode, with the ) Tj /F5 10 Tf (libm) Tj /F1 10 Tf ( in play, and across platforms \227 none of) Tj T* 0 Tw (which a portal should let into a replay trace.) Tj T* ET +Q +Q +q +1 0 0 1 57.02362 611.8236 cm +q +BT 1 0 0 1 0 26 Tm 2.533196 Tw 12 TL /F5 10 Tf 0 0 0 rg (\(isqrt) Tj ( ) Tj (n\)) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (floor\(sqrt\(n\)\)) Tj /F1 10 Tf ( ships in all three implementations. Contract matches Python 3.8+) Tj T* 0 Tw 3.752835 Tw /F5 10 Tf (math.isqrt) Tj /F1 10 Tf ( and the integer half of R7RS ) Tj /F5 10 Tf (exact-integer-sqrt) Tj /F1 10 Tf (: integer-in, integer-out, negative) Tj T* 0 Tw (argument raises. No floats anywhere in the pipeline.) Tj T* ET +Q +Q +q +1 0 0 1 57.02362 542.6236 cm +q +q +1 0 0 1 0 0 cm +q +1 0 0 1 6.6 6.6 cm +q +.662745 .662745 .662745 RG +.5 w +.960784 .960784 .960784 rg +n -6 -6 480.0283 60 re B* +Q +q +BT 1 0 0 1 0 40 Tm 9.6 TL /F5 8 Tf 0 0 0 rg (\(isqrt 0\) ; =) Tj (>) Tj ( 0) Tj T* (\(isqrt 16\) ; =) Tj (>) Tj ( 4 ; exact) Tj T* (\(isqrt 17\) ; =) Tj (>) Tj ( 4 ; floor, not round) Tj T* (\(isqrt 1000000\) ; =) Tj (>) Tj ( 1000) Tj T* (\(isqrt -1\) ; error: negative argument) Tj T* ET +Q +Q +Q +Q +Q +q +1 0 0 1 57.02362 474.6236 cm +q +BT 1 0 0 1 0 50 Tm -0.038471 Tw 12 TL /F3 10 Tf 0 0 0 rg (Algorithm.) Tj /F1 10 Tf ( Bit-by-bit digit-recurrence \(Wikipedia "Methods of computing square roots"\). O\(log n\) shifts, adds,) Tj T* 0 Tw 1.488647 Tw (and compares; no multiplies, no divides, no FPU. The C and asm implementations share the same loop) Tj T* 0 Tw 1.015596 Tw (skeleton \227 the asm version \() Tj /F5 10 Tf (bi_isqrt) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (asm/lumbda.s) Tj /F1 10 Tf (\) runs it in three integer registers \() Tj /F5 10 Tf (%r8) Tj /F1 10 Tf ( radicand,) Tj T* 0 Tw 1.86131 Tw /F5 10 Tf (%r9) Tj /F1 10 Tf ( bit, ) Tj /F5 10 Tf (%r10) Tj /F1 10 Tf ( result\) with no memory traffic per iteration. Python delegates to CPython's ) Tj /F5 10 Tf (math.isqrt) Tj /F1 10 Tf (,) Tj T* 0 Tw (which uses Karatsuba-square-root for bignums.) Tj T* ET +Q +Q +q +1 0 0 1 57.02362 420.6236 cm +q +BT 1 0 0 1 0 38 Tm 3.483719 Tw 12 TL /F3 10 Tf 0 0 0 rg (Domain limits.) Tj /F1 10 Tf ( Python: unbounded \227 works on arbitrary-precision ) Tj /F5 10 Tf (int) Tj /F1 10 Tf (. asm: 61-bit \(three tag bits) Tj T* 0 Tw 2.529272 Tw (consumed at the bottom of the word\). C: 48-bit \(NaN-boxed doubles carry the integer payload in the) Tj T* 0 Tw .159314 Tw (mantissa\). Portal round-trips remain bit-identical within the smaller of the two tiers on either end; a value that) Tj T* 0 Tw (fits in the C tier's 48-bit window survives every Python ) Tj /F6 10 Tf 12 TL (\253) Tj /F1 10 Tf 12 TL ( C ) Tj /F6 10 Tf 12 TL (\253) Tj /F1 10 Tf 12 TL ( asm crossing in \2477.2's 3\3273 matrix.) Tj T* ET +Q +Q +q +1 0 0 1 57.02362 378.6236 cm +q +BT 1 0 0 1 0 26 Tm .745917 Tw 12 TL /F3 10 Tf 0 0 0 rg (MOAD-0001 note.) Tj /F1 10 Tf ( Each call is O\(log n\) in the value, not in the heap or the symbol table. No hidden linear) Tj T* 0 Tw 2.156019 Tw (scan, no per-call allocation in C or asm. Safe to invoke inside a tight loop without inflating the overall) Tj T* 0 Tw (complexity class.) Tj T* ET +Q +Q +q +1 0 0 1 57.02362 339.4236 cm q BT 1 0 0 1 0 3.2 Tm 117.2782 0 Td 19.2 TL /F2 16 Tf .133333 .133333 .133333 rg (10. Relationship to Companion Papers) Tj T* -117.2782 0 Td ET Q Q q -1 0 0 1 57.02362 683.8236 cm +1 0 0 1 57.02362 321.4236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Lumbda forms one piece of a larger permacomputer machine learning stack:) Tj T* ET Q Q q -1 0 0 1 57.02362 677.8236 cm +1 0 0 1 57.02362 315.4236 cm Q q -1 0 0 1 57.02362 539.8236 cm +1 0 0 1 57.02362 177.4236 cm q 1 1 1 rg n 0 138 481.2283 -18 re f* @@ -9228,25 +9290,34 @@ Q Q Q q -1 0 0 1 57.02362 539.8236 cm +1 0 0 1 57.02362 177.4236 cm Q q -1 0 0 1 57.02362 485.8236 cm +1 0 0 1 57.02362 123.4236 cm q BT 1 0 0 1 0 38 Tm 1.738453 Tw 12 TL /F1 10 Tf 0 0 0 rg (Lumbda provides the runtime layer: a language that can checkpoint its own execution, migrate between) Tj T* 0 Tw 3.051529 Tw (machines, & resume from serialized state. The portal system enables distributed computation across) Tj T* 0 Tw 1.058196 Tw (permacomputer nodes. Categorization & feedback activities could run inside Lumbda's VM, with ) Tj /F5 10 Tf (call/cc) Tj /F1 10 Tf T* 0 Tw (providing the state machine transitions & portal providing persistence.) Tj T* ET Q Q q -1 0 0 1 57.02362 446.6236 cm +1 0 0 1 57.02362 84.22362 cm q BT 1 0 0 1 0 3.2 Tm 91.52617 0 Td 19.2 TL /F2 16 Tf .133333 .133333 .133333 rg (11. Four Implementation Tiers, One Language) Tj T* -91.52617 0 Td ET Q Q q -1 0 0 1 57.02362 434.6236 cm +1 0 0 1 57.02362 72.22362 cm Q + +endstream +endobj +166 0 obj +<< +/Length 2289 +>> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 422.6236 cm +1 0 0 1 57.02362 753.0236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -9262,28 +9333,19 @@ Q Q Q q -1 0 0 1 57.02362 422.6236 cm +1 0 0 1 57.02362 753.0236 cm Q q -1 0 0 1 57.02362 344.6236 cm +1 0 0 1 57.02362 675.0236 cm q BT 1 0 0 1 0 62 Tm .778726 Tw 12 TL /F1 10 Tf 0 0 0 rg (Lumbda ships as four independently built tiers: a Python bytecode VM, a C tree-walker, a C bytecode VM,) Tj T* 0 Tw 2.18402 Tw (and a C x86_64 JIT \(the last three packaged in one binary, selectable by flag\), plus a pure-assembly) Tj T* 0 Tw .931492 Tw (interpreter. Each tier is MOAD-isolated from the others \227 a defect surfaced in one is fixed in that tier, not) Tj T* 0 Tw 2.098556 Tw (patched across shared infrastructure. All four run the same ) Tj /F5 10 Tf (.lsp) Tj /F1 10 Tf ( source files and exchange the same) Tj T* 0 Tw 2.266213 Tw (S-expression portal format; \24711.3-\24711.5 demonstrate this end-to-end across sockets, relays, and HTTP) Tj T* 0 Tw (portal transfers.) Tj T* ET Q Q q -1 0 0 1 57.02362 336.6236 cm +1 0 0 1 57.02362 667.0236 cm Q - -endstream -endobj -165 0 obj -<< -/Length 1782 ->> -stream -1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 263.1875 cm +1 0 0 1 57.02362 165.1875 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -9306,24 +9368,42 @@ Q Q Q q -1 0 0 1 57.02362 255.1875 cm +1 0 0 1 57.02362 157.1875 cm Q q -1 0 0 1 57.02362 247.1875 cm +1 0 0 1 57.02362 149.1875 cm Q q -1 0 0 1 57.02362 111.9891 cm +1 0 0 1 57.02362 67.98905 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET q -1 0 0 1 52.92283 57 cm +1 0 0 1 52.92283 3 cm q 375.3827 0 0 75.19848 0 0 cm /FormXob.02a72be19fedaa76bd1061921e7cc82b Do Q Q q +Q +Q +Q + +endstream +endobj +167 0 obj +<< +/Length 13436 +>> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 57.02362 711.0236 cm +q +0 0 0 rg +BT /F1 10 Tf 12 TL ET +q 1 0 0 1 6 3 cm q 0 0 0 rg @@ -9335,28 +9415,19 @@ Q Q Q q -1 0 0 1 57.02362 103.9891 cm +1 0 0 1 57.02362 703.0236 cm Q - -endstream -endobj -166 0 obj -<< -/Length 13406 ->> -stream -1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 729.0236 cm +1 0 0 1 57.02362 661.0236 cm q BT 1 0 0 1 0 26 Tm -0.132261 Tw 12 TL /F1 10 Tf 0 0 0 rg (Lumbda implements R7RS Scheme in three implementations sharing the same ) Tj /F5 10 Tf (.lsp) Tj /F1 10 Tf ( test files. The language) Tj T* 0 Tw .58213 Tw (is Scheme \(a dialect of Lisp, designed 1975\). The project name plays on Common Lisp \227 this is decidedly) Tj T* 0 Tw (uncommon.) Tj T* ET Q Q q -1 0 0 1 57.02362 723.0236 cm +1 0 0 1 57.02362 655.0236 cm Q q -1 0 0 1 57.02362 603.0236 cm +1 0 0 1 57.02362 535.0236 cm q 1 1 1 rg n 0 120 481.2283 -30 re f* @@ -9692,52 +9763,52 @@ Q Q Q q -1 0 0 1 57.02362 603.0236 cm +1 0 0 1 57.02362 535.0236 cm Q q -1 0 0 1 57.02362 573.0236 cm +1 0 0 1 57.02362 505.0236 cm q BT 1 0 0 1 0 14 Tm 1.743453 Tw 12 TL /F1 10 Tf 0 0 0 rg (All C & Python benchmarks measured in-process \(no startup overhead\). Assembly times \(\206\) include full) Tj T* 0 Tw (process lifetime: startup + tokenizer + parser + eval. "\227" = not applicable / interpreted.) Tj T* ET Q Q q -1 0 0 1 57.02362 495.0236 cm +1 0 0 1 57.02362 427.0236 cm q BT 1 0 0 1 0 62 Tm .118138 Tw 12 TL /F3 10 Tf 0 0 0 rg (The JIT runs Scheme faster than CPython runs Python.) Tj /F1 10 Tf ( ) Tj /F5 10 Tf (ack\(3,4\)) Tj /F1 10 Tf ( completes in 0.19 ms \(JIT\) vs 1.3 ms) Tj T* 0 Tw .050491 Tw (\(CPython\) \227 7\327 faster. ) Tj /F5 10 Tf (sum-to\(50000\)) Tj /F1 10 Tf ( completes in 0.55 ms \(JIT\) vs 5.5 ms \(CPython\) \227 10\327 faster. The) Tj T* 0 Tw .368556 Tw (JIT compiles Scheme AST directly to x86_64 machine code via ) Tj /F5 10 Tf (mmap\(PROT_EXEC\)) Tj /F1 10 Tf ( & raw byte emission. It) Tj T* 0 Tw 2.31631 Tw (handles ) Tj /F5 10 Tf (if) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (cond) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (and) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (or) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (let) Tj /F1 10 Tf (, named-let loops \(native ) Tj /F5 10 Tf (jmp) Tj /F1 10 Tf ( \227 zero call overhead\), ) Tj /F5 10 Tf (car) Tj /F1 10 Tf (/) Tj /F5 10 Tf (cdr) Tj /F1 10 Tf (/) Tj /F5 10 Tf (cons) Tj /F1 10 Tf (,) Tj T* 0 Tw .786027 Tw (arithmetic, comparisons, & self-recursive calls. Functions that use ) Tj /F5 10 Tf (call/cc) Tj /F1 10 Tf (, macros, or complex forms fall) Tj T* 0 Tw (back to the interpreter.) Tj T* ET Q Q q -1 0 0 1 57.02362 345.0236 cm +1 0 0 1 57.02362 277.0236 cm q BT 1 0 0 1 0 134 Tm .274168 Tw 12 TL /F3 10 Tf 0 0 0 rg (The assembly implementation proves the language runs on bare metal.) Tj /F1 10 Tf ( 6,645 lines of ) Tj /F3 10 Tf (GNU assembler) Tj T* 0 Tw .321147 Tw (\(GAS, AT) Tj (&) Tj (T syntax\)) Tj /F1 10 Tf (, assembled with ) Tj /F5 10 Tf (as) Tj /F1 10 Tf ( and linked with ) Tj /F5 10 Tf (ld) Tj /F1 10 Tf ( from GNU binutils; ~22 KB stripped bump-only) Tj T* 0 Tw .295257 Tw (binary, ~25 KB stripped under the optional ) Tj /F5 10 Tf (GC_NAIVE) Tj /F1 10 Tf ( assemble flag. Zero external dependencies. Fourteen) Tj T* 0 Tw 1.588196 Tw (Linux syscalls \() Tj /F5 10 Tf (read) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (write) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (open) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (close) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (lseek) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (mmap) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (munmap) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (socket) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (connect) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (accept) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (bind) Tj /F1 10 Tf (,) Tj T* 0 Tw 12.76076 Tw /F5 10 Tf (listen) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (clock_gettime) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (exit) Tj /F1 10 Tf (\) \227 no libc, no stdlib. A bump allocator with) Tj T* 0 Tw 1.343543 Tw /F5 10 Tf (heap-snapshot) Tj /F1 10 Tf (/) Tj /F5 10 Tf (heap-restore) Tj /F1 10 Tf ( arena primitives, tag-in-low-3-bits values, ) Tj /F3 10 Tf (95+ builtins) Tj /F1 10 Tf ( \(including ) Tj /F5 10 Tf (load) Tj /F1 10 Tf (,) Tj T* 0 Tw 1.562038 Tw (ports, ) Tj /F5 10 Tf (write-file) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (file-) Tj (>) Tj (string) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (portal-save) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (portal-resume) Tj /F1 10 Tf (, the six ) Tj /F5 10 Tf (tcp-*) Tj /F1 10 Tf ( socket primitives,) Tj T* 0 Tw 7.344724 Tw /F5 10 Tf (read-from-string) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (eval) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (symbol-) Tj (>) Tj (string) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (current-time-ms) Tj /F1 10 Tf (, native ) Tj /F5 10 Tf (hash-table-*) Tj /F1 10 Tf ( and) Tj T* 0 Tw .773223 Tw /F5 10 Tf (hash-set-*) Tj /F1 10 Tf (, plus ) Tj /F5 10 Tf (with-arena) Tj /F1 10 Tf ( / ) Tj /F5 10 Tf (gc-collect) Tj /F1 10 Tf ( / ) Tj /F5 10 Tf (gc-stats) Tj /F1 10 Tf ( / ) Tj /F5 10 Tf (arena-stats) Tj /F1 10 Tf ( in the GC build\), & TCO via) Tj T* 0 Tw 1.293071 Tw /F5 10 Tf (jmp) Tj /F1 10 Tf (. It runs ) Tj /F5 10 Tf (\(ack) Tj ( ) Tj (3) Tj ( ) Tj (4\)) Tj ( ) Tj (=) Tj ( ) Tj (125) Tj /F1 10 Tf ( & ) Tj /F5 10 Tf (\(fib) Tj ( ) Tj (35\)) Tj ( ) Tj (=) Tj ( ) Tj (9227465) Tj /F1 10 Tf ( correctly, serves HTTP at ) Tj /F3 10 Tf (2,994 req/s) Tj /F1 10 Tf (, and) Tj T* 0 Tw 1.62589 Tw (survives indefinitely with flat O\(1\) memory via either the snapshot/restore arena in a per-request loop ) Tj /F4 10 Tf (or) Tj /F1 10 Tf T* 0 Tw /F5 10 Tf (\(with-arena) Tj ( ) Tj (thunk\)) Tj /F1 10 Tf ( under the collecting build \(see \2476.6\).) Tj T* ET Q Q q -1 0 0 1 57.02362 291.0236 cm +1 0 0 1 57.02362 223.0236 cm q BT 1 0 0 1 0 38 Tm 2.546213 Tw 12 TL /F3 10 Tf 0 0 0 rg (The bytecode VM delivers 7--19\327 speedup over tree-walking.) Tj /F1 10 Tf ( The Python implementation compiles) Tj T* 0 Tw .411147 Tw (Scheme to 40 opcodes \(plus 20 specialized & 5 superinstructions\), executed on an explicit frame stack with) Tj T* 0 Tw 1.206213 Tw (inline caching, constant folding, & peephole optimization. Full first-class continuations \(multi-shot, upward\)) Tj T* 0 Tw (enable generators, coroutines, & machine state migration via portal.) Tj T* ET Q Q q -1 0 0 1 57.02362 259.8236 cm +1 0 0 1 57.02362 191.8236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (11.1 Test Coverage) Tj T* ET Q Q q -1 0 0 1 57.02362 239.8236 cm +1 0 0 1 57.02362 171.8236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (980 verified assertions) Tj /F1 10 Tf ( across all implementations, all green under ) Tj /F5 10 Tf (make) Tj ( ) Tj (test-all) Tj /F1 10 Tf (:) Tj T* ET Q Q q -1 0 0 1 57.02362 233.8236 cm +1 0 0 1 57.02362 165.8236 cm Q q -1 0 0 1 57.02362 233.8236 cm +1 0 0 1 57.02362 165.8236 cm Q q -1 0 0 1 57.02362 221.8236 cm +1 0 0 1 57.02362 153.8236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -9759,10 +9830,10 @@ Q Q Q q -1 0 0 1 57.02362 215.8236 cm +1 0 0 1 57.02362 147.8236 cm Q q -1 0 0 1 57.02362 203.8236 cm +1 0 0 1 57.02362 135.8236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -9784,10 +9855,10 @@ Q Q Q q -1 0 0 1 57.02362 197.8236 cm +1 0 0 1 57.02362 129.8236 cm Q q -1 0 0 1 57.02362 173.8236 cm +1 0 0 1 57.02362 105.8236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -9809,10 +9880,10 @@ Q Q Q q -1 0 0 1 57.02362 167.8236 cm +1 0 0 1 57.02362 99.82362 cm Q q -1 0 0 1 57.02362 155.8236 cm +1 0 0 1 57.02362 87.82362 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -9834,47 +9905,47 @@ Q Q Q q -1 0 0 1 57.02362 137.8236 cm +1 0 0 1 57.02362 69.82362 cm Q + +endstream +endobj +168 0 obj +<< +/Length 15434 +>> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 95.82362 cm +1 0 0 1 57.02362 729.0236 cm q BT 1 0 0 1 0 26 Tm .98631 Tw 12 TL /F1 10 Tf 0 0 0 rg (The shared functional suite matters: it runs byte-identical Scheme source through two different runtimes &) Tj T* 0 Tw .353432 Tw (compares output. Python & C agree 189 times per run. When they disagree, that tells us something specific) Tj T* 0 Tw (& actionable.) Tj T* ET Q Q q -1 0 0 1 57.02362 65.82362 cm +1 0 0 1 57.02362 699.0236 cm q BT 1 0 0 1 0 14 Tm 3.001043 Tw 12 TL /F1 10 Tf 0 0 0 rg (Cross-implementation portal exchange is verified separately: ) Tj /F5 10 Tf (tests/portal-cross-test.sh) Tj /F1 10 Tf ( runs 9) Tj T* 0 Tw (producer\327consumer combinations. All 9 green.) Tj T* ET Q Q - -endstream -endobj -167 0 obj -<< -/Length 16147 ->> -stream -1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 751.8236 cm +1 0 0 1 57.02362 667.8236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (11.2 File I/O Parity) Tj T* ET Q Q q -1 0 0 1 57.02362 719.8236 cm +1 0 0 1 57.02362 635.8236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .155596 Tw (All three implementations share the same minimal file I/O vocabulary \227 discovered necessary while building) Tj T* 0 Tw (the cross-impl portal:) Tj T* ET Q Q q -1 0 0 1 57.02362 713.8236 cm +1 0 0 1 57.02362 629.8236 cm Q q -1 0 0 1 57.02362 533.8236 cm +1 0 0 1 57.02362 449.8236 cm q 1 1 1 rg n 0 180 481.2283 -18 re f* @@ -10267,32 +10338,32 @@ Q Q Q q -1 0 0 1 57.02362 533.8236 cm +1 0 0 1 57.02362 449.8236 cm Q q -1 0 0 1 57.02362 467.8236 cm +1 0 0 1 57.02362 383.8236 cm q BT 1 0 0 1 0 50 Tm .254609 Tw 12 TL /F1 10 Tf 0 0 0 rg (The asm port representation deserves a note. Because all three tag bits are consumed by the existing value) Tj T* 0 Tw 4.102038 Tw (types \(int/pair/sym/closure/builtin/special/string/vector\), we encode ports as ) Tj /F5 10 Tf (SPECIAL) Tj /F1 10 Tf ( values ) Tj /F6 10 Tf 12 TL (\263) Tj /F1 10 Tf 12 TL ( 1000:) Tj T* 0 Tw 8.520835 Tw /F5 10 Tf (port_val) Tj ( ) Tj (=) Tj ( ) Tj (\(\(PORT_SPECIAL_BASE) Tj ( ) Tj (+) Tj ( ) Tj (fd\)) Tj ( ) Tj (<) Tj (<) Tj ( ) Tj (3\)) Tj ( ) Tj (|) Tj ( ) Tj (TAG_SPECIAL) Tj /F1 10 Tf (. Extraction is) Tj T* 0 Tw .162256 Tw /F5 10 Tf (fd) Tj ( ) Tj (=) Tj ( ) Tj (\(val) Tj ( ) Tj (>) Tj (>) Tj ( ) Tj (3\)) Tj ( ) Tj (-) Tj ( ) Tj (PORT_SPECIAL_BASE) Tj /F1 10 Tf (. ) Tj /F5 10 Tf (port?) Tj /F1 10 Tf ( is a range check. No tag expansion, no heap object,) Tj T* 0 Tw (no allocator pressure \227 the port is the file descriptor, wrapped.) Tj T* ET Q Q q -1 0 0 1 57.02362 436.6236 cm +1 0 0 1 57.02362 352.6236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (11.3 Sockets: One HTTP Server, Three Runtimes) Tj T* ET Q Q q -1 0 0 1 57.02362 416.6236 cm +1 0 0 1 57.02362 332.6236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Six primitives extend the file-I/O vocabulary to TCP:) Tj T* ET Q Q q -1 0 0 1 57.02362 410.6236 cm +1 0 0 1 57.02362 326.6236 cm Q q -1 0 0 1 57.02362 272.6236 cm +1 0 0 1 57.02362 188.6236 cm q 1 1 1 rg n 0 138 481.2283 -18 re f* @@ -10574,22 +10645,22 @@ Q Q Q q -1 0 0 1 57.02362 272.6236 cm +1 0 0 1 57.02362 188.6236 cm Q q -1 0 0 1 57.02362 230.6236 cm +1 0 0 1 57.02362 146.6236 cm q BT 1 0 0 1 0 26 Tm .215176 Tw 12 TL /F1 10 Tf 0 0 0 rg (Sockets share the same port representation as files \227 in asm the fd is packed into ) Tj /F5 10 Tf (SPECIAL) Tj /F1 10 Tf ( values ) Tj /F6 10 Tf 12 TL (\263) Tj /F1 10 Tf 12 TL ( 1000,) Tj T* 0 Tw .794123 Tw (in Python + C the fd lives inside an existing ULPort struct. ) Tj /F5 10 Tf (read) Tj /F1 10 Tf (/) Tj /F5 10 Tf (write) Tj /F1 10 Tf ( unify because to Linux a socket is) Tj T* 0 Tw (just an fd.) Tj T* ET Q Q q -1 0 0 1 57.02362 200.6236 cm +1 0 0 1 57.02362 116.6236 cm q BT 1 0 0 1 0 14 Tm .886796 Tw 12 TL /F5 10 Tf 0 0 0 rg (examples/http-server.lsp) Tj /F1 10 Tf ( is a 90-line HTTP/1.0 server. It parses a request line, dispatches by path,) Tj T* 0 Tw (and returns 200/404 with Content-Length. The same file runs unmodified in all three impls:) Tj T* ET Q Q q -1 0 0 1 57.02362 150.6236 cm +1 0 0 1 57.02362 66.62362 cm q q 1 0 0 1 0 0 cm @@ -10608,77 +10679,60 @@ Q Q Q Q + +endstream +endobj +169 0 obj +<< +/Length 9729 +>> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 94.62362 cm +1 0 0 1 57.02362 717.0236 cm q BT 1 0 0 1 0 38 Tm -0.093471 Tw 12 TL /F1 10 Tf 0 0 0 rg (The companion ) Tj /F5 10 Tf (examples/http-client-bench.lsp) Tj /F1 10 Tf ( is a 45-line load generator using only the six ) Tj /F5 10 Tf (tcp-*) Tj /F1 10 Tf T* 0 Tw 2.952577 Tw (primitives plus ) Tj /F5 10 Tf (current-time-ms) Tj /F1 10 Tf (. In-process client eliminates the ~2 ms/request fork overhead that) Tj T* 0 Tw 1.553486 Tw (curl-based benchmarks suffer, so real server throughput shows through. ) Tj /F3 10 Tf (Reproduce:) Tj /F1 10 Tf ( ) Tj /F5 10 Tf (make) Tj ( ) Tj (bench-web) Tj /F1 10 Tf T* 0 Tw (\(source: ) Tj /F5 10 Tf (tests/web-benchmark.sh) Tj /F1 10 Tf (\).) Tj T* ET Q Q q -1 0 0 1 57.02362 88.62362 cm +1 0 0 1 57.02362 711.0236 cm Q q -1 0 0 1 57.02362 70.62362 cm +1 0 0 1 57.02362 621.0236 cm q 1 1 1 rg +n 0 90 481.2283 -18 re f* +.878431 .878431 .878431 rg +n 0 72 481.2283 -18 re f* +1 1 1 rg +n 0 54 481.2283 -18 re f* +.878431 .878431 .878431 rg +n 0 36 481.2283 -18 re f* +1 1 1 rg n 0 18 481.2283 -18 re f* 0 0 0 rg BT /F3 10 Tf 12 TL ET q -1 0 0 1 6 3 cm +1 0 0 1 6 75 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 111.934 0 Td (Pair) Tj T* -111.934 0 Td ET Q Q q -1 0 0 1 260.7679 3 cm +1 0 0 1 260.7679 75 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 18.3801 0 Td (Requests/sec) Tj T* -18.3801 0 Td ET Q Q q -1 0 0 1 373.9981 3 cm +1 0 0 1 373.9981 75 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 18.3801 0 Td (vs curl bench) Tj T* -18.3801 0 Td ET Q Q -q -1 J -1 j -0 0 0 RG -.25 w -n 0 0 m 481.2283 0 l S -n 254.7679 0 m 254.7679 18 l S -n 367.9981 0 m 367.9981 18 l S -n 0 18 m 481.2283 18 l S -n 0 0 m 0 18 l S -n 481.2283 0 m 481.2283 18 l S -Q -Q -Q - -endstream -endobj -168 0 obj -<< -/Length 10543 ->> -stream -1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET -q -1 0 0 1 57.02362 693.0236 cm -q -1 1 1 rg -n 0 72 481.2283 -18 re f* -.878431 .878431 .878431 rg -n 0 54 481.2283 -18 re f* -1 1 1 rg -n 0 36 481.2283 -18 re f* -.878431 .878431 .878431 rg -n 0 18 481.2283 -18 re f* 0 0 0 rg BT /F1 10 Tf 12 TL ET q @@ -10774,40 +10828,41 @@ n 0 72 m 481.2283 72 l S n 0 54 m 481.2283 54 l S n 0 36 m 481.2283 36 l S n 0 18 m 481.2283 18 l S -n 254.7679 0 m 254.7679 72 l S -n 367.9981 0 m 367.9981 72 l S -n 0 0 m 0 72 l S -n 481.2283 0 m 481.2283 72 l S +n 254.7679 0 m 254.7679 90 l S +n 367.9981 0 m 367.9981 90 l S +n 0 90 m 481.2283 90 l S n 0 0 m 481.2283 0 l S +n 0 0 m 0 90 l S +n 481.2283 0 m 481.2283 90 l S Q Q Q q -1 0 0 1 57.02362 693.0236 cm +1 0 0 1 57.02362 621.0236 cm Q q -1 0 0 1 57.02362 663.0236 cm +1 0 0 1 57.02362 591.0236 cm q BT 1 0 0 1 0 14 Tm .163917 Tw 12 TL /F1 10 Tf 0 0 0 rg (\(The asm-server / asm-client pair is the fastest cell here \227 2,994 req/s from a 22 KB binary, served & driven) Tj T* 0 Tw (by the same 22 KB binary.\)) Tj T* ET Q Q q -1 0 0 1 57.02362 621.0236 cm +1 0 0 1 57.02362 549.0236 cm q BT 1 0 0 1 0 26 Tm .050596 Tw 12 TL /F1 10 Tf 0 0 0 rg (For external comparison: ) Tj /F5 10 Tf (python3) Tj ( ) Tj (-m) Tj ( ) Tj (http.server) Tj /F1 10 Tf ( and busybox httpd both land around 382 req/s under) Tj T* 0 Tw 1.458334 Tw (a curl client on the same machine. When driven by an in-process client they hit the same ceiling as our) Tj T* 0 Tw (servers \227 the bottleneck has always been the client fork/exec, not the server.) Tj T* ET Q Q q -1 0 0 1 57.02362 567.0236 cm +1 0 0 1 57.02362 495.0236 cm q BT 1 0 0 1 0 38 Tm 2.116575 Tw 12 TL /F3 10 Tf 0 0 0 rg (What's remarkable is not the speed.) Tj /F1 10 Tf ( It is that a 22 KB binary with zero libc dependency and seven) Tj T* 0 Tw .829353 Tw (canonical Linux syscalls plus the socket family runs HTTP as fast as anything else on the machine, with a) Tj T* 0 Tw .829272 Tw (protocol handler written in portable Scheme that runs byte-for-byte in all three runtimes. The asm binary is) Tj T* 0 Tw /F3 10 Tf (96\327 smaller than busybox httpd) Tj /F1 10 Tf ( \(2.1 MB\) and ) Tj /F3 10 Tf (360\327 smaller than the Python interpreter) Tj /F1 10 Tf ( alone \(8 MB\).) Tj T* ET Q Q q -1 0 0 1 57.02362 559.0236 cm +1 0 0 1 57.02362 487.0236 cm Q q -1 0 0 1 57.02362 510.6988 cm +1 0 0 1 57.02362 438.6988 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -10830,29 +10885,29 @@ Q Q Q q -1 0 0 1 57.02362 502.6988 cm +1 0 0 1 57.02362 430.6988 cm Q q -1 0 0 1 57.02362 471.4988 cm +1 0 0 1 57.02362 399.4988 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (11.4 S-expressions over Sockets: RPC, REPL, and Chains) Tj T* ET Q Q q -1 0 0 1 57.02362 427.4988 cm +1 0 0 1 57.02362 355.4988 cm q 0 0 0 rg BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .048022 Tw (The HTTP example sends request-line bytes and response-line bytes. Those bytes don't have to be HTTP. If) Tj T* 0 Tw .199913 Tw (both sides of the wire speak Scheme, the wire protocol can be Scheme source itself \227 the reader is already) Tj T* 0 Tw (the parser you need. Two new builtins close the loop in all three impls:) Tj T* ET Q Q q -1 0 0 1 57.02362 421.4988 cm +1 0 0 1 57.02362 349.4988 cm Q q -1 0 0 1 57.02362 421.4988 cm +1 0 0 1 57.02362 349.4988 cm Q q -1 0 0 1 57.02362 409.4988 cm +1 0 0 1 57.02362 337.4988 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -10874,10 +10929,10 @@ Q Q Q q -1 0 0 1 57.02362 403.4988 cm +1 0 0 1 57.02362 331.4988 cm Q q -1 0 0 1 57.02362 379.4988 cm +1 0 0 1 57.02362 307.4988 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -10899,79 +10954,105 @@ Q Q Q q -1 0 0 1 57.02362 361.4988 cm +1 0 0 1 57.02362 289.4988 cm Q q -1 0 0 1 57.02362 343.4988 cm +1 0 0 1 57.02362 271.4988 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Two server patterns emerge:) Tj T* ET Q Q q -1 0 0 1 57.02362 301.4988 cm +1 0 0 1 57.02362 229.4988 cm q BT 1 0 0 1 0 26 Tm .027362 Tw 12 TL /F3 10 Tf 0 0 0 rg (Whitelisted RPC) Tj /F1 10 Tf ( \() Tj /F5 10 Tf (examples/rpc-server.lsp) Tj /F1 10 Tf (, 90 lines\). The server reads a request sexp, dispatches by) Tj T* 0 Tw 1.114908 Tw (car on a closed set \() Tj /F5 10 Tf (ping) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (add) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (mul) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (fib) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (echo) Tj /F1 10 Tf (\), never calls ) Tj /F5 10 Tf (eval) Tj /F1 10 Tf ( on client input. Safe by construction.) Tj T* 0 Tw (Uses ) Tj /F5 10 Tf (heap-snapshot) Tj /F1 10 Tf (/) Tj /F5 10 Tf (heap-restore) Tj /F1 10 Tf ( for O\(1\) memory on asm.) Tj T* ET Q Q q -1 0 0 1 57.02362 235.4988 cm +1 0 0 1 57.02362 163.4988 cm q BT 1 0 0 1 0 50 Tm .076027 Tw 12 TL /F3 10 Tf 0 0 0 rg (Full remote REPL) Tj /F1 10 Tf ( \() Tj /F5 10 Tf (examples/repl-server.lsp) Tj /F1 10 Tf (, 70 lines\). The server reads a request sexp and passes) Tj T* 0 Tw .534609 Tw (it straight to ) Tj /F5 10 Tf (eval) Tj /F1 10 Tf (. Persistent global env across connections; ) Tj /F5 10 Tf (\(define) Tj ( ) Tj (x) Tj ( ) Tj (42\)) Tj /F1 10 Tf ( from one call is visible from) Tj T* 0 Tw 1.463453 Tw (the next. DANGER: any reachable client can run arbitrary Scheme in-process. Deliberately does not use) Tj T* 0 Tw .876027 Tw /F5 10 Tf (heap-snapshot) Tj /F1 10 Tf ( because remote ) Tj /F5 10 Tf (define) Tj /F1 10 Tf ( adds bindings past any snapshot point; the ) Tj /F5 10 Tf (ulimit) Tj ( ) Tj (-v) Tj /F1 10 Tf ( safety) Tj T* 0 Tw (cap \(512 MB\) backstops the leak.) Tj T* ET Q Q q -1 0 0 1 57.02362 205.4988 cm +1 0 0 1 57.02362 133.4988 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .909903 Tw (Both patterns run byte-identically in Python, C, and asm. The 3\3273 server\327client matrix is 9/9 green \227 any) Tj T* 0 Tw (runtime can host either side.) Tj T* ET Q Q q -1 0 0 1 57.02362 163.4988 cm +1 0 0 1 57.02362 91.49883 cm q BT 1 0 0 1 0 26 Tm 1.432577 Tw 12 TL /F3 10 Tf 0 0 0 rg (Chains: relays across runtimes.) Tj /F1 10 Tf ( A transparent relay \() Tj /F5 10 Tf (examples/rpc-relay.lsp) Tj /F1 10 Tf (, 50 lines\) accepts a) Tj T* 0 Tw 1.39989 Tw (connection, forwards the request bytes to a backend without parsing, relays the reply back. Because the) Tj T* 0 Tw (envelope is Scheme source and the relay never opens it, chains of arbitrary runtimes compose naturally:) Tj T* ET Q Q q -1 0 0 1 57.02362 157.4988 cm +1 0 0 1 57.02362 85.49883 cm Q q 1 0 0 1 57.02362 67.49883 cm q 1 1 1 rg -n 0 90 481.2283 -18 re f* -.878431 .878431 .878431 rg -n 0 72 481.2283 -18 re f* -1 1 1 rg -n 0 54 481.2283 -18 re f* -.878431 .878431 .878431 rg -n 0 36 481.2283 -18 re f* -1 1 1 rg n 0 18 481.2283 -18 re f* 0 0 0 rg BT /F3 10 Tf 12 TL ET q -1 0 0 1 6 75 cm +1 0 0 1 6 3 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 79.91699 0 Td (Chain \(200 ping requests\)) Tj T* -79.91699 0 Td ET Q Q q -1 0 0 1 300.084 75 cm +1 0 0 1 300.084 3 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 14.11109 0 Td (Requests/s) Tj T* -14.11109 0 Td ET Q Q q -1 0 0 1 393.6562 75 cm +1 0 0 1 393.6562 3 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 10.22609 0 Td (Per-hop cost) Tj T* -10.22609 0 Td ET Q Q +q +1 J +1 j +0 0 0 RG +.25 w +n 0 0 m 481.2283 0 l S +n 294.084 0 m 294.084 18 l S +n 387.6562 0 m 387.6562 18 l S +n 0 18 m 481.2283 18 l S +n 0 0 m 0 18 l S +n 481.2283 0 m 481.2283 18 l S +Q +Q +Q + +endstream +endobj +170 0 obj +<< +/Length 8969 +>> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET +q +1 0 0 1 57.02362 693.0236 cm +q +1 1 1 rg +n 0 72 481.2283 -18 re f* +.878431 .878431 .878431 rg +n 0 54 481.2283 -18 re f* +1 1 1 rg +n 0 36 481.2283 -18 re f* +.878431 .878431 .878431 rg +n 0 18 481.2283 -18 re f* 0 0 0 rg BT /F1 10 Tf 12 TL ET q @@ -11067,67 +11148,57 @@ n 0 72 m 481.2283 72 l S n 0 54 m 481.2283 54 l S n 0 36 m 481.2283 36 l S n 0 18 m 481.2283 18 l S -n 294.084 0 m 294.084 90 l S -n 387.6562 0 m 387.6562 90 l S -n 0 90 m 481.2283 90 l S +n 294.084 0 m 294.084 72 l S +n 387.6562 0 m 387.6562 72 l S +n 0 0 m 0 72 l S +n 481.2283 0 m 481.2283 72 l S n 0 0 m 481.2283 0 l S -n 0 0 m 0 90 l S -n 481.2283 0 m 481.2283 90 l S Q Q Q q -1 0 0 1 57.02362 67.49883 cm +1 0 0 1 57.02362 693.0236 cm Q - -endstream -endobj -169 0 obj -<< -/Length 7017 ->> -stream -1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 705.0236 cm +1 0 0 1 57.02362 627.0236 cm q BT 1 0 0 1 0 50 Tm 1.815464 Tw 12 TL /F1 10 Tf 0 0 0 rg (Each relay hop costs ~650 \265s \(one full TCP round-trip + context switches on the same host, no actual) Tj T* 0 Tw 5.709882 Tw (parsing work\). The relay never allocates anything beyond a transient buffer; on asm it uses) Tj T* 0 Tw 1.25985 Tw /F5 10 Tf (heap-snapshot) Tj /F1 10 Tf (/) Tj /F5 10 Tf (heap-restore) Tj /F1 10 Tf ( to keep memory flat under load. Four runtimes strung together through) Tj T* 0 Tw 3.232362 Tw (two relay machines, the same ) Tj /F5 10 Tf (.lsp) Tj /F1 10 Tf ( on every hop. ) Tj /F3 10 Tf (Reproduce:) Tj /F1 10 Tf ( ) Tj /F5 10 Tf (make) Tj ( ) Tj (bench-rpc-chain) Tj /F1 10 Tf ( \(source:) Tj T* 0 Tw /F5 10 Tf (tests/rpc-chain-bench.sh) Tj /F1 10 Tf (\).) Tj T* ET Q Q q -1 0 0 1 57.02362 663.0236 cm +1 0 0 1 57.02362 585.0236 cm q 0 0 0 rg BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .921575 Tw (The result is not a performance story \227 it is a composition story. S-expressions are the envelope and the) Tj T* 0 Tw .649925 Tw (payload. A 22 KB binary can be a backend, a relay, a client, or any point in a chain; the protocol needs no) Tj T* 0 Tw (separate definition because the protocol IS the language.) Tj T* ET Q Q q -1 0 0 1 57.02362 631.8236 cm +1 0 0 1 57.02362 553.8236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (11.5 Portal over HTTP: State Transfer Between Machines) Tj T* ET Q Q q -1 0 0 1 57.02362 587.8236 cm +1 0 0 1 57.02362 509.8236 cm q 0 0 0 rg BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .273647 Tw (The HTTP server carries request bytes. The portal serializes machine state to bytes. Combine them: a node) Tj T* 0 Tw .711667 Tw (exposes its state as an HTTP endpoint, another node pulls that endpoint down and resumes. This was the) Tj T* 0 Tw (first item in \24713 Future Work \227 it is now a running demo.) Tj T* ET Q Q q -1 0 0 1 57.02362 545.8236 cm +1 0 0 1 57.02362 467.8236 cm q BT 1 0 0 1 0 26 Tm .363486 Tw 12 TL /F5 10 Tf 0 0 0 rg (examples/portal-http-server.lsp) Tj /F1 10 Tf ( holds some state \(integer counter, list, string, the result of fib\(30\)\)) Tj T* 0 Tw 1.391223 Tw (and answers ) Tj /F5 10 Tf (GET) Tj ( ) Tj (/portal) Tj /F1 10 Tf ( with an S-expression portal body \227 literally a sequence of ) Tj /F5 10 Tf (\(define) Tj ( ) Tj (...\)) Tj /F1 10 Tf T* 0 Tw (forms.) Tj T* ET Q Q q -1 0 0 1 57.02362 503.8236 cm +1 0 0 1 57.02362 425.8236 cm q BT 1 0 0 1 0 26 Tm 1.574395 Tw 12 TL /F5 10 Tf 0 0 0 rg (examples/portal-http-client.lsp) Tj /F1 10 Tf ( dials the endpoint, strips the HTTP headers, splits the body by) Tj T* 0 Tw 2.070759 Tw (newline, and for each non-empty, non-comment line calls ) Tj /F5 10 Tf (\(eval) Tj ( ) Tj (\(read-from-string) Tj ( ) Tj (line\)\)) Tj /F1 10 Tf (. The) Tj T* 0 Tw (remote bindings become local.) Tj T* ET Q Q q -1 0 0 1 57.02362 367.4236 cm +1 0 0 1 57.02362 289.4236 cm q q 1 0 0 1 0 0 cm @@ -11147,32 +11218,32 @@ Q Q Q q -1 0 0 1 57.02362 311.4236 cm +1 0 0 1 57.02362 233.4236 cm q BT 1 0 0 1 0 38 Tm .351019 Tw 12 TL /F3 10 Tf 0 0 0 rg (3\3273 matrix green:) Tj /F1 10 Tf ( Python/C/asm in any role \227 server or client or both \227 exchange state correctly. All nine) Tj T* 0 Tw 2.399835 Tw (combinations verified. ) Tj /F5 10 Tf (examples/portal-http-client.lsp) Tj /F1 10 Tf ( is 90 lines of portable Scheme; the full) Tj T* 0 Tw 3.611529 Tw (round-trip uses only the six ) Tj /F5 10 Tf (tcp-*) Tj /F1 10 Tf ( primitives plus ) Tj /F5 10 Tf (read-from-string) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (eval) Tj /F1 10 Tf (, and standard string) Tj T* 0 Tw (manipulation.) Tj T* ET Q Q q -1 0 0 1 57.02362 257.4236 cm +1 0 0 1 57.02362 179.4236 cm q BT 1 0 0 1 0 38 Tm 1.468556 Tw 12 TL /F1 10 Tf 0 0 0 rg (The client needs ) Tj /F5 10 Tf (eval) Tj /F1 10 Tf ( semantics that install define-bindings in the global env regardless of the dynamic) Tj T* 0 Tw .000439 Tw (scope of the ) Tj /F5 10 Tf (eval) Tj /F1 10 Tf ( call. Python and C originally evaluated the ) Tj /F5 10 Tf (eval) Tj /F1 10 Tf ( result in the caller's env, which worked at) Tj T* 0 Tw .282545 Tw (top level but silently failed inside a helper function. A two-line fix in each \() Tj /F5 10 Tf (env) Tj ( ) Tj (=) Tj ( ) Tj (env.g) Tj /F1 10 Tf ( in Python's ) Tj /F5 10 Tf (leval) Tj /F1 10 Tf (,) Tj T* 0 Tw /F5 10 Tf (env) Tj ( ) Tj (=) Tj ( ) Tj (env-) Tj (>) Tj (global) Tj /F1 10 Tf ( in C's SYM_EVAL branch\) aligns both with asm's long-standing ) Tj /F5 10 Tf (bi_eval) Tj /F1 10 Tf ( behavior.) Tj T* ET Q Q q -1 0 0 1 57.02362 227.4236 cm +1 0 0 1 57.02362 149.4236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 3.231772 Tw (This is the closing demonstration of "feedback is all you need" extended across all four scopes. A) Tj T* 0 Tw (continuation-style value \227 here, a set of bindings \227 travels:) Tj T* ET Q Q q -1 0 0 1 57.02362 221.4236 cm +1 0 0 1 57.02362 143.4236 cm Q q -1 0 0 1 57.02362 221.4236 cm +1 0 0 1 57.02362 143.4236 cm Q q -1 0 0 1 57.02362 209.4236 cm +1 0 0 1 57.02362 131.4236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11194,10 +11265,10 @@ Q Q Q q -1 0 0 1 57.02362 203.4236 cm +1 0 0 1 57.02362 125.4236 cm Q q -1 0 0 1 57.02362 191.4236 cm +1 0 0 1 57.02362 113.4236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11220,10 +11291,10 @@ Q Q Q q -1 0 0 1 57.02362 185.4236 cm +1 0 0 1 57.02362 107.4236 cm Q q -1 0 0 1 57.02362 173.4236 cm +1 0 0 1 57.02362 95.42362 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11246,10 +11317,10 @@ Q Q Q q -1 0 0 1 57.02362 167.4236 cm +1 0 0 1 57.02362 89.42362 cm Q q -1 0 0 1 57.02362 155.4236 cm +1 0 0 1 57.02362 77.42362 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11272,45 +11343,45 @@ Q Q Q q -1 0 0 1 57.02362 137.4236 cm +1 0 0 1 57.02362 62.69291 cm Q + +endstream +endobj +171 0 obj +<< +/Length 6860 +>> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 107.4236 cm +1 0 0 1 57.02362 741.0236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .68135 Tw (The wire protocol and the language are the same artifact. A 22 KB binary can be any node in any chain of) Tj T* 0 Tw (any scope.) Tj T* ET Q Q - -endstream -endobj -170 0 obj -<< -/Length 7833 ->> -stream -1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 751.8236 cm +1 0 0 1 57.02362 709.8236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (11.6 heap-snapshot: The Arena Escape Hatch) Tj T* ET Q Q q -1 0 0 1 57.02362 707.8236 cm +1 0 0 1 57.02362 665.8236 cm q BT 1 0 0 1 0 26 Tm -0.12705 Tw 12 TL /F1 10 Tf 0 0 0 rg (The asm bump allocator has no GC. Every ) Tj /F5 10 Tf (string-append) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (tcp-recv) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (make-pair) Tj /F1 10 Tf (, or similar per-request) Tj T* 0 Tw 1.173647 Tw (allocation grows r15. Over a long-running server that is an unbounded leak \227 an incident on 2026-04-16) Tj T* 0 Tw (drove an asm server to 19.3 GB RSS before being killed.) Tj T* ET Q Q q -1 0 0 1 57.02362 689.8236 cm +1 0 0 1 57.02362 647.8236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Two new builtins fix this without introducing a collector:) Tj T* ET Q Q q -1 0 0 1 57.02362 649.4236 cm +1 0 0 1 57.02362 607.4236 cm q q 1 0 0 1 0 0 cm @@ -11330,21 +11401,21 @@ Q Q Q q -1 0 0 1 57.02362 617.4236 cm +1 0 0 1 57.02362 575.4236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .828138 Tw (Python + C expose the same names as no-ops \(their real GCs already handle this\). Portable Scheme can) Tj T* 0 Tw (call them unconditionally.) Tj T* ET Q Q q -1 0 0 1 57.02362 599.4236 cm +1 0 0 1 57.02362 557.4236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The pattern is narrow by design:) Tj T* ET Q Q q -1 0 0 1 57.02362 530.2236 cm +1 0 0 1 57.02362 488.2236 cm q q 1 0 0 1 0 0 cm @@ -11365,39 +11436,39 @@ Q Q Q q -1 0 0 1 57.02362 474.2236 cm +1 0 0 1 57.02362 432.2236 cm q 0 0 0 rg BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .76989 Tw (The snapshot is dangerously precise: anything allocated after the snap and still reachable after the restore) Tj T* 0 Tw -0.00705 Tw (becomes a dangling pointer. The canonical pattern \(HTTP request scope\) allocates per-request and discards) Tj T* 0 Tw 1.660522 Tw (per-request \227 nothing escapes. Measured asm RSS with this pattern: 88 KB initial, 100 KB after 1,100) Tj T* 0 Tw (requests. Flat.) Tj T* ET Q Q q -1 0 0 1 57.02362 432.2236 cm +1 0 0 1 57.02362 390.2236 cm q 0 0 0 rg BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .241019 Tw (This is not a general-purpose allocator. It is an escape hatch the programmer uses when they can prove the) Tj T* 0 Tw 1.593647 Tw (scope boundary. For general programs on asm, the heap still grows. For the HTTP server pattern, O\(1\)) Tj T* 0 Tw (memory costs two lines of code.) Tj T* ET Q Q q -1 0 0 1 57.02362 401.0236 cm +1 0 0 1 57.02362 359.0236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (11.7 Static File Serving: Cache, Sendfile, and Adaptive Preload) Tj T* ET Q Q q -1 0 0 1 57.02362 345.0236 cm +1 0 0 1 57.02362 303.0236 cm q BT 1 0 0 1 0 38 Tm .551223 Tw 12 TL /F1 10 Tf 0 0 0 rg (The HTTP demo in \24711.3 served synthesized responses. To host ) Tj /F5 10 Tf (lumbda.com) Tj /F1 10 Tf ( we needed a real static-file) Tj T* 0 Tw .579908 Tw (path \227 something that hands a 2.67 MiB PDF \(this whitepaper\) off the disk without bouncing it through the) Tj T* 0 Tw 1.830596 Tw (Scheme heap. Three variants now ship in ) Tj /F5 10 Tf (examples/) Tj /F1 10 Tf (, each ~100\226200 lines of portable Scheme, each) Tj T* 0 Tw (running on ) Tj /F5 10 Tf (asm/lumbda-gc) Tj /F1 10 Tf ( \(the GC build, 27 KB stripped\).) Tj T* ET Q Q q -1 0 0 1 57.02362 339.0236 cm +1 0 0 1 57.02362 297.0236 cm Q q -1 0 0 1 57.02362 339.0236 cm +1 0 0 1 57.02362 297.0236 cm Q q -1 0 0 1 57.02362 303.0236 cm +1 0 0 1 57.02362 261.0236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11419,10 +11490,10 @@ Q Q Q q -1 0 0 1 57.02362 297.0236 cm +1 0 0 1 57.02362 255.0236 cm Q q -1 0 0 1 57.02362 249.0236 cm +1 0 0 1 57.02362 207.0236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11444,10 +11515,10 @@ Q Q Q q -1 0 0 1 57.02362 243.0236 cm +1 0 0 1 57.02362 201.0236 cm Q q -1 0 0 1 57.02362 195.0236 cm +1 0 0 1 57.02362 153.0236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11469,93 +11540,75 @@ Q Q Q q -1 0 0 1 57.02362 177.0236 cm +1 0 0 1 57.02362 135.0236 cm Q q -1 0 0 1 57.02362 123.0236 cm +1 0 0 1 57.02362 81.02362 cm q BT 1 0 0 1 0 38 Tm 3.259272 Tw 12 TL /F5 10 Tf 0 0 0 rg (tcp-sendfile) Tj /F1 10 Tf ( is a 90-line asm-gc builtin. It opens the path, ) Tj /F5 10 Tf (lseek) Tj /F1 10 Tf ('s to find the size, then loops) Tj T* 0 Tw 1.390522 Tw /F5 10 Tf (sendfile\(2\)) Tj /F1 10 Tf ( until the full body is written, and ) Tj /F5 10 Tf (close\(\)) Tj /F1 10 Tf ('s. The body never enters the Lumbda heap \227) Tj T* 0 Tw .243432 Tw (headers are composed in Scheme and flushed via ) Tj /F5 10 Tf (tcp-send) Tj /F1 10 Tf (, then the kernel DMAs the file directly into the) Tj T* 0 Tw (socket buffer.) Tj T* ET Q Q + +endstream +endobj +172 0 obj +<< +/Length 9582 +>> +stream +1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 93.02362 cm +1 0 0 1 57.02362 741.0236 cm q BT 1 0 0 1 0 14 Tm 4.109816 Tw 12 TL /F3 10 Tf 0 0 0 rg (Four-way race) Tj /F1 10 Tf ( \() Tj /F5 10 Tf (tests/bench-www-race.sh) Tj /F1 10 Tf (, i5-8350U, 1000 small requests, 100 large requests,) Tj T* 0 Tw (concurrency 8, ) Tj /F5 10 Tf (xargs) Tj ( ) Tj (-P) Tj ( ) Tj (8) Tj ( ) Tj (curl) Tj /F1 10 Tf (, adjacent runs\):) Tj T* ET Q Q q -1 0 0 1 57.02362 87.02362 cm +1 0 0 1 57.02362 735.0236 cm Q q -1 0 0 1 57.02362 69.02362 cm +1 0 0 1 57.02362 645.0236 cm q 1 1 1 rg +n 0 90 481.2283 -18 re f* +.878431 .878431 .878431 rg +n 0 72 481.2283 -18 re f* +1 1 1 rg +n 0 54 481.2283 -18 re f* +.878431 .878431 .878431 rg +n 0 36 481.2283 -18 re f* +1 1 1 rg n 0 18 481.2283 -18 re f* 0 0 0 rg BT /F3 10 Tf 12 TL ET q -1 0 0 1 6 3 cm +1 0 0 1 6 75 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 74.68067 0 Td (Server) Tj T* -74.68067 0 Td ET Q Q q -1 0 0 1 198.4913 3 cm +1 0 0 1 198.4913 75 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 18.78283 0 Td (PDF req/s) Tj T* -18.78283 0 Td ET Q Q q -1 0 0 1 294.737 3 cm +1 0 0 1 294.737 75 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 17.39783 0 Td (PDF MiB/s) Tj T* -17.39783 0 Td ET Q Q q -1 0 0 1 390.9827 3 cm +1 0 0 1 390.9827 75 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F3 10 Tf 12 TL 18.77783 0 Td (Peak RSS) Tj T* -18.77783 0 Td ET Q Q -q -1 J -1 j -0 0 0 RG -.25 w -n 0 0 m 481.2283 0 l S -n 192.4913 0 m 192.4913 18 l S -n 288.737 0 m 288.737 18 l S -n 384.9827 0 m 384.9827 18 l S -n 0 18 m 481.2283 18 l S -n 0 0 m 0 18 l S -n 481.2283 0 m 481.2283 18 l S -Q -Q -Q - -endstream -endobj -171 0 obj -<< -/Length 8924 ->> -stream -1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET -q -1 0 0 1 57.02362 693.0236 cm -q -1 1 1 rg -n 0 72 481.2283 -18 re f* -.878431 .878431 .878431 rg -n 0 54 481.2283 -18 re f* -1 1 1 rg -n 0 36 481.2283 -18 re f* -.878431 .878431 .878431 rg -n 0 18 481.2283 -18 re f* 0 0 0 rg BT /F1 10 Tf 12 TL ET q @@ -11679,110 +11732,90 @@ n 0 72 m 481.2283 72 l S n 0 54 m 481.2283 54 l S n 0 36 m 481.2283 36 l S n 0 18 m 481.2283 18 l S -n 192.4913 0 m 192.4913 72 l S -n 288.737 0 m 288.737 72 l S -n 384.9827 0 m 384.9827 72 l S -n 0 0 m 0 72 l S -n 481.2283 0 m 481.2283 72 l S +n 192.4913 0 m 192.4913 90 l S +n 288.737 0 m 288.737 90 l S +n 384.9827 0 m 384.9827 90 l S +n 0 90 m 481.2283 90 l S n 0 0 m 481.2283 0 l S +n 0 0 m 0 90 l S +n 481.2283 0 m 481.2283 90 l S Q Q Q q -1 0 0 1 57.02362 693.0236 cm +1 0 0 1 57.02362 645.0236 cm Q q -1 0 0 1 57.02362 639.0236 cm +1 0 0 1 57.02362 591.0236 cm q BT 1 0 0 1 0 38 Tm -0.070097 Tw 12 TL /F1 10 Tf 0 0 0 rg (All four servers return the PDF byte-identical against the on-disk master. The sendfile path lands within 2% of) Tj T* 0 Tw -0.036403 Tw (Caddy on throughput while holding ) Tj /F3 10 Tf (9\327 less peak RSS) Tj /F1 10 Tf ( in a binary ) Tj /F3 10 Tf (1,400\327 smaller) Tj /F1 10 Tf ( \(27 KB stripped vs 38 MB\).) Tj T* 0 Tw 1.29189 Tw (Small-request throughput \() Tj /F5 10 Tf (GET) Tj ( ) Tj (/) Tj /F1 10 Tf (\) is essentially flat across the three lumbda variants \227 the cached path) Tj T* 0 Tw (already removed per-request work, so sendfile's win is entirely on large bodies.) Tj T* ET Q Q q -1 0 0 1 57.02362 549.0236 cm +1 0 0 1 57.02362 501.0236 cm q BT 1 0 0 1 0 74 Tm .177835 Tw 12 TL /F3 10 Tf 0 0 0 rg (Adaptive preload: ``http-static-server-adaptive.lsp``.) Tj /F1 10 Tf ( A hit-counter hash-table \(URL ) Tj /F6 10 Tf 12 TL (\256) Tj /F1 10 Tf 12 TL ( integer\) is updated) Tj T* 0 Tw 1.609168 Tw (every request. Every ) Tj /F4 10 Tf (N) Tj /F1 10 Tf ( requests the counter is flushed to ) Tj /F5 10 Tf (www.hits) Tj /F1 10 Tf ( as newline-delimited ) Tj /F5 10 Tf (path) Tj ( ) Tj (count) Tj /F1 10 Tf T* 0 Tw .451079 Tw (records. On startup the file is loaded, sorted descending, and the top ) Tj /F4 10 Tf (cache-max) Tj /F1 10 Tf ( URLs are preloaded \227 so) Tj T* 0 Tw 2.841575 Tw (each boot reflects what the previous run actually served. Cold start falls back to a seed list \() Tj /F5 10 Tf (/) Tj /F1 10 Tf ( and) Tj T* 0 Tw 1.316019 Tw /F5 10 Tf (/404.html) Tj /F1 10 Tf (\). Cold requests beyond the seed set are promoted into the cache on first hit until the cap is) Tj T* 0 Tw 1.39989 Tw (reached. Because this server mutates persistent state \(the counter and the cache\) on every request, the) Tj T* 0 Tw (arena-pattern ) Tj /F5 10 Tf (heap-restore) Tj /F1 10 Tf ( is dropped and the GC build's mark-sweep reclaims transients instead.) Tj T* ET Q Q q -1 0 0 1 57.02362 507.0236 cm +1 0 0 1 57.02362 459.0236 cm q BT 1 0 0 1 0 26 Tm -0.123981 Tw 12 TL /F1 10 Tf 0 0 0 rg (For small deployments \() Tj /F6 10 Tf 12 TL (\243) Tj /F1 10 Tf 12 TL ( ~1000 resources\) this is ~95% of the win of a full predictive-preload system: the top) Tj T* 0 Tw .681079 Tw (few URLs dominate traffic and get pinned at boot. Anything rarer warms on demand. The remaining 5% \227) Tj T* 0 Tw (predicting which URLs will be needed from ) Tj /F4 10 Tf (co-occurrence) Tj /F1 10 Tf ( rather than raw frequency \227 is \24713 Future Work.) Tj T* ET Q Q q -1 0 0 1 57.02362 467.8236 cm +1 0 0 1 57.02362 419.8236 cm q BT 1 0 0 1 0 3.2 Tm 108.3902 0 Td 19.2 TL /F2 16 Tf .133333 .133333 .133333 rg (12. MOAD Audit: Fixing What We Built) Tj T* -108.3902 0 Td ET Q Q q -1 0 0 1 57.02362 413.8236 cm +1 0 0 1 57.02362 365.8236 cm q BT 1 0 0 1 0 38 Tm .158726 Tw 12 TL /F1 10 Tf 0 0 0 rg (We scanned all three implementations for the five MOADs. The taxonomy used here is defined in the ) Tj 0 .4 .6 rg (MOAD) Tj T* 0 Tw 3.384835 Tw (Cheat Sheet) Tj 0 0 0 rg ( at undefect.com \227 MOAD-0001 \(sedimentary O\(N\262\) defects\), MOAD-0002 \(intertangle\),) Tj T* 0 Tw .059816 Tw (MOAD-0003 \(context-leak\), MOAD-0004 \(stringly-typed\), MOAD-0005 \(bus-factor\). Every project contains its) Tj T* 0 Tw (own sediment.) Tj T* ET Q Q q -1 0 0 1 57.02362 323.8236 cm +1 0 0 1 57.02362 275.8236 cm q BT 1 0 0 1 0 74 Tm 7.459168 Tw 12 TL /F3 10 Tf 0 0 0 rg (Standard: what the Lean EML proof sets.) Tj /F1 10 Tf ( \2478 documents a formal Lean 4 proof that) Tj T* 0 Tw .542844 Tw /F5 10 Tf (eml\(x,) Tj ( ) Tj (y\)) Tj ( ) Tj (=) Tj ( ) Tj (exp\(x\)) Tj ( ) Tj (-) Tj ( ) Tj (ln\(y\)) Tj /F1 10 Tf ( generates every elementary function \227 and that the proof is 40\327 faster) Tj T* 0 Tw .55131 Tw (than the brute-force numerical verification it replaced. That speedup is the MOAD-0001 story in microcosm:) Tj T* 0 Tw 1.171667 Tw (algebraic understanding beats O\(N\262\) search, at the proof layer just like at every other layer. We take that) Tj T* 0 Tw .048417 Tw (standard as the bar for the implementations too. Every hot path should be fast for a ) Tj /F4 10 Tf (reason) Tj /F1 10 Tf ( \(a hash, a cache,) Tj T* 0 Tw -0.019034 Tw (an O\(1\) invariant\), not because a test didn't happen to hit the slow case. Every behavior should be correct for) Tj T* 0 Tw (a reason, not by coincidence. The audit below is where we hold ourselves to that bar.) Tj T* ET Q Q q -1 0 0 1 57.02362 209.8236 cm +1 0 0 1 57.02362 161.8236 cm q BT 1 0 0 1 0 98 Tm 1.954609 Tw 12 TL /F1 10 Tf 0 0 0 rg (We also ran the unmoad scanner on the full tree at each release. Most recent scan \(2026-04-17, post) Tj T* 0 Tw .255223 Tw (portal-over-HTTP\): 18 HIGH MOAD-0001 candidates in C and 4 MOAD-0003 candidates in Python. All 18 C) Tj T* 0 Tw 1.186796 Tw (candidates inspected individually turn out to be false positives \227 one-shot option parsing, bounded-depth) Tj T* 0 Tw .330596 Tw (ancestor walks, hash bucket chain walks \(already O\(1\) amortized\), or static 6-element tables \(e.g. ) Tj /F5 10 Tf (#\\space) Tj /F1 10 Tf T* 0 Tw 3.004862 Tw (char-literal names\). The 4 Python MOAD-0003 candidates are scanner misfires on a non-ContextVar) Tj T* 0 Tw 6.764835 Tw /F5 10 Tf (Env.set\(\)) Tj /F1 10 Tf ( method. New-work-introduced MOAD-0001: ) Tj /F3 10 Tf (zero) Tj /F1 10 Tf (. The defects fixed in this paper) Tj T* 0 Tw 2.914587 Tw (\() Tj /F5 10 Tf (intern_symbol) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (_define_record_type) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (bi_string_replace) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (_tokenize_lines) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (Env.lookup) Tj /F1 10 Tf T* 0 Tw 1.773223 Tw (shortcut\) were all surfaced by other pressures \227 benchmarks, crashes, portal exchanges \227 not by the) Tj T* 0 Tw (scanner. The scanner remains a second line; the first line is building with understanding.) Tj T* ET Q Q q -1 0 0 1 57.02362 178.6236 cm +1 0 0 1 57.02362 130.6236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (12.1 MOAD-0001: The Sedimentary Defect in Our Own Code) Tj T* ET Q Q q -1 0 0 1 57.02362 134.6236 cm +1 0 0 1 57.02362 86.62362 cm q BT 1 0 0 1 0 26 Tm 1.195596 Tw 12 TL /F1 10 Tf 0 0 0 rg (The assembly interpreter's ) Tj /F5 10 Tf (intern_symbol) Tj /F1 10 Tf ( used a linear scan through all interned symbols \227 O\(N\) per) Tj T* 0 Tw .024897 Tw (lookup, O\(N\262\) over a program's lifetime. For a program defining 34 builtins plus user symbols, every ) Tj /F5 10 Tf (define) Tj /F1 10 Tf (,) Tj T* 0 Tw (every lambda parameter, every variable reference walked the entire table.) Tj T* ET Q Q q -1 0 0 1 57.02362 116.6236 cm +1 0 0 1 57.02362 68.62362 cm q BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (Before \(linear scan\)) Tj /F1 10 Tf (:) Tj T* ET Q Q -q -1 0 0 1 57.02362 66.62362 cm -q -q -1 0 0 1 0 0 cm -q -1 0 0 1 6.6 6.6 cm -q -.662745 .662745 .662745 RG -.5 w -.960784 .960784 .960784 rg -n -6 -6 480.0283 40.8 re B* -Q -q -0 0 0 rg -BT 1 0 0 1 0 20.8 Tm /F5 8 Tf 9.6 TL (.isym_search:) Tj T* ( cmpq %rcx, %r8 # compare lengths) Tj T* ( jne .isym_next) Tj T* ET -Q -Q -Q -Q -Q endstream endobj -172 0 obj +173 0 obj << -/Length 7975 +/Length 8080 >> stream 1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET q -1 0 0 1 57.02362 703.8236 cm +1 0 0 1 57.02362 675.0236 cm q q 1 0 0 1 0 0 cm @@ -11792,24 +11825,24 @@ q .662745 .662745 .662745 RG .5 w .960784 .960784 .960784 rg -n -6 -6 480.0283 60 re B* +n -6 -6 480.0283 88.8 re B* Q q 0 0 0 rg -BT 1 0 0 1 0 40 Tm /F5 8 Tf 9.6 TL ( rep cmpsb # compare bytes) Tj T* ( je .isym_found) Tj T* (.isym_next:) Tj T* ( addq $24, %rax # next entry) Tj T* ( jmp .isym_search # O\(N\) per intern) Tj T* ET +BT 1 0 0 1 0 68.8 Tm /F5 8 Tf 9.6 TL (.isym_search:) Tj T* ( cmpq %rcx, %r8 # compare lengths) Tj T* ( jne .isym_next) Tj T* ( rep cmpsb # compare bytes) Tj T* ( je .isym_found) Tj T* (.isym_next:) Tj T* ( addq $24, %rax # next entry) Tj T* ( jmp .isym_search # O\(N\) per intern) Tj T* ET Q Q Q Q Q q -1 0 0 1 57.02362 683.8236 cm +1 0 0 1 57.02362 655.0236 cm q BT 1 0 0 1 0 2 Tm 12 TL /F3 10 Tf 0 0 0 rg (After \(djb2 hash table, 1024 buckets\)) Tj /F1 10 Tf (:) Tj T* ET Q Q q -1 0 0 1 57.02362 605.0236 cm +1 0 0 1 57.02362 576.2236 cm q q 1 0 0 1 0 0 cm @@ -11829,32 +11862,32 @@ Q Q Q q -1 0 0 1 57.02362 549.0236 cm +1 0 0 1 57.02362 520.2236 cm q BT 1 0 0 1 0 38 Tm .721772 Tw 12 TL /F1 10 Tf 0 0 0 rg (The fix: 99 lines changed, 1024-bucket hash table with chaining. ) Tj /F3 10 Tf (2.9x faster) Tj /F1 10 Tf ( on a 2000-symbol stress test.) Tj T* 0 Tw 2.453719 Tw (On benchmarks with fewer symbols \() Tj /F5 10 Tf (ack) Tj /F1 10 Tf (, ) Tj /F5 10 Tf (fib) Tj /F1 10 Tf (\), the improvement is modest \(15% on ) Tj /F5 10 Tf (sum-to\(50k\)) Tj /F1 10 Tf (\),) Tj T* 0 Tw 1.940417 Tw (because the linear scan was already fast at small N. The fix pays off at scale \227 the same pattern as) Tj T* 0 Tw (MOAD-0001 everywhere: invisible at small inputs, catastrophic at large ones.) Tj T* ET Q Q q -1 0 0 1 57.02362 519.0236 cm +1 0 0 1 57.02362 490.2236 cm q BT 1 0 0 1 0 14 Tm 1.423486 Tw 12 TL /F1 10 Tf 0 0 0 rg (The Python implementation had a similar defect: ) Tj /F5 10 Tf (_define_record_type) Tj /F1 10 Tf ( used ) Tj /F5 10 Tf (list.index\(\)) Tj /F1 10 Tf ( for field) Tj T* 0 Tw (lookup. Replaced with a dict. O\(N\) ) Tj /F6 10 Tf 12 TL (\256) Tj /F1 10 Tf 12 TL ( O\(1\).) Tj T* ET Q Q q -1 0 0 1 57.02362 489.0236 cm +1 0 0 1 57.02362 460.2236 cm q 0 0 0 rg BT 1 0 0 1 0 14 Tm /F3 10 Tf 12 TL 1.554556 Tw (Two more MOAD-0001 defects surfaced during the HTTP server work and were fixed in the same) Tj T* 0 Tw (pass:) Tj T* ET Q Q q -1 0 0 1 57.02362 483.0236 cm +1 0 0 1 57.02362 454.2236 cm Q q -1 0 0 1 57.02362 483.0236 cm +1 0 0 1 57.02362 454.2236 cm Q q -1 0 0 1 57.02362 447.0236 cm +1 0 0 1 57.02362 418.2236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11876,10 +11909,10 @@ Q Q Q q -1 0 0 1 57.02362 441.0236 cm +1 0 0 1 57.02362 412.2236 cm Q q -1 0 0 1 57.02362 405.0236 cm +1 0 0 1 57.02362 376.2236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11901,42 +11934,42 @@ Q Q Q q -1 0 0 1 57.02362 387.0236 cm +1 0 0 1 57.02362 358.2236 cm Q q -1 0 0 1 57.02362 309.0236 cm +1 0 0 1 57.02362 280.2236 cm q BT 1 0 0 1 0 62 Tm .226796 Tw 12 TL /F1 10 Tf 0 0 0 rg (A third correctness fix landed after the portal-over-HTTP demo exposed it: ) Tj /F5 10 Tf (lumbda.py) Tj /F1 10 Tf ('s ) Tj /F5 10 Tf (Env.lookup) Tj /F1 10 Tf ( used) Tj T* 0 Tw .794272 Tw (to short-cut from the local frame directly to the global frame before walking intermediate parents. That was) Tj T* 0 Tw .366019 Tw (fast but wrong \227 a let-loop parameter named the same as a global builtin \() Tj /F5 10 Tf (count) Tj /F1 10 Tf (, a SRFI-1 procedure\) got) Tj T* 0 Tw .949897 Tw (shadowed in reverse, the shortcut returned the global builtin instead of walking up to the loop's parameter) Tj T* 0 Tw .453797 Tw (frame. Fix: walk ) Tj /F5 10 Tf (self) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (self.p) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (...) Tj ( ) Tj /F6 10 Tf 12 TL (\256) Tj /F5 10 Tf 12 TL ( ) Tj (global) Tj /F1 10 Tf ( in order, without any shortcut. The inline cache at) Tj T* 0 Tw /F5 10 Tf (OP_LOOKUP) Tj /F1 10 Tf ( was correspondingly tightened to validate the full chain before firing. 980 tests remained green.) Tj T* ET Q Q q -1 0 0 1 57.02362 291.0236 cm +1 0 0 1 57.02362 262.2236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Every release audit surfaces more. Writing new code is writing new sediment, unless the audit runs.) Tj T* ET Q Q q -1 0 0 1 57.02362 259.8236 cm +1 0 0 1 57.02362 231.0236 cm q BT 1 0 0 1 0 2.2 Tm 13.2 TL /F2 11 Tf .133333 .133333 .133333 rg (12.2 MOAD-0002: The Intertangle in Our Own Design) Tj T* ET Q Q q -1 0 0 1 57.02362 239.8236 cm +1 0 0 1 57.02362 211.0236 cm q 0 0 0 rg BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (All three implementations share mutable global state between subsystems:) Tj T* ET Q Q q -1 0 0 1 57.02362 233.8236 cm +1 0 0 1 57.02362 205.0236 cm Q q -1 0 0 1 57.02362 233.8236 cm +1 0 0 1 57.02362 205.0236 cm Q q -1 0 0 1 57.02362 185.8236 cm +1 0 0 1 57.02362 157.0236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11958,10 +11991,10 @@ Q Q Q q -1 0 0 1 57.02362 179.8236 cm +1 0 0 1 57.02362 151.0236 cm Q q -1 0 0 1 57.02362 143.8236 cm +1 0 0 1 57.02362 115.0236 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -11983,10 +12016,10 @@ Q Q Q q -1 0 0 1 57.02362 137.8236 cm +1 0 0 1 57.02362 109.0236 cm Q q -1 0 0 1 57.02362 101.8236 cm +1 0 0 1 57.02362 73.02362 cm q 0 0 0 rg BT /F1 10 Tf 12 TL ET @@ -12008,12 +12041,12 @@ Q Q Q q -1 0 0 1 57.02362 83.82362 cm +1 0 0 1 57.02362 62.69291 cm Q endstream endobj -173 0 obj +174 0 obj << /Length 8035 >> @@ -12284,7 +12317,7 @@ Q endstream endobj -174 0 obj +175 0 obj << /Length 7245 >> @@ -12500,7 +12533,7 @@ Q endstream endobj -175 0 obj +176 0 obj << /Length 2137 >> @@ -12578,7 +12611,7 @@ q 1 0 0 1 142.0762 3 cm q 197.0759 0 0 197.0759 0 0 cm -/FormXob.c9411fecc114c344e33ac82182b38f43 Do +/FormXob.abf5431e047a12a84b98349be6f1e444 Do Q Q q @@ -12640,7 +12673,7 @@ Q endstream endobj -176 0 obj +177 0 obj << /Length 2231 >> @@ -12669,200 +12702,200 @@ Q endstream endobj -177 0 obj -<< -/Nums [ 0 178 0 R 1 179 0 R 2 180 0 R 3 181 0 R 4 182 0 R - 5 183 0 R 6 184 0 R 7 185 0 R 8 186 0 R 9 187 0 R - 10 188 0 R 11 189 0 R 12 190 0 R 13 191 0 R 14 192 0 R - 15 193 0 R 16 194 0 R 17 195 0 R 18 196 0 R 19 197 0 R - 20 198 0 R 21 199 0 R 22 200 0 R 23 201 0 R 24 202 0 R - 25 203 0 R 26 204 0 R 27 205 0 R 28 206 0 R 29 207 0 R - 30 208 0 R 31 209 0 R 32 210 0 R 33 211 0 R 34 212 0 R - 35 213 0 R ] ->> -endobj 178 0 obj << -/S /D /St 1 +/Nums [ 0 179 0 R 1 180 0 R 2 181 0 R 3 182 0 R 4 183 0 R + 5 184 0 R 6 185 0 R 7 186 0 R 8 187 0 R 9 188 0 R + 10 189 0 R 11 190 0 R 12 191 0 R 13 192 0 R 14 193 0 R + 15 194 0 R 16 195 0 R 17 196 0 R 18 197 0 R 19 198 0 R + 20 199 0 R 21 200 0 R 22 201 0 R 23 202 0 R 24 203 0 R + 25 204 0 R 26 205 0 R 27 206 0 R 28 207 0 R 29 208 0 R + 30 209 0 R 31 210 0 R 32 211 0 R 33 212 0 R 34 213 0 R + 35 214 0 R ] >> endobj 179 0 obj << -/S /D /St 2 +/S /D /St 1 >> endobj 180 0 obj << -/S /D /St 3 +/S /D /St 2 >> endobj 181 0 obj << -/S /D /St 4 +/S /D /St 3 >> endobj 182 0 obj << -/S /D /St 5 +/S /D /St 4 >> endobj 183 0 obj << -/S /D /St 6 +/S /D /St 5 >> endobj 184 0 obj << -/S /D /St 7 +/S /D /St 6 >> endobj 185 0 obj << -/S /D /St 8 +/S /D /St 7 >> endobj 186 0 obj << -/S /D /St 9 +/S /D /St 8 >> endobj 187 0 obj << -/S /D /St 10 +/S /D /St 9 >> endobj 188 0 obj << -/S /D /St 11 +/S /D /St 10 >> endobj 189 0 obj << -/S /D /St 12 +/S /D /St 11 >> endobj 190 0 obj << -/S /D /St 13 +/S /D /St 12 >> endobj 191 0 obj << -/S /D /St 14 +/S /D /St 13 >> endobj 192 0 obj << -/S /D /St 15 +/S /D /St 14 >> endobj 193 0 obj << -/S /D /St 16 +/S /D /St 15 >> endobj 194 0 obj << -/S /D /St 17 +/S /D /St 16 >> endobj 195 0 obj << -/S /D /St 18 +/S /D /St 17 >> endobj 196 0 obj << -/S /D /St 19 +/S /D /St 18 >> endobj 197 0 obj << -/S /D /St 20 +/S /D /St 19 >> endobj 198 0 obj << -/S /D /St 21 +/S /D /St 20 >> endobj 199 0 obj << -/S /D /St 22 +/S /D /St 21 >> endobj 200 0 obj << -/S /D /St 23 +/S /D /St 22 >> endobj 201 0 obj << -/S /D /St 24 +/S /D /St 23 >> endobj 202 0 obj << -/S /D /St 25 +/S /D /St 24 >> endobj 203 0 obj << -/S /D /St 26 +/S /D /St 25 >> endobj 204 0 obj << -/S /D /St 27 +/S /D /St 26 >> endobj 205 0 obj << -/S /D /St 28 +/S /D /St 27 >> endobj 206 0 obj << -/S /D /St 29 +/S /D /St 28 >> endobj 207 0 obj << -/S /D /St 30 +/S /D /St 29 >> endobj 208 0 obj << -/S /D /St 31 +/S /D /St 30 >> endobj 209 0 obj << -/S /D /St 32 +/S /D /St 31 >> endobj 210 0 obj << -/S /D /St 33 +/S /D /St 32 >> endobj 211 0 obj << -/S /D /St 34 +/S /D /St 33 >> endobj 212 0 obj << -/S /D /St 35 +/S /D /St 34 >> endobj 213 0 obj << +/S /D /St 35 +>> +endobj +214 0 obj +<< /S /D /St 36 >> endobj xref -0 214 +0 215 0000000000 65535 f 0000000061 00000 n 0000000180 00000 n @@ -12911,11 +12944,11 @@ xref 0001853322 00000 n 0001853530 00000 n 0001853738 00000 n -0001853916 00000 n -0001854143 00000 n -0001989034 00000 n -0001993298 00000 n -0002281611 00000 n +0001853946 00000 n +0001854124 00000 n +0001989015 00000 n +0001993279 00000 n +0002281592 00000 n 0002281932 00000 n 0002282140 00000 n 0002282348 00000 n @@ -12984,109 +13017,110 @@ xref 0002389132 00000 n 0002389286 00000 n 0002389427 00000 n -0002389565 00000 n -0002389719 00000 n -0002389921 00000 n -0002390044 00000 n -0002390183 00000 n -0002390347 00000 n -0002390520 00000 n -0002390693 00000 n -0002390854 00000 n -0002391022 00000 n -0002391217 00000 n -0002391376 00000 n -0002391544 00000 n -0002391679 00000 n -0002391812 00000 n -0002391957 00000 n -0002392090 00000 n -0002392216 00000 n -0002392344 00000 n -0002392455 00000 n -0002392772 00000 n -0002396064 00000 n -0002404186 00000 n -0002407645 00000 n -0002415533 00000 n -0002423350 00000 n -0002431858 00000 n -0002441741 00000 n -0002454192 00000 n -0002465823 00000 n -0002474553 00000 n -0002482697 00000 n -0002493993 00000 n -0002506022 00000 n -0002517661 00000 n -0002525696 00000 n -0002536831 00000 n -0002544302 00000 n -0002552721 00000 n -0002567116 00000 n -0002575629 00000 n -0002584644 00000 n -0002593852 00000 n -0002604244 00000 n -0002609314 00000 n -0002611149 00000 n -0002624609 00000 n -0002640810 00000 n -0002651407 00000 n -0002658477 00000 n -0002666363 00000 n -0002675340 00000 n -0002683368 00000 n -0002691456 00000 n -0002698754 00000 n -0002700944 00000 n -0002703228 00000 n -0002703668 00000 n -0002703703 00000 n -0002703738 00000 n -0002703773 00000 n -0002703808 00000 n -0002703843 00000 n -0002703878 00000 n -0002703913 00000 n -0002703948 00000 n -0002703983 00000 n -0002704019 00000 n -0002704055 00000 n -0002704091 00000 n -0002704127 00000 n -0002704163 00000 n -0002704199 00000 n -0002704235 00000 n -0002704271 00000 n -0002704307 00000 n -0002704343 00000 n -0002704379 00000 n -0002704415 00000 n -0002704451 00000 n -0002704487 00000 n -0002704523 00000 n -0002704559 00000 n -0002704595 00000 n -0002704631 00000 n -0002704667 00000 n -0002704703 00000 n -0002704739 00000 n -0002704775 00000 n -0002704811 00000 n -0002704847 00000 n -0002704883 00000 n -0002704919 00000 n +0002389606 00000 n +0002389730 00000 n +0002389884 00000 n +0002390086 00000 n +0002390209 00000 n +0002390348 00000 n +0002390512 00000 n +0002390685 00000 n +0002390858 00000 n +0002391019 00000 n +0002391187 00000 n +0002391382 00000 n +0002391541 00000 n +0002391709 00000 n +0002391844 00000 n +0002391977 00000 n +0002392122 00000 n +0002392255 00000 n +0002392381 00000 n +0002392509 00000 n +0002392620 00000 n +0002392937 00000 n +0002396229 00000 n +0002404351 00000 n +0002407810 00000 n +0002415698 00000 n +0002423515 00000 n +0002432023 00000 n +0002441906 00000 n +0002454357 00000 n +0002465988 00000 n +0002474718 00000 n +0002482862 00000 n +0002494158 00000 n +0002506187 00000 n +0002517826 00000 n +0002525861 00000 n +0002536996 00000 n +0002544467 00000 n +0002552886 00000 n +0002567281 00000 n +0002575794 00000 n +0002584809 00000 n +0002594017 00000 n +0002604409 00000 n +0002612190 00000 n +0002614532 00000 n +0002628022 00000 n +0002643510 00000 n +0002653292 00000 n +0002662314 00000 n +0002669227 00000 n +0002678862 00000 n +0002686995 00000 n +0002695083 00000 n +0002702381 00000 n +0002704571 00000 n +0002706855 00000 n +0002707295 00000 n +0002707330 00000 n +0002707365 00000 n +0002707400 00000 n +0002707435 00000 n +0002707470 00000 n +0002707505 00000 n +0002707540 00000 n +0002707575 00000 n +0002707610 00000 n +0002707646 00000 n +0002707682 00000 n +0002707718 00000 n +0002707754 00000 n +0002707790 00000 n +0002707826 00000 n +0002707862 00000 n +0002707898 00000 n +0002707934 00000 n +0002707970 00000 n +0002708006 00000 n +0002708042 00000 n +0002708078 00000 n +0002708114 00000 n +0002708150 00000 n +0002708186 00000 n +0002708222 00000 n +0002708258 00000 n +0002708294 00000 n +0002708330 00000 n +0002708366 00000 n +0002708402 00000 n +0002708438 00000 n +0002708474 00000 n +0002708510 00000 n +0002708546 00000 n trailer << /ID -[] +[] % ReportLab generated PDF document -- digest (opensource) /Info 74 0 R /Root 73 0 R -/Size 214 +/Size 215 >> startxref -2704955 +2708582 %%EOF diff --git a/whitepaper/lumbda-whitepaper.rst b/whitepaper/lumbda-whitepaper.rst index e5767f7..cedf32c 100644 --- a/whitepaper/lumbda-whitepaper.rst +++ b/whitepaper/lumbda-whitepaper.rst @@ -1066,6 +1066,27 @@ Lumbda implements a near-complete R7RS-small Scheme: **Test suite**: 974 verified assertions covering lexing, parsing, special forms, bytecode compilation, macros (hygienic & procedural), continuations, generators, record types, modules, arithmetic, higher-order functions, error handling, portal serialization, cross-implementation portal exchange, file I/O parity, & graceful degradation on mismatched or corrupt input. +9.1 Integer Square Root (``isqrt``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``sqrt`` returns an inexact real. That is the right answer when the caller wants a distance or a norm, and the wrong answer when the caller wants a count: bucket indices, loop bounds, coordinates on a grid, bignum primality witnesses. Float ``sqrt`` drifts with FPU mode, with the ``libm`` in play, and across platforms — none of which a portal should let into a replay trace. + +``(isqrt n) → floor(sqrt(n))`` ships in all three implementations. Contract matches Python 3.8+ ``math.isqrt`` and the integer half of R7RS ``exact-integer-sqrt``: integer-in, integer-out, negative argument raises. No floats anywhere in the pipeline. + +:: + + (isqrt 0) ; => 0 + (isqrt 16) ; => 4 ; exact + (isqrt 17) ; => 4 ; floor, not round + (isqrt 1000000) ; => 1000 + (isqrt -1) ; error: negative argument + +**Algorithm.** Bit-by-bit digit-recurrence (Wikipedia "Methods of computing square roots"). O(log n) shifts, adds, and compares; no multiplies, no divides, no FPU. The C and asm implementations share the same loop skeleton — the asm version (``bi_isqrt``, ``asm/lumbda.s``) runs it in three integer registers (``%r8`` radicand, ``%r9`` bit, ``%r10`` result) with no memory traffic per iteration. Python delegates to CPython's ``math.isqrt``, which uses Karatsuba-square-root for bignums. + +**Domain limits.** Python: unbounded — works on arbitrary-precision ``int``. asm: 61-bit (three tag bits consumed at the bottom of the word). C: 48-bit (NaN-boxed doubles carry the integer payload in the mantissa). Portal round-trips remain bit-identical within the smaller of the two tiers on either end; a value that fits in the C tier's 48-bit window survives every Python ↔ C ↔ asm crossing in §7.2's 3×3 matrix. + +**MOAD-0001 note.** Each call is O(log n) in the value, not in the heap or the symbol table. No hidden linear scan, no per-call allocation in C or asm. Safe to invoke inside a tight loop without inflating the overall complexity class. + 10. Relationship to Companion Papers --------------------------------------