@hviana/sema 0.2.5 → 0.2.6

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 (133) hide show
  1. package/package.json +1 -1
  2. package/src/mind/attention.ts +355 -19
  3. package/test/53-cross-region-probe-instrumentation.test.mjs +356 -0
  4. package/dist/example/demo.d.ts +0 -1
  5. package/dist/example/demo.js +0 -39
  6. package/dist/example/train_base.d.ts +0 -87
  7. package/dist/example/train_base.js +0 -2252
  8. package/dist/src/alphabet.d.ts +0 -7
  9. package/dist/src/alphabet.js +0 -33
  10. package/dist/src/alu/src/alu.d.ts +0 -185
  11. package/dist/src/alu/src/alu.js +0 -440
  12. package/dist/src/alu/src/expr.d.ts +0 -61
  13. package/dist/src/alu/src/expr.js +0 -318
  14. package/dist/src/alu/src/index.d.ts +0 -11
  15. package/dist/src/alu/src/index.js +0 -19
  16. package/dist/src/alu/src/kernel-arith.d.ts +0 -16
  17. package/dist/src/alu/src/kernel-arith.js +0 -264
  18. package/dist/src/alu/src/kernel-bits.d.ts +0 -19
  19. package/dist/src/alu/src/kernel-bits.js +0 -152
  20. package/dist/src/alu/src/kernel-logic.d.ts +0 -4
  21. package/dist/src/alu/src/kernel-logic.js +0 -60
  22. package/dist/src/alu/src/kernel-nd.d.ts +0 -3
  23. package/dist/src/alu/src/kernel-nd.js +0 -208
  24. package/dist/src/alu/src/kernel-numeric.d.ts +0 -54
  25. package/dist/src/alu/src/kernel-numeric.js +0 -366
  26. package/dist/src/alu/src/operation.d.ts +0 -168
  27. package/dist/src/alu/src/operation.js +0 -189
  28. package/dist/src/alu/src/parser.d.ts +0 -221
  29. package/dist/src/alu/src/parser.js +0 -577
  30. package/dist/src/alu/src/resonance.d.ts +0 -55
  31. package/dist/src/alu/src/resonance.js +0 -126
  32. package/dist/src/alu/src/text.d.ts +0 -31
  33. package/dist/src/alu/src/text.js +0 -73
  34. package/dist/src/alu/src/value.d.ts +0 -109
  35. package/dist/src/alu/src/value.js +0 -300
  36. package/dist/src/alu/test/alu.test.d.ts +0 -1
  37. package/dist/src/alu/test/alu.test.js +0 -764
  38. package/dist/src/bytes.d.ts +0 -14
  39. package/dist/src/bytes.js +0 -59
  40. package/dist/src/canon.d.ts +0 -26
  41. package/dist/src/canon.js +0 -57
  42. package/dist/src/config.d.ts +0 -111
  43. package/dist/src/config.js +0 -91
  44. package/dist/src/derive/src/deduction.d.ts +0 -125
  45. package/dist/src/derive/src/deduction.js +0 -155
  46. package/dist/src/derive/src/index.d.ts +0 -7
  47. package/dist/src/derive/src/index.js +0 -11
  48. package/dist/src/derive/src/priority-queue.d.ts +0 -20
  49. package/dist/src/derive/src/priority-queue.js +0 -73
  50. package/dist/src/derive/src/rewrite.d.ts +0 -56
  51. package/dist/src/derive/src/rewrite.js +0 -100
  52. package/dist/src/derive/src/trie.d.ts +0 -90
  53. package/dist/src/derive/src/trie.js +0 -217
  54. package/dist/src/derive/test/derive.test.d.ts +0 -1
  55. package/dist/src/derive/test/derive.test.js +0 -122
  56. package/dist/src/extension.d.ts +0 -37
  57. package/dist/src/extension.js +0 -7
  58. package/dist/src/geometry.d.ts +0 -202
  59. package/dist/src/geometry.js +0 -575
  60. package/dist/src/index.d.ts +0 -16
  61. package/dist/src/index.js +0 -18
  62. package/dist/src/ingest-cache.d.ts +0 -41
  63. package/dist/src/ingest-cache.js +0 -161
  64. package/dist/src/mind/articulation.d.ts +0 -6
  65. package/dist/src/mind/articulation.js +0 -99
  66. package/dist/src/mind/attention.d.ts +0 -315
  67. package/dist/src/mind/attention.js +0 -1549
  68. package/dist/src/mind/bridge.d.ts +0 -30
  69. package/dist/src/mind/bridge.js +0 -569
  70. package/dist/src/mind/canonical.d.ts +0 -29
  71. package/dist/src/mind/canonical.js +0 -88
  72. package/dist/src/mind/graph-search.d.ts +0 -285
  73. package/dist/src/mind/graph-search.js +0 -956
  74. package/dist/src/mind/index.d.ts +0 -7
  75. package/dist/src/mind/index.js +0 -5
  76. package/dist/src/mind/junction.d.ts +0 -124
  77. package/dist/src/mind/junction.js +0 -317
  78. package/dist/src/mind/learning.d.ts +0 -47
  79. package/dist/src/mind/learning.js +0 -248
  80. package/dist/src/mind/match.d.ts +0 -126
  81. package/dist/src/mind/match.js +0 -441
  82. package/dist/src/mind/mechanisms/alu.d.ts +0 -4
  83. package/dist/src/mind/mechanisms/alu.js +0 -36
  84. package/dist/src/mind/mechanisms/cast.d.ts +0 -89
  85. package/dist/src/mind/mechanisms/cast.js +0 -716
  86. package/dist/src/mind/mechanisms/confluence.d.ts +0 -24
  87. package/dist/src/mind/mechanisms/confluence.js +0 -225
  88. package/dist/src/mind/mechanisms/cover.d.ts +0 -6
  89. package/dist/src/mind/mechanisms/cover.js +0 -203
  90. package/dist/src/mind/mechanisms/extraction.d.ts +0 -67
  91. package/dist/src/mind/mechanisms/extraction.js +0 -387
  92. package/dist/src/mind/mechanisms/recall.d.ts +0 -13
  93. package/dist/src/mind/mechanisms/recall.js +0 -325
  94. package/dist/src/mind/mind.d.ts +0 -276
  95. package/dist/src/mind/mind.js +0 -572
  96. package/dist/src/mind/pipeline-mechanism.d.ts +0 -142
  97. package/dist/src/mind/pipeline-mechanism.js +0 -213
  98. package/dist/src/mind/pipeline.d.ts +0 -20
  99. package/dist/src/mind/pipeline.js +0 -217
  100. package/dist/src/mind/primitives.d.ts +0 -70
  101. package/dist/src/mind/primitives.js +0 -287
  102. package/dist/src/mind/rationale.d.ts +0 -139
  103. package/dist/src/mind/rationale.js +0 -163
  104. package/dist/src/mind/reasoning.d.ts +0 -34
  105. package/dist/src/mind/reasoning.js +0 -240
  106. package/dist/src/mind/recognition.d.ts +0 -20
  107. package/dist/src/mind/recognition.js +0 -390
  108. package/dist/src/mind/resonance.d.ts +0 -23
  109. package/dist/src/mind/resonance.js +0 -0
  110. package/dist/src/mind/trace.d.ts +0 -15
  111. package/dist/src/mind/trace.js +0 -73
  112. package/dist/src/mind/traverse.d.ts +0 -113
  113. package/dist/src/mind/traverse.js +0 -568
  114. package/dist/src/mind/types.d.ts +0 -289
  115. package/dist/src/mind/types.js +0 -130
  116. package/dist/src/rabitq-ivf/src/database.d.ts +0 -113
  117. package/dist/src/rabitq-ivf/src/database.js +0 -201
  118. package/dist/src/rabitq-ivf/src/index.d.ts +0 -7
  119. package/dist/src/rabitq-ivf/src/index.js +0 -4
  120. package/dist/src/rabitq-ivf/src/ivf.d.ts +0 -200
  121. package/dist/src/rabitq-ivf/src/ivf.js +0 -1165
  122. package/dist/src/rabitq-ivf/src/prng.d.ts +0 -19
  123. package/dist/src/rabitq-ivf/src/prng.js +0 -36
  124. package/dist/src/rabitq-ivf/src/rabitq.d.ts +0 -95
  125. package/dist/src/rabitq-ivf/src/rabitq.js +0 -283
  126. package/dist/src/sema.d.ts +0 -31
  127. package/dist/src/sema.js +0 -63
  128. package/dist/src/store-sqlite.d.ts +0 -184
  129. package/dist/src/store-sqlite.js +0 -942
  130. package/dist/src/store.d.ts +0 -663
  131. package/dist/src/store.js +0 -1618
  132. package/dist/src/vec.d.ts +0 -31
  133. package/dist/src/vec.js +0 -109
@@ -1,126 +0,0 @@
1
- // resonance.ts — ALU's window onto meaning, and how the host pre-resolves it.
2
- //
3
- // ALU computes on bytes of any modality, but WHICH operation a byte span invokes
4
- // — and what the opposite of a symbol is — are questions of MEANING, and only
5
- // resonance can read meaning from an opaque span. Two behaviours need it, and
6
- // BOTH are generic (any operation, any modality), not special cases:
7
- //
8
- // • operation recognition — the operation a query asks for is, in general, NOT
9
- // literally spelled. "2+2" carries a "+", but "the integral of …", "the
10
- // limit as …", "the derivative of …", or the analogous request expressed as
11
- // an image / audio gesture carry NO operator symbol at all. The operation
12
- // must be recognised from the span's GIST resonating with the operation's
13
- // CONCEPT. This is the primary, generic recognition path; the literal
14
- // symbol scan (alu.ts `scan`) is merely the easy special case layered under
15
- // it. Recognition is by gist, so it is modality-agnostic: a "+" drawn, a
16
- // "plus" spoken, and the byte "+" all resonate toward the same `add`
17
- // concept.
18
- //
19
- // • the polymorphic inverse — the opposite of a SYMBOL (the bytes of a learnt
20
- // form, any modality) is its RESONANT opposite, found in the resonance
21
- // space, not by arithmetic. The inverse of a number is its negation; the
22
- // inverse of a form is its antonym/complement.
23
- //
24
- // Both are ASYNC in SEMA (they hit the gist / halo index), but the
25
- // lightest-derivation search is SYNCHRONOUS. So — exactly as src/mind/pipeline.ts hoists
26
- // concept hops and connectors into Maps before the search and reads them
27
- // synchronously inside the rules — ALU splits each capability in two:
28
- //
29
- // AluResonance (async) — what the HOST implements over its resonance index.
30
- // Called only during pre-resolution.
31
- // ResonanceSync (sync) — the pre-resolved snapshot the op callbacks / rules
32
- // read (ResonanceSync is declared in operation.ts).
33
- //
34
- // {@link prefetchOpposites} and {@link prefetchRecognisedOps} turn the async side
35
- // into synchronous lookups for a known set of spans; the host calls them during
36
- // its pre-resolution pass. This file is the ENTIRE coupling surface to SEMA —
37
- // ALU imports nothing from the mind or store; the host supplies a AluResonance
38
- // built over its own perception + resonance (gist nearness to the operation
39
- // vocabulary ALU exposes via `conceptForms`, and halo resonance for the
40
- // opposite).
41
- import { latin1 } from "../../bytes.js";
42
- /** A AluResonance that knows nothing — the default when the host wires none in,
43
- * so the kernel runs fully decoupled (operations resolve by literal forms only,
44
- * and a symbol inverse is left unchanged). */
45
- export const NO_ALU_RESONANCE = {
46
- recogniseOp: async () => null,
47
- opposite: async () => null,
48
- };
49
- /** Pre-resolve the resonant opposite of each symbol in `symbols`, awaiting the
50
- * host's async resonance once per distinct span, and return a SYNCHRONOUS
51
- * snapshot the op callbacks read during the search. Keyed by the latin1 view
52
- * of the bytes (a lossless, stable string key — the same device the search's
53
- * chart uses). This is the async→sync bridge for the polymorphic inverse,
54
- * mirroring how a concept hop's target is pre-resolved and read synchronously. */
55
- export async function prefetchOpposites(resonance, symbols) {
56
- const table = new Map();
57
- const seen = new Set();
58
- for (const bytes of symbols) {
59
- const key = latin1(bytes);
60
- if (seen.has(key))
61
- continue;
62
- seen.add(key);
63
- const opp = await resonance.opposite(bytes);
64
- if (opp)
65
- table.set(key, opp);
66
- }
67
- return {
68
- opposite: (bytes) => table.get(latin1(bytes)) ?? null,
69
- // Opposites-only prefetch carries no op recognition; a higher-order nd op
70
- // resolving through this falls back to literal forms / canonical names.
71
- recogniseOp: () => null,
72
- };
73
- }
74
- /** Pre-resolve BOTH capabilities a computation may need synchronously — the
75
- * resonant opposite of a symbol (for the polymorphic inverse) AND the operation
76
- * a symbol's MEANING names (for a higher-order nd op's function argument) — over
77
- * one set of candidate spans, and return a single {@link ResonanceSync}. Each
78
- * distinct span is awaited once per capability. This is the unified async→sync
79
- * bridge the host uses for an nd computation, where the same spans may serve as
80
- * inverse operands and as a reduce/map/filter operator. Either lookup yields
81
- * null for a span that resonates with nothing, so callbacks decline rather than
82
- * guess. */
83
- export async function prefetchResonance(resonance, spans) {
84
- const opposites = new Map();
85
- const ops = new Map();
86
- const seen = new Set();
87
- for (const bytes of spans) {
88
- const key = latin1(bytes);
89
- if (seen.has(key))
90
- continue;
91
- seen.add(key);
92
- const [opp, op] = await Promise.all([
93
- resonance.opposite(bytes),
94
- resonance.recogniseOp(bytes),
95
- ]);
96
- if (opp)
97
- opposites.set(key, opp);
98
- if (op)
99
- ops.set(key, op);
100
- }
101
- return {
102
- opposite: (bytes) => opposites.get(latin1(bytes)) ?? null,
103
- recogniseOp: (bytes) => ops.get(latin1(bytes)) ?? null,
104
- };
105
- }
106
- /** Pre-resolve, for each candidate span, the operation its MEANING names —
107
- * awaiting the host's async gist resonance once per distinct span — and return
108
- * a synchronous map keyed by the span's latin1 bytes → canonical op name. This
109
- * is the async→sync bridge for the GENERIC operation-recognition path: a span
110
- * the literal scan could not classify (no operator symbol) but whose gist
111
- * resonates with an operation's concept. Spans that resonate with nothing are
112
- * omitted, so the caller treats a miss as "not an operation". */
113
- export async function prefetchRecognisedOps(resonance, spans) {
114
- const table = new Map();
115
- const seen = new Set();
116
- for (const bytes of spans) {
117
- const key = latin1(bytes);
118
- if (seen.has(key))
119
- continue;
120
- seen.add(key);
121
- const op = await resonance.recogniseOp(bytes);
122
- if (op)
123
- table.set(key, op);
124
- }
125
- return table;
126
- }
@@ -1,31 +0,0 @@
1
- /** An ASCII decimal digit. */
2
- export declare const isDigitByte: (c: number) => boolean;
3
- /** The decimal point of a numeral. */
4
- export declare const DOT = 46;
5
- /** The explicit list container's delimiters — the canonical nd spelling the
6
- * codec emits, so a computed list feeds straight back in as an operand. */
7
- export declare const OPEN = 91;
8
- export declare const CLOSE = 93;
9
- /** ASCII whitespace (space, tab, newline, carriage return) — the one spacing
10
- * convention bytes of every textual modality share. */
11
- export declare const isSpaceByte: (c: number) => boolean;
12
- /** A byte that DELIMITS list elements inside an explicit container: whitespace,
13
- * a comma, or a semicolon. Deliberately excludes anything that can sit inside
14
- * a numeral or a symbol token (letters, digits, sign/decimal `+ - .`) and the
15
- * brackets themselves, so an element's own bytes are never split. */
16
- export declare const isSepByte: (c: number) => boolean;
17
- /** The index of the first non-whitespace byte (or the length, if all space). */
18
- export declare function trimStart(b: Uint8Array): number;
19
- /** The index one past the last non-whitespace byte (or 0, if all space). */
20
- export declare function trimEnd(b: Uint8Array): number;
21
- /** The index of the `]` matching the `[` at `open`, bracket-depth aware, or -1
22
- * when it is unbalanced — used to test whether a span is one explicit list
23
- * CONTAINER (its opening bracket closing exactly at its end). */
24
- export declare function matchBracket(b: Uint8Array, open: number): number;
25
- /** The maximal non-whitespace runs of `bytes` within [from, to) — the spacing
26
- * floor's reading of "the tokens", shared by the structural host's segmenter
27
- * and the parser's term lexing so neither re-implements the walk. */
28
- export declare function nonSpaceRuns(bytes: Uint8Array, from?: number, to?: number): Array<{
29
- i: number;
30
- j: number;
31
- }>;
@@ -1,73 +0,0 @@
1
- // text.ts — the byte-class floor the ALU's lexing rests on.
2
- //
3
- // SEMA is byte-native and multimodal; the ALU keeps its knowledge of raw text
4
- // as small as possible. What remains is the IRREDUCIBLE floor — the decimal
5
- // numeral grammar (digits ground a quantity exactly as the byte alphabet
6
- // grounds a symbol), whitespace as the universal spacing byte, and the list
7
- // grammar's delimiters — collected HERE, once, so no other module hardcodes a
8
- // character class of its own. Everything above this floor (which spans name
9
- // operations, where terms begin and end, what an expression means) is resolved
10
- // from the operation registry, the host's geometric segmentation, or resonance.
11
- /** An ASCII decimal digit. */
12
- export const isDigitByte = (c) => c >= 0x30 && c <= 0x39;
13
- /** The decimal point of a numeral. */
14
- export const DOT = 0x2e; // "."
15
- /** The explicit list container's delimiters — the canonical nd spelling the
16
- * codec emits, so a computed list feeds straight back in as an operand. */
17
- export const OPEN = 0x5b; // "["
18
- export const CLOSE = 0x5d; // "]"
19
- /** ASCII whitespace (space, tab, newline, carriage return) — the one spacing
20
- * convention bytes of every textual modality share. */
21
- export const isSpaceByte = (c) => c === 0x20 || c === 0x09 || c === 0x0a || c === 0x0d;
22
- /** A byte that DELIMITS list elements inside an explicit container: whitespace,
23
- * a comma, or a semicolon. Deliberately excludes anything that can sit inside
24
- * a numeral or a symbol token (letters, digits, sign/decimal `+ - .`) and the
25
- * brackets themselves, so an element's own bytes are never split. */
26
- export const isSepByte = (c) => isSpaceByte(c) || c === 0x2c /* , */ || c === 0x3b /* ; */;
27
- /** The index of the first non-whitespace byte (or the length, if all space). */
28
- export function trimStart(b) {
29
- let i = 0;
30
- while (i < b.length && isSpaceByte(b[i]))
31
- i++;
32
- return i;
33
- }
34
- /** The index one past the last non-whitespace byte (or 0, if all space). */
35
- export function trimEnd(b) {
36
- let j = b.length;
37
- const lo = trimStart(b);
38
- while (j > lo && isSpaceByte(b[j - 1]))
39
- j--;
40
- return j;
41
- }
42
- /** The index of the `]` matching the `[` at `open`, bracket-depth aware, or -1
43
- * when it is unbalanced — used to test whether a span is one explicit list
44
- * CONTAINER (its opening bracket closing exactly at its end). */
45
- export function matchBracket(b, open) {
46
- let depth = 0;
47
- for (let i = open; i < b.length; i++) {
48
- if (b[i] === OPEN)
49
- depth++;
50
- else if (b[i] === CLOSE && --depth === 0)
51
- return i;
52
- }
53
- return -1;
54
- }
55
- /** The maximal non-whitespace runs of `bytes` within [from, to) — the spacing
56
- * floor's reading of "the tokens", shared by the structural host's segmenter
57
- * and the parser's term lexing so neither re-implements the walk. */
58
- export function nonSpaceRuns(bytes, from = 0, to = bytes.length) {
59
- const out = [];
60
- let i = from;
61
- while (i < to) {
62
- if (isSpaceByte(bytes[i])) {
63
- i++;
64
- continue;
65
- }
66
- let j = i;
67
- while (j < to && !isSpaceByte(bytes[j]))
68
- j++;
69
- out.push({ i, j });
70
- i = j;
71
- }
72
- return out;
73
- }
@@ -1,109 +0,0 @@
1
- /** Which stratum a {@link Value} belongs to. Four scalar domains + the
2
- * recursive container `nd`. */
3
- export type Domain = "bit" | "int" | "real" | "symbol" | "nd";
4
- /** A quantity the ALU computes on — a tagged union over the scalar domains plus
5
- * the recursive n-dimensional container. An `nd`'s `items` are themselves
6
- * Values of any domain, so nesting (a matrix = an nd of nd) and heterogeneity
7
- * (a list mixing numbers, symbols, sub-lists) are the same case. */
8
- export type Value = {
9
- domain: "bit";
10
- b: 0 | 1;
11
- } | {
12
- domain: "int";
13
- n: bigint;
14
- } | {
15
- domain: "real";
16
- x: number;
17
- } | {
18
- domain: "symbol";
19
- bytes: Uint8Array;
20
- } | {
21
- domain: "nd";
22
- items: Value[];
23
- };
24
- export declare const bit: (b: 0 | 1) => Value;
25
- export declare const int: (n: bigint) => Value;
26
- export declare const real: (x: number) => Value;
27
- /** A symbolic value: an opaque byte span of any modality (see module note). */
28
- export declare const symbol: (bytes: Uint8Array) => Value;
29
- /** An n-dimensional value: an ordered list of element values (each any domain,
30
- * including a nested nd). See the module note on nd. */
31
- export declare const nd: (items: Value[]) => Value;
32
- /** The domain tag of a value. */
33
- export declare const tagOf: (v: Value) => Domain;
34
- /** Whether a value is a numeric SCALAR (bit, int, or real) — an nd is not, even
35
- * if every element is numeric (it is a container; reduce it to a scalar). */
36
- export declare function isNumeric(v: Value): boolean;
37
- /** Whether a value is the n-dimensional container. */
38
- export declare function isNd(v: Value): v is {
39
- domain: "nd";
40
- items: Value[];
41
- };
42
- /** Collect, into `out`, every SYMBOL byte span reachable inside a value — itself
43
- * when it is a symbol, or each element recursively when it is an nd. These are
44
- * the spans whose MEANING (a resonant opposite, the operation a higher-order op
45
- * argument names) the host pre-resolves before a computation; numbers carry no
46
- * meaning to resolve, so they are skipped. */
47
- export declare function symbolSpans(v: Value, out: Uint8Array[]): void;
48
- /** A value as a JS number — bit→0|1, int→Number, real as-is. Throws on a
49
- * symbol, because arithmetic on an opaque form is a programming error the
50
- * caller (or the graph adapter's try/catch) should surface, never silently
51
- * coerce to NaN. */
52
- export declare function asReal(v: Value): number;
53
- /** A value as an exact bigint — real is truncated toward zero (a real that is
54
- * not integral loses its fraction; callers wanting exactness keep it int). */
55
- export declare function asInt(v: Value): bigint;
56
- /** A value as a logic bit — nonzero numbers read as 1, zero as 0. Throws on a
57
- * symbol (an opaque form is not a truth value). */
58
- export declare function asBit(v: Value): 0 | 1;
59
- /** Promote a value into a target numeric domain (bit ⊂ int ⊂ real). Used when
60
- * a mixed-domain expression must agree on one domain before a primitive runs —
61
- * the rule is the natural lattice: any real operand pulls the whole expression
62
- * to real, otherwise any int pulls it to int, otherwise bit. */
63
- export declare function coerce(v: Value, domain: "bit" | "int" | "real"): Value;
64
- /** The common numeric domain of a list of operands, by the bit ⊂ int ⊂ real
65
- * lattice: real if any operand is real, else int if any is int, else bit.
66
- * Throws if any operand is a symbol. This is how a polymorphic arithmetic op
67
- * decides whether to take the exact bigint path or the native-double path. */
68
- export declare function joinDomain(args: Value[]): "bit" | "int" | "real";
69
- /** The host's bridge between byte spans and values. ALU emits and consumes
70
- * bytes only through this, so the surrounding system owns how a number is
71
- * spelled. A default ({@link decimalCodec}) is provided. */
72
- export interface ValueCodec {
73
- encode(v: Value): Uint8Array;
74
- decode(bytes: Uint8Array): Value | null;
75
- }
76
- /** Parse a byte span into a SCALAR value: a clean integer numeral → exact int, a
77
- * fractional/exponent numeral → real, anything else → a symbol carrying its
78
- * bytes verbatim for the polymorphic inverse.
79
- *
80
- * This is the IRREDUCIBLE FLOOR — and the ONLY structure read at the value
81
- * model's base: a number-form's digits ground a quantity, the exact analogue of
82
- * the byte alphabet grounding a symbol. It does NOT read n-dimensional
83
- * STRUCTURE (no bracket/comma grammar); recognising a list — a run of element
84
- * values joined by a consistent separator — is layered ONE level up, in the
85
- * facade's {@link "./alu.js".Alu.recogniseValue} (over the operand scanner),
86
- * which calls this for each element. So the codec's `decode` (which delegates
87
- * here) is scalar-only: a bracket literal decodes to an opaque symbol.
88
- *
89
- * Numerals are ASCII by construction; for any other byte content the bytes are
90
- * preserved opaquely, so a symbol of any modality round-trips untouched. */
91
- export declare function parseValue(bytes: Uint8Array): Value;
92
- /** Canonically format a real as a decimal string: round to `precision` places,
93
- * then trim trailing zeros (and a bare trailing point), normalising -0 to 0.
94
- * Determinism here is load-bearing — the search keys an output span by its
95
- * bytes, so two derivations of the same number MUST spell it identically. */
96
- export declare function formatReal(x: number, precision: number): string;
97
- /** The default codec: integers as exact decimals, reals canonically formatted,
98
- * bits as "0"/"1", symbols as their own bytes (verbatim, any modality), and an
99
- * nd as a bracket literal `[e0,e1,…]` of its element encodings (recursive, so a
100
- * nested list nests its brackets and a symbol element keeps its raw bytes).
101
- * `precision` controls real rounding (see {@link formatReal}).
102
- *
103
- * The bracket layout is the CANONICAL OUTPUT spelling of an `nd` — one
104
- * deterministic form, the analogue of decimal for a number, so the search's
105
- * chart memoises identical results identically. It is an ENCODE-only grammar:
106
- * {@link parseValue} (hence `decode`) reads only scalars, never structure — a
107
- * bracket literal decodes back to an opaque symbol. Reading list STRUCTURE from
108
- * bytes is layered one level up, in {@link "./alu.js".Alu.recogniseValue}. */
109
- export declare function decimalCodec(precision: number): ValueCodec;
@@ -1,300 +0,0 @@
1
- // value.ts — the ALU value model.
2
- //
3
- // One tagged union carries every kind of quantity the ALU computes on, so a
4
- // single Operation registry can dispatch on the tag rather than maintaining
5
- // disjoint kernels. The four domains are exactly the strata the kernel needs:
6
- //
7
- // • bit — a logic value 0|1. The completeness layer (nand and the gates
8
- // derived from it) lives here.
9
- // • int — an EXACT integer (JS bigint). The "everything derives from nand"
10
- // bootstrap runs here: add is a ripple of full_adders, multiply is
11
- // shift-add, and so on. bigint keeps the proof exact past 2^53.
12
- // • real — an IEEE double. The limit layer (converge, exp, sin, …) is
13
- // intrinsically continuous, so it runs on the host's native reals
14
- // rather than a fixed-point reimplementation atop bits.
15
- // • symbol — a raw BYTE SPAN that is not a number. SEMA is byte-native and
16
- // multimodal: a symbol's bytes may name a written form, a region of
17
- // an image, a fragment of audio — any learned form, in any
18
- // modality. ALU never interprets those bytes; it treats a symbol
19
- // as an opaque token. This is the carrier for the POLYMORPHIC
20
- // inverse: the inverse of a number is its negation, but the inverse
21
- // of a symbol is its RESONANT OPPOSITE — found in the resonance
22
- // space, not by arithmetic (e.g. the bytes of "large" resolve to
23
- // "small", but the mechanism is modality-agnostic — see
24
- // resonance.ts). Resonance is the only thing that can read meaning
25
- // from a symbol, and ALU reaches it only through an injected
26
- // capability, never directly.
27
- //
28
- // • nd — an N-DIMENSIONAL value: an ordered list of elements, each of which
29
- // is ITSELF a Value of ANY domain — a scalar (bit/int/real/symbol)
30
- // OR another nd. So nd is recursive (a tensor is an nd of nds), it
31
- // is RAGGED (rows need not be equal length — it is a list, not a
32
- // rectangular array), and it is HETEROGENEOUS (a row may mix a
33
- // number, a symbol, and a sub-list). This one recursive case is the
34
- // whole generalisation: there is no separate "vector" vs "matrix"
35
- // type, only nd nesting, and the rank is read off the nesting depth.
36
- // Every scalar operation lifts over it automatically (broadcast, see
37
- // operation.ts), and the structural operations (the nd kernel) build
38
- // the list-processing layer — map/reduce/filter/find/… — on a tiny
39
- // core of nd/length/at, exactly as logic builds on nand.
40
- //
41
- // The module is pure: it knows nothing of SEMA, the store, or the search. The
42
- // only host coupling is the injected ValueCodec, whose default lives here.
43
- // ── constructors ──────────────────────────────────────────────────────────
44
- export const bit = (b) => ({ domain: "bit", b });
45
- export const int = (n) => ({ domain: "int", n });
46
- export const real = (x) => ({ domain: "real", x });
47
- /** A symbolic value: an opaque byte span of any modality (see module note). */
48
- export const symbol = (bytes) => ({
49
- domain: "symbol",
50
- bytes,
51
- });
52
- /** An n-dimensional value: an ordered list of element values (each any domain,
53
- * including a nested nd). See the module note on nd. */
54
- export const nd = (items) => ({ domain: "nd", items });
55
- /** The domain tag of a value. */
56
- export const tagOf = (v) => v.domain;
57
- /** Whether a value is a numeric SCALAR (bit, int, or real) — an nd is not, even
58
- * if every element is numeric (it is a container; reduce it to a scalar). */
59
- export function isNumeric(v) {
60
- return v.domain === "bit" || v.domain === "int" || v.domain === "real";
61
- }
62
- /** Whether a value is the n-dimensional container. */
63
- export function isNd(v) {
64
- return v.domain === "nd";
65
- }
66
- /** Collect, into `out`, every SYMBOL byte span reachable inside a value — itself
67
- * when it is a symbol, or each element recursively when it is an nd. These are
68
- * the spans whose MEANING (a resonant opposite, the operation a higher-order op
69
- * argument names) the host pre-resolves before a computation; numbers carry no
70
- * meaning to resolve, so they are skipped. */
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);
77
- }
78
- }
79
- // ── coercions (the functor's object map between domains) ────────────────────
80
- /** A value as a JS number — bit→0|1, int→Number, real as-is. Throws on a
81
- * symbol, because arithmetic on an opaque form is a programming error the
82
- * caller (or the graph adapter's try/catch) should surface, never silently
83
- * coerce to NaN. */
84
- export function asReal(v) {
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
- }
100
- }
101
- /** A value as an exact bigint — real is truncated toward zero (a real that is
102
- * not integral loses its fraction; callers wanting exactness keep it int). */
103
- export function asInt(v) {
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
- }
116
- }
117
- /** A value as a logic bit — nonzero numbers read as 1, zero as 0. Throws on a
118
- * symbol (an opaque form is not a truth value). */
119
- export function asBit(v) {
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
- }
132
- }
133
- /** Promote a value into a target numeric domain (bit ⊂ int ⊂ real). Used when
134
- * a mixed-domain expression must agree on one domain before a primitive runs —
135
- * the rule is the natural lattice: any real operand pulls the whole expression
136
- * to real, otherwise any int pulls it to int, otherwise bit. */
137
- export function coerce(v, domain) {
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
- }
148
- }
149
- /** The common numeric domain of a list of operands, by the bit ⊂ int ⊂ real
150
- * lattice: real if any operand is real, else int if any is int, else bit.
151
- * Throws if any operand is a symbol. This is how a polymorphic arithmetic op
152
- * decides whether to take the exact bigint path or the native-double path. */
153
- export function joinDomain(args) {
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";
166
- }
167
- return d;
168
- }
169
- const ASCII = {
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
- },
182
- };
183
- /** A decimal numeral, sign, optional fraction, optional exponent — the syntax
184
- * {@link parseScalar} accepts as a number. Anything else is a symbol. */
185
- const NUMERAL = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
186
- /** Concatenate byte arrays — used to build an nd literal's encoding without
187
- * routing a (possibly non-ASCII, multimodal) symbol's bytes through a string. */
188
- function concatBytes(arrs) {
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;
199
- }
200
- /** Parse a SCALAR span: a clean integer numeral → exact int, a fractional/
201
- * exponent numeral → real, anything else → a symbol carrying `bytes` verbatim.
202
- * Strict, so it never hijacks a form that merely begins with a digit. */
203
- function parseScalar(bytes, s) {
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
- }
219
- }
220
- return symbol(bytes);
221
- }
222
- /** Parse a byte span into a SCALAR value: a clean integer numeral → exact int, a
223
- * fractional/exponent numeral → real, anything else → a symbol carrying its
224
- * bytes verbatim for the polymorphic inverse.
225
- *
226
- * This is the IRREDUCIBLE FLOOR — and the ONLY structure read at the value
227
- * model's base: a number-form's digits ground a quantity, the exact analogue of
228
- * the byte alphabet grounding a symbol. It does NOT read n-dimensional
229
- * STRUCTURE (no bracket/comma grammar); recognising a list — a run of element
230
- * values joined by a consistent separator — is layered ONE level up, in the
231
- * facade's {@link "./alu.js".Alu.recogniseValue} (over the operand scanner),
232
- * which calls this for each element. So the codec's `decode` (which delegates
233
- * here) is scalar-only: a bracket literal decodes to an opaque symbol.
234
- *
235
- * Numerals are ASCII by construction; for any other byte content the bytes are
236
- * preserved opaquely, so a symbol of any modality round-trips untouched. */
237
- export function parseValue(bytes) {
238
- return parseScalar(bytes, ASCII.decode(bytes));
239
- }
240
- /** Canonically format a real as a decimal string: round to `precision` places,
241
- * then trim trailing zeros (and a bare trailing point), normalising -0 to 0.
242
- * Determinism here is load-bearing — the search keys an output span by its
243
- * bytes, so two derivations of the same number MUST spell it identically. */
244
- export function formatReal(x, precision) {
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;
253
- }
254
- /** The default codec: integers as exact decimals, reals canonically formatted,
255
- * bits as "0"/"1", symbols as their own bytes (verbatim, any modality), and an
256
- * nd as a bracket literal `[e0,e1,…]` of its element encodings (recursive, so a
257
- * nested list nests its brackets and a symbol element keeps its raw bytes).
258
- * `precision` controls real rounding (see {@link formatReal}).
259
- *
260
- * The bracket layout is the CANONICAL OUTPUT spelling of an `nd` — one
261
- * deterministic form, the analogue of decimal for a number, so the search's
262
- * chart memoises identical results identically. It is an ENCODE-only grammar:
263
- * {@link parseValue} (hence `decode`) reads only scalars, never structure — a
264
- * bracket literal decodes back to an opaque symbol. Reading list STRUCTURE from
265
- * bytes is layered one level up, in {@link "./alu.js".Alu.recogniseValue}. */
266
- export function decimalCodec(precision) {
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
- }
292
- }
293
- };
294
- return {
295
- encode: enc,
296
- decode(bytes) {
297
- return parseValue(bytes);
298
- },
299
- };
300
- }
@@ -1 +0,0 @@
1
- export {};