aontu 0.61.0 → 0.63.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/README.md +4 -4
- package/dist/agentsmd.d.ts +1 -0
- package/dist/agentsmd.js +7 -28
- package/dist/agentsmd.js.map +1 -1
- package/dist/alias.js.map +1 -1
- package/dist/allow.d.ts +23 -0
- package/dist/allow.js +138 -0
- package/dist/allow.js.map +1 -0
- package/dist/aontu.d.ts +4 -2
- package/dist/aontu.js +4 -80
- package/dist/aontu.js.map +1 -1
- package/dist/aontumodel.d.ts +4 -0
- package/dist/aontumodel.js +33 -0
- package/dist/aontumodel.js.map +1 -0
- package/dist/cli.d.ts +10 -1
- package/dist/cli.js +877 -479
- package/dist/cli.js.map +1 -1
- package/dist/ctx.js +0 -48
- package/dist/ctx.js.map +1 -1
- package/dist/diff.js +0 -32
- package/dist/diff.js.map +1 -1
- package/dist/err.js +0 -40
- package/dist/err.js.map +1 -1
- package/dist/escape.js +0 -45
- package/dist/escape.js.map +1 -1
- package/dist/exactjson.d.ts +0 -35
- package/dist/exactjson.js +0 -131
- package/dist/exactjson.js.map +1 -1
- package/dist/format.js +55 -189
- package/dist/format.js.map +1 -1
- package/dist/grammar.d.ts +9 -0
- package/dist/grammar.js +54 -0
- package/dist/grammar.js.map +1 -0
- package/dist/graph.js +0 -26
- package/dist/graph.js.map +1 -1
- package/dist/hcanon.js +0 -82
- package/dist/hcanon.js.map +1 -1
- package/dist/helpdoc.d.ts +16 -0
- package/dist/helpdoc.js +59 -0
- package/dist/helpdoc.js.map +1 -0
- package/dist/hints.d.ts +0 -6
- package/dist/hints.js +59 -47
- package/dist/hints.js.map +1 -1
- package/dist/jsonschema.js +0 -114
- package/dist/jsonschema.js.map +1 -1
- package/dist/keyorder.d.ts +0 -7
- package/dist/keyorder.js +0 -41
- package/dist/keyorder.js.map +1 -1
- package/dist/lang.js +32 -877
- package/dist/lang.js.map +1 -1
- package/dist/lower.d.ts +3 -0
- package/dist/lower.js +14 -61
- package/dist/lower.js.map +1 -1
- package/dist/lsp-server.js +0 -16
- package/dist/lsp-server.js.map +1 -1
- package/dist/lsp.d.ts +1 -1
- package/dist/lsp.js +12 -159
- package/dist/lsp.js.map +1 -1
- package/dist/mcp-server.js +0 -26
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp.js +0 -113
- package/dist/mcp.js.map +1 -1
- package/dist/mod-tool.js +0 -130
- package/dist/mod-tool.js.map +1 -1
- package/dist/mod.js +0 -162
- package/dist/mod.js.map +1 -1
- package/dist/patch.js +0 -217
- package/dist/patch.js.map +1 -1
- package/dist/provenance.js +0 -140
- package/dist/provenance.js.map +1 -1
- package/dist/query.js +0 -75
- package/dist/query.js.map +1 -1
- package/dist/reach.js +0 -43
- package/dist/reach.js.map +1 -1
- package/dist/relation.d.ts +2 -0
- package/dist/relation.js +3 -58
- package/dist/relation.js.map +1 -1
- package/dist/render.js +33 -143
- package/dist/render.js.map +1 -1
- package/dist/report-sarif.d.ts +0 -11
- package/dist/report-sarif.js +0 -28
- package/dist/report-sarif.js.map +1 -1
- package/dist/sig.js +0 -35
- package/dist/sig.js.map +1 -1
- package/dist/sigdecl.js +1 -1
- package/dist/sigdecl.js.map +1 -1
- package/dist/siggate.js +0 -4
- package/dist/siggate.js.map +1 -1
- package/dist/site.js +3 -29
- package/dist/site.js.map +1 -1
- package/dist/subsume.d.ts +0 -10
- package/dist/subsume.js +0 -137
- package/dist/subsume.js.map +1 -1
- package/dist/template.d.ts +2 -1
- package/dist/template.js +58 -138
- package/dist/template.js.map +1 -1
- package/dist/trim.js +0 -41
- package/dist/trim.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/type.js.map +1 -1
- package/dist/unify.js +12 -242
- package/dist/unify.js.map +1 -1
- package/dist/utility.js +0 -22
- package/dist/utility.js.map +1 -1
- package/dist/val/AbnfFuncVal.d.ts +18 -0
- package/dist/val/AbnfFuncVal.js +132 -0
- package/dist/val/AbnfFuncVal.js.map +1 -0
- package/dist/val/AbsentVal.d.ts +11 -0
- package/dist/val/AbsentVal.js +30 -0
- package/dist/val/AbsentVal.js.map +1 -0
- package/dist/val/AggFuncVal.d.ts +10 -1
- package/dist/val/AggFuncVal.js +104 -116
- package/dist/val/AggFuncVal.js.map +1 -1
- package/dist/val/ArithFuncVal.js +0 -12
- package/dist/val/ArithFuncVal.js.map +1 -1
- package/dist/val/BagVal.js +1 -78
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.js +0 -16
- package/dist/val/BigDecimalVal.js.map +1 -1
- package/dist/val/BigIntegerVal.js +0 -16
- package/dist/val/BigIntegerVal.js.map +1 -1
- package/dist/val/CloseFuncVal.js +0 -9
- package/dist/val/CloseFuncVal.js.map +1 -1
- package/dist/val/CmpFuncVal.d.ts +20 -0
- package/dist/val/CmpFuncVal.js +188 -0
- package/dist/val/CmpFuncVal.js.map +1 -0
- package/dist/val/ConjunctVal.js +0 -29
- package/dist/val/ConjunctVal.js.map +1 -1
- package/dist/val/ConstraintVal.js +0 -500
- package/dist/val/ConstraintVal.js.map +1 -1
- package/dist/val/ContainerKindVal.js +0 -2
- package/dist/val/ContainerKindVal.js.map +1 -1
- package/dist/val/CopyFuncVal.js +0 -3
- package/dist/val/CopyFuncVal.js.map +1 -1
- package/dist/val/Decimal.js +0 -179
- package/dist/val/Decimal.js.map +1 -1
- package/dist/val/DeprecateFuncVal.js.map +1 -1
- package/dist/val/DisjunctVal.js +0 -152
- package/dist/val/DisjunctVal.js.map +1 -1
- package/dist/val/EachFuncVal.d.ts +1 -2
- package/dist/val/EachFuncVal.js +12 -29
- package/dist/val/EachFuncVal.js.map +1 -1
- package/dist/val/EmitFuncVal.d.ts +1 -1
- package/dist/val/EmitFuncVal.js +6 -119
- package/dist/val/EmitFuncVal.js.map +1 -1
- package/dist/val/ExpectVal.js +0 -62
- package/dist/val/ExpectVal.js.map +1 -1
- package/dist/val/FilterFuncVal.js +0 -25
- package/dist/val/FilterFuncVal.js.map +1 -1
- package/dist/val/FuncBaseVal.d.ts +1 -0
- package/dist/val/FuncBaseVal.js +7 -127
- package/dist/val/FuncBaseVal.js.map +1 -1
- package/dist/val/GraphAtomVal.js +0 -15
- package/dist/val/GraphAtomVal.js.map +1 -1
- package/dist/val/HideFuncVal.js +0 -13
- package/dist/val/HideFuncVal.js.map +1 -1
- package/dist/val/IntegerVal.js +0 -61
- package/dist/val/IntegerVal.js.map +1 -1
- package/dist/val/JunctionVal.js +0 -20
- package/dist/val/JunctionVal.js.map +1 -1
- package/dist/val/KeyFuncVal.js +0 -46
- package/dist/val/KeyFuncVal.js.map +1 -1
- package/dist/val/ListVal.js +0 -57
- package/dist/val/ListVal.js.map +1 -1
- package/dist/val/LowerFuncVal.js +11 -6
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +0 -151
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MatchFuncVal.js +0 -27
- package/dist/val/MatchFuncVal.js.map +1 -1
- package/dist/val/{FormFuncVal.d.ts → MaybeFuncVal.d.ts} +5 -5
- package/dist/val/MaybeFuncVal.js +50 -0
- package/dist/val/MaybeFuncVal.js.map +1 -0
- package/dist/val/MoveFuncVal.js +0 -18
- package/dist/val/MoveFuncVal.js.map +1 -1
- package/dist/val/NilVal.js +2 -36
- package/dist/val/NilVal.js.map +1 -1
- package/dist/val/NomFuncVal.d.ts +12 -0
- package/dist/val/NomFuncVal.js +153 -0
- package/dist/val/NomFuncVal.js.map +1 -0
- package/dist/val/NumberVal.js +0 -15
- package/dist/val/NumberVal.js.map +1 -1
- package/dist/val/OpBaseVal.d.ts +1 -0
- package/dist/val/OpBaseVal.js +3 -15
- package/dist/val/OpBaseVal.js.map +1 -1
- package/dist/val/PackFuncVal.js +0 -34
- package/dist/val/PackFuncVal.js.map +1 -1
- package/dist/val/PathFuncVal.js +0 -6
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PathVal.js +0 -41
- package/dist/val/PathVal.js.map +1 -1
- package/dist/val/PlaceVal.js +0 -25
- package/dist/val/PlaceVal.js.map +1 -1
- package/dist/val/PlusOpVal.d.ts +1 -7
- package/dist/val/PlusOpVal.js +13 -74
- package/dist/val/PlusOpVal.js.map +1 -1
- package/dist/val/PrefFuncVal.js +0 -1
- package/dist/val/PrefFuncVal.js.map +1 -1
- package/dist/val/PrefVal.js +0 -167
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RecurseVal.js +0 -55
- package/dist/val/RecurseVal.js.map +1 -1
- package/dist/val/RefVal.js +0 -282
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ReferFuncVal.js +0 -232
- package/dist/val/ReferFuncVal.js.map +1 -1
- package/dist/val/ScalarKindVal.js +0 -49
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.js +0 -11
- package/dist/val/ScalarVal.js.map +1 -1
- package/dist/val/StrFuncVal.js +0 -18
- package/dist/val/StrFuncVal.js.map +1 -1
- package/dist/val/SuperFuncVal.js +0 -32
- package/dist/val/SuperFuncVal.js.map +1 -1
- package/dist/val/TopVal.js +0 -1
- package/dist/val/TopVal.js.map +1 -1
- package/dist/val/TranslateFuncVal.d.ts +12 -0
- package/dist/val/TranslateFuncVal.js +99 -0
- package/dist/val/TranslateFuncVal.js.map +1 -0
- package/dist/val/UpperFuncVal.js +11 -6
- package/dist/val/UpperFuncVal.js.map +1 -1
- package/dist/val/Val.d.ts +1 -0
- package/dist/val/Val.js +2 -133
- package/dist/val/Val.js.map +1 -1
- package/dist/val/VarVal.js +0 -12
- package/dist/val/VarVal.js.map +1 -1
- package/dist/val/arith.js +0 -37
- package/dist/val/arith.js.map +1 -1
- package/dist/val/caserange.d.ts +3 -0
- package/dist/val/caserange.js +49 -0
- package/dist/val/caserange.js.map +1 -0
- package/dist/val/members.js +0 -6
- package/dist/val/members.js.map +1 -1
- package/dist/val/numcmp.js +0 -11
- package/dist/val/numcmp.js.map +1 -1
- package/dist/val/numkind.js +0 -145
- package/dist/val/numkind.js.map +1 -1
- package/dist/val/valutil.js +0 -16
- package/dist/val/valutil.js.map +1 -1
- package/dist/vet.d.ts +12 -0
- package/dist/vet.js +159 -412
- package/dist/vet.js.map +1 -1
- package/dist/view.js +0 -414
- package/dist/view.js.map +1 -1
- package/dist/walk.js +0 -41
- package/dist/walk.js.map +1 -1
- package/grammar/aontu.abnf +9 -7
- package/grammar/aontu.gbnf +5 -5
- package/grammar/aontu.lark +5 -5
- package/grammar/aontu.tmLanguage.json +1 -1
- package/package.json +4 -2
- package/skill/SKILL.md +8 -0
- package/skill/init/check.sh +28 -0
- package/skill/init/data.aon +12 -0
- package/skill/init/model.aon +19 -0
- package/skill/tasks.md +151 -0
- package/src/agentsmd.ts +8 -32
- package/src/alias.ts +0 -39
- package/src/allow.ts +221 -0
- package/src/aontu.ts +10 -108
- package/src/aontumodel.ts +32 -0
- package/src/cli.ts +1009 -540
- package/src/ctx.ts +0 -103
- package/src/diff.ts +0 -40
- package/src/err.ts +0 -40
- package/src/escape.ts +0 -46
- package/src/exactjson.ts +0 -131
- package/src/format.ts +63 -234
- package/src/grammar.ts +72 -0
- package/src/graph.ts +0 -61
- package/src/hcanon.ts +0 -82
- package/src/helpdoc.ts +77 -0
- package/src/hints.ts +72 -49
- package/src/jsonschema.ts +0 -123
- package/src/keyorder.ts +0 -42
- package/src/lang.ts +39 -895
- package/src/lower.ts +15 -65
- package/src/lsp-server.ts +0 -16
- package/src/lsp.ts +12 -180
- package/src/mcp-server.ts +0 -31
- package/src/mcp.ts +0 -130
- package/src/mod-tool.ts +0 -158
- package/src/mod.ts +0 -178
- package/src/patch.ts +0 -232
- package/src/provenance.ts +0 -183
- package/src/query.ts +0 -84
- package/src/reach.ts +0 -53
- package/src/relation.ts +7 -71
- package/src/render.ts +33 -180
- package/src/report-sarif.ts +0 -48
- package/src/sig.ts +0 -35
- package/src/sigdecl.ts +1 -1
- package/src/siggate.ts +0 -30
- package/src/site.ts +3 -29
- package/src/subsume.ts +1 -161
- package/src/template.ts +69 -140
- package/src/trim.ts +0 -53
- package/src/type.ts +2 -45
- package/src/unify.ts +13 -251
- package/src/utility.ts +0 -31
- package/src/val/AbnfFuncVal.ts +181 -0
- package/src/val/AbsentVal.ts +54 -0
- package/src/val/AggFuncVal.ts +152 -188
- package/src/val/ArithFuncVal.ts +0 -20
- package/src/val/BagVal.ts +1 -78
- package/src/val/BigDecimalVal.ts +0 -16
- package/src/val/BigIntegerVal.ts +0 -16
- package/src/val/CloseFuncVal.ts +0 -9
- package/src/val/CmpFuncVal.ts +249 -0
- package/src/val/ConjunctVal.ts +0 -33
- package/src/val/ConstraintVal.ts +2 -537
- package/src/val/ContainerKindVal.ts +0 -18
- package/src/val/CopyFuncVal.ts +0 -5
- package/src/val/Decimal.ts +1 -185
- package/src/val/DeprecateFuncVal.ts +0 -10
- package/src/val/DisjunctVal.ts +0 -157
- package/src/val/EachFuncVal.ts +12 -53
- package/src/val/EmitFuncVal.ts +8 -208
- package/src/val/ExpectVal.ts +0 -62
- package/src/val/FilterFuncVal.ts +0 -55
- package/src/val/FuncBaseVal.ts +9 -130
- package/src/val/GraphAtomVal.ts +0 -42
- package/src/val/HideFuncVal.ts +0 -15
- package/src/val/IntegerVal.ts +0 -61
- package/src/val/JunctionVal.ts +0 -20
- package/src/val/KeyFuncVal.ts +0 -48
- package/src/val/ListVal.ts +0 -59
- package/src/val/LowerFuncVal.ts +12 -7
- package/src/val/MapVal.ts +0 -151
- package/src/val/MatchFuncVal.ts +0 -59
- package/src/val/MaybeFuncVal.ts +86 -0
- package/src/val/MoveFuncVal.ts +0 -20
- package/src/val/NilVal.ts +2 -36
- package/src/val/NomFuncVal.ts +200 -0
- package/src/val/NumberVal.ts +0 -16
- package/src/val/OpBaseVal.ts +4 -17
- package/src/val/PackFuncVal.ts +0 -63
- package/src/val/PathFuncVal.ts +0 -32
- package/src/val/PathVal.ts +0 -66
- package/src/val/PlaceVal.ts +0 -45
- package/src/val/PlusOpVal.ts +18 -75
- package/src/val/PrefFuncVal.ts +0 -1
- package/src/val/PrefVal.ts +0 -179
- package/src/val/RecurseVal.ts +0 -81
- package/src/val/RefVal.ts +1 -285
- package/src/val/ReferFuncVal.ts +0 -255
- package/src/val/ScalarKindVal.ts +0 -50
- package/src/val/ScalarVal.ts +0 -12
- package/src/val/StrFuncVal.ts +0 -44
- package/src/val/SuperFuncVal.ts +0 -42
- package/src/val/TopVal.ts +0 -1
- package/src/val/TranslateFuncVal.ts +132 -0
- package/src/val/UpperFuncVal.ts +12 -7
- package/src/val/Val.ts +3 -192
- package/src/val/VarVal.ts +0 -15
- package/src/val/arith.ts +0 -92
- package/src/val/caserange.ts +53 -0
- package/src/val/members.ts +0 -23
- package/src/val/numcmp.ts +1 -27
- package/src/val/numkind.ts +0 -149
- package/src/val/valutil.ts +0 -16
- package/src/vet.ts +209 -504
- package/src/view.ts +0 -507
- package/src/walk.ts +0 -41
- package/dist/std.d.ts +0 -3
- package/dist/std.js +0 -637
- package/dist/std.js.map +0 -1
- package/dist/val/FormFuncVal.js +0 -55
- package/dist/val/FormFuncVal.js.map +0 -1
- package/src/std.ts +0 -648
- package/src/val/FormFuncVal.ts +0 -119
package/src/val/AggFuncVal.ts
CHANGED
|
@@ -1,47 +1,5 @@
|
|
|
1
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
2
2
|
|
|
3
|
-
// AGGREGATION, PROJECTION AND THE STRING FOLD: `sum(d)`, `least(d)`,
|
|
4
|
-
// `greatest(d)`, `pick(d, k)` and `join(d, sep?)`.
|
|
5
|
-
//
|
|
6
|
-
// The review's finding I: "No aggregation. `length()` counts but
|
|
7
|
-
// nothing sums: an invoice total, a fleet-wide resource budget, a quota
|
|
8
|
-
// roll-up -- all inexpressible." Use case 10 had to write totals by
|
|
9
|
-
// hand and spot-check them with `must()`, which is a model asserting
|
|
10
|
-
// what it should be able to COMPUTE.
|
|
11
|
-
//
|
|
12
|
-
// total: sum($.lines) # an invoice total
|
|
13
|
-
// cheapest: least($.quotes) # ... and the extremes
|
|
14
|
-
// peak: greatest($.hourly)
|
|
15
|
-
//
|
|
16
|
-
// A FOLD OVER A FINITE, SETTLED BAG IS AS TOTAL AS `each`. There is no
|
|
17
|
-
// recursion here and no user-supplied step: the bag is the one the
|
|
18
|
-
// model already holds, the operation is fixed, and the walk visits each
|
|
19
|
-
// child exactly once. That is the whole reason these are built-ins
|
|
20
|
-
// rather than a `fold` combinator -- a fold takes a function, and a
|
|
21
|
-
// language with no user functions has none to take.
|
|
22
|
-
//
|
|
23
|
-
// THE NAMES ARE `least` AND `greatest`, NOT `min` AND `max`, because
|
|
24
|
-
// those two are already the constraint atoms for a LOWER and UPPER
|
|
25
|
-
// BOUND (`min(3)` means "at least 3"). An aggregate over a bag and a
|
|
26
|
-
// bound on a value are different things and must not share a spelling;
|
|
27
|
-
// least and greatest are the lattice's own words for the extremes of a
|
|
28
|
-
// set, which is exactly what these compute.
|
|
29
|
-
//
|
|
30
|
-
// `sum` FOLDS WITH `add`, so the number tower's whole law comes with it
|
|
31
|
-
// (arith.ts): the exact ladder, R5 contagion, the refusal to mix a
|
|
32
|
-
// binary float with an exact leaf, and the refusal to store a result
|
|
33
|
-
// that will not fit. A bag of integers sums to an integer; one integer
|
|
34
|
-
// float among them makes the total a float; `0d` operands keep it
|
|
35
|
-
// exact. And `sum([])` is `0` -- addition has an identity, which is
|
|
36
|
-
// what makes the empty case answerable.
|
|
37
|
-
//
|
|
38
|
-
// `least`/`greatest` have NO identity to answer an empty bag with: the
|
|
39
|
-
// least element of nothing is not a value, it is a question with no
|
|
40
|
-
// answer, so an empty bag is a located `aggregate_empty` rather than an
|
|
41
|
-
// invented zero or infinity. They compare with the tower's EXACT
|
|
42
|
-
// comparator (numcmp), so an integer and a bigdecimal in one bag order
|
|
43
|
-
// correctly rather than through binary64, and the winner is returned
|
|
44
|
-
// with its own kind intact.
|
|
45
3
|
|
|
46
4
|
import type {
|
|
47
5
|
Val,
|
|
@@ -59,6 +17,7 @@ import { StringVal } from './StringVal'
|
|
|
59
17
|
import { FuncBaseVal } from './FuncBaseVal'
|
|
60
18
|
import { arith } from './arith'
|
|
61
19
|
import { cmpNumeric } from './numcmp'
|
|
20
|
+
import { cmpCodePoint } from '../keyorder'
|
|
62
21
|
import { memberVals } from './members'
|
|
63
22
|
import { plusText } from './PlusOpVal'
|
|
64
23
|
|
|
@@ -66,12 +25,6 @@ import { plusText } from './PlusOpVal'
|
|
|
66
25
|
type AggOp = 'sum' | 'least' | 'greatest'
|
|
67
26
|
|
|
68
27
|
|
|
69
|
-
// The children of a bag, in the order the aggregate sees them: source
|
|
70
|
-
// order for a list, sorted-key order for a map -- `each`'s order, and
|
|
71
|
-
// for the same reason (a map has no order of its own, so the language
|
|
72
|
-
// picks one and states it).
|
|
73
|
-
// The members of the bag a fold reads: what generation would emit
|
|
74
|
-
// (./members.ts, BUGS.md §79), in the one map-key order (BUGS.md §62).
|
|
75
28
|
function bagChildren(data: any, ctx: AontuContext): Val[] | undefined {
|
|
76
29
|
return memberVals(data, ctx)
|
|
77
30
|
}
|
|
@@ -80,9 +33,6 @@ function bagChildren(data: any, ctx: AontuContext): Val[] | undefined {
|
|
|
80
33
|
class AggFuncVal extends FuncBaseVal {
|
|
81
34
|
isAggFunc = true
|
|
82
35
|
|
|
83
|
-
// THE STAGING RULE (G8 phase 0). A total over a bag that is still
|
|
84
|
-
// being merged into is a total of the wrong bag -- the same reason
|
|
85
|
-
// `filter` and `each` wait.
|
|
86
36
|
staged = true
|
|
87
37
|
|
|
88
38
|
op: AggOp
|
|
@@ -97,21 +47,11 @@ class AggFuncVal extends FuncBaseVal {
|
|
|
97
47
|
}
|
|
98
48
|
|
|
99
49
|
|
|
100
|
-
// NO `make` OVERRIDE, matching the other STAGED funcs (pack, each,
|
|
101
|
-
// filter, match): a staged call returns `residuate` before `unify`
|
|
102
|
-
// ever reaches the rebuild branch, so an override there would be
|
|
103
|
-
// unreachable code pretending to be a contract. The base's `make`
|
|
104
|
-
// raises `func:<name>` if that ever stops being true, which is the
|
|
105
|
-
// loud answer rather than a value that silently lost its operation.
|
|
106
|
-
|
|
107
50
|
funcname() {
|
|
108
51
|
return this.op
|
|
109
52
|
}
|
|
110
53
|
|
|
111
54
|
|
|
112
|
-
// The base does not drive the argument: `unify` drives it by hand,
|
|
113
|
-
// because a staged func must advance what it is waiting on every
|
|
114
|
-
// pass rather than only on the pass it fires.
|
|
115
55
|
prepare(_ctx: AontuContext, _args: Val[]) {
|
|
116
56
|
return null
|
|
117
57
|
}
|
|
@@ -137,9 +77,6 @@ class AggFuncVal extends FuncBaseVal {
|
|
|
137
77
|
}
|
|
138
78
|
|
|
139
79
|
if ('sum' === this.op) {
|
|
140
|
-
// Zero is addition's identity, so an empty bag has an answer and
|
|
141
|
-
// it is an integer -- the narrowest kind, which the first real
|
|
142
|
-
// operand then widens under R5 exactly as `add(0, x)` would.
|
|
143
80
|
let total: Val = new IntegerVal({ peg: 0 })
|
|
144
81
|
for (const child of children) {
|
|
145
82
|
total = arith(ctx, 'add', this, total, child, this.op)
|
|
@@ -192,28 +129,6 @@ function unpref(v: any): any {
|
|
|
192
129
|
}
|
|
193
130
|
|
|
194
131
|
|
|
195
|
-
// PROJECTION: `pick(d, k)` -- one element per child of `d`, being that
|
|
196
|
-
// child's `k`.
|
|
197
|
-
//
|
|
198
|
-
// The other half of the review's finding I: "`_.field` is unspellable,
|
|
199
|
-
// `filter` cannot see into lists, `unique()`-by-field is reserved but
|
|
200
|
-
// absent -- so 'no two services share a port' and 'unique event ids'
|
|
201
|
-
// cannot be said." Without it the aggregates above cannot reach the
|
|
202
|
-
// case that motivated them, because `sum` needs a bag of NUMBERS and a
|
|
203
|
-
// model holds a bag of RECORDS:
|
|
204
|
-
//
|
|
205
|
-
// total: sum(pick($.lines, amountCents))
|
|
206
|
-
//
|
|
207
|
-
// IT IS NOT `each` WITH A CLEVER TEMPLATE. `each(d, t)` MEETS each
|
|
208
|
-
// child with `t`, and a meet cannot select: `each($.lines, _.amount)`
|
|
209
|
-
// asks for a child that is simultaneously the whole record and one of
|
|
210
|
-
// its fields, which is why every spelling of it answers `no_path`.
|
|
211
|
-
// Selection is a different operation and gets its own verb.
|
|
212
|
-
//
|
|
213
|
-
// A CHILD MISSING THE KEY IS AN ERROR, not a silently shorter list.
|
|
214
|
-
// Skipping would make `sum(pick(...))` quietly total the wrong set of
|
|
215
|
-
// records -- the failure mode an aggregate exists to prevent -- so the
|
|
216
|
-
// refusal names the child (`pick_key`).
|
|
217
132
|
class PickFuncVal extends FuncBaseVal {
|
|
218
133
|
isPickFunc = true
|
|
219
134
|
|
|
@@ -293,56 +208,159 @@ class PickFuncVal extends FuncBaseVal {
|
|
|
293
208
|
}
|
|
294
209
|
|
|
295
210
|
|
|
211
|
+
// `pick`'s rule, plus: the empty string is the member itself, which is
|
|
212
|
+
// how a keyless descending sort is spelled.
|
|
213
|
+
function projectorName(key: any): [string, boolean] {
|
|
214
|
+
if (null == key || null == key.peg) {
|
|
215
|
+
return ['', true]
|
|
216
|
+
}
|
|
217
|
+
if ('string' === typeof key.peg) {
|
|
218
|
+
return [key.peg, true]
|
|
219
|
+
}
|
|
220
|
+
if ('number' === typeof key.peg && key.isInteger) {
|
|
221
|
+
return [String(key.peg), true]
|
|
222
|
+
}
|
|
223
|
+
return ['', false]
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
function fieldOf(child: any, name: string): Val | undefined {
|
|
228
|
+
return true === child?.isMap ? child.peg[name] :
|
|
229
|
+
true === child?.isList ? child.peg[Number(name)] :
|
|
230
|
+
undefined
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
const SORT_DIRECTIONS: Record<string, number> = { asc: 1, desc: -1 }
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
function directionOf(v: any): number | undefined {
|
|
238
|
+
if (null == v || null == v.peg) {
|
|
239
|
+
return 1
|
|
240
|
+
}
|
|
241
|
+
return 'string' === typeof v.peg ? SORT_DIRECTIONS[v.peg] : undefined
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
// Text by code point, numbers by the exact comparator, nothing else.
|
|
246
|
+
function sortDomain(u: any): 'text' | 'number' | undefined {
|
|
247
|
+
if (true !== u?.isVal || true !== u.isScalar || true === u.isNull) {
|
|
248
|
+
return undefined
|
|
249
|
+
}
|
|
250
|
+
if ('string' === typeof u.peg) {
|
|
251
|
+
return 'text'
|
|
252
|
+
}
|
|
253
|
+
return 'boolean' === typeof u.peg ? undefined : 'number'
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
type SortRow = { idx: number, val: Val, key: any }
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
class SortFuncVal extends FuncBaseVal {
|
|
261
|
+
isSortFunc = true
|
|
262
|
+
|
|
263
|
+
// The bag must settle before it is ordered, exactly as it must
|
|
264
|
+
// before it is projected.
|
|
265
|
+
staged = true
|
|
266
|
+
|
|
267
|
+
constructor(
|
|
268
|
+
spec: ValSpec,
|
|
269
|
+
ctx?: AontuContext
|
|
270
|
+
) {
|
|
271
|
+
super(spec, ctx)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
funcname() {
|
|
276
|
+
return 'sort'
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
// The base drives no argument: the DATA is driven by hand below, and
|
|
281
|
+
// the projector is a bare word the parser has already made a string.
|
|
282
|
+
prepare(_ctx: AontuContext, _args: Val[]) {
|
|
283
|
+
return null
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
unify(peer: Val, ctx: AontuContext): Val {
|
|
288
|
+
const ready = this.driveStagedArgs(ctx, 1)
|
|
289
|
+
|
|
290
|
+
if (!ready || !ctx.settle) {
|
|
291
|
+
return this.residuate(peer, ctx)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return super.unify(peer, ctx)
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
resolve(ctx: AontuContext, args: Val[]) {
|
|
299
|
+
const children = bagChildren(args?.[0], ctx)
|
|
300
|
+
|
|
301
|
+
if (undefined === children) {
|
|
302
|
+
return this.place(makeNilErr(ctx, 'aggregate_data', this, undefined,
|
|
303
|
+
'sort'))
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const [name, nameok] = projectorName(args?.[1])
|
|
307
|
+
|
|
308
|
+
if (!nameok) {
|
|
309
|
+
return this.place(makeNilErr(ctx, 'invalid-arg', this, undefined,
|
|
310
|
+
'sort'))
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
const dir = directionOf(args?.[2])
|
|
314
|
+
|
|
315
|
+
if (undefined === dir) {
|
|
316
|
+
return this.place(makeNilErr(ctx, 'sort_dir', this, undefined, 'sort',
|
|
317
|
+
{ dir: (args[2] as any).canon }))
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const rows: SortRow[] = []
|
|
321
|
+
let domain: 'text' | 'number' | undefined = undefined
|
|
322
|
+
|
|
323
|
+
for (const child of children) {
|
|
324
|
+
const at: any = '' === name ? child : fieldOf(child, name)
|
|
325
|
+
|
|
326
|
+
if (null == at) {
|
|
327
|
+
return this.place(makeNilErr(ctx, 'sort_key', this, undefined, 'sort',
|
|
328
|
+
{ key: name }))
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const u = unpref(at)
|
|
332
|
+
const found = sortDomain(u)
|
|
333
|
+
|
|
334
|
+
if (undefined === found ||
|
|
335
|
+
(undefined !== domain && found !== domain)) {
|
|
336
|
+
return this.place(makeNilErr(ctx, 'sort_domain', this, undefined,
|
|
337
|
+
'sort', { member: u.canon }))
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
domain = found
|
|
341
|
+
rows.push({ idx: rows.length, val: child, key: u })
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// The source index breaks every tie, so the order is TOTAL and
|
|
345
|
+
// neither port's sort algorithm can reorder equals.
|
|
346
|
+
rows.sort((a, b) => {
|
|
347
|
+
const c = 'text' === domain ?
|
|
348
|
+
cmpCodePoint(a.key.peg as string, b.key.peg as string) :
|
|
349
|
+
cmpNumeric(a.key, b.key)
|
|
350
|
+
return 0 === c ? a.idx - b.idx : dir * c
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
const peg: Val[] = rows.map(
|
|
354
|
+
(r, i) => r.val.clone(ctx.descend(String(i))))
|
|
355
|
+
|
|
356
|
+
return this.place(new ListVal({ peg }, ctx))
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
296
360
|
|
|
297
|
-
// THE FOLD TO A STRING: `join(coll, sep?)` -- G9 phase 2.
|
|
298
|
-
//
|
|
299
|
-
// The one primitive between a model and a generated file. A spread can
|
|
300
|
-
// put a separator AFTER each element; putting one BETWEEN N elements is
|
|
301
|
-
// a reduction over strings, and the language had none: `sum` is numeric,
|
|
302
|
-
// `+` does not reduce a list, and indexed concatenation needs the arity
|
|
303
|
-
// known in advance. So a generated SQL column list carried a trailing
|
|
304
|
-
// comma and did not parse (use-cases/15-code-generation).
|
|
305
|
-
//
|
|
306
|
-
// IT FOLDS WITH `+` SEEDED WITH `""`, exactly as `sum` folds with `add`
|
|
307
|
-
// seeded with `0`. That is not a figure of speech: the members are
|
|
308
|
-
// rendered by `plusText`, which IS the function `+`'s string branch
|
|
309
|
-
// calls, so the language keeps exactly one answer to "how does a number
|
|
310
|
-
// become text" and the two cannot drift. `join(coll)` is therefore
|
|
311
|
-
// concatenation and no `concat` is needed; `join(coll, "\n")` is lines
|
|
312
|
-
// and no `lines` is needed. ONE BUILTIN, NOT A FAMILY.
|
|
313
|
-
//
|
|
314
|
-
// `split`/`words` is the inverse -- an input-PARSING operation with no
|
|
315
|
-
// generation use -- and is deliberately absent.
|
|
316
|
-
//
|
|
317
|
-
// EMPTY IS `""`, concatenation's identity, the exact parallel of
|
|
318
|
-
// `sum([]) == 0` and the opposite of `least([])`: a fold with an
|
|
319
|
-
// identity can answer the empty bag, and one without has to refuse it.
|
|
320
|
-
//
|
|
321
|
-
// MEMBERS ARE VALIDATED BEFORE THE FOLD, which is the whole reason this
|
|
322
|
-
// is not three lines. `+` with a string on the left RESIDUATES on a
|
|
323
|
-
// container or a null rather than refusing (`"" + {b:1}` and `"x" +
|
|
324
|
-
// null` both reach generation as `mapval_no_gen`), so folding blindly
|
|
325
|
-
// would turn a bad member into a useless late error pointing at the
|
|
326
|
-
// wrong thing. The three verdicts below are that check.
|
|
327
361
|
type MemberVerdict = 'text' | 'never' | 'notyet'
|
|
328
362
|
|
|
329
363
|
|
|
330
|
-
// Which of the three a value is.
|
|
331
|
-
//
|
|
332
|
-
// `text` -- `+` would take it, so the fold can.
|
|
333
|
-
//
|
|
334
|
-
// `never` -- a SETTLED value that will never become text: a map, a
|
|
335
|
-
// list, a null. This is `join_member`, class `conflict`, and it names
|
|
336
|
-
// the member rather than the call, because "one of these is not a
|
|
337
|
-
// string" is only actionable if you are told which.
|
|
338
|
-
//
|
|
339
|
-
// `notyet` -- an unresolved kind, a top, a stable residue. NOT a join
|
|
340
|
-
// failure at all: the call stays residual and generation reports
|
|
341
|
-
// `mapval_no_gen`, class `incomplete`, exactly as docs/trust.md
|
|
342
|
-
// requires ("a stable residue ... is ordinary incompleteness"). Getting
|
|
343
|
-
// this split wrong in either direction is the defect that matters here:
|
|
344
|
-
// refusing a residue makes `join` unusable inside a schema, and
|
|
345
|
-
// deferring on a map makes a real error arrive as a shrug.
|
|
346
364
|
function memberVerdict(v: any): MemberVerdict {
|
|
347
365
|
const u = unpref(v)
|
|
348
366
|
if (undefined !== plusText(u)) {
|
|
@@ -355,15 +373,6 @@ function memberVerdict(v: any): MemberVerdict {
|
|
|
355
373
|
}
|
|
356
374
|
|
|
357
375
|
|
|
358
|
-
// The separator is a STRING or it is nothing.
|
|
359
|
-
//
|
|
360
|
-
// A number would render perfectly well through `+`, and is still
|
|
361
|
-
// refused: the separator is not a member of the fold, it is the
|
|
362
|
-
// parameter naming the text between members, and `join(x, 5)` is far
|
|
363
|
-
// likelier a mistake than an intent to separate with "5". `pick`'s key
|
|
364
|
-
// argument draws the same line for the same reason. This is the
|
|
365
|
-
// direction that can be loosened later without breaking a document;
|
|
366
|
-
// the other direction cannot.
|
|
367
376
|
function sepVerdict(v: any): MemberVerdict {
|
|
368
377
|
const u = unpref(v)
|
|
369
378
|
if (u?.isVal && u.isScalar) {
|
|
@@ -391,22 +400,6 @@ class JoinFuncVal extends FuncBaseVal {
|
|
|
391
400
|
}
|
|
392
401
|
|
|
393
402
|
|
|
394
|
-
// A `make` OVERRIDE, WHERE ITS AggFuncVal SIBLINGS HAVE NONE, and the
|
|
395
|
-
// difference is worth stating because it is not arbitrary. `sum`,
|
|
396
|
-
// `pick` and the rest are staged and nothing more: they residuate
|
|
397
|
-
// before `unify` reaches the rebuild branch, so a `make` there would
|
|
398
|
-
// be unreachable code pretending to be a contract, and the base's
|
|
399
|
-
// `func:<name>` refusal is the loud answer if that ever changes.
|
|
400
|
-
//
|
|
401
|
-
// `join` is the first builtin that is BOTH staged AND defers its
|
|
402
|
-
// resolution (see `deferResolve`). A deferred call has settled
|
|
403
|
-
// arguments, so it does reach the rebuild branch, and without this it
|
|
404
|
-
// raised `func:join` on the first document with an unresolved member
|
|
405
|
-
// — where the Go port residuated and reported `mapval_no_gen`.
|
|
406
|
-
// Opposite answers on `join($.m, ",")` with `m: [string]`, caught by
|
|
407
|
-
// running both engines rather than by either test suite. `super` and
|
|
408
|
-
// bare `id`, the two other deferring calls, each carry the same
|
|
409
|
-
// override for the same reason.
|
|
410
403
|
make(_ctx: AontuContext, spec: ValSpec): Val {
|
|
411
404
|
return new JoinFuncVal(spec)
|
|
412
405
|
}
|
|
@@ -426,10 +419,6 @@ class JoinFuncVal extends FuncBaseVal {
|
|
|
426
419
|
|
|
427
420
|
|
|
428
421
|
unify(peer: Val, ctx: AontuContext): Val {
|
|
429
|
-
// BOTH arguments, unlike `pick`, which drives only its bag: `pick`'s
|
|
430
|
-
// key is a bare word the parser has already made a string, while a
|
|
431
|
-
// separator is an ordinary expression and `join($.rows, $.sep)` has
|
|
432
|
-
// to wait for it.
|
|
433
422
|
const ready = this.driveStagedArgs(ctx, 2)
|
|
434
423
|
|
|
435
424
|
if (!ready || !ctx.settle) {
|
|
@@ -440,10 +429,6 @@ class JoinFuncVal extends FuncBaseVal {
|
|
|
440
429
|
}
|
|
441
430
|
|
|
442
431
|
|
|
443
|
-
// The `notyet` half of the verdict, taken before `resolve` runs: with
|
|
444
|
-
// arguments settled but a member still a kind, the call rides the
|
|
445
|
-
// ordinary args-not-done path and residuates, which is what makes an
|
|
446
|
-
// unresolved member ordinary incompleteness rather than a refusal.
|
|
447
432
|
deferResolve(ctx: AontuContext, args?: Val[]): boolean {
|
|
448
433
|
const children = bagChildren(args?.[0], ctx)
|
|
449
434
|
if (undefined === children) {
|
|
@@ -467,28 +452,11 @@ class JoinFuncVal extends FuncBaseVal {
|
|
|
467
452
|
'join'))
|
|
468
453
|
}
|
|
469
454
|
|
|
470
|
-
// Arity is [1,2], so a second argument is present or the separator
|
|
471
|
-
// is the empty string -- which makes `join(coll)` concatenation.
|
|
472
|
-
// The separator's SHAPE is settled before resolve runs: the
|
|
473
|
-
// signature gate refuses every concrete non-string
|
|
474
|
-
// (docs/design/SIGNATURES.0.md; join(d: map|list, sep?: string)),
|
|
475
|
-
// and deferResolve holds the call while sepVerdict answers notyet
|
|
476
|
-
// -- so a present separator here is text.
|
|
477
455
|
let sep = ''
|
|
478
456
|
if (1 < args.length) {
|
|
479
457
|
sep = unpref(args[1]).peg
|
|
480
458
|
}
|
|
481
459
|
|
|
482
|
-
// NO NIL-MEMBER GUARD, WHERE `sum` HAS ONE, and the difference is
|
|
483
|
-
// the fold's shape rather than an oversight. `sum` folds with
|
|
484
|
-
// `arith`, which MINTS a nil part-way through — a non-numeric child
|
|
485
|
-
// or an overflow — so it has to stop and return it. `join` folds
|
|
486
|
-
// already-unified values, and a nil among a list's elements
|
|
487
|
-
// collapses the list before this call resolves: `join([least([])],
|
|
488
|
-
// ",")` reports `aggregate_empty` at the member's own path,
|
|
489
|
-
// `$.o.0`, and never reaches here. A guard was written, the
|
|
490
|
-
// ADR-002 gate found it unexecuted, and probing confirmed no
|
|
491
|
-
// spelling reaches it, so it is removed rather than excused.
|
|
492
460
|
const parts: string[] = []
|
|
493
461
|
for (const child of children) {
|
|
494
462
|
const u: any = unpref(child)
|
|
@@ -500,16 +468,11 @@ class JoinFuncVal extends FuncBaseVal {
|
|
|
500
468
|
parts.push(text)
|
|
501
469
|
}
|
|
502
470
|
|
|
503
|
-
// Every part is already a string, so this IS the `+` fold seeded
|
|
504
|
-
// with `""` -- written as one concatenation because a loop of `+`
|
|
505
|
-
// over settled strings cannot differ from it, and because the Go
|
|
506
|
-
// twin's strings.Join must produce the same bytes.
|
|
507
471
|
return this.place(new StringVal({ peg: parts.join(sep) }))
|
|
508
472
|
}
|
|
509
473
|
}
|
|
510
474
|
|
|
511
475
|
|
|
512
|
-
// The three the registry names. Each is its operation and nothing else.
|
|
513
476
|
class SumFuncVal extends AggFuncVal {
|
|
514
477
|
constructor(spec: ValSpec, ctx?: AontuContext) { super(spec, ctx, 'sum') }
|
|
515
478
|
}
|
|
@@ -522,13 +485,14 @@ class GreatestFuncVal extends AggFuncVal {
|
|
|
522
485
|
constructor(spec: ValSpec, ctx?: AontuContext) {
|
|
523
486
|
super(spec, ctx, 'greatest')
|
|
524
487
|
}
|
|
525
|
-
} /* node:coverage ignore next
|
|
488
|
+
} /* node:coverage ignore next 11 */
|
|
526
489
|
|
|
527
490
|
|
|
528
491
|
export {
|
|
529
492
|
AggFuncVal,
|
|
530
493
|
JoinFuncVal,
|
|
531
494
|
PickFuncVal,
|
|
495
|
+
SortFuncVal,
|
|
532
496
|
SumFuncVal,
|
|
533
497
|
LeastFuncVal,
|
|
534
498
|
GreatestFuncVal,
|
package/src/val/ArithFuncVal.ts
CHANGED
|
@@ -15,17 +15,6 @@ import { arith } from './arith'
|
|
|
15
15
|
import type { ArithOp } from './arith'
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
// ONE CLASS FOR SIX FUNCTIONS, because every rule they obey is a rule
|
|
19
|
-
// about arithmetic rather than about any one operation (see arith.ts).
|
|
20
|
-
// Six near-identical classes would be six places for the exact ladder,
|
|
21
|
-
// the zero divisor and the storage contract to drift apart, and the
|
|
22
|
-
// number tower's whole point is that they cannot.
|
|
23
|
-
//
|
|
24
|
-
// The op is carried on the instance and answered by `funcname()`, which
|
|
25
|
-
// is what canon renders and what an error names. The six one-line
|
|
26
|
-
// subclasses below exist only because the parser's registry constructs
|
|
27
|
-
// with `new funcval({peg: args})` and has nowhere to put a name; every
|
|
28
|
-
// line of behaviour is here.
|
|
29
18
|
class ArithFuncVal extends FuncBaseVal {
|
|
30
19
|
isArithFunc = true
|
|
31
20
|
|
|
@@ -60,18 +49,9 @@ class ArithFuncVal extends FuncBaseVal {
|
|
|
60
49
|
}
|
|
61
50
|
|
|
62
51
|
|
|
63
|
-
// NO superior() OVERRIDE, deliberately. An arithmetic call could only
|
|
64
|
-
// advertise a kind once both its operands were concrete scalars -- and
|
|
65
|
-
// at that point it has RESOLVED, so what `super()` sees is the result,
|
|
66
|
-
// whose own superior is already the right answer:
|
|
67
|
-
// `super(mul(2,3))` is `integer` and `super(mul(2,1.5))` is `float`,
|
|
68
|
-
// through the value rather than through a promise about it. The
|
|
69
|
-
// override was written and then removed as unreachable; the same is
|
|
70
|
-
// true of FuncVal.superior in the Go port.
|
|
71
52
|
}
|
|
72
53
|
|
|
73
54
|
|
|
74
|
-
// The six the registry names. Each is its operation and nothing else.
|
|
75
55
|
class AddFuncVal extends ArithFuncVal {
|
|
76
56
|
constructor(spec: ValSpec, ctx?: AontuContext) { super(spec, ctx, 'add') }
|
|
77
57
|
}
|
package/src/val/BagVal.ts
CHANGED
|
@@ -30,15 +30,6 @@ abstract class BagVal extends FeatureVal {
|
|
|
30
30
|
closed: boolean = false
|
|
31
31
|
optionalKeys: string[] = []
|
|
32
32
|
|
|
33
|
-
// ALIAS DECLARATIONS, by key. `%uint8 = …` binds a name for this file
|
|
34
|
-
// and is not a field of the document: it does not generate and does
|
|
35
|
-
// not appear in canon, so a document using aliases and its expanded
|
|
36
|
-
// twin are the SAME document and hash identically
|
|
37
|
-
// (docs/design/ALIASES.0.md §4).
|
|
38
|
-
//
|
|
39
|
-
// Keyed on the map rather than marked on the value, because a
|
|
40
|
-
// reference copies the value it resolves to -- a mark riding the
|
|
41
|
-
// value would erase the referring field along with the declaration.
|
|
42
33
|
aliasKeys: string[] = []
|
|
43
34
|
|
|
44
35
|
spread = {
|
|
@@ -60,30 +51,9 @@ abstract class BagVal extends FeatureVal {
|
|
|
60
51
|
|
|
61
52
|
|
|
62
53
|
handleExpectedVal(key: string, val: Val, parent: Val, ctx: AontuContext): Val {
|
|
63
|
-
// A MARKED value is carried, never expected (ADR-005 era, BUGS.md
|
|
64
|
-
// §12's include form): a type()/hide()-marked child legitimately
|
|
65
|
-
// participates in unification without ever generating — that is
|
|
66
|
-
// the marks contract — so wrapping one as an expectation turned a
|
|
67
|
-
// schema field arriving through an include's map meet into a
|
|
68
|
-
// bogus `mapval_spread_required` naming a spread that exists in
|
|
69
|
-
// neither file. The bag's gen already skips marked children.
|
|
70
|
-
//
|
|
71
|
-
// An OPERATOR is carried too (BUGS.md §36): an expression is a
|
|
72
|
-
// computation that resolves by itself once its operands do — the
|
|
73
|
-
// bag's own-key loop drives it every pass — so `m:{y:.x+1}`
|
|
74
|
-
// arriving as a peer key must keep computing exactly as it does
|
|
75
|
-
// written inline. Wrapping it froze the op (an expectation only
|
|
76
|
-
// advances when a peer arrives) and the residue then reported the
|
|
77
|
-
// phantom `mapval_spread_required` naming a spread that exists
|
|
78
|
-
// nowhere. An op that truly never resolves is honest *_no_gen
|
|
79
|
-
// residue naming the expression itself.
|
|
80
54
|
if (val.isGenable || val.isOp || val.mark.type || val.mark.hide) {
|
|
81
55
|
return val
|
|
82
56
|
}
|
|
83
|
-
// An expectation baked into a combined spread template (the
|
|
84
|
-
// 'map-self' meet of two unequal templates) is re-wrapped FRESH, so
|
|
85
|
-
// key/parent name THIS bag and the template's own node is never
|
|
86
|
-
// stored at a destination.
|
|
87
57
|
const expectVal = new ExpectVal({ peg: val.isExpect ? val.peg : val }, ctx)
|
|
88
58
|
expectVal.key = key
|
|
89
59
|
expectVal.parent = parent
|
|
@@ -91,20 +61,6 @@ abstract class BagVal extends FeatureVal {
|
|
|
91
61
|
}
|
|
92
62
|
|
|
93
63
|
|
|
94
|
-
// TWO BAGS ARE THE SAME VALUE WHEN THEY HAVE THE SAME SHAPE. Val.same
|
|
95
|
-
// falls back to object IDENTITY, which no two separately built maps
|
|
96
|
-
// share -- so `x:*{a:1}|{a:number}` met by `x:{a:2}` left
|
|
97
|
-
// `{"a":2}|{"a":2}`, a disjunction of one value spelled twice, past
|
|
98
|
-
// the DisjunctVal dedup. Generation's old member FOLD hid that
|
|
99
|
-
// (folding a value with itself is that value); ADR-007 does not, and
|
|
100
|
-
// a disjunction whose alternatives are all the SAME value is
|
|
101
|
-
// resolved, not ambiguous. Canon prints the collapse too, which is
|
|
102
|
-
// the more honest text.
|
|
103
|
-
//
|
|
104
|
-
// Structural, and deliberately strict: container kind, closedness,
|
|
105
|
-
// the marks, the optional keys and the key set must all agree before
|
|
106
|
-
// the children are compared pairwise. Recursion terminates because a
|
|
107
|
-
// reference is not a bag -- RefVal keeps the identity comparison.
|
|
108
64
|
same(peer: any): boolean {
|
|
109
65
|
if (this === peer) {
|
|
110
66
|
return true
|
|
@@ -118,11 +74,6 @@ abstract class BagVal extends FeatureVal {
|
|
|
118
74
|
this.mark.hide !== peer.mark.hide) {
|
|
119
75
|
return false
|
|
120
76
|
}
|
|
121
|
-
// The SPREAD is part of the shape (BUGS.md §52 regime 4): `[]`
|
|
122
|
-
// and `[&: T]` share an empty key set, and calling them the same
|
|
123
|
-
// value collapsed the disjunction to its first arm before any
|
|
124
|
-
// data could pick -- the vacuous-schema hole. Two spreads are the
|
|
125
|
-
// same when their canons are.
|
|
126
77
|
const scj: any = (this as any).spread?.cj
|
|
127
78
|
const pcj: any = peer.spread?.cj
|
|
128
79
|
if ((null == scj) !== (null == pcj) ||
|
|
@@ -158,12 +109,6 @@ abstract class BagVal extends FeatureVal {
|
|
|
158
109
|
return undefined
|
|
159
110
|
}
|
|
160
111
|
|
|
161
|
-
// Maps emit their keys in CODE POINT order so the generated output
|
|
162
|
-
// is independent of insertion/unification order and matches the Go
|
|
163
|
-
// port. Lists keep their numeric index order.
|
|
164
|
-
//
|
|
165
|
-
// The keys are String()-coerced because a list entry carries a
|
|
166
|
-
// numeric index here; the coercion is a no-op for every map key.
|
|
167
112
|
let entries = items(this.peg)
|
|
168
113
|
if (this.isMap) {
|
|
169
114
|
entries = entries
|
|
@@ -214,22 +159,7 @@ abstract class BagVal extends FeatureVal {
|
|
|
214
159
|
put(cval)
|
|
215
160
|
}
|
|
216
161
|
|
|
217
|
-
// A CONJUNCT IS GENERABLE WHEN IT IS A SETTLED SIZING RESIDUE
|
|
218
|
-
// (the review's finding C, use-cases/BUGS.md §16). `length` and
|
|
219
|
-
// `unique` over a container keep the readings more members could
|
|
220
|
-
// still change, so `a: length(3) a:[1,2,3]` is a conjunct of the
|
|
221
|
-
// atom and the list right up to generation -- which is where the
|
|
222
|
-
// atom decides, in ConjunctVal.gen. Any OTHER conjunct is
|
|
223
|
-
// unresolved and falls through to the residue error below,
|
|
224
|
-
// exactly as before.
|
|
225
162
|
else if (bagGenable(child)) {
|
|
226
|
-
// An optional child is generated in an isolated collect context so an
|
|
227
|
-
// unresolved inner value (a bare type that survived unification, e.g.
|
|
228
|
-
// an absent optional sub-map's `field: string`) is dropped rather than
|
|
229
|
-
// raised: the optional subtree is simply omitted. Without isolation
|
|
230
|
-
// such inner errors pollute the shared ctx.err and make generate()
|
|
231
|
-
// throw even though the key is skipped below. Mirrors the
|
|
232
|
-
// optional-disjunct path above.
|
|
233
163
|
const cctx = optional ? ctx.clone({ err: [], collect: true }) : ctx
|
|
234
164
|
|
|
235
165
|
let cval = child.gen(cctx)
|
|
@@ -273,7 +203,6 @@ abstract class BagVal extends FeatureVal {
|
|
|
273
203
|
break
|
|
274
204
|
}
|
|
275
205
|
|
|
276
|
-
// else optional so we can ignore it
|
|
277
206
|
}
|
|
278
207
|
|
|
279
208
|
return out
|
|
@@ -304,13 +233,6 @@ export function sizingResidue(v: any): { con: any, bag: any } | undefined {
|
|
|
304
233
|
{ con, bag } : undefined
|
|
305
234
|
}
|
|
306
235
|
|
|
307
|
-
// bagGenable is the bag's generability whitelist. A graph atom
|
|
308
|
-
// (RELATIONS P2) is exactly as generable as the value it carries: the
|
|
309
|
-
// atom is transparent at generation, so wrapping a field's value in
|
|
310
|
-
// acyclic() must not change whether the bag accepts it -- an unmet
|
|
311
|
-
// rel() refuses required generation with or without the atom, and a
|
|
312
|
-
// BARE atom generates nothing and is dropped, exactly as an unmet
|
|
313
|
-
// rel() under an optional key is.
|
|
314
236
|
export function bagGenable(child: any): boolean {
|
|
315
237
|
if (true === child.isGraphAtom) {
|
|
316
238
|
return undefined === child.held || bagGenable(child.held)
|
|
@@ -322,6 +244,7 @@ export function bagGenable(child: any): boolean {
|
|
|
322
244
|
return true
|
|
323
245
|
}
|
|
324
246
|
return true === child.isScalar
|
|
247
|
+
|| true === child.isAbsent
|
|
325
248
|
|| true === child.isMap
|
|
326
249
|
|| true === child.isList
|
|
327
250
|
|| true === child.isPref
|
package/src/val/BigDecimalVal.ts
CHANGED
|
@@ -22,15 +22,6 @@ import {
|
|
|
22
22
|
} from '../utility'
|
|
23
23
|
|
|
24
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
25
|
class BigDecimalVal extends ScalarVal {
|
|
35
26
|
isBigDecimal = true
|
|
36
27
|
|
|
@@ -40,10 +31,6 @@ class BigDecimalVal extends ScalarVal {
|
|
|
40
31
|
spec: ValSpec,
|
|
41
32
|
ctx?: AontuContext
|
|
42
33
|
) {
|
|
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
34
|
let peg = spec.peg
|
|
48
35
|
if ('string' === typeof peg) {
|
|
49
36
|
try {
|
|
@@ -78,9 +65,6 @@ class BigDecimalVal extends ScalarVal {
|
|
|
78
65
|
peer.kind === this.kind &&
|
|
79
66
|
this.peg.equals(peer.peg)
|
|
80
67
|
) {
|
|
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
68
|
out = this
|
|
85
69
|
}
|
|
86
70
|
else if (peer.isTop) {
|