@hviana/sema 0.1.5 → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (170) hide show
  1. package/AGENTS.md +6 -5
  2. package/CITATION.cff +49 -0
  3. package/HOW_IT_WORKS.md +11 -12
  4. package/README.md +7 -5
  5. package/dist/example/demo.js +25 -25
  6. package/dist/example/train_base.d.ts +19 -21
  7. package/dist/example/train_base.js +1700 -1952
  8. package/dist/src/alphabet.d.ts +3 -3
  9. package/dist/src/alphabet.js +24 -27
  10. package/dist/src/alu/src/alu.d.ts +169 -194
  11. package/dist/src/alu/src/alu.js +374 -414
  12. package/dist/src/alu/src/expr.d.ts +36 -43
  13. package/dist/src/alu/src/expr.js +252 -278
  14. package/dist/src/alu/src/index.d.ts +9 -98
  15. package/dist/src/alu/src/index.js +10 -64
  16. package/dist/src/alu/src/kernel-arith.d.ts +1 -5
  17. package/dist/src/alu/src/kernel-arith.js +195 -285
  18. package/dist/src/alu/src/kernel-bits.d.ts +1 -5
  19. package/dist/src/alu/src/kernel-bits.js +81 -115
  20. package/dist/src/alu/src/kernel-logic.js +33 -63
  21. package/dist/src/alu/src/kernel-nd.js +155 -195
  22. package/dist/src/alu/src/kernel-numeric.d.ts +16 -80
  23. package/dist/src/alu/src/kernel-numeric.js +259 -331
  24. package/dist/src/alu/src/operation.d.ts +112 -132
  25. package/dist/src/alu/src/operation.js +149 -163
  26. package/dist/src/alu/src/parser.d.ts +168 -175
  27. package/dist/src/alu/src/parser.js +382 -421
  28. package/dist/src/alu/src/resonance.d.ts +16 -25
  29. package/dist/src/alu/src/resonance.js +49 -56
  30. package/dist/src/alu/src/text.d.ts +3 -7
  31. package/dist/src/alu/src/text.js +31 -37
  32. package/dist/src/alu/src/value.d.ts +14 -14
  33. package/dist/src/alu/src/value.js +150 -160
  34. package/dist/src/alu/test/alu.test.js +543 -656
  35. package/dist/src/bytes.d.ts +1 -5
  36. package/dist/src/bytes.js +33 -40
  37. package/dist/src/config.d.ts +99 -102
  38. package/dist/src/config.js +78 -83
  39. package/dist/src/derive/src/deduction.d.ts +60 -62
  40. package/dist/src/derive/src/deduction.js +103 -109
  41. package/dist/src/derive/src/index.d.ts +1 -7
  42. package/dist/src/derive/src/priority-queue.d.ts +8 -8
  43. package/dist/src/derive/src/priority-queue.js +57 -61
  44. package/dist/src/derive/src/rewrite.d.ts +15 -18
  45. package/dist/src/derive/src/rewrite.js +59 -67
  46. package/dist/src/derive/src/trie.d.ts +56 -56
  47. package/dist/src/derive/src/trie.js +175 -179
  48. package/dist/src/derive/test/derive.test.js +96 -100
  49. package/dist/src/extension.d.ts +13 -16
  50. package/dist/src/geometry.d.ts +29 -43
  51. package/dist/src/geometry.js +324 -268
  52. package/dist/src/index.d.ts +2 -17
  53. package/dist/src/index.js +2 -12
  54. package/dist/src/ingest-cache.d.ts +25 -30
  55. package/dist/src/ingest-cache.js +108 -127
  56. package/dist/src/mind/articulation.d.ts +1 -5
  57. package/dist/src/mind/articulation.js +77 -112
  58. package/dist/src/mind/attention.d.ts +40 -108
  59. package/dist/src/mind/attention.js +754 -872
  60. package/dist/src/mind/canonical.d.ts +4 -19
  61. package/dist/src/mind/canonical.js +27 -31
  62. package/dist/src/mind/graph-search.d.ts +201 -225
  63. package/dist/src/mind/graph-search.js +742 -821
  64. package/dist/src/mind/index.d.ts +2 -10
  65. package/dist/src/mind/junction.d.ts +31 -58
  66. package/dist/src/mind/junction.js +172 -237
  67. package/dist/src/mind/learning.d.ts +16 -52
  68. package/dist/src/mind/learning.js +143 -165
  69. package/dist/src/mind/match.d.ts +20 -69
  70. package/dist/src/mind/match.js +259 -318
  71. package/dist/src/mind/mechanisms/alu.js +16 -16
  72. package/dist/src/mind/mechanisms/cast.d.ts +9 -13
  73. package/dist/src/mind/mechanisms/cast.js +363 -456
  74. package/dist/src/mind/mechanisms/confluence.d.ts +8 -12
  75. package/dist/src/mind/mechanisms/confluence.js +152 -183
  76. package/dist/src/mind/mechanisms/cover.d.ts +2 -8
  77. package/dist/src/mind/mechanisms/cover.js +148 -210
  78. package/dist/src/mind/mechanisms/extraction.d.ts +8 -34
  79. package/dist/src/mind/mechanisms/extraction.js +234 -288
  80. package/dist/src/mind/mechanisms/recall.d.ts +6 -10
  81. package/dist/src/mind/mechanisms/recall.js +141 -185
  82. package/dist/src/mind/mind.d.ts +194 -155
  83. package/dist/src/mind/mind.js +392 -289
  84. package/dist/src/mind/pipeline-mechanism.d.ts +112 -124
  85. package/dist/src/mind/pipeline-mechanism.js +161 -172
  86. package/dist/src/mind/pipeline.d.ts +4 -14
  87. package/dist/src/mind/pipeline.js +125 -189
  88. package/dist/src/mind/primitives.d.ts +20 -33
  89. package/dist/src/mind/primitives.js +124 -120
  90. package/dist/src/mind/rationale.d.ts +86 -98
  91. package/dist/src/mind/rationale.js +113 -121
  92. package/dist/src/mind/reasoning.d.ts +2 -13
  93. package/dist/src/mind/reasoning.js +129 -166
  94. package/dist/src/mind/recognition.d.ts +1 -4
  95. package/dist/src/mind/recognition.js +198 -210
  96. package/dist/src/mind/resonance.d.ts +5 -22
  97. package/dist/src/mind/resonance.js +0 -0
  98. package/dist/src/mind/trace.d.ts +6 -25
  99. package/dist/src/mind/trace.js +50 -58
  100. package/dist/src/mind/traverse.d.ts +29 -58
  101. package/dist/src/mind/traverse.js +344 -356
  102. package/dist/src/mind/types.d.ts +122 -127
  103. package/dist/src/mind/types.js +60 -69
  104. package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
  105. package/dist/src/rabitq-ivf/src/database.js +201 -0
  106. package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
  107. package/dist/src/{rabitq-hnsw → rabitq-ivf}/src/index.js +1 -3
  108. package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
  109. package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
  110. package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
  111. package/dist/src/rabitq-ivf/src/prng.js +36 -0
  112. package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
  113. package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
  114. package/dist/src/sema.d.ts +9 -13
  115. package/dist/src/sema.js +26 -40
  116. package/dist/src/store-sqlite.d.ts +171 -166
  117. package/dist/src/store-sqlite.js +768 -662
  118. package/dist/src/store.d.ts +597 -630
  119. package/dist/src/store.js +1434 -1581
  120. package/dist/src/vec.d.ts +5 -9
  121. package/dist/src/vec.js +61 -73
  122. package/example/train_base.ts +33 -15
  123. package/index.html +65 -0
  124. package/package.json +1 -1
  125. package/src/alu/README.md +1 -1
  126. package/src/alu/src/index.ts +1 -1
  127. package/src/config.ts +19 -27
  128. package/src/geometry.ts +93 -1
  129. package/src/index.ts +6 -11
  130. package/src/mind/attention.ts +11 -6
  131. package/src/mind/mechanisms/recall.ts +29 -13
  132. package/src/mind/mind.ts +250 -19
  133. package/src/mind/primitives.ts +43 -6
  134. package/src/mind/recognition.ts +26 -8
  135. package/src/mind/traverse.ts +47 -0
  136. package/src/mind/types.ts +20 -21
  137. package/src/rabitq-ivf/README.md +56 -0
  138. package/src/rabitq-ivf/src/database.ts +276 -0
  139. package/src/{rabitq-hnsw → rabitq-ivf}/src/index.ts +2 -5
  140. package/src/rabitq-ivf/src/ivf.ts +1330 -0
  141. package/src/{rabitq-hnsw → rabitq-ivf}/src/prng.ts +1 -1
  142. package/src/store-sqlite.ts +204 -9
  143. package/src/store.ts +27 -34
  144. package/test/08-storage.test.mjs +3 -3
  145. package/test/13-conversation.test.mjs +190 -20
  146. package/test/14-scaling.test.mjs +2 -2
  147. package/test/35-ivf.test.mjs +263 -0
  148. package/test/36-bloom.test.mjs +123 -0
  149. package/dist/src/rabitq-hnsw/src/database.d.ts +0 -202
  150. package/dist/src/rabitq-hnsw/src/database.js +0 -405
  151. package/dist/src/rabitq-hnsw/src/heap.d.ts +0 -22
  152. package/dist/src/rabitq-hnsw/src/heap.js +0 -94
  153. package/dist/src/rabitq-hnsw/src/hnsw.d.ts +0 -125
  154. package/dist/src/rabitq-hnsw/src/hnsw.js +0 -500
  155. package/dist/src/rabitq-hnsw/src/index.d.ts +0 -15
  156. package/dist/src/rabitq-hnsw/src/prng.d.ts +0 -19
  157. package/dist/src/rabitq-hnsw/src/prng.js +0 -38
  158. package/dist/src/rabitq-hnsw/src/rabitq.d.ts +0 -95
  159. package/dist/src/rabitq-hnsw/src/rabitq.js +0 -299
  160. package/dist/src/rabitq-hnsw/src/store.d.ts +0 -162
  161. package/dist/src/rabitq-hnsw/src/store.js +0 -916
  162. package/dist/src/rabitq-hnsw/test/hnsw.test.d.ts +0 -1
  163. package/dist/src/rabitq-hnsw/test/hnsw.test.js +0 -1197
  164. package/src/rabitq-hnsw/README.md +0 -303
  165. package/src/rabitq-hnsw/src/database.ts +0 -492
  166. package/src/rabitq-hnsw/src/heap.ts +0 -90
  167. package/src/rabitq-hnsw/src/hnsw.ts +0 -514
  168. package/src/rabitq-hnsw/src/store.ts +0 -994
  169. package/src/rabitq-hnsw/test/hnsw.test.ts +0 -1213
  170. /package/src/{rabitq-hnsw → rabitq-ivf}/src/rabitq.ts +0 -0
@@ -46,8 +46,8 @@ export const int = (n) => ({ domain: "int", n });
46
46
  export const real = (x) => ({ domain: "real", x });
47
47
  /** A symbolic value: an opaque byte span of any modality (see module note). */
48
48
  export const symbol = (bytes) => ({
49
- domain: "symbol",
50
- bytes,
49
+ domain: "symbol",
50
+ bytes,
51
51
  });
52
52
  /** An n-dimensional value: an ordered list of element values (each any domain,
53
53
  * including a nested nd). See the module note on nd. */
@@ -57,11 +57,11 @@ export const tagOf = (v) => v.domain;
57
57
  /** Whether a value is a numeric SCALAR (bit, int, or real) — an nd is not, even
58
58
  * if every element is numeric (it is a container; reduce it to a scalar). */
59
59
  export function isNumeric(v) {
60
- return v.domain === "bit" || v.domain === "int" || v.domain === "real";
60
+ return v.domain === "bit" || v.domain === "int" || v.domain === "real";
61
61
  }
62
62
  /** Whether a value is the n-dimensional container. */
63
63
  export function isNd(v) {
64
- return v.domain === "nd";
64
+ return v.domain === "nd";
65
65
  }
66
66
  /** Collect, into `out`, every SYMBOL byte span reachable inside a value — itself
67
67
  * when it is a symbol, or each element recursively when it is an nd. These are
@@ -69,13 +69,12 @@ export function isNd(v) {
69
69
  * argument names) the host pre-resolves before a computation; numbers carry no
70
70
  * meaning to resolve, so they are skipped. */
71
71
  export function symbolSpans(v, out) {
72
- if (v.domain === "symbol") {
73
- out.push(v.bytes);
74
- } else if (isNd(v)) {
75
- for (const e of v.items) {
76
- symbolSpans(e, out);
72
+ if (v.domain === "symbol")
73
+ out.push(v.bytes);
74
+ else if (isNd(v)) {
75
+ for (const e of v.items)
76
+ symbolSpans(e, out);
77
77
  }
78
- }
79
78
  }
80
79
  // ── coercions (the functor's object map between domains) ────────────────────
81
80
  /** A value as a JS number — bit→0|1, int→Number, real as-is. Throws on a
@@ -83,108 +82,103 @@ export function symbolSpans(v, out) {
83
82
  * caller (or the graph adapter's try/catch) should surface, never silently
84
83
  * coerce to NaN. */
85
84
  export function asReal(v) {
86
- switch (v.domain) {
87
- case "bit":
88
- return v.b;
89
- case "int":
90
- return Number(v.n);
91
- case "real":
92
- return v.x;
93
- case "symbol":
94
- throw new TypeError("asReal: a symbol value has no numeric reading");
95
- case "nd":
96
- // An nd has no scalar reading: a scalar primitive never sees one, because
97
- // broadcast (operation.ts) lifts it element-wise first. Reaching here
98
- // means a structural op was mis-called on a list as if it were a scalar.
99
- throw new TypeError("asReal: an nd value has no scalar numeric reading");
100
- }
85
+ switch (v.domain) {
86
+ case "bit":
87
+ return v.b;
88
+ case "int":
89
+ return Number(v.n);
90
+ case "real":
91
+ return v.x;
92
+ case "symbol":
93
+ throw new TypeError("asReal: a symbol value has no numeric reading");
94
+ case "nd":
95
+ // An nd has no scalar reading: a scalar primitive never sees one, because
96
+ // broadcast (operation.ts) lifts it element-wise first. Reaching here
97
+ // means a structural op was mis-called on a list as if it were a scalar.
98
+ throw new TypeError("asReal: an nd value has no scalar numeric reading");
99
+ }
101
100
  }
102
101
  /** A value as an exact bigint — real is truncated toward zero (a real that is
103
102
  * not integral loses its fraction; callers wanting exactness keep it int). */
104
103
  export function asInt(v) {
105
- switch (v.domain) {
106
- case "bit":
107
- return BigInt(v.b);
108
- case "int":
109
- return v.n;
110
- case "real":
111
- return BigInt(Math.trunc(v.x));
112
- case "symbol":
113
- throw new TypeError("asInt: a symbol value has no integer reading");
114
- case "nd":
115
- throw new TypeError("asInt: an nd value has no scalar integer reading");
116
- }
104
+ switch (v.domain) {
105
+ case "bit":
106
+ return BigInt(v.b);
107
+ case "int":
108
+ return v.n;
109
+ case "real":
110
+ return BigInt(Math.trunc(v.x));
111
+ case "symbol":
112
+ throw new TypeError("asInt: a symbol value has no integer reading");
113
+ case "nd":
114
+ throw new TypeError("asInt: an nd value has no scalar integer reading");
115
+ }
117
116
  }
118
117
  /** A value as a logic bit — nonzero numbers read as 1, zero as 0. Throws on a
119
118
  * symbol (an opaque form is not a truth value). */
120
119
  export function asBit(v) {
121
- switch (v.domain) {
122
- case "bit":
123
- return v.b;
124
- case "int":
125
- return v.n === 0n ? 0 : 1;
126
- case "real":
127
- return v.x === 0 ? 0 : 1;
128
- case "symbol":
129
- throw new TypeError("asBit: a symbol value is not a truth value");
130
- case "nd":
131
- throw new TypeError("asBit: an nd value is not a scalar truth value");
132
- }
120
+ switch (v.domain) {
121
+ case "bit":
122
+ return v.b;
123
+ case "int":
124
+ return v.n === 0n ? 0 : 1;
125
+ case "real":
126
+ return v.x === 0 ? 0 : 1;
127
+ case "symbol":
128
+ throw new TypeError("asBit: a symbol value is not a truth value");
129
+ case "nd":
130
+ throw new TypeError("asBit: an nd value is not a scalar truth value");
131
+ }
133
132
  }
134
133
  /** Promote a value into a target numeric domain (bit ⊂ int ⊂ real). Used when
135
134
  * a mixed-domain expression must agree on one domain before a primitive runs —
136
135
  * the rule is the natural lattice: any real operand pulls the whole expression
137
136
  * to real, otherwise any int pulls it to int, otherwise bit. */
138
137
  export function coerce(v, domain) {
139
- if (v.domain === domain) {
140
- return v;
141
- }
142
- switch (domain) {
143
- case "bit":
144
- return bit(asBit(v));
145
- case "int":
146
- return int(asInt(v));
147
- case "real":
148
- return real(asReal(v));
149
- }
138
+ if (v.domain === domain)
139
+ return v;
140
+ switch (domain) {
141
+ case "bit":
142
+ return bit(asBit(v));
143
+ case "int":
144
+ return int(asInt(v));
145
+ case "real":
146
+ return real(asReal(v));
147
+ }
150
148
  }
151
149
  /** The common numeric domain of a list of operands, by the bit ⊂ int ⊂ real
152
150
  * lattice: real if any operand is real, else int if any is int, else bit.
153
151
  * Throws if any operand is a symbol. This is how a polymorphic arithmetic op
154
152
  * decides whether to take the exact bigint path or the native-double path. */
155
153
  export function joinDomain(args) {
156
- let d = "bit";
157
- for (const a of args) {
158
- if (a.domain === "symbol") {
159
- throw new TypeError("joinDomain: cannot join a symbol value numerically");
160
- }
161
- if (a.domain === "nd") {
162
- throw new TypeError("joinDomain: cannot join an nd value numerically");
163
- }
164
- if (a.domain === "real") {
165
- return "real";
166
- }
167
- if (a.domain === "int" && d === "bit") {
168
- d = "int";
154
+ let d = "bit";
155
+ for (const a of args) {
156
+ if (a.domain === "symbol") {
157
+ throw new TypeError("joinDomain: cannot join a symbol value numerically");
158
+ }
159
+ if (a.domain === "nd") {
160
+ throw new TypeError("joinDomain: cannot join an nd value numerically");
161
+ }
162
+ if (a.domain === "real")
163
+ return "real";
164
+ if (a.domain === "int" && d === "bit")
165
+ d = "int";
169
166
  }
170
- }
171
- return d;
167
+ return d;
172
168
  }
173
169
  const ASCII = {
174
- decode: (b) => {
175
- let s = "";
176
- for (let i = 0; i < b.length; i++) {
177
- s += String.fromCharCode(b[i]);
178
- }
179
- return s;
180
- },
181
- encode: (s) => {
182
- const out = new Uint8Array(s.length);
183
- for (let i = 0; i < s.length; i++) {
184
- out[i] = s.charCodeAt(i) & 0xff;
185
- }
186
- return out;
187
- },
170
+ decode: (b) => {
171
+ let s = "";
172
+ for (let i = 0; i < b.length; i++)
173
+ s += String.fromCharCode(b[i]);
174
+ return s;
175
+ },
176
+ encode: (s) => {
177
+ const out = new Uint8Array(s.length);
178
+ for (let i = 0; i < s.length; i++)
179
+ out[i] = s.charCodeAt(i) & 0xff;
180
+ return out;
181
+ },
188
182
  };
189
183
  /** A decimal numeral, sign, optional fraction, optional exponent — the syntax
190
184
  * {@link parseScalar} accepts as a number. Anything else is a symbol. */
@@ -192,38 +186,38 @@ const NUMERAL = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
192
186
  /** Concatenate byte arrays — used to build an nd literal's encoding without
193
187
  * routing a (possibly non-ASCII, multimodal) symbol's bytes through a string. */
194
188
  function concatBytes(arrs) {
195
- let len = 0;
196
- for (const a of arrs) {
197
- len += a.length;
198
- }
199
- const out = new Uint8Array(len);
200
- let o = 0;
201
- for (const a of arrs) {
202
- out.set(a, o);
203
- o += a.length;
204
- }
205
- return out;
189
+ let len = 0;
190
+ for (const a of arrs)
191
+ len += a.length;
192
+ const out = new Uint8Array(len);
193
+ let o = 0;
194
+ for (const a of arrs) {
195
+ out.set(a, o);
196
+ o += a.length;
197
+ }
198
+ return out;
206
199
  }
207
200
  /** Parse a SCALAR span: a clean integer numeral → exact int, a fractional/
208
201
  * exponent numeral → real, anything else → a symbol carrying `bytes` verbatim.
209
202
  * Strict, so it never hijacks a form that merely begins with a digit. */
210
203
  function parseScalar(bytes, s) {
211
- if (s.length > 0 && NUMERAL.test(s)) {
212
- if (/[.eE]/.test(s)) {
213
- const x = Number(s);
214
- if (Number.isFinite(x)) {
215
- return real(x);
216
- }
217
- } else {
218
- // A clean integer: strip a leading '+' that BigInt rejects.
219
- try {
220
- return int(BigInt(s[0] === "+" ? s.slice(1) : s));
221
- } catch {
222
- /* fall through to symbol */
223
- }
204
+ if (s.length > 0 && NUMERAL.test(s)) {
205
+ if (/[.eE]/.test(s)) {
206
+ const x = Number(s);
207
+ if (Number.isFinite(x))
208
+ return real(x);
209
+ }
210
+ else {
211
+ // A clean integer: strip a leading '+' that BigInt rejects.
212
+ try {
213
+ return int(BigInt(s[0] === "+" ? s.slice(1) : s));
214
+ }
215
+ catch {
216
+ /* fall through to symbol */
217
+ }
218
+ }
224
219
  }
225
- }
226
- return symbol(bytes);
220
+ return symbol(bytes);
227
221
  }
228
222
  /** Parse a byte span into a SCALAR value: a clean integer numeral → exact int, a
229
223
  * fractional/exponent numeral → real, anything else → a symbol carrying its
@@ -241,24 +235,21 @@ function parseScalar(bytes, s) {
241
235
  * Numerals are ASCII by construction; for any other byte content the bytes are
242
236
  * preserved opaquely, so a symbol of any modality round-trips untouched. */
243
237
  export function parseValue(bytes) {
244
- return parseScalar(bytes, ASCII.decode(bytes));
238
+ return parseScalar(bytes, ASCII.decode(bytes));
245
239
  }
246
240
  /** Canonically format a real as a decimal string: round to `precision` places,
247
241
  * then trim trailing zeros (and a bare trailing point), normalising -0 to 0.
248
242
  * Determinism here is load-bearing — the search keys an output span by its
249
243
  * bytes, so two derivations of the same number MUST spell it identically. */
250
244
  export function formatReal(x, precision) {
251
- if (!Number.isFinite(x)) {
252
- return String(x); // "Infinity" / "NaN" / "-Infinity"
253
- }
254
- let s = x.toFixed(precision);
255
- if (s.indexOf(".") >= 0) {
256
- s = s.replace(/\.?0+$/, "");
257
- }
258
- if (s === "-0" || s === "") {
259
- s = "0";
260
- }
261
- return s;
245
+ if (!Number.isFinite(x))
246
+ return String(x); // "Infinity" / "NaN" / "-Infinity"
247
+ let s = x.toFixed(precision);
248
+ if (s.indexOf(".") >= 0)
249
+ s = s.replace(/\.?0+$/, "");
250
+ if (s === "-0" || s === "")
251
+ s = "0";
252
+ return s;
262
253
  }
263
254
  /** The default codec: integers as exact decimals, reals canonically formatted,
264
255
  * bits as "0"/"1", symbols as their own bytes (verbatim, any modality), and an
@@ -273,38 +264,37 @@ export function formatReal(x, precision) {
273
264
  * bracket literal decodes back to an opaque symbol. Reading list STRUCTURE from
274
265
  * bytes is layered one level up, in {@link "./alu.js".Alu.recogniseValue}. */
275
266
  export function decimalCodec(precision) {
276
- const enc = (v) => {
277
- switch (v.domain) {
278
- case "bit":
279
- return ASCII.encode(String(v.b));
280
- case "int":
281
- return ASCII.encode(v.n.toString());
282
- case "real":
283
- return ASCII.encode(formatReal(v.x, precision));
284
- case "symbol":
285
- return v.bytes;
286
- case "nd": {
287
- // [e0,e1,…] at the byte level, so a symbol element's arbitrary
288
- // (possibly non-ASCII / multimodal) bytes pass through untouched.
289
- const OPEN = ASCII.encode("[");
290
- const CLOSE = ASCII.encode("]");
291
- const COMMA = ASCII.encode(",");
292
- const parts = [OPEN];
293
- for (let i = 0; i < v.items.length; i++) {
294
- if (i > 0) {
295
- parts.push(COMMA);
296
- }
297
- parts.push(enc(v.items[i]));
267
+ const enc = (v) => {
268
+ switch (v.domain) {
269
+ case "bit":
270
+ return ASCII.encode(String(v.b));
271
+ case "int":
272
+ return ASCII.encode(v.n.toString());
273
+ case "real":
274
+ return ASCII.encode(formatReal(v.x, precision));
275
+ case "symbol":
276
+ return v.bytes;
277
+ case "nd": {
278
+ // [e0,e1,…] at the byte level, so a symbol element's arbitrary
279
+ // (possibly non-ASCII / multimodal) bytes pass through untouched.
280
+ const OPEN = ASCII.encode("[");
281
+ const CLOSE = ASCII.encode("]");
282
+ const COMMA = ASCII.encode(",");
283
+ const parts = [OPEN];
284
+ for (let i = 0; i < v.items.length; i++) {
285
+ if (i > 0)
286
+ parts.push(COMMA);
287
+ parts.push(enc(v.items[i]));
288
+ }
289
+ parts.push(CLOSE);
290
+ return concatBytes(parts);
291
+ }
298
292
  }
299
- parts.push(CLOSE);
300
- return concatBytes(parts);
301
- }
302
- }
303
- };
304
- return {
305
- encode: enc,
306
- decode(bytes) {
307
- return parseValue(bytes);
308
- },
309
- };
293
+ };
294
+ return {
295
+ encode: enc,
296
+ decode(bytes) {
297
+ return parseValue(bytes);
298
+ },
299
+ };
310
300
  }