aontu 0.50.0 → 0.51.0

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 (102) hide show
  1. package/dist/aontu.d.ts +4 -2
  2. package/dist/aontu.js +18 -2
  3. package/dist/aontu.js.map +1 -1
  4. package/dist/cli.js +33 -7
  5. package/dist/cli.js.map +1 -1
  6. package/dist/exactjson.d.ts +37 -0
  7. package/dist/exactjson.js +228 -0
  8. package/dist/exactjson.js.map +1 -0
  9. package/dist/hints.js +61 -4
  10. package/dist/hints.js.map +1 -1
  11. package/dist/keyorder.d.ts +9 -0
  12. package/dist/keyorder.js +65 -0
  13. package/dist/keyorder.js.map +1 -0
  14. package/dist/lang.js +200 -4
  15. package/dist/lang.js.map +1 -1
  16. package/dist/lsp.js +12 -2
  17. package/dist/lsp.js.map +1 -1
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/dist/val/BagVal.js +8 -5
  20. package/dist/val/BagVal.js.map +1 -1
  21. package/dist/val/BigDecimalVal.d.ts +13 -0
  22. package/dist/val/BigDecimalVal.js +80 -0
  23. package/dist/val/BigDecimalVal.js.map +1 -0
  24. package/dist/val/BigIntegerVal.d.ts +11 -0
  25. package/dist/val/BigIntegerVal.js +75 -0
  26. package/dist/val/BigIntegerVal.js.map +1 -0
  27. package/dist/val/Decimal.d.ts +32 -0
  28. package/dist/val/Decimal.js +318 -0
  29. package/dist/val/Decimal.js.map +1 -0
  30. package/dist/val/IntegerVal.d.ts +2 -0
  31. package/dist/val/IntegerVal.js +75 -3
  32. package/dist/val/IntegerVal.js.map +1 -1
  33. package/dist/val/KeyFuncVal.d.ts +1 -1
  34. package/dist/val/KeyFuncVal.js +33 -3
  35. package/dist/val/KeyFuncVal.js.map +1 -1
  36. package/dist/val/LowerFuncVal.js +20 -3
  37. package/dist/val/LowerFuncVal.js.map +1 -1
  38. package/dist/val/MapVal.js +6 -4
  39. package/dist/val/MapVal.js.map +1 -1
  40. package/dist/val/MoveFuncVal.js +25 -8
  41. package/dist/val/MoveFuncVal.js.map +1 -1
  42. package/dist/val/NumberVal.d.ts +1 -0
  43. package/dist/val/NumberVal.js +23 -2
  44. package/dist/val/NumberVal.js.map +1 -1
  45. package/dist/val/PathFuncVal.js +9 -1
  46. package/dist/val/PathFuncVal.js.map +1 -1
  47. package/dist/val/PlusOpVal.d.ts +3 -1
  48. package/dist/val/PlusOpVal.js +140 -29
  49. package/dist/val/PlusOpVal.js.map +1 -1
  50. package/dist/val/PrefVal.d.ts +2 -0
  51. package/dist/val/PrefVal.js +40 -4
  52. package/dist/val/PrefVal.js.map +1 -1
  53. package/dist/val/RefVal.js +57 -2
  54. package/dist/val/RefVal.js.map +1 -1
  55. package/dist/val/ScalarKindVal.d.ts +12 -2
  56. package/dist/val/ScalarKindVal.js +100 -11
  57. package/dist/val/ScalarKindVal.js.map +1 -1
  58. package/dist/val/ScalarVal.d.ts +1 -0
  59. package/dist/val/ScalarVal.js +16 -1
  60. package/dist/val/ScalarVal.js.map +1 -1
  61. package/dist/val/SuperFuncVal.d.ts +1 -1
  62. package/dist/val/SuperFuncVal.js +14 -1
  63. package/dist/val/SuperFuncVal.js.map +1 -1
  64. package/dist/val/UpperFuncVal.js +20 -3
  65. package/dist/val/UpperFuncVal.js.map +1 -1
  66. package/dist/val/VarVal.js +7 -1
  67. package/dist/val/VarVal.js.map +1 -1
  68. package/dist/val/numkind.d.ts +6 -0
  69. package/dist/val/numkind.js +224 -0
  70. package/dist/val/numkind.js.map +1 -0
  71. package/dist/val/valutil.d.ts +1 -0
  72. package/dist/val/valutil.js +35 -0
  73. package/dist/val/valutil.js.map +1 -1
  74. package/package.json +7 -7
  75. package/src/aontu.ts +23 -2
  76. package/src/cli.ts +36 -8
  77. package/src/exactjson.ts +254 -0
  78. package/src/hints.ts +73 -4
  79. package/src/keyorder.ts +73 -0
  80. package/src/lang.ts +229 -5
  81. package/src/lsp.ts +10 -2
  82. package/src/val/BagVal.ts +8 -5
  83. package/src/val/BigDecimalVal.ts +117 -0
  84. package/src/val/BigIntegerVal.ts +110 -0
  85. package/src/val/Decimal.ts +385 -0
  86. package/src/val/IntegerVal.ts +79 -3
  87. package/src/val/KeyFuncVal.ts +35 -3
  88. package/src/val/LowerFuncVal.ts +21 -4
  89. package/src/val/MapVal.ts +6 -4
  90. package/src/val/MoveFuncVal.ts +26 -9
  91. package/src/val/NumberVal.ts +25 -2
  92. package/src/val/PathFuncVal.ts +9 -1
  93. package/src/val/PlusOpVal.ts +168 -32
  94. package/src/val/PrefVal.ts +66 -5
  95. package/src/val/RefVal.ts +61 -2
  96. package/src/val/ScalarKindVal.ts +115 -10
  97. package/src/val/ScalarVal.ts +18 -1
  98. package/src/val/SuperFuncVal.ts +14 -1
  99. package/src/val/UpperFuncVal.ts +21 -4
  100. package/src/val/VarVal.ts +7 -1
  101. package/src/val/numkind.ts +256 -0
  102. package/src/val/valutil.ts +36 -0
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ /* Copyright (c) 2025 Richard Rodger, MIT License */
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Decimal = exports.DECIMAL_SCALE_BUDGET = exports.DECIMAL_COEFFICIENT_BUDGET = exports.BIG_LITERAL_RE = void 0;
5
+ exports.decimalOverBudget = decimalOverBudget;
6
+ exports.readBigLiteral = readBigLiteral;
7
+ /*
8
+ * The exact base-10 decimal value behind the `bigdecimal` leaf, and the
9
+ * parser for the `0d` literal family that reaches both exact leaves.
10
+ *
11
+ * A Decimal is a coefficient and a scale:
12
+ *
13
+ * value = unscaled / 10^scale
14
+ *
15
+ * with `unscaled` a native bigint and `scale` a plain integer. Every
16
+ * operation here is EXACT: aontu's whole numeric operator surface
17
+ * (`+`, `upper()`, `lower()`, unary minus) is exact, so no rounding
18
+ * context, precision or rounding mode exists anywhere in this file --
19
+ * addition aligns scales and adds coefficients, and ceiling/floor is
20
+ * coefficient arithmetic that never lets a float64 near the value.
21
+ * Where an exact answer will not fit the budget the answer is refused,
22
+ * never rounded (see decimalOverBudget).
23
+ *
24
+ * D4 -- ONE VALUE, ONE RENDERING. In a unifier canon must be a function
25
+ * of the value, so scale is presentation and not identity: `0d0.10`,
26
+ * `0d0.1` and `0d1e-1` are the same lattice point and must render
27
+ * identically. A Decimal therefore NORMALISES IN ITS CONSTRUCTOR --
28
+ * every Decimal in existence is in minimal form, which is what makes
29
+ * `equals` a two-field comparison and `same()` correct without any
30
+ * pointer identity (D2).
31
+ *
32
+ * The minimal form keeps ONE decimal place at the bottom. `0d` names the
33
+ * numeric FAMILY, not the leaf, so an integral bigdecimal that rendered
34
+ * as `0d1000` would reparse as a biginteger -- a kind-flipping canon of
35
+ * exactly the sort R4's `.0` suffix exists to prevent. So `0d1e3` canons
36
+ * as `0d1000.0`, and scale is never reduced below 1.
37
+ *
38
+ * Go mirror (D8): a struct of (coeff *big.Int, scale int32) normalised
39
+ * by the same rule -- strip trailing zeros while scale > 1, then raise
40
+ * the scale to 1 when it is lower, zero always at scale 1.
41
+ */
42
+ // D6 -- THE EXACTNESS BUDGET, enforced at parse.
43
+ //
44
+ // Both halves are needed and the scale half is the load-bearing one: a
45
+ // coefficient-only check never fires for `0d1e1000000000`, whose
46
+ // coefficient is one digit, yet plain-form rendering of that value would
47
+ // have to materialise a gigabyte of zeros (and overflow the Go port's
48
+ // int32 scale field) without any arithmetic having occurred.
49
+ //
50
+ // A literal over either bound is a located error, never a rounded or
51
+ // expanded value: this language does not round, so the only honest
52
+ // answer at the limit is refusal.
53
+ const DECIMAL_COEFFICIENT_BUDGET = 4096;
54
+ exports.DECIMAL_COEFFICIENT_BUDGET = DECIMAL_COEFFICIENT_BUDGET;
55
+ const DECIMAL_SCALE_BUDGET = 4096;
56
+ exports.DECIMAL_SCALE_BUDGET = DECIMAL_SCALE_BUDGET;
57
+ // Powers of ten as bigints, memoised: normalisation of an
58
+ // exponent-bearing literal needs one per parse.
59
+ function pow10(n) {
60
+ return 10n ** BigInt(n);
61
+ }
62
+ // True when a decimal's SOURCE form is over either budget bound.
63
+ //
64
+ // Every route that builds a Decimal from text must ask this BEFORE
65
+ // constructing one, because normalising an over-budget value is itself
66
+ // the resource event the bound exists to prevent: the constructor folds
67
+ // a negative scale by multiplying the coefficient by 10^-scale, so
68
+ // `1e1000000000` would try to build a billion-digit bigint.
69
+ //
70
+ // Written once and used by both routes -- the `0d` literal and the
71
+ // exact-input API -- because the Go port bounds both (NewBigDecimal
72
+ // shares the literal path's checker) and a TypeScript route that did not
73
+ // would be a silent cross-port divergence as well as a hazard.
74
+ //
75
+ // `scale` may be Infinity or NaN when the exponent digits overflow a JS
76
+ // number; the comparison is written so that either answers "over".
77
+ function overBudget(coeffDigits, scale) {
78
+ return DECIMAL_COEFFICIENT_BUDGET < coeffDigits ||
79
+ !(Math.abs(scale) <= DECIMAL_SCALE_BUDGET);
80
+ }
81
+ // The decimal digit count of a coefficient, sign ignored (zero counts as
82
+ // one digit). Only the budget test needs it.
83
+ function coeffDigits(unscaled) {
84
+ return (unscaled < 0n ? -unscaled : unscaled).toString().length;
85
+ }
86
+ class Decimal {
87
+ constructor(unscaled, scale) {
88
+ let u = unscaled;
89
+ let s = Math.trunc(scale);
90
+ if (0n === u) {
91
+ // R2/D5: there is no negative zero here to begin with (a bigint
92
+ // has one zero), and every zero is the same lattice point, so it
93
+ // takes the one canonical form `0d0.0`.
94
+ s = 1;
95
+ }
96
+ else {
97
+ // Strip the trailing zeros that scale-as-presentation would
98
+ // otherwise smuggle into identity (`0d0.10` -> `0d0.1`)...
99
+ while (1 < s && 0n === u % 10n) {
100
+ u /= 10n;
101
+ s--;
102
+ }
103
+ // ...and fold a negative scale (an exponent) back up to the one
104
+ // decimal place the leaf marker requires (`0d1e3` -> 10000/10^1).
105
+ if (s < 1) {
106
+ u *= pow10(1 - s);
107
+ s = 1;
108
+ }
109
+ }
110
+ this.unscaled = u;
111
+ this.scale = s;
112
+ }
113
+ // Exact numeric equality. Both operands are normalised by
114
+ // construction, so equal values have equal fields -- this is value
115
+ // comparison, never object identity (D2).
116
+ equals(peer) {
117
+ return this.unscaled === peer.unscaled && this.scale === peer.scale;
118
+ }
119
+ // Exact ordering: -1, 0 or 1. Compares on a common scale, so no
120
+ // float64 ever touches the operands.
121
+ compare(peer) {
122
+ let a = this.unscaled;
123
+ let b = peer.unscaled;
124
+ if (this.scale < peer.scale) {
125
+ a *= pow10(peer.scale - this.scale);
126
+ }
127
+ else if (peer.scale < this.scale) {
128
+ b *= pow10(this.scale - peer.scale);
129
+ }
130
+ return a < b ? -1 : a > b ? 1 : 0;
131
+ }
132
+ // Exact negation, keeping the leaf. -0 folds to 0 (D5) because the
133
+ // normalising constructor sends every zero to the same form.
134
+ negate() {
135
+ return new Decimal(-this.unscaled, this.scale);
136
+ }
137
+ // D6 -- EXACT ADDITION. Align the scales, add the coefficients. That
138
+ // is the entire algorithm: there is no rounding mode to consult and no
139
+ // precision to run out of, which is why `0d0.1 + 0d0.2` is exactly
140
+ // `0d0.3` here and 0.30000000000000004 in binary64.
141
+ //
142
+ // The work is bounded because both operands are within the parse-time
143
+ // budget, so alignment can inflate a coefficient only by the scale
144
+ // span. The RESULT, however, can be over budget even when both
145
+ // operands are inside it (`0d1e4000 + 0d1e-4000` needs 8001
146
+ // coefficient digits), so every caller must test the result with
147
+ // decimalOverBudget() and report `decimal_budget` rather than store
148
+ // it. Refusal is the only honest answer at the limit: rounding to fit
149
+ // is exactly what this leaf exists to prevent.
150
+ add(peer) {
151
+ const scale = this.scale < peer.scale ? peer.scale : this.scale;
152
+ const a = this.unscaled * pow10(scale - this.scale);
153
+ const b = peer.unscaled * pow10(scale - peer.scale);
154
+ return new Decimal(a + b, scale);
155
+ }
156
+ // Exact ceiling and floor, for `upper()`/`lower()`. Coefficient
157
+ // arithmetic only -- Math.ceil of this value would mean rounding it to
158
+ // binary64 first, which for a leaf that exists to escape binary64 is
159
+ // no answer at all.
160
+ //
161
+ // The leaf is kept (R5 contagion): the result is a bigdecimal whose
162
+ // value happens to be integral, so it keeps the one decimal place the
163
+ // family marker requires -- `upper(0d1.1)` is `0d2.0`, not `0d2`.
164
+ //
165
+ // Neither can leave the exactness budget: with scale >= 1 the integer
166
+ // part drops `scale` digits and normalisation adds one back, so the
167
+ // coefficient never grows. That is why these return a Decimal
168
+ // directly while add() makes its caller check.
169
+ ceil() {
170
+ return new Decimal(this.intPart(1n), 0);
171
+ }
172
+ floor() {
173
+ return new Decimal(this.intPart(-1n), 0);
174
+ }
175
+ // The integer part, stepped one in the direction of `dir` when a
176
+ // remainder of that sign was discarded. bigint division truncates
177
+ // toward zero and the remainder carries the dividend's sign, so
178
+ // truncation already IS the floor of a positive and the ceiling of a
179
+ // negative; only the other half of each case needs the step.
180
+ intPart(dir) {
181
+ const p = pow10(this.scale);
182
+ const q = this.unscaled / p;
183
+ const r = this.unscaled % p;
184
+ return 0n !== r && (0n < r) === (0n < dir) ? q + dir : q;
185
+ }
186
+ isZero() {
187
+ return 0n === this.unscaled;
188
+ }
189
+ // Plain digits, no `0d` marker: `1000.0`, `-0.1`. Plain form at every
190
+ // magnitude, never scientific -- the budget is what makes that safe.
191
+ // This is also the rendering string concatenation will want in Phase 4
192
+ // (`"q" + 0d0.1` is `"q0.1"`), which is why the marker lives in
193
+ // `canon()` and not here.
194
+ toString() {
195
+ const neg = this.unscaled < 0n;
196
+ let d = (neg ? -this.unscaled : this.unscaled).toString();
197
+ if (d.length <= this.scale) {
198
+ d = '0'.repeat(this.scale - d.length + 1) + d;
199
+ }
200
+ const cut = d.length - this.scale;
201
+ return (neg ? '-' : '') + d.slice(0, cut) + '.' + d.slice(cut);
202
+ }
203
+ // Canon rendering: the sign goes BEFORE the marker (`-0d1.5`), because
204
+ // `0d-1.5` is not a literal this language accepts.
205
+ canon() {
206
+ const neg = this.unscaled < 0n;
207
+ return (neg ? '-0d' : '0d') + (neg ? this.negate() : this).toString();
208
+ }
209
+ // Exact-input construction for library consumers (D8). A JS `number`
210
+ // argument is already rounded before this library could inspect it, so
211
+ // the exact leaves are reachable only from a bigint or from text.
212
+ // Accepts `[+-]?digits[.digits][(e|E)[+-]digits]`, with or without the
213
+ // `0d` marker, and no `_` separators (those are literal syntax).
214
+ static fromString(src) {
215
+ const m = /^([-+]?)(?:0[dD])?([0-9]+)(?:\.([0-9]+))?(?:[eE]([-+]?[0-9]+))?$/
216
+ .exec(src);
217
+ if (null == m) {
218
+ throw new Error('not-decimal: ' + src);
219
+ }
220
+ const frac = m[3] ?? '';
221
+ const exp = null == m[4] ? 0 : Number(m[4]);
222
+ const scale = frac.length - exp;
223
+ // The same bound the `0d` literal obeys (D6). Without it this API
224
+ // route reached the resource exhaustion the budget exists to
225
+ // prevent -- `fromString('1e1000000000')` would normalise by
226
+ // building a billion-digit coefficient -- and disagreed with the Go
227
+ // port, whose NewBigDecimal shares the literal path's checker.
228
+ if (overBudget(m[2].length + frac.length, scale)) {
229
+ throw new Error('decimal-budget: ' + src);
230
+ }
231
+ const unscaled = BigInt(m[2] + frac);
232
+ return new Decimal('-' === m[1] ? -unscaled : unscaled, scale);
233
+ }
234
+ }
235
+ exports.Decimal = Decimal;
236
+ // D6 -- THE BUDGET APPLIES TO RESULTS, NOT JUST LITERALS. True when a
237
+ // Decimal produced by arithmetic is over either bound and so must be
238
+ // refused with `decimal_budget`.
239
+ //
240
+ // The test is applied to the NORMAL form -- the representation the value
241
+ // is actually stored and rendered in -- rather than to some minimal
242
+ // re-derived source form. That keeps the rule cheap and mechanical
243
+ // enough for the Go port to mirror exactly (count the coefficient's
244
+ // digits, read the scale), and it bounds precisely the thing the bound
245
+ // exists to bound: the digits plain-form rendering will have to
246
+ // materialise.
247
+ //
248
+ // One consequence is worth naming: a literal is budget-checked on its
249
+ // SOURCE form, so an extreme literal whose normal form is wider than its
250
+ // source (`0d1e4096` -- one written digit, 4098 normalised ones) parses
251
+ // but cannot take part in arithmetic. Both bounds are deliberately far
252
+ // beyond any real document, and the alternative -- re-deriving a minimal
253
+ // form per operation -- only moves the same edge somewhere else
254
+ // (`0d100e4096` has minimal scale -4098, over the bound its source form
255
+ // was under), at the cost of a second normal form that both ports would
256
+ // then have to agree on digit for digit.
257
+ function decimalOverBudget(d) {
258
+ return overBudget(coeffDigits(d.unscaled), d.scale);
259
+ }
260
+ // D3 -- THE `0d` LITERAL.
261
+ //
262
+ // 0[dD] digits [ . digits ] [ (e|E) [+-] digits ]
263
+ //
264
+ // with single `_` separators between digits, exactly as the landed
265
+ // separator rule allows for ordinary numbers (`[0-9](?:_?[0-9])*` admits
266
+ // `1_000` and refuses `1__0`, `_1`, `1_`).
267
+ //
268
+ // LEAF BY SOURCE, mirroring R1's precedent that the source text and not
269
+ // the value decides the kind: digits only is a biginteger, a `.` or an
270
+ // exponent anywhere makes it a bigdecimal. So `0d5` is a biginteger and
271
+ // `0d1e3` is a bigdecimal whose value happens to be integral.
272
+ //
273
+ // THE SIGN IS NOT PART OF THIS PATTERN, though it is part of the D3
274
+ // grammar: `-0d5` is read as the existing unary-minus prefix applied to
275
+ // `0d5` (see negative-prefix in lang.ts), exactly as `-1.5` already is.
276
+ // Aontu's lexer runs regexp value matchers BEFORE the fixed-token
277
+ // matcher, so a `[-+]?` here would claim the `+` of `0d1 +0d2` as a
278
+ // literal sign and silently turn an addition into an implicit list --
279
+ // while plain `1 +2` stayed an addition. The sign belongs to the same
280
+ // operator for both, which is also what keeps `0d-5` rejected.
281
+ //
282
+ // Kept RE2-compatible (no lookaround, no backreferences) so the Go port
283
+ // can use the byte-identical pattern.
284
+ const BIG_LITERAL_RE = /^0[dD]([0-9](?:_?[0-9])*)(?:\.([0-9](?:_?[0-9])*))?(?:[eE]([-+]?[0-9](?:_?[0-9])*))?/;
285
+ exports.BIG_LITERAL_RE = BIG_LITERAL_RE;
286
+ function stripSep(s) {
287
+ return -1 === s.indexOf('_') ? s : s.replace(/_/g, '');
288
+ }
289
+ // Read a `0d` literal from the groups of BIG_LITERAL_RE:
290
+ // 1 integer digits, 2 fraction digits, 3 exponent.
291
+ function readBigLiteral(m) {
292
+ const intd = stripSep(m[1]);
293
+ const fracd = null == m[2] ? undefined : stripSep(m[2]);
294
+ const expd = null == m[3] ? undefined : stripSep(m[3]);
295
+ // Leaf by SOURCE, not by value.
296
+ if (undefined === fracd && undefined === expd) {
297
+ return { leaf: 'biginteger', int: BigInt(intd) };
298
+ }
299
+ // The exponent is read as a plain number on purpose: a 4000-digit
300
+ // exponent lands on Infinity, whose absolute value is over budget, so
301
+ // the refusal below fires without any bigint ever being built.
302
+ const exp = undefined === expd ? 0 : Number(expd);
303
+ const fracLen = undefined === fracd ? 0 : fracd.length;
304
+ const scale = fracLen - exp;
305
+ // The budget is checked on the SOURCE form, before normalisation:
306
+ // normalising `0d1e1000000000` is itself the resource event the bound
307
+ // exists to prevent. Coefficient digits are counted as written
308
+ // (leading zeros included) so the two ports need not agree on any
309
+ // cleverer rule.
310
+ if (overBudget(intd.length + fracLen, scale)) {
311
+ return { leaf: 'error', code: 'decimal_budget' };
312
+ }
313
+ return {
314
+ leaf: 'bigdecimal',
315
+ dec: new Decimal(BigInt(intd + (fracd ?? '')), scale),
316
+ };
317
+ }
318
+ //# sourceMappingURL=Decimal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Decimal.js","sourceRoot":"","sources":["../../src/val/Decimal.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@ import { AontuContext } from '../ctx';
3
3
  import { ScalarVal } from './ScalarVal';
4
4
  declare class IntegerVal extends ScalarVal {
5
5
  isInteger: boolean;
6
+ get canon(): string;
7
+ gen(_ctx?: AontuContext): number | bigint;
6
8
  constructor(spec: ValSpec, ctx?: AontuContext);
7
9
  unify(peer: any, ctx: AontuContext): Val;
8
10
  }
@@ -5,12 +5,84 @@ exports.IntegerVal = void 0;
5
5
  const err_1 = require("../err");
6
6
  const ScalarVal_1 = require("./ScalarVal");
7
7
  const ScalarKindVal_1 = require("./ScalarKindVal");
8
+ const numkind_1 = require("./numkind");
8
9
  const utility_1 = require("../utility");
9
10
  class IntegerVal extends ScalarVal_1.ScalarVal {
11
+ // Canon renders the EXACT digits of the value, not JavaScript's
12
+ // shortest round-tripping form.
13
+ //
14
+ // A JS number's toString emits the shortest decimal that parses back
15
+ // to the same double — at most 17 significant digits — so 2^60 printed
16
+ // as `1152921504606847000`, a DIFFERENT integer that merely rounds to
17
+ // the same double, while the Go port printed the true
18
+ // `1152921504606846976` from its int64. That was the one entry in the
19
+ // parity ledger (issue #21).
20
+ //
21
+ // Neither rendering was "the wrong number" while lossy literals were
22
+ // still accepted, which is why the ledger deferred to the Phase 6
23
+ // refusal — but Phase 6 refuses INEXACT literals, and every value in
24
+ // this window (2^60, 2^63-1024, …) is exactly representable and so is
25
+ // accepted. The divergence was never about exactness; it was about
26
+ // rendering. Once the value is exactly what the source asked for,
27
+ // there IS a right answer, and it is the exact digits.
28
+ //
29
+ // BigInt is exact here by construction: an IntegerVal's peg is
30
+ // integral and inside the int64 window (isIntegerKind, enforced in the
31
+ // constructor), so the bigint conversion cannot lose anything.
32
+ get canon() {
33
+ return (0, numkind_1.integerDigits)(this.peg);
34
+ }
35
+ // The same exactness in GENERATED output -- the other half of #21, and
36
+ // the half canon cannot reach.
37
+ //
38
+ // `generate()` returns NATIVE values, and the emitter sees only those:
39
+ // by the time exactJSON has a JS number it can no longer tell an
40
+ // integer-kind 2^60 (whose exact digits are the answer) from a
41
+ // float-kind 1e21 (whose shortest form `1e+21` is the answer, and is
42
+ // what Go prints too). The kind has to travel WITH the value, so above
43
+ // the safe-integer range an integer-kind value generates as a `bigint`,
44
+ // which the emitter already writes as exact digits.
45
+ //
46
+ // WHY Number.isSafeInteger IS THE LINE. It is precisely "this double is
47
+ // an integer that renders its own exact digits": inside the range the
48
+ // integers are contiguous, so toString round-trips exactly and a
49
+ // `number` loses nothing. Outside it they are not, and JS itself
50
+ // declares the value untrustworthy -- so handing back a `number` there
51
+ // would give a consumer something that prints wrong AND does
52
+ // arithmetic wrong, silently. A bigint makes both explicit: mixing it
53
+ // with a number throws rather than quietly rounding.
54
+ //
55
+ // The line is deliberately the WELL-KNOWN one rather than the tightest
56
+ // possible one. Some doubles above the range do still render exactly
57
+ // (2^54, say), so a predicate of `BigInt(peg).toString() === String(peg)`
58
+ // would keep marginally more values as `number` -- at the cost of a
59
+ // contract no consumer could evaluate in their head, and of handing
60
+ // back unsafe numbers for arithmetic. "Integers up to
61
+ // Number.MAX_SAFE_INTEGER are numbers; beyond that, bigints" is a rule
62
+ // that can be stated once and relied on.
63
+ //
64
+ // This is a BREAKING change for a consumer reading integers above 2^53
65
+ // out of generate() -- but those were the values that were already
66
+ // silently wrong, and a TypeError on `out.x + 1` is the better failure.
67
+ // Go needs none of this: its integer leaf is an int64, exact across the
68
+ // whole window, and encoding/json writes its digits.
69
+ //
70
+ // The BYTES are unchanged below the line, and the values that cross it
71
+ // with 17 or fewer significant digits (2^53 itself) serialise the same
72
+ // either way -- only their runtime type moves, which is why the `gens`
73
+ // rows cannot see it and ts/test/exactjson.test.ts pins it instead.
74
+ gen(_ctx) {
75
+ const peg = this.peg;
76
+ return Number.isSafeInteger(peg) ? peg : BigInt(peg);
77
+ }
10
78
  constructor(spec, ctx) {
11
- if (!Number.isInteger(spec.peg)) {
12
- // TODO: use Nil?
13
- throw new err_1.AontuError('not-integer: ' + spec.peg);
79
+ // An IntegerVal must hold a value of *integer kind*: integral AND
80
+ // within the int64 range, so it can never hold something the Go
81
+ // port's int64 storage could not (see isIntegerKind). Every
82
+ // construction site pre-checks with the same helper, so reaching
83
+ // here is a programming error, not user input — hence a throw.
84
+ if (!(0, numkind_1.isIntegerKind)(spec.peg)) {
85
+ throw new err_1.AontuError('not-integer-kind: ' + spec.peg);
14
86
  }
15
87
  // super({ peg: spec.peg, kind: Integer }, ctx)
16
88
  super({ ...spec, kind: ScalarKindVal_1.Integer }, ctx);
@@ -1 +1 @@
1
- {"version":3,"file":"IntegerVal.js","sourceRoot":"","sources":["../../src/val/IntegerVal.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;AAWzD,gCAA+C;AAE/C,2CAAuC;AACvC,mDAAyC;AAEzC,wCAImB;AAGnB,MAAM,UAAW,SAAQ,qBAAS;IAGhC,YACE,IAAa,EACb,GAAkB;QAElB,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,iBAAiB;YACjB,MAAM,IAAI,gBAAU,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAA;QAClD,CAAC;QACD,+CAA+C;QAC/C,KAAK,CAAC,EAAE,GAAG,IAAI,EAAE,IAAI,EAAE,uBAAO,EAAE,EAAE,GAAG,CAAC,CAAA;QAXxC,cAAS,GAAG,IAAI,CAAA;IAYhB,CAAC;IAED,KAAK,CAAC,IAAS,EAAE,GAAiB;QAChC,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,IAAI,IAAA,qBAAW,EAAC,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;QAE9E,IAAI,GAAG,GAAQ,IAAI,CAAA;QAEnB,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC;YACjB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,IAAA,YAAE,EAAC,EAAE,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;YAC1E,CAAC;iBACI,IACH,IAAI,CAAC,QAAQ;gBACb,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;gBACvB,IAAI,CAAC,GAAG,KAAK,IAAI,CAAC,GAAG,EACrB,CAAC;gBACD,GAAG,GAAG,IAAI,CAAA;YACZ,CAAC;iBACI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACpB,GAAG,GAAG,IAAI,CAAA;YACZ,CAAC;iBACI,CAAC;gBACJ,GAAG,GAAG,IAAA,gBAAU,EAAC,GAAG,EAAE,SAAS;oBAC7B,CAAE,IAAY,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;YACtE,CAAC;QACH,CAAC;aACI,CAAC;YACJ,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC9B,CAAC;QAED,IAAA,sBAAY,EAAC,EAAE,EAAE,GAAG,CAAC,CAAA;QAErB,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;QAIC,UAAU"}
1
+ {"version":3,"file":"IntegerVal.js","sourceRoot":"","sources":["../../src/val/IntegerVal.ts"],"names":[],"mappings":"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"}
@@ -7,7 +7,7 @@ declare class KeyFuncVal extends FuncBaseVal {
7
7
  make(_ctx: AontuContext, spec: ValSpec): Val;
8
8
  funcname(): string;
9
9
  unify(peer: Val, ctx: AontuContext): Val;
10
- resolve(_ctx: AontuContext, _args: Val[]): Val;
10
+ resolve(ctx: AontuContext, _args: Val[]): import("./NilVal").NilVal | Val;
11
11
  gen(_ctx: AontuContext): any;
12
12
  }
13
13
  export { KeyFuncVal, };
@@ -5,6 +5,7 @@ exports.KeyFuncVal = void 0;
5
5
  const StringVal_1 = require("../val/StringVal");
6
6
  const ConjunctVal_1 = require("../val/ConjunctVal");
7
7
  const FuncBaseVal_1 = require("./FuncBaseVal");
8
+ const err_1 = require("../err");
8
9
  class KeyFuncVal extends FuncBaseVal_1.FuncBaseVal {
9
10
  constructor(spec, ctx) {
10
11
  super(spec, ctx);
@@ -45,11 +46,40 @@ class KeyFuncVal extends FuncBaseVal_1.FuncBaseVal {
45
46
  }
46
47
  return out;
47
48
  }
48
- resolve(_ctx, _args) {
49
+ resolve(ctx, _args) {
49
50
  let out = this;
50
51
  // if (!this.mark.type && !this.mark.hide) {
51
- let move = this.peg?.[0]?.peg;
52
- move = isNaN(move) ? 1 : +move;
52
+ //
53
+ // THE LEVEL MUST BE AN INTEGER, OR ABSENT.
54
+ //
55
+ // A level is an index into the path (0 the own key, the default 1 the
56
+ // parent), so the argument is an integer or it is a mistake. Both
57
+ // exact integer leaves qualify -- `integer` and `biginteger` -- and
58
+ // everything else is refused rather than silently meaning "parent",
59
+ // which is what made a mistyped level undetectable.
60
+ //
61
+ // This also removes a crash. The test used to be
62
+ // `isNaN(move) ? 1 : +move` with the COERCING global isNaN, which is
63
+ // ToNumber, and ToNumber THROWS for a bigint (a biginteger's peg) and
64
+ // for the null-prototype object a map's peg is -- neither has a
65
+ // toString or valueOf to call. The exception escaped into unify's
66
+ // catch-all and surfaced as an opaque [aontu/internal].
67
+ const argval = this.peg?.[0];
68
+ let move = 1;
69
+ if (null != argval) {
70
+ if (argval.isInteger) {
71
+ move = argval.peg;
72
+ }
73
+ else if (argval.isBigInteger) {
74
+ // A level far outside the path simply misses, exactly as an
75
+ // out-of-range plain integer already does, so Number() here needs
76
+ // no bound of its own.
77
+ move = Number(argval.peg);
78
+ }
79
+ else {
80
+ return (0, err_1.makeNilErr)(ctx, 'key_level', this);
81
+ }
82
+ }
53
83
  const key = this.path[this.path.length - (1 + move)] ?? '';
54
84
  // console.log('KEY', this.path, move, key)
55
85
  out = new StringVal_1.StringVal({ peg: key });
@@ -1 +1 @@
1
- {"version":3,"file":"KeyFuncVal.js","sourceRoot":"","sources":["../../src/val/KeyFuncVal.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;AAazD,gDAA4C;AAC5C,oDAAgD;AAIhD,+CAA2C;AAG3C,MAAM,UAAW,SAAQ,yBAAW;IAGlC,YACE,IAAa,EACb,GAAkB;QAElB,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QANlB,cAAS,GAAG,IAAI,CAAA;QAOd,iBAAiB;IACnB,CAAC;IAGD,IAAI,CAAC,IAAkB,EAAE,IAAa;QACpC,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,CAAA;IAC7B,CAAC;IAED,QAAQ;QACN,OAAO,KAAK,CAAA;IACd,CAAC;IAGD,KAAK,CAAC,IAAS,EAAE,GAAiB;QAChC,8FAA8F;QAC9F,IAAI,GAAG,GAAQ,IAAI,CAAA;QAEnB,IAAI,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;YACf,IAAI,CAAC,OAAO,EAAE,CAAA;YAEd,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;gBACxC,yEAAyE;gBACzE,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;YACvB,CAAC;iBACI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACpB,GAAG,GAAG,IAAI,CAAA;YACZ,CAAC;iBACI,CAAC;gBACJ,IACE,IAAI,CAAC,SAAS;uBACX,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;uBAC3C,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,EAC5C,CAAC;oBACD,GAAG,GAAG,IAAI,CAAA;gBACZ,CAAC;qBACI,CAAC;oBACJ,GAAG,GAAG,IAAI,yBAAW,CAAC,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,GAAG,CAAC,CAAA;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;aACI,CAAC;YACJ,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC9B,CAAC;QAED,OAAO,GAAG,CAAA;IACZ,CAAC;IAGD,OAAO,CAAC,IAAkB,EAAE,KAAY;QACtC,IAAI,GAAG,GAAQ,IAAI,CAAA;QAEnB,4CAA4C;QAC5C,IAAI,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAA;QAC7B,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;QAC1D,2CAA2C;QAE3C,GAAG,GAAG,IAAI,qBAAS,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;QACjC,IAAI;QAEJ,OAAO,GAAG,CAAA;IACZ,CAAC;IAGD,GAAG,CAAC,IAAkB;QACpB,OAAO,SAAS,CAAA;IAClB,CAAC;CAEF;QAIC,UAAU"}
1
+ {"version":3,"file":"KeyFuncVal.js","sourceRoot":"","sources":["../../src/val/KeyFuncVal.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ exports.LowerFuncVal = void 0;
5
5
  const err_1 = require("../err");
6
6
  const ScalarKindVal_1 = require("../val/ScalarKindVal");
7
7
  const valutil_1 = require("../val/valutil");
8
+ const Decimal_1 = require("../val/Decimal");
8
9
  const FuncBaseVal_1 = require("./FuncBaseVal");
9
10
  class LowerFuncVal extends FuncBaseVal_1.FuncBaseVal {
10
11
  constructor(spec, ctx) {
@@ -18,13 +19,29 @@ class LowerFuncVal extends FuncBaseVal_1.FuncBaseVal {
18
19
  return 'lower';
19
20
  }
20
21
  resolve(ctx, args) {
21
- const oldpeg = args?.[0].peg;
22
+ // A missing argument (`lower()`) must produce an invalid-arg error
23
+ // value, as the Go port does — reading .peg off nothing threw a
24
+ // TypeError that the unifier could only report as an opaque
25
+ // internal error.
26
+ const arg = args?.[0];
27
+ const oldpeg = arg?.peg;
22
28
  const peg = 'string' === typeof oldpeg ? oldpeg.toLowerCase() :
23
29
  'number' === typeof oldpeg ? Math.floor(oldpeg) :
24
- undefined;
30
+ // The exact leaves take an EXACT floor and keep their kind: a
31
+ // biginteger is already integral so it is its own floor, and a
32
+ // bigdecimal floors by coefficient arithmetic. Math.floor is not
33
+ // an option for either — it would round the value into binary64
34
+ // first, which is the loss the `0d` leaves exist to refuse.
35
+ 'bigint' === typeof oldpeg ? oldpeg :
36
+ oldpeg instanceof Decimal_1.Decimal ? oldpeg.floor() :
37
+ undefined;
25
38
  const out = this.place(null == peg ?
26
39
  (0, err_1.makeNilErr)(ctx, 'invalid-arg', this) :
27
- (0, valutil_1.makeScalar)(peg));
40
+ // The floor keeps the ARGUMENT's kind (lower(2) is an integer 2,
41
+ // lower(1.9) is a number 1) — the function must not narrow
42
+ // number to integer, and this also makes the actual result kind
43
+ // agree with the superior() advertised below.
44
+ (0, valutil_1.makeScalarLike)(peg, arg));
28
45
  return out;
29
46
  }
30
47
  superior() {
@@ -1 +1 @@
1
- {"version":3,"file":"LowerFuncVal.js","sourceRoot":"","sources":["../../src/val/LowerFuncVal.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;AAYzD,gCAAmC;AAInC,wDAAoD;AACpD,4CAA2C;AAI3C,+CAA2C;AAG3C,MAAM,YAAa,SAAQ,yBAAW;IAGpC,YACE,IAAa,EACb,GAAkB;QAElB,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QANlB,gBAAW,GAAG,IAAI,CAAA;IAOlB,CAAC;IAGD,IAAI,CAAC,IAAkB,EAAE,IAAa;QACpC,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAA;IAC/B,CAAC;IAED,QAAQ;QACN,OAAO,OAAO,CAAA;IAChB,CAAC;IAGD,OAAO,CAAC,GAA6B,EAAE,IAAW;QAChD,MAAM,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAA;QAC5B,MAAM,GAAG,GAAG,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7D,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC/C,SAAS,CAAA;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,IAAI,IAAI,GAAG,CAAC,CAAC;YACX,IAAA,gBAAU,EAAC,GAAG,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC;YACtC,IAAA,oBAAU,EAAC,GAAG,CAAC,CAClB,CAAA;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAGD,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;QACzB,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC;YACpB,IAAI,CAAC,KAAK,CAAC,IAAI,6BAAa,CAAC;gBAC3B,GAAG,EAAE,GAAG,CAAC,IAAI;aACd,CAAC,CAAC,CAAC,CAAC;YACL,KAAK,CAAC,QAAQ,EAAE,CAAA;IACpB,CAAC;CAEF;QAIC,YAAY"}
1
+ {"version":3,"file":"LowerFuncVal.js","sourceRoot":"","sources":["../../src/val/LowerFuncVal.ts"],"names":[],"mappings":";AAAA,yDAAyD;;;AAYzD,gCAAmC;AAInC,wDAAoD;AACpD,4CAA+C;AAC/C,4CAAwC;AAIxC,+CAA2C;AAG3C,MAAM,YAAa,SAAQ,yBAAW;IAGpC,YACE,IAAa,EACb,GAAkB;QAElB,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QANlB,gBAAW,GAAG,IAAI,CAAA;IAOlB,CAAC;IAGD,IAAI,CAAC,IAAkB,EAAE,IAAa;QACpC,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,CAAA;IAC/B,CAAC;IAED,QAAQ;QACN,OAAO,OAAO,CAAA;IAChB,CAAC;IAGD,OAAO,CAAC,GAA6B,EAAE,IAAW;QAChD,mEAAmE;QACnE,gEAAgE;QAChE,4DAA4D;QAC5D,kBAAkB;QAClB,MAAM,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;QACrB,MAAM,MAAM,GAAG,GAAG,EAAE,GAAG,CAAA;QACvB,MAAM,GAAG,GAAG,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC7D,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC/C,8DAA8D;gBAC9D,+DAA+D;gBAC/D,iEAAiE;gBACjE,gEAAgE;gBAChE,4DAA4D;gBAC5D,QAAQ,KAAK,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;oBACnC,MAAM,YAAY,iBAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;wBAC1C,SAAS,CAAA;QACjB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CACpB,IAAI,IAAI,GAAG,CAAC,CAAC;YACX,IAAA,gBAAU,EAAC,GAAG,EAAE,aAAa,EAAE,IAAI,CAAC,CAAC,CAAC;YACtC,iEAAiE;YACjE,2DAA2D;YAC3D,gEAAgE;YAChE,8CAA8C;YAC9C,IAAA,wBAAc,EAAC,GAAG,EAAE,GAAG,CAAC,CAC3B,CAAA;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;IAGD,QAAQ;QACN,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAA;QACzB,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC;YACpB,IAAI,CAAC,KAAK,CAAC,IAAI,6BAAa,CAAC;gBAC3B,GAAG,EAAE,GAAG,CAAC,IAAI;aACd,CAAC,CAAC,CAAC,CAAC;YACL,KAAK,CAAC,QAAQ,EAAE,CAAA;IACpB,CAAC;CAEF;QAIC,YAAY"}
@@ -9,6 +9,7 @@ const err_1 = require("../err");
9
9
  const top_1 = require("./top");
10
10
  const ConjunctVal_1 = require("./ConjunctVal");
11
11
  const BagVal_1 = require("./BagVal");
12
+ const keyorder_1 = require("../keyorder");
12
13
  // Structural snapshots of ref spreads (see MapVal.unify), keyed by the
13
14
  // ref's canon + source site rather than object identity: spread
14
15
  // application clones templates (and the refs inside them) freely, and a
@@ -316,10 +317,11 @@ class MapVal extends BagVal_1.BagVal {
316
317
  return out;
317
318
  }
318
319
  get canon() {
319
- // Keys are emitted alphabetically so the canonical form is
320
- // independent of insertion/unification order (and matches the Go
321
- // port, whose JSON marshaling also sorts keys).
322
- let keys = Object.keys(this.peg).sort();
320
+ // Keys are emitted in CODE POINT order so the canonical form is
321
+ // independent of insertion/unification order and matches the Go
322
+ // port. A bare .sort() is UTF-16 code-unit order, which puts an
323
+ // astral key ahead of everything in U+E000-U+FFFF -- see cmpCodePoint.
324
+ let keys = Object.keys(this.peg).sort(keyorder_1.cmpCodePoint);
323
325
  return '' +
324
326
  // this.errcanon() +
325
327
  // (this.mark.type ? '<type>' : '') +