aontu 0.50.1 → 0.52.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/bin/aontu-lsp.js +6 -0
- package/bin/aontu.js +7 -0
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +21 -8
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +43 -53
- package/dist/cli.js.map +1 -1
- package/dist/ctx.js +1 -1
- package/dist/ctx.js.map +1 -1
- package/dist/err.js +3 -2
- package/dist/err.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.d.ts +3 -1
- package/dist/hints.js +187 -5
- 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 +263 -30
- package/dist/lang.js.map +1 -1
- package/dist/lsp-server.d.ts +2 -2
- package/dist/lsp-server.js +10 -10
- package/dist/lsp-server.js.map +1 -1
- package/dist/lsp.js +39 -21
- package/dist/lsp.js.map +1 -1
- package/dist/site.js +1 -1
- package/dist/site.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/unify.js +48 -1
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +3 -8
- package/dist/utility.js.map +1 -1
- package/dist/val/BagVal.js +9 -6
- 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/BooleanVal.js +1 -1
- package/dist/val/BooleanVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +1 -1
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/ConjunctVal.js +1 -1
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.d.ts +56 -0
- package/dist/val/ConstraintVal.js +407 -0
- package/dist/val/ConstraintVal.js.map +1 -0
- package/dist/val/CopyFuncVal.js +1 -1
- package/dist/val/CopyFuncVal.js.map +1 -1
- 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/DisjunctVal.js +1 -29
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/ExpectVal.js +1 -1
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FeatureVal.js +1 -1
- package/dist/val/FeatureVal.js.map +1 -1
- package/dist/val/FuncBaseVal.js +1 -1
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/HideFuncVal.js +1 -1
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IntegerVal.d.ts +2 -0
- package/dist/val/IntegerVal.js +77 -5
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/JunctionVal.js +1 -1
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.d.ts +1 -1
- package/dist/val/KeyFuncVal.js +34 -4
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +7 -7
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +21 -4
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +17 -13
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MoveFuncVal.js +26 -9
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.d.ts +1 -0
- package/dist/val/NilVal.js +10 -3
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NullVal.js +1 -1
- package/dist/val/NullVal.js.map +1 -1
- package/dist/val/NumberVal.d.ts +1 -0
- package/dist/val/NumberVal.js +25 -4
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.js +10 -8
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/OpenFuncVal.js +1 -1
- package/dist/val/OpenFuncVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +10 -2
- 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/PrefFuncVal.js +1 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.d.ts +2 -0
- package/dist/val/PrefVal.js +44 -7
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RefVal.d.ts +2 -0
- package/dist/val/RefVal.js +135 -11
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ScalarKindVal.d.ts +12 -2
- package/dist/val/ScalarKindVal.js +108 -13
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.d.ts +1 -0
- package/dist/val/ScalarVal.js +18 -3
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/StringVal.js +1 -1
- package/dist/val/StringVal.js.map +1 -1
- package/dist/val/SuperFuncVal.d.ts +1 -1
- package/dist/val/SuperFuncVal.js +15 -2
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.js +1 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TypeFuncVal.js +1 -1
- package/dist/val/TypeFuncVal.js.map +1 -1
- package/dist/val/UpperFuncVal.js +21 -4
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +1 -1
- package/dist/val/Val.js +11 -21
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +8 -2
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/numcmp.d.ts +14 -0
- package/dist/val/numcmp.js +134 -0
- package/dist/val/numcmp.js.map +1 -0
- 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 -5
- package/src/aontu.ts +26 -9
- package/src/cli.ts +48 -21
- package/src/ctx.ts +1 -1
- package/src/err.ts +3 -2
- package/src/exactjson.ts +254 -0
- package/src/hints.ts +213 -4
- package/src/keyorder.ts +73 -0
- package/src/lang.ts +303 -31
- package/src/lsp-server.ts +17 -15
- package/src/lsp.ts +37 -14
- package/src/site.ts +1 -1
- package/src/type.ts +1 -1
- package/src/unify.ts +52 -1
- package/src/utility.ts +3 -9
- package/src/val/BagVal.ts +9 -6
- package/src/val/BigDecimalVal.ts +117 -0
- package/src/val/BigIntegerVal.ts +110 -0
- package/src/val/BooleanVal.ts +1 -1
- package/src/val/CloseFuncVal.ts +1 -1
- package/src/val/ConjunctVal.ts +1 -1
- package/src/val/ConstraintVal.ts +561 -0
- package/src/val/CopyFuncVal.ts +1 -1
- package/src/val/Decimal.ts +385 -0
- package/src/val/DisjunctVal.ts +1 -37
- package/src/val/ExpectVal.ts +1 -1
- package/src/val/FeatureVal.ts +1 -1
- package/src/val/FuncBaseVal.ts +1 -1
- package/src/val/HideFuncVal.ts +1 -1
- package/src/val/IntegerVal.ts +81 -5
- package/src/val/JunctionVal.ts +1 -1
- package/src/val/KeyFuncVal.ts +36 -4
- package/src/val/ListVal.ts +3 -5
- package/src/val/LowerFuncVal.ts +22 -5
- package/src/val/MapVal.ts +13 -9
- package/src/val/MoveFuncVal.ts +27 -10
- package/src/val/NilVal.ts +13 -3
- package/src/val/NullVal.ts +1 -1
- package/src/val/NumberVal.ts +27 -4
- package/src/val/OpBaseVal.ts +10 -10
- package/src/val/OpenFuncVal.ts +1 -1
- package/src/val/PathFuncVal.ts +10 -2
- package/src/val/PlusOpVal.ts +168 -32
- package/src/val/PrefFuncVal.ts +1 -1
- package/src/val/PrefVal.ts +70 -8
- package/src/val/RefVal.ts +143 -11
- package/src/val/ScalarKindVal.ts +123 -12
- package/src/val/ScalarVal.ts +20 -3
- package/src/val/StringVal.ts +1 -1
- package/src/val/SuperFuncVal.ts +15 -2
- package/src/val/TopVal.ts +1 -1
- package/src/val/TypeFuncVal.ts +1 -1
- package/src/val/UpperFuncVal.ts +22 -5
- package/src/val/Val.ts +13 -8
- package/src/val/VarVal.ts +8 -2
- package/src/val/numcmp.ts +189 -0
- package/src/val/numkind.ts +256 -0
- package/src/val/valutil.ts +36 -0
package/src/unify.ts
CHANGED
|
@@ -205,6 +205,30 @@ function update(x: Val, _y: Val) {
|
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
|
|
208
|
+
// The still-refining paths named by a budget_passes error: the first
|
|
209
|
+
// `max` non-done nodes of the residue, as `$.dotted.paths`. Depth-first
|
|
210
|
+
// over bag children only -- this feeds an error message, not a report,
|
|
211
|
+
// so a small deterministic sample beats completeness.
|
|
212
|
+
function residuePaths(v: Val, max: number): string[] {
|
|
213
|
+
const out: string[] = []
|
|
214
|
+
const visit = (n: any, isroot: boolean) => {
|
|
215
|
+
if (null == n || max <= out.length) {
|
|
216
|
+
return
|
|
217
|
+
}
|
|
218
|
+
if (!isroot && !n.done) {
|
|
219
|
+
out.push('$' + (0 < (n.path?.length ?? 0) ? '.' + n.path.join('.') : ''))
|
|
220
|
+
}
|
|
221
|
+
if (n.isMap || n.isList) {
|
|
222
|
+
for (const k in n.peg) {
|
|
223
|
+
visit(n.peg[k], false)
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
visit(v, true)
|
|
228
|
+
return out
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
|
|
208
232
|
class Unify {
|
|
209
233
|
root: Val
|
|
210
234
|
res: Val
|
|
@@ -264,6 +288,7 @@ class Unify {
|
|
|
264
288
|
|
|
265
289
|
// NOTE: if true === res.done already, then this loop never needs to run.
|
|
266
290
|
let maxcc = 9 // 99
|
|
291
|
+
let prevCanon: string | undefined = undefined
|
|
267
292
|
for (; this.cc < maxcc && DONE !== res.dc; this.cc++) {
|
|
268
293
|
// console.log('CC', this.cc, res.canon)
|
|
269
294
|
uctx.cc = this.cc
|
|
@@ -274,15 +299,41 @@ class Unify {
|
|
|
274
299
|
break
|
|
275
300
|
}
|
|
276
301
|
|
|
302
|
+
// Snapshot the second-to-last pass's result, so exhaustion can
|
|
303
|
+
// tell "still refining" from "stable residue" below. Only paid
|
|
304
|
+
// by models still unresolved this late.
|
|
305
|
+
if (this.cc === maxcc - 2 && DONE !== res.dc) {
|
|
306
|
+
prevCanon = res.canon
|
|
307
|
+
}
|
|
308
|
+
|
|
277
309
|
uctx = uctx.clone({ root: res })
|
|
278
310
|
}
|
|
279
311
|
|
|
312
|
+
// The pass budget is spent AND the final pass still made
|
|
313
|
+
// progress: the model was cut off while converging, and no other
|
|
314
|
+
// error explains why. Silent truncation would surface later as
|
|
315
|
+
// ordinary incompleteness, so exhaustion is a semantic error of
|
|
316
|
+
// its own (class budget, docs/trust.md clause 2) -- retrying with
|
|
317
|
+
// a larger budget is a valid response to THIS code and useless
|
|
318
|
+
// for path_cycle or no_path. A STABLE residue (the final pass
|
|
319
|
+
// changed nothing -- e.g. a stuck `1+true`) is not a budget
|
|
320
|
+
// failure: it is ordinary incompleteness and stays silent here,
|
|
321
|
+
// surfacing at generate exactly as before.
|
|
322
|
+
if (maxcc <= this.cc && DONE !== res.dc && 0 === uctx.err.length
|
|
323
|
+
&& undefined !== prevCanon && prevCanon !== res.canon) {
|
|
324
|
+
makeNilErr(uctx, 'budget_passes', undefined, undefined, 'resolve', {
|
|
325
|
+
budget: 'passes',
|
|
326
|
+
limit: maxcc,
|
|
327
|
+
paths: residuePaths(res, 4).join(' ') || '$',
|
|
328
|
+
})
|
|
329
|
+
}
|
|
330
|
+
|
|
280
331
|
uctx.explain && explainClose(te, res)
|
|
281
332
|
}
|
|
282
333
|
|
|
283
334
|
this.res = res
|
|
284
335
|
}
|
|
285
|
-
}
|
|
336
|
+
} /* node:coverage ignore next 9 */
|
|
286
337
|
|
|
287
338
|
|
|
288
339
|
|
package/src/utility.ts
CHANGED
|
@@ -84,6 +84,8 @@ function walk(
|
|
|
84
84
|
|
|
85
85
|
// Container Vals (Map etc) have peg = plain {} or []
|
|
86
86
|
if (null != child && !child.isVal) {
|
|
87
|
+
// A ListVal's array peg is an object too, and for-in yields its
|
|
88
|
+
// indices as string keys, so this one loop covers both bag shapes.
|
|
87
89
|
if ('object' === typeof child) {
|
|
88
90
|
for (let ckey in child) {
|
|
89
91
|
if (child[ckey] && child[ckey].isVal) {
|
|
@@ -92,14 +94,6 @@ function walk(
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
}
|
|
95
|
-
else if (Array.isArray(child)) {
|
|
96
|
-
for (let i = 0; i < child.length; i++) {
|
|
97
|
-
if (child[i] && child[i].isVal) {
|
|
98
|
-
child[i] = walk(
|
|
99
|
-
child[i], before, after, maxdepth, i, out, [...(path || []), '' + i])
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
97
|
}
|
|
104
98
|
|
|
105
99
|
out = null == after ? out : after(key, out, parent, path || [])
|
|
@@ -194,7 +188,7 @@ function items(o: any) {
|
|
|
194
188
|
else {
|
|
195
189
|
return []
|
|
196
190
|
}
|
|
197
|
-
}
|
|
191
|
+
} /* node:coverage ignore next 15 */
|
|
198
192
|
|
|
199
193
|
|
|
200
194
|
export {
|
package/src/val/BagVal.ts
CHANGED
|
@@ -20,6 +20,7 @@ import { Val } from './Val'
|
|
|
20
20
|
import { NilVal } from './NilVal'
|
|
21
21
|
import { FeatureVal } from './FeatureVal'
|
|
22
22
|
import { ExpectVal } from './ExpectVal'
|
|
23
|
+
import { cmpCodePoint } from '../keyorder'
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
abstract class BagVal extends FeatureVal {
|
|
@@ -65,15 +66,17 @@ abstract class BagVal extends FeatureVal {
|
|
|
65
66
|
return undefined
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
// Maps emit their keys
|
|
69
|
-
// independent of insertion/unification order
|
|
70
|
-
// port
|
|
71
|
-
//
|
|
69
|
+
// Maps emit their keys in CODE POINT order so the generated output
|
|
70
|
+
// is independent of insertion/unification order and matches the Go
|
|
71
|
+
// port. Lists keep their numeric index order.
|
|
72
|
+
//
|
|
73
|
+
// The keys are String()-coerced because a list entry carries a
|
|
74
|
+
// numeric index here; the coercion is a no-op for every map key.
|
|
72
75
|
let entries = items(this.peg)
|
|
73
76
|
if (this.isMap) {
|
|
74
77
|
entries = entries
|
|
75
78
|
.slice()
|
|
76
|
-
.sort((a: any, b: any) => (a[0]
|
|
79
|
+
.sort((a: any, b: any) => cmpCodePoint(String(a[0]), String(b[0])))
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
for (let item of entries) {
|
|
@@ -175,7 +178,7 @@ abstract class BagVal extends FeatureVal {
|
|
|
175
178
|
return out
|
|
176
179
|
}
|
|
177
180
|
|
|
178
|
-
}
|
|
181
|
+
} /* node:coverage ignore next 6 */
|
|
179
182
|
|
|
180
183
|
|
|
181
184
|
export {
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
Val,
|
|
5
|
+
ValSpec,
|
|
6
|
+
} from '../type'
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
AontuContext,
|
|
10
|
+
} from '../ctx'
|
|
11
|
+
|
|
12
|
+
import { makeNilErr, AontuError } from '../err'
|
|
13
|
+
|
|
14
|
+
import { ScalarVal } from './ScalarVal'
|
|
15
|
+
import { BigDecimal } from './ScalarKindVal'
|
|
16
|
+
import { Decimal } from './Decimal'
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
explainOpen,
|
|
20
|
+
ec,
|
|
21
|
+
explainClose,
|
|
22
|
+
} from '../utility'
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
// The exact base-10 decimal leaf of the number tower, reached only by a
|
|
26
|
+
// `0d` literal carrying a `.` or an exponent (`0d1.5`, `0d1e3`) or by
|
|
27
|
+
// direct construction.
|
|
28
|
+
//
|
|
29
|
+
// Its peg is a Decimal -- an OBJECT, so unlike every other scalar leaf
|
|
30
|
+
// its identity cannot be `===` on the peg. Two bigdecimals are the same
|
|
31
|
+
// value when their NUMBERS are equal (D2), which normalisation at
|
|
32
|
+
// construction reduces to a two-field comparison; `samePeg` and `unify`
|
|
33
|
+
// below are the two places that must not forget it.
|
|
34
|
+
class BigDecimalVal extends ScalarVal {
|
|
35
|
+
isBigDecimal = true
|
|
36
|
+
|
|
37
|
+
declare peg: Decimal
|
|
38
|
+
|
|
39
|
+
constructor(
|
|
40
|
+
spec: ValSpec,
|
|
41
|
+
ctx?: AontuContext
|
|
42
|
+
) {
|
|
43
|
+
// Exact-input construction (D8): a Decimal, or a decimal literal as
|
|
44
|
+
// text (`'1.5'`, `'0d1e3'`). A JS `number` is deliberately NOT
|
|
45
|
+
// accepted -- binary64 has already rounded it, so `0.1` could never
|
|
46
|
+
// arrive exact.
|
|
47
|
+
let peg = spec.peg
|
|
48
|
+
if ('string' === typeof peg) {
|
|
49
|
+
try {
|
|
50
|
+
peg = Decimal.fromString(peg)
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
// Includes a budget refusal (Decimal.fromString enforces D6),
|
|
54
|
+
// so an over-budget string cannot enter through this route
|
|
55
|
+
// either.
|
|
56
|
+
throw new AontuError('not-bigdecimal: ' + spec.peg)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!(peg instanceof Decimal)) {
|
|
60
|
+
throw new AontuError('not-bigdecimal: ' + peg)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
super({ ...spec, peg, kind: BigDecimal }, ctx)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
unify(peer: any, ctx: AontuContext): Val {
|
|
68
|
+
const te = ctx.explain && explainOpen(ctx, ctx.explain, 'BigDecimal', this, peer)
|
|
69
|
+
|
|
70
|
+
let out: Val = this
|
|
71
|
+
|
|
72
|
+
if (null != peer) {
|
|
73
|
+
if (peer.isScalarKind || (peer as any).isConstraint) {
|
|
74
|
+
out = peer.unify(this, te ? ctx.clone({ explain: ec(te, 'KND') }) : ctx)
|
|
75
|
+
}
|
|
76
|
+
else if (
|
|
77
|
+
peer.isScalar &&
|
|
78
|
+
peer.kind === this.kind &&
|
|
79
|
+
this.peg.equals(peer.peg)
|
|
80
|
+
) {
|
|
81
|
+
// Same kind and equal NUMBER. Never `peer.peg === this.peg`:
|
|
82
|
+
// that is object identity, and `0d0.10 & 0d0.1` (two Decimals
|
|
83
|
+
// holding one value) has to succeed.
|
|
84
|
+
out = this
|
|
85
|
+
}
|
|
86
|
+
else if (peer.isTop) {
|
|
87
|
+
out = this
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
out = makeNilErr(ctx, 'scalar_' +
|
|
91
|
+
((peer as any).kind === this.kind ? 'value' : 'kind'), this, peer)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
out = super.unify(peer, ctx)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
explainClose(te, out)
|
|
99
|
+
|
|
100
|
+
return out
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
samePeg(peg: any): boolean {
|
|
105
|
+
return peg instanceof Decimal && this.peg.equals(peg)
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
get canon() {
|
|
110
|
+
return this.peg.canon()
|
|
111
|
+
}
|
|
112
|
+
} /* node:coverage ignore next 6 */
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
export {
|
|
116
|
+
BigDecimalVal,
|
|
117
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
|
+
|
|
3
|
+
import type {
|
|
4
|
+
Val,
|
|
5
|
+
ValSpec,
|
|
6
|
+
} from '../type'
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
AontuContext,
|
|
10
|
+
} from '../ctx'
|
|
11
|
+
|
|
12
|
+
import { makeNilErr, AontuError } from '../err'
|
|
13
|
+
|
|
14
|
+
import { ScalarVal } from './ScalarVal'
|
|
15
|
+
import { BigInteger } from './ScalarKindVal'
|
|
16
|
+
|
|
17
|
+
import {
|
|
18
|
+
explainOpen,
|
|
19
|
+
ec,
|
|
20
|
+
explainClose,
|
|
21
|
+
} from '../utility'
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
// The unbounded exact integer leaf of the number tower, reached only by
|
|
25
|
+
// a `0d` literal with no fraction and no exponent (`0d5`, `-0d5`,
|
|
26
|
+
// `0d123456789012345678901234567890`) or by direct construction.
|
|
27
|
+
//
|
|
28
|
+
// Its peg is a native bigint: exact at any magnitude, immutable, and
|
|
29
|
+
// compared by VALUE with `===` (D2 -- two separately built bigints
|
|
30
|
+
// holding the same number are `===`, which is exactly the property the
|
|
31
|
+
// Go port has to reproduce by hand for `*big.Int`).
|
|
32
|
+
//
|
|
33
|
+
// `biginteger` is DISJOINT from `integer`: `5 & 0d5` is an error, since
|
|
34
|
+
// a successful meet would have to pick one of the two kinds and either
|
|
35
|
+
// choice makes `&` asymmetric in kind.
|
|
36
|
+
class BigIntegerVal extends ScalarVal {
|
|
37
|
+
isBigInteger = true
|
|
38
|
+
|
|
39
|
+
declare peg: bigint
|
|
40
|
+
|
|
41
|
+
constructor(
|
|
42
|
+
spec: ValSpec,
|
|
43
|
+
ctx?: AontuContext
|
|
44
|
+
) {
|
|
45
|
+
// Exact-input construction (D8): a bigint, or the digits as text. A
|
|
46
|
+
// JS `number` is deliberately NOT accepted -- it has already been
|
|
47
|
+
// rounded before this library could inspect it, so an exact value
|
|
48
|
+
// above 2^53 could never arrive that way intact.
|
|
49
|
+
let peg = spec.peg
|
|
50
|
+
if ('string' === typeof peg) {
|
|
51
|
+
if (!/^[-+]?[0-9]+$/.test(peg)) {
|
|
52
|
+
throw new AontuError('not-biginteger: ' + peg)
|
|
53
|
+
}
|
|
54
|
+
peg = BigInt(peg)
|
|
55
|
+
}
|
|
56
|
+
if ('bigint' !== typeof peg) {
|
|
57
|
+
throw new AontuError('not-biginteger: ' + peg)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
super({ ...spec, peg, kind: BigInteger }, ctx)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
unify(peer: any, ctx: AontuContext): Val {
|
|
65
|
+
const te = ctx.explain && explainOpen(ctx, ctx.explain, 'BigInteger', this, peer)
|
|
66
|
+
|
|
67
|
+
let out: Val = this
|
|
68
|
+
|
|
69
|
+
if (null != peer) {
|
|
70
|
+
if (peer.isScalarKind || (peer as any).isConstraint) {
|
|
71
|
+
out = peer.unify(this, te ? ctx.clone({ explain: ec(te, 'KND') }) : ctx)
|
|
72
|
+
}
|
|
73
|
+
else if (
|
|
74
|
+
peer.isScalar &&
|
|
75
|
+
peer.kind === this.kind &&
|
|
76
|
+
peer.peg === this.peg
|
|
77
|
+
) {
|
|
78
|
+
// Same kind and equal NUMBER (bigint `===` is value equality).
|
|
79
|
+
out = this
|
|
80
|
+
}
|
|
81
|
+
else if (peer.isTop) {
|
|
82
|
+
out = this
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
out = makeNilErr(ctx, 'scalar_' +
|
|
86
|
+
((peer as any).kind === this.kind ? 'value' : 'kind'), this, peer)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
out = super.unify(peer, ctx)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
explainClose(te, out)
|
|
94
|
+
|
|
95
|
+
return out
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// The sign renders BEFORE the marker (`-0d5`): `0d-5` is not a literal
|
|
100
|
+
// this language accepts, so canon must not produce it.
|
|
101
|
+
get canon() {
|
|
102
|
+
const neg = this.peg < 0n
|
|
103
|
+
return (neg ? '-0d' : '0d') + (neg ? -this.peg : this.peg).toString()
|
|
104
|
+
}
|
|
105
|
+
} /* node:coverage ignore next 6 */
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
export {
|
|
109
|
+
BigIntegerVal,
|
|
110
|
+
}
|
package/src/val/BooleanVal.ts
CHANGED
package/src/val/CloseFuncVal.ts
CHANGED