aontu 0.51.0 → 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 +1 -1
- package/dist/aontu.js +4 -7
- package/dist/aontu.js.map +1 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +10 -46
- 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.js +1 -1
- package/dist/exactjson.js.map +1 -1
- package/dist/hints.d.ts +3 -1
- package/dist/hints.js +126 -1
- package/dist/hints.js.map +1 -1
- package/dist/keyorder.js +1 -1
- package/dist/keyorder.js.map +1 -1
- package/dist/lang.js +64 -27
- 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 +27 -19
- 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 +1 -1
- package/dist/val/BagVal.js.map +1 -1
- package/dist/val/BigDecimalVal.js +2 -2
- package/dist/val/BigDecimalVal.js.map +1 -1
- package/dist/val/BigIntegerVal.js +2 -2
- package/dist/val/BigIntegerVal.js.map +1 -1
- 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.js +1 -1
- package/dist/val/Decimal.js.map +1 -1
- 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.js +2 -2
- 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.js +1 -1
- 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 +1 -1
- package/dist/val/LowerFuncVal.js.map +1 -1
- package/dist/val/MapVal.js +11 -9
- package/dist/val/MapVal.js.map +1 -1
- package/dist/val/MoveFuncVal.js +1 -1
- 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.js +2 -2
- 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 +1 -1
- package/dist/val/PathFuncVal.js.map +1 -1
- package/dist/val/PlusOpVal.js +1 -1
- 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.js +4 -3
- package/dist/val/PrefVal.js.map +1 -1
- package/dist/val/RefVal.d.ts +2 -0
- package/dist/val/RefVal.js +78 -9
- package/dist/val/RefVal.js.map +1 -1
- package/dist/val/ScalarKindVal.js +8 -2
- package/dist/val/ScalarKindVal.js.map +1 -1
- package/dist/val/ScalarVal.js +2 -2
- 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.js +1 -1
- 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 +1 -1
- 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 +1 -1
- 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.js +1 -1
- package/dist/val/numkind.js.map +1 -1
- package/package.json +6 -4
- package/src/aontu.ts +4 -8
- package/src/cli.ts +12 -13
- package/src/ctx.ts +1 -1
- package/src/err.ts +3 -2
- package/src/exactjson.ts +1 -1
- package/src/hints.ts +140 -0
- package/src/keyorder.ts +1 -1
- package/src/lang.ts +75 -27
- package/src/lsp-server.ts +17 -15
- package/src/lsp.ts +27 -12
- 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 +1 -1
- package/src/val/BigDecimalVal.ts +2 -2
- package/src/val/BigIntegerVal.ts +2 -2
- 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 +1 -1
- 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 +2 -2
- package/src/val/JunctionVal.ts +1 -1
- package/src/val/KeyFuncVal.ts +1 -1
- package/src/val/ListVal.ts +3 -5
- package/src/val/LowerFuncVal.ts +1 -1
- package/src/val/MapVal.ts +7 -5
- package/src/val/MoveFuncVal.ts +1 -1
- package/src/val/NilVal.ts +13 -3
- package/src/val/NullVal.ts +1 -1
- package/src/val/NumberVal.ts +2 -2
- package/src/val/OpBaseVal.ts +10 -10
- package/src/val/OpenFuncVal.ts +1 -1
- package/src/val/PathFuncVal.ts +1 -1
- package/src/val/PlusOpVal.ts +1 -1
- package/src/val/PrefFuncVal.ts +1 -1
- package/src/val/PrefVal.ts +4 -3
- package/src/val/RefVal.ts +82 -9
- package/src/val/ScalarKindVal.ts +8 -2
- package/src/val/ScalarVal.ts +2 -2
- package/src/val/StringVal.ts +1 -1
- package/src/val/SuperFuncVal.ts +1 -1
- package/src/val/TopVal.ts +1 -1
- package/src/val/TypeFuncVal.ts +1 -1
- package/src/val/UpperFuncVal.ts +1 -1
- package/src/val/Val.ts +13 -8
- package/src/val/VarVal.ts +1 -1
- package/src/val/numcmp.ts +189 -0
- package/src/val/numkind.ts +1 -1
package/src/lang.ts
CHANGED
|
@@ -102,6 +102,13 @@ import { PrefFuncVal } from './val/PrefFuncVal'
|
|
|
102
102
|
import { CloseFuncVal } from './val/CloseFuncVal'
|
|
103
103
|
import { OpenFuncVal } from './val/OpenFuncVal'
|
|
104
104
|
import { SuperFuncVal } from './val/SuperFuncVal'
|
|
105
|
+
import {
|
|
106
|
+
MinConstraintVal,
|
|
107
|
+
MaxConstraintVal,
|
|
108
|
+
AboveConstraintVal,
|
|
109
|
+
BelowConstraintVal,
|
|
110
|
+
NeqConstraintVal,
|
|
111
|
+
} from './val/ConstraintVal'
|
|
105
112
|
|
|
106
113
|
|
|
107
114
|
const asPlugin = (p: unknown): Plugin => p as Plugin
|
|
@@ -120,7 +127,11 @@ const asPlugin = (p: unknown): Plugin => p as Plugin
|
|
|
120
127
|
// not part of the literal, so the text has to be rebuilt here to keep
|
|
121
128
|
// `src` meaning "how this value is spelled" (see bigVal).
|
|
122
129
|
function negsrc(src: string): string {
|
|
123
|
-
|
|
130
|
+
// src is never empty here: it is a BIG_LITERAL_RE match (at minimum
|
|
131
|
+
// the two chars `0d`) or an already-negated spelling. Computed exact
|
|
132
|
+
// values do carry src '', but they are built at unify time, long
|
|
133
|
+
// after this parse-time opmap.
|
|
134
|
+
return src.startsWith('-') ? src.slice(1) : '-' + src
|
|
124
135
|
}
|
|
125
136
|
|
|
126
137
|
|
|
@@ -151,6 +162,12 @@ let AontuJsonic: Plugin = function AontuLang(jsonic: Jsonic) {
|
|
|
151
162
|
// docs/reference-language.md; go/lang.go sets the same). Clear the
|
|
152
163
|
// underlying jsonic comment markers entirely, then define # directly,
|
|
153
164
|
// so the comment set is hash-only regardless of those defaults.
|
|
165
|
+
let dotRef = (r: Rule, ctx: JsonicContext, terms: any, prefix: boolean) => {
|
|
166
|
+
terms = dropUnfilled(terms)
|
|
167
|
+
if (0 === terms.length) return incompleteNil(r, ctx)
|
|
168
|
+
return addsite(new RefVal({ peg: terms, prefix }), r, ctx)
|
|
169
|
+
}
|
|
170
|
+
|
|
154
171
|
jsonic.options({ comment: { def: null } })
|
|
155
172
|
jsonic.options({
|
|
156
173
|
comment: {
|
|
@@ -266,7 +283,8 @@ let AontuJsonic: Plugin = function AontuLang(jsonic: Jsonic) {
|
|
|
266
283
|
v.site.row = null == r.o0 ? -1 : r.o0.rI
|
|
267
284
|
v.site.col = null == r.o0 ? -1 : r.o0.cI
|
|
268
285
|
v.site.url = ctx.meta.multisource ? ctx.meta.multisource.path : ''
|
|
269
|
-
|
|
286
|
+
// A keyed rule always carries a path array; a keyless one has none.
|
|
287
|
+
v.path = r.k ? [...r.k.path] : []
|
|
270
288
|
|
|
271
289
|
return v
|
|
272
290
|
}
|
|
@@ -392,6 +410,16 @@ help isolate the syntax error.`,
|
|
|
392
410
|
close: CloseFuncVal,
|
|
393
411
|
open: OpenFuncVal,
|
|
394
412
|
super: SuperFuncVal,
|
|
413
|
+
|
|
414
|
+
// The constraint algebra's Band A atoms (G1 phase 1;
|
|
415
|
+
// docs/reference-language.md, "The constraint algebra"): bounds
|
|
416
|
+
// and exclusion enter through the function registry — the
|
|
417
|
+
// established extension point — with zero grammar change.
|
|
418
|
+
min: MinConstraintVal,
|
|
419
|
+
max: MaxConstraintVal,
|
|
420
|
+
above: AboveConstraintVal,
|
|
421
|
+
below: BelowConstraintVal,
|
|
422
|
+
neq: NeqConstraintVal,
|
|
395
423
|
}
|
|
396
424
|
|
|
397
425
|
|
|
@@ -412,17 +440,14 @@ help isolate the syntax error.`,
|
|
|
412
440
|
'disjunct-infix': (r: Rule, ctx: JsonicContext, _op: Op, terms: any) =>
|
|
413
441
|
addsite(new DisjunctVal({ peg: dropUnfilled(terms) }), r, ctx),
|
|
414
442
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
443
|
+
// `.a` (prefix) and `a.b` (infix) build the same reference; only the
|
|
444
|
+
// prefix flag differs, and both need the same missing-operand guard,
|
|
445
|
+
// so they share one builder.
|
|
446
|
+
'dot-prefix': (r: Rule, ctx: JsonicContext, _op: Op, terms: any) =>
|
|
447
|
+
dotRef(r, ctx, terms, true),
|
|
420
448
|
|
|
421
|
-
'dot-infix': (r: Rule, ctx: JsonicContext, _op: Op, terms: any) =>
|
|
422
|
-
|
|
423
|
-
if (0 === terms.length) return incompleteNil(r, ctx)
|
|
424
|
-
return addsite(new RefVal({ peg: terms }), r, ctx)
|
|
425
|
-
},
|
|
449
|
+
'dot-infix': (r: Rule, ctx: JsonicContext, _op: Op, terms: any) =>
|
|
450
|
+
dotRef(r, ctx, terms, false),
|
|
426
451
|
|
|
427
452
|
'star-prefix': (r: Rule, ctx: JsonicContext, _op: Op, terms: any) => {
|
|
428
453
|
if (null == terms[0]) return incompleteNil(r, ctx)
|
|
@@ -809,18 +834,10 @@ help isolate the syntax error.`,
|
|
|
809
834
|
}
|
|
810
835
|
}
|
|
811
836
|
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
// TODO: needs addpath?
|
|
817
|
-
let aopv = new ListVal({ peg: aop })
|
|
818
|
-
aopv.optionalKeys = optionalKeys
|
|
819
|
-
|
|
820
|
-
r.node =
|
|
821
|
-
addsite(new ConjunctVal({ peg: [aopv, ...ao.___merge] }), r, ctx)
|
|
822
|
-
}
|
|
823
|
-
else {
|
|
837
|
+
// No ___merge arm here: the deferred map.merge that writes it
|
|
838
|
+
// only ever fires for a `pair` rule, whose parent is always a
|
|
839
|
+
// `map` rule with a plain-object node — never a list.
|
|
840
|
+
{
|
|
824
841
|
r.node = addsite(new ListVal({ peg: ao }), r, ctx)
|
|
825
842
|
r.node.optionalKeys = optionalKeys
|
|
826
843
|
}
|
|
@@ -1000,7 +1017,10 @@ function makeModelResolver(options: any) {
|
|
|
1000
1017
|
jsonic: Tabnas
|
|
1001
1018
|
) {
|
|
1002
1019
|
|
|
1003
|
-
|
|
1020
|
+
// The aontu val rule's ac has already wrapped every raw string node
|
|
1021
|
+
// as a StringVal, so spec is a Val here (or a raw object from a
|
|
1022
|
+
// .json/.js include, whose peg is undefined -> not found).
|
|
1023
|
+
let path = spec?.peg
|
|
1004
1024
|
|
|
1005
1025
|
// A bare `@` with no path (`a:@`) has nothing to resolve; report
|
|
1006
1026
|
// not-found instead of crashing in the underlying resolvers.
|
|
@@ -1042,6 +1062,34 @@ function makeModelResolver(options: any) {
|
|
|
1042
1062
|
// the aontu val rule conversions (mirrors asVal in go/lang.go; like
|
|
1043
1063
|
// there, source text is unavailable, so an integral number is an
|
|
1044
1064
|
// integer).
|
|
1065
|
+
// The targeted parse hint for CUE-trained authors and models: `>` and
|
|
1066
|
+
// `<` are not Aontu operators (the op-chars reservation stands), and an
|
|
1067
|
+
// agent that emits `number > 0` should be redirected to the bound
|
|
1068
|
+
// atoms, not left with a bare "unexpected character". Appended to a
|
|
1069
|
+
// parse error's message when the source carries an unquoted `<` or
|
|
1070
|
+
// `>`; the Go twin is opCharHint in go/lang.go, byte-identical text.
|
|
1071
|
+
function opCharHint(src: string): string {
|
|
1072
|
+
let q = ''
|
|
1073
|
+
for (let i = 0; i < src.length; i++) {
|
|
1074
|
+
const c = src[i]
|
|
1075
|
+
if ('' !== q) {
|
|
1076
|
+
if (c === q && '\\' !== src[i - 1]) {
|
|
1077
|
+
q = ''
|
|
1078
|
+
}
|
|
1079
|
+
continue
|
|
1080
|
+
}
|
|
1081
|
+
if ('"' === c || '\'' === c || '`' === c) {
|
|
1082
|
+
q = c
|
|
1083
|
+
}
|
|
1084
|
+
else if ('<' === c || '>' === c) {
|
|
1085
|
+
return '\nThe > and < characters are not Aontu operators: write the ' +
|
|
1086
|
+
'bound functions min(x), max(x), above(x), below(x) instead.'
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
return ''
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
|
|
1045
1093
|
function rawToVal(n: any): Val {
|
|
1046
1094
|
if (null == n) {
|
|
1047
1095
|
return new NullVal({ peg: null })
|
|
@@ -1164,7 +1212,7 @@ class Lang {
|
|
|
1164
1212
|
why: 'parse',
|
|
1165
1213
|
err: new NilVal({
|
|
1166
1214
|
why: 'syntax',
|
|
1167
|
-
msg: e.message,
|
|
1215
|
+
msg: e.message + opCharHint(src),
|
|
1168
1216
|
err: e,
|
|
1169
1217
|
})
|
|
1170
1218
|
})
|
|
@@ -1176,7 +1224,7 @@ class Lang {
|
|
|
1176
1224
|
|
|
1177
1225
|
return val
|
|
1178
1226
|
}
|
|
1179
|
-
}
|
|
1227
|
+
} /* node:coverage ignore next 6 */
|
|
1180
1228
|
|
|
1181
1229
|
export {
|
|
1182
1230
|
Lang,
|
package/src/lsp-server.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
1
|
/* Copyright (c) 2025 Richard Rodger, MIT License */
|
|
3
2
|
|
|
4
3
|
// Aontu Language Server (stdio).
|
|
@@ -85,25 +84,28 @@ class FrameCodec {
|
|
|
85
84
|
}
|
|
86
85
|
|
|
87
86
|
|
|
88
|
-
|
|
87
|
+
// The streams and exit are injectable (defaulting to real stdio) so the
|
|
88
|
+
// full wiring is unit-testable — the same shape as the Go server's
|
|
89
|
+
// serve(in, out, logw).
|
|
90
|
+
function main(
|
|
91
|
+
stdin: NodeJS.ReadableStream = process.stdin,
|
|
92
|
+
write: (chunk: Buffer) => void = (chunk) => void process.stdout.write(chunk),
|
|
93
|
+
exit: (code: number) => void = (code) => process.exit(code),
|
|
94
|
+
): FrameCodec {
|
|
89
95
|
const handler = new LspHandler()
|
|
90
|
-
const codec = new FrameCodec(
|
|
91
|
-
handler,
|
|
92
|
-
(chunk) => process.stdout.write(chunk),
|
|
93
|
-
(code) => process.exit(code),
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
process.stdin.on('data', (chunk: Buffer) => codec.push(chunk))
|
|
97
|
-
process.stdin.on('end', () => codec.end())
|
|
98
|
-
}
|
|
96
|
+
const codec = new FrameCodec(handler, write, exit)
|
|
99
97
|
|
|
98
|
+
stdin.on('data', (chunk: Buffer) => codec.push(chunk))
|
|
99
|
+
stdin.on('end', () => codec.end())
|
|
100
|
+
return codec
|
|
101
|
+
} /* node:coverage ignore next 11 */
|
|
100
102
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
103
|
+
|
|
104
|
+
// No require.main guard here: bin/aontu-lsp.js is the executable entry
|
|
105
|
+
// and calls main() itself, so this module stays import-only.
|
|
105
106
|
|
|
106
107
|
|
|
107
108
|
export {
|
|
108
109
|
FrameCodec,
|
|
110
|
+
main,
|
|
109
111
|
}
|
package/src/lsp.ts
CHANGED
|
@@ -78,8 +78,9 @@ function computeDiagnostics(
|
|
|
78
78
|
const aontu = new Aontu()
|
|
79
79
|
|
|
80
80
|
let root: any
|
|
81
|
+
let ac: any
|
|
81
82
|
try {
|
|
82
|
-
|
|
83
|
+
ac = aontu.ctx({ collect: true })
|
|
83
84
|
if (opts?.vars) {
|
|
84
85
|
Object.assign(ac.vars, opts.vars)
|
|
85
86
|
}
|
|
@@ -92,7 +93,21 @@ function computeDiagnostics(
|
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
const nils: any[] = []
|
|
95
|
-
|
|
96
|
+
const seen = new Set()
|
|
97
|
+
walkNils(root, nils, seen)
|
|
98
|
+
|
|
99
|
+
// Errors recorded on the context but not present in the tree — e.g. a
|
|
100
|
+
// budget_passes exhaustion nil, which is about the whole evaluation
|
|
101
|
+
// rather than any node — would otherwise be invisible here, and the
|
|
102
|
+
// trust contract forbids silent truncation (docs/trust.md clause 2).
|
|
103
|
+
// Tree nils are already on ctx.err too, so dedup by identity; the
|
|
104
|
+
// transient disjunct-trial sentinel never surfaces.
|
|
105
|
+
for (const e of ac.err) {
|
|
106
|
+
if (e?.isNil && '|:trial-nil' !== e.why && !seen.has(e)) {
|
|
107
|
+
seen.add(e)
|
|
108
|
+
nils.push(e)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
96
111
|
|
|
97
112
|
return nils.map(nilToDiagnostic)
|
|
98
113
|
}
|
|
@@ -277,8 +292,8 @@ function collectHoverCandidates(
|
|
|
277
292
|
if (seen.has(v)) return
|
|
278
293
|
seen.add(v)
|
|
279
294
|
|
|
280
|
-
const row = v.site
|
|
281
|
-
const col = v.site
|
|
295
|
+
const row = v.site.row
|
|
296
|
+
const col = v.site.col
|
|
282
297
|
let canon = ''
|
|
283
298
|
try { canon = v.canon } catch { canon = '' }
|
|
284
299
|
// Hover targets concrete values (scalars, kinds, refs, …), not
|
|
@@ -305,8 +320,9 @@ function collectHoverCandidates(
|
|
|
305
320
|
|
|
306
321
|
|
|
307
322
|
function hoverMarkdown(val: any): string {
|
|
308
|
-
|
|
309
|
-
|
|
323
|
+
// No try needed: a Val only becomes a hover candidate after
|
|
324
|
+
// collectHoverCandidates read this same getter successfully.
|
|
325
|
+
const canon = val.canon
|
|
310
326
|
return '```aontu\n' + canon + '\n```\n\n' + '*' + valKind(val) + '*'
|
|
311
327
|
}
|
|
312
328
|
|
|
@@ -315,8 +331,7 @@ function hoverMarkdown(val: any): string {
|
|
|
315
331
|
function valKind(val: any): string {
|
|
316
332
|
if (val.isNil) return 'error'
|
|
317
333
|
if (val.isScalarKind) return 'type'
|
|
318
|
-
if (val.
|
|
319
|
-
if (val.isList) return 'list'
|
|
334
|
+
if (val.isConstraint) return 'constraint'
|
|
320
335
|
if (val.isRef) return 'reference'
|
|
321
336
|
if (val.isInteger) return 'integer'
|
|
322
337
|
// NumberVal is the binary64 leaf, whose kind keyword is `float`;
|
|
@@ -343,11 +358,11 @@ type CompletionItem = {
|
|
|
343
358
|
const COMPLETION_FUNCTION = 3
|
|
344
359
|
const COMPLETION_KEYWORD = 14
|
|
345
360
|
|
|
346
|
-
// The
|
|
361
|
+
// The seventeen built-in functions. Kept in sync with the engine by
|
|
347
362
|
// `lsp.test.ts`, which asserts each is recognised and no others are.
|
|
348
363
|
const BUILTIN_FUNCS = [
|
|
349
|
-
'close', 'copy', 'hide', 'key', 'lower', '
|
|
350
|
-
'open', 'path', 'pref', 'super', 'type', 'upper',
|
|
364
|
+
'above', 'below', 'close', 'copy', 'hide', 'key', 'lower', 'max',
|
|
365
|
+
'min', 'move', 'neq', 'open', 'path', 'pref', 'super', 'type', 'upper',
|
|
351
366
|
]
|
|
352
367
|
|
|
353
368
|
// Scalar-kind and literal keywords.
|
|
@@ -464,7 +479,7 @@ class LspHandler {
|
|
|
464
479
|
private publish(uri: string): OutMessage {
|
|
465
480
|
return publishDiagnosticsMsg(uri, computeDiagnostics(this.docs.get(uri) ?? ''))
|
|
466
481
|
}
|
|
467
|
-
}
|
|
482
|
+
} /* node:coverage ignore next 28 */
|
|
468
483
|
|
|
469
484
|
|
|
470
485
|
export {
|
package/src/site.ts
CHANGED
package/src/type.ts
CHANGED
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
package/src/val/BigDecimalVal.ts
CHANGED
|
@@ -70,7 +70,7 @@ class BigDecimalVal extends ScalarVal {
|
|
|
70
70
|
let out: Val = this
|
|
71
71
|
|
|
72
72
|
if (null != peer) {
|
|
73
|
-
if (peer.isScalarKind) {
|
|
73
|
+
if (peer.isScalarKind || (peer as any).isConstraint) {
|
|
74
74
|
out = peer.unify(this, te ? ctx.clone({ explain: ec(te, 'KND') }) : ctx)
|
|
75
75
|
}
|
|
76
76
|
else if (
|
|
@@ -109,7 +109,7 @@ class BigDecimalVal extends ScalarVal {
|
|
|
109
109
|
get canon() {
|
|
110
110
|
return this.peg.canon()
|
|
111
111
|
}
|
|
112
|
-
}
|
|
112
|
+
} /* node:coverage ignore next 6 */
|
|
113
113
|
|
|
114
114
|
|
|
115
115
|
export {
|
package/src/val/BigIntegerVal.ts
CHANGED
|
@@ -67,7 +67,7 @@ class BigIntegerVal extends ScalarVal {
|
|
|
67
67
|
let out: Val = this
|
|
68
68
|
|
|
69
69
|
if (null != peer) {
|
|
70
|
-
if (peer.isScalarKind) {
|
|
70
|
+
if (peer.isScalarKind || (peer as any).isConstraint) {
|
|
71
71
|
out = peer.unify(this, te ? ctx.clone({ explain: ec(te, 'KND') }) : ctx)
|
|
72
72
|
}
|
|
73
73
|
else if (
|
|
@@ -102,7 +102,7 @@ class BigIntegerVal extends ScalarVal {
|
|
|
102
102
|
const neg = this.peg < 0n
|
|
103
103
|
return (neg ? '-0d' : '0d') + (neg ? -this.peg : this.peg).toString()
|
|
104
104
|
}
|
|
105
|
-
}
|
|
105
|
+
} /* node:coverage ignore next 6 */
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
export {
|
package/src/val/BooleanVal.ts
CHANGED
package/src/val/CloseFuncVal.ts
CHANGED