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.
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +18 -2
- package/dist/aontu.js.map +1 -1
- package/dist/cli.js +33 -7
- package/dist/cli.js.map +1 -1
- package/dist/exactjson.d.ts +37 -0
- package/dist/exactjson.js +228 -0
- package/dist/exactjson.js.map +1 -0
- package/dist/hints.js +61 -4
- package/dist/hints.js.map +1 -1
- package/dist/keyorder.d.ts +9 -0
- package/dist/keyorder.js +65 -0
- package/dist/keyorder.js.map +1 -0
- package/dist/lang.js +200 -4
- package/dist/lang.js.map +1 -1
- package/dist/lsp.js +12 -2
- package/dist/lsp.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/val/BagVal.js +8 -5
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.d.ts +13 -0
- package/dist/val/BigDecimalVal.js +80 -0
- package/dist/val/BigDecimalVal.js.map +1 -0
- package/dist/val/BigIntegerVal.d.ts +11 -0
- package/dist/val/BigIntegerVal.js +75 -0
- package/dist/val/BigIntegerVal.js.map +1 -0
- package/dist/val/Decimal.d.ts +32 -0
- package/dist/val/Decimal.js +318 -0
- package/dist/val/Decimal.js.map +1 -0
- package/dist/val/IntegerVal.d.ts +2 -0
- package/dist/val/IntegerVal.js +75 -3
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/KeyFuncVal.d.ts +1 -1
- package/dist/val/KeyFuncVal.js +33 -3
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +20 -3
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +6 -4
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MoveFuncVal.js +25 -8
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NumberVal.d.ts +1 -0
- package/dist/val/NumberVal.js +23 -2
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +9 -1
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PlusOpVal.d.ts +3 -1
- package/dist/val/PlusOpVal.js +140 -29
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefVal.d.ts +2 -0
- package/dist/val/PrefVal.js +40 -4
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RefVal.js +57 -2
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ScalarKindVal.d.ts +12 -2
- package/dist/val/ScalarKindVal.js +100 -11
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.d.ts +1 -0
- package/dist/val/ScalarVal.js +16 -1
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/SuperFuncVal.d.ts +1 -1
- package/dist/val/SuperFuncVal.js +14 -1
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/UpperFuncVal.js +20 -3
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/VarVal.js +7 -1
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/numkind.d.ts +6 -0
- package/dist/val/numkind.js +224 -0
- package/dist/val/numkind.js.map +1 -0
- package/dist/val/valutil.d.ts +1 -0
- package/dist/val/valutil.js +35 -0
- package/dist/val/valutil.js.map +1 -1
- package/package.json +7 -7
- package/src/aontu.ts +23 -2
- package/src/cli.ts +36 -8
- package/src/exactjson.ts +254 -0
- package/src/hints.ts +73 -4
- package/src/keyorder.ts +73 -0
- package/src/lang.ts +229 -5
- package/src/lsp.ts +10 -2
- package/src/val/BagVal.ts +8 -5
- package/src/val/BigDecimalVal.ts +117 -0
- package/src/val/BigIntegerVal.ts +110 -0
- package/src/val/Decimal.ts +385 -0
- package/src/val/IntegerVal.ts +79 -3
- package/src/val/KeyFuncVal.ts +35 -3
- package/src/val/LowerFuncVal.ts +21 -4
- package/src/val/MapVal.ts +6 -4
- package/src/val/MoveFuncVal.ts +26 -9
- package/src/val/NumberVal.ts +25 -2
- package/src/val/PathFuncVal.ts +9 -1
- package/src/val/PlusOpVal.ts +168 -32
- package/src/val/PrefVal.ts +66 -5
- package/src/val/RefVal.ts +61 -2
- package/src/val/ScalarKindVal.ts +115 -10
- package/src/val/ScalarVal.ts +18 -1
- package/src/val/SuperFuncVal.ts +14 -1
- package/src/val/UpperFuncVal.ts +21 -4
- package/src/val/VarVal.ts +7 -1
- package/src/val/numkind.ts +256 -0
- 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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"}
|
package/dist/val/IntegerVal.d.ts
CHANGED
|
@@ -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
|
}
|
package/dist/val/IntegerVal.js
CHANGED
|
@@ -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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"IntegerVal.js","sourceRoot":"","sources":["../../src/val/IntegerVal.ts"],"names":[],"mappings":"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"}
|
package/dist/val/KeyFuncVal.d.ts
CHANGED
|
@@ -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(
|
|
10
|
+
resolve(ctx: AontuContext, _args: Val[]): import("./NilVal").NilVal | Val;
|
|
11
11
|
gen(_ctx: AontuContext): any;
|
|
12
12
|
}
|
|
13
13
|
export { KeyFuncVal, };
|
package/dist/val/KeyFuncVal.js
CHANGED
|
@@ -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(
|
|
49
|
+
resolve(ctx, _args) {
|
|
49
50
|
let out = this;
|
|
50
51
|
// if (!this.mark.type && !this.mark.hide) {
|
|
51
|
-
|
|
52
|
-
|
|
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;
|
|
1
|
+
{"version":3,"file":"KeyFuncVal.js","sourceRoot":"","sources":["../../src/val/KeyFuncVal.ts"],"names":[],"mappings":"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"}
|
package/dist/val/LowerFuncVal.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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"}
|
package/dist/val/MapVal.js
CHANGED
|
@@ -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
|
|
320
|
-
// independent of insertion/unification order
|
|
321
|
-
// port
|
|
322
|
-
|
|
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>' : '') +
|