@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.
- package/AGENTS.md +6 -5
- package/CITATION.cff +49 -0
- package/HOW_IT_WORKS.md +11 -12
- package/README.md +7 -5
- package/dist/example/demo.js +25 -25
- package/dist/example/train_base.d.ts +19 -21
- package/dist/example/train_base.js +1700 -1952
- package/dist/src/alphabet.d.ts +3 -3
- package/dist/src/alphabet.js +24 -27
- package/dist/src/alu/src/alu.d.ts +169 -194
- package/dist/src/alu/src/alu.js +374 -414
- package/dist/src/alu/src/expr.d.ts +36 -43
- package/dist/src/alu/src/expr.js +252 -278
- package/dist/src/alu/src/index.d.ts +9 -98
- package/dist/src/alu/src/index.js +10 -64
- package/dist/src/alu/src/kernel-arith.d.ts +1 -5
- package/dist/src/alu/src/kernel-arith.js +195 -285
- package/dist/src/alu/src/kernel-bits.d.ts +1 -5
- package/dist/src/alu/src/kernel-bits.js +81 -115
- package/dist/src/alu/src/kernel-logic.js +33 -63
- package/dist/src/alu/src/kernel-nd.js +155 -195
- package/dist/src/alu/src/kernel-numeric.d.ts +16 -80
- package/dist/src/alu/src/kernel-numeric.js +259 -331
- package/dist/src/alu/src/operation.d.ts +112 -132
- package/dist/src/alu/src/operation.js +149 -163
- package/dist/src/alu/src/parser.d.ts +168 -175
- package/dist/src/alu/src/parser.js +382 -421
- package/dist/src/alu/src/resonance.d.ts +16 -25
- package/dist/src/alu/src/resonance.js +49 -56
- package/dist/src/alu/src/text.d.ts +3 -7
- package/dist/src/alu/src/text.js +31 -37
- package/dist/src/alu/src/value.d.ts +14 -14
- package/dist/src/alu/src/value.js +150 -160
- package/dist/src/alu/test/alu.test.js +543 -656
- package/dist/src/bytes.d.ts +1 -5
- package/dist/src/bytes.js +33 -40
- package/dist/src/config.d.ts +99 -102
- package/dist/src/config.js +78 -83
- package/dist/src/derive/src/deduction.d.ts +60 -62
- package/dist/src/derive/src/deduction.js +103 -109
- package/dist/src/derive/src/index.d.ts +1 -7
- package/dist/src/derive/src/priority-queue.d.ts +8 -8
- package/dist/src/derive/src/priority-queue.js +57 -61
- package/dist/src/derive/src/rewrite.d.ts +15 -18
- package/dist/src/derive/src/rewrite.js +59 -67
- package/dist/src/derive/src/trie.d.ts +56 -56
- package/dist/src/derive/src/trie.js +175 -179
- package/dist/src/derive/test/derive.test.js +96 -100
- package/dist/src/extension.d.ts +13 -16
- package/dist/src/geometry.d.ts +29 -43
- package/dist/src/geometry.js +324 -268
- package/dist/src/index.d.ts +2 -17
- package/dist/src/index.js +2 -12
- package/dist/src/ingest-cache.d.ts +25 -30
- package/dist/src/ingest-cache.js +108 -127
- package/dist/src/mind/articulation.d.ts +1 -5
- package/dist/src/mind/articulation.js +77 -112
- package/dist/src/mind/attention.d.ts +40 -108
- package/dist/src/mind/attention.js +754 -872
- package/dist/src/mind/canonical.d.ts +4 -19
- package/dist/src/mind/canonical.js +27 -31
- package/dist/src/mind/graph-search.d.ts +201 -225
- package/dist/src/mind/graph-search.js +742 -821
- package/dist/src/mind/index.d.ts +2 -10
- package/dist/src/mind/junction.d.ts +31 -58
- package/dist/src/mind/junction.js +172 -237
- package/dist/src/mind/learning.d.ts +16 -52
- package/dist/src/mind/learning.js +143 -165
- package/dist/src/mind/match.d.ts +20 -69
- package/dist/src/mind/match.js +259 -318
- package/dist/src/mind/mechanisms/alu.js +16 -16
- package/dist/src/mind/mechanisms/cast.d.ts +9 -13
- package/dist/src/mind/mechanisms/cast.js +363 -456
- package/dist/src/mind/mechanisms/confluence.d.ts +8 -12
- package/dist/src/mind/mechanisms/confluence.js +152 -183
- package/dist/src/mind/mechanisms/cover.d.ts +2 -8
- package/dist/src/mind/mechanisms/cover.js +148 -210
- package/dist/src/mind/mechanisms/extraction.d.ts +8 -34
- package/dist/src/mind/mechanisms/extraction.js +234 -288
- package/dist/src/mind/mechanisms/recall.d.ts +6 -10
- package/dist/src/mind/mechanisms/recall.js +141 -185
- package/dist/src/mind/mind.d.ts +194 -155
- package/dist/src/mind/mind.js +392 -289
- package/dist/src/mind/pipeline-mechanism.d.ts +112 -124
- package/dist/src/mind/pipeline-mechanism.js +161 -172
- package/dist/src/mind/pipeline.d.ts +4 -14
- package/dist/src/mind/pipeline.js +125 -189
- package/dist/src/mind/primitives.d.ts +20 -33
- package/dist/src/mind/primitives.js +124 -120
- package/dist/src/mind/rationale.d.ts +86 -98
- package/dist/src/mind/rationale.js +113 -121
- package/dist/src/mind/reasoning.d.ts +2 -13
- package/dist/src/mind/reasoning.js +129 -166
- package/dist/src/mind/recognition.d.ts +1 -4
- package/dist/src/mind/recognition.js +198 -210
- package/dist/src/mind/resonance.d.ts +5 -22
- package/dist/src/mind/resonance.js +0 -0
- package/dist/src/mind/trace.d.ts +6 -25
- package/dist/src/mind/trace.js +50 -58
- package/dist/src/mind/traverse.d.ts +29 -58
- package/dist/src/mind/traverse.js +344 -356
- package/dist/src/mind/types.d.ts +122 -127
- package/dist/src/mind/types.js +60 -69
- package/dist/src/rabitq-ivf/src/database.d.ts +113 -0
- package/dist/src/rabitq-ivf/src/database.js +201 -0
- package/dist/src/rabitq-ivf/src/index.d.ts +7 -0
- package/dist/src/{rabitq-hnsw → rabitq-ivf}/src/index.js +1 -3
- package/dist/src/rabitq-ivf/src/ivf.d.ts +200 -0
- package/dist/src/rabitq-ivf/src/ivf.js +1165 -0
- package/dist/src/rabitq-ivf/src/prng.d.ts +19 -0
- package/dist/src/rabitq-ivf/src/prng.js +36 -0
- package/dist/src/rabitq-ivf/src/rabitq.d.ts +95 -0
- package/dist/src/rabitq-ivf/src/rabitq.js +283 -0
- package/dist/src/sema.d.ts +9 -13
- package/dist/src/sema.js +26 -40
- package/dist/src/store-sqlite.d.ts +171 -166
- package/dist/src/store-sqlite.js +768 -662
- package/dist/src/store.d.ts +597 -630
- package/dist/src/store.js +1434 -1581
- package/dist/src/vec.d.ts +5 -9
- package/dist/src/vec.js +61 -73
- package/example/train_base.ts +33 -15
- package/index.html +65 -0
- package/package.json +1 -1
- package/src/alu/README.md +1 -1
- package/src/alu/src/index.ts +1 -1
- package/src/config.ts +19 -27
- package/src/geometry.ts +93 -1
- package/src/index.ts +6 -11
- package/src/mind/attention.ts +11 -6
- package/src/mind/mechanisms/recall.ts +29 -13
- package/src/mind/mind.ts +250 -19
- package/src/mind/primitives.ts +43 -6
- package/src/mind/recognition.ts +26 -8
- package/src/mind/traverse.ts +47 -0
- package/src/mind/types.ts +20 -21
- package/src/rabitq-ivf/README.md +56 -0
- package/src/rabitq-ivf/src/database.ts +276 -0
- package/src/{rabitq-hnsw → rabitq-ivf}/src/index.ts +2 -5
- package/src/rabitq-ivf/src/ivf.ts +1330 -0
- package/src/{rabitq-hnsw → rabitq-ivf}/src/prng.ts +1 -1
- package/src/store-sqlite.ts +204 -9
- package/src/store.ts +27 -34
- package/test/08-storage.test.mjs +3 -3
- package/test/13-conversation.test.mjs +190 -20
- package/test/14-scaling.test.mjs +2 -2
- package/test/35-ivf.test.mjs +263 -0
- package/test/36-bloom.test.mjs +123 -0
- package/dist/src/rabitq-hnsw/src/database.d.ts +0 -202
- package/dist/src/rabitq-hnsw/src/database.js +0 -405
- package/dist/src/rabitq-hnsw/src/heap.d.ts +0 -22
- package/dist/src/rabitq-hnsw/src/heap.js +0 -94
- package/dist/src/rabitq-hnsw/src/hnsw.d.ts +0 -125
- package/dist/src/rabitq-hnsw/src/hnsw.js +0 -500
- package/dist/src/rabitq-hnsw/src/index.d.ts +0 -15
- package/dist/src/rabitq-hnsw/src/prng.d.ts +0 -19
- package/dist/src/rabitq-hnsw/src/prng.js +0 -38
- package/dist/src/rabitq-hnsw/src/rabitq.d.ts +0 -95
- package/dist/src/rabitq-hnsw/src/rabitq.js +0 -299
- package/dist/src/rabitq-hnsw/src/store.d.ts +0 -162
- package/dist/src/rabitq-hnsw/src/store.js +0 -916
- package/dist/src/rabitq-hnsw/test/hnsw.test.d.ts +0 -1
- package/dist/src/rabitq-hnsw/test/hnsw.test.js +0 -1197
- package/src/rabitq-hnsw/README.md +0 -303
- package/src/rabitq-hnsw/src/database.ts +0 -492
- package/src/rabitq-hnsw/src/heap.ts +0 -90
- package/src/rabitq-hnsw/src/hnsw.ts +0 -514
- package/src/rabitq-hnsw/src/store.ts +0 -994
- package/src/rabitq-hnsw/test/hnsw.test.ts +0 -1213
- /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
|
-
|
|
50
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
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
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
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
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
s
|
|
257
|
-
|
|
258
|
-
|
|
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
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
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
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
}
|