@hyperscale0/hsx 1.0.341 → 1.0.347

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +1 -1
  2. package/bases/cards.hsx +0 -1
  3. package/bases/collections.hsx +0 -2
  4. package/bases/escrow.hsx +0 -1
  5. package/bases/financing.hsx +0 -1
  6. package/bases/insurance.hsx +0 -1
  7. package/bases/lending.hsx +0 -3
  8. package/bases/marketplace.hsx +0 -2
  9. package/bases/money.hsx +0 -1
  10. package/bases/reporting.hsx +0 -2
  11. package/bases/savings.hsx +0 -1
  12. package/bases/wallet.hsx +0 -1
  13. package/dist/src/ast.d.ts +57 -7
  14. package/dist/src/ast.d.ts.map +1 -1
  15. package/dist/src/ast.js.map +1 -1
  16. package/dist/src/bases-bundle.js +11 -11
  17. package/dist/src/bases-bundle.js.map +1 -1
  18. package/dist/src/catalog-program.d.ts +1 -1
  19. package/dist/src/catalog-program.d.ts.map +1 -1
  20. package/dist/src/catalog-program.js +0 -13
  21. package/dist/src/catalog-program.js.map +1 -1
  22. package/dist/src/checks.d.ts +60 -0
  23. package/dist/src/checks.d.ts.map +1 -0
  24. package/dist/src/checks.js +240 -0
  25. package/dist/src/checks.js.map +1 -0
  26. package/dist/src/cli.d.ts.map +1 -1
  27. package/dist/src/cli.js +6 -25
  28. package/dist/src/cli.js.map +1 -1
  29. package/dist/src/compile.d.ts +29 -12
  30. package/dist/src/compile.d.ts.map +1 -1
  31. package/dist/src/compile.js +414 -316
  32. package/dist/src/compile.js.map +1 -1
  33. package/dist/src/diagnostics.d.ts +14 -1
  34. package/dist/src/diagnostics.d.ts.map +1 -1
  35. package/dist/src/diagnostics.js +31 -0
  36. package/dist/src/diagnostics.js.map +1 -1
  37. package/dist/src/examples-bundle.js +15 -15
  38. package/dist/src/examples-bundle.js.map +1 -1
  39. package/dist/src/header-source.d.ts +30 -0
  40. package/dist/src/header-source.d.ts.map +1 -1
  41. package/dist/src/header-source.js +120 -9
  42. package/dist/src/header-source.js.map +1 -1
  43. package/dist/src/headers.d.ts +9 -18
  44. package/dist/src/headers.d.ts.map +1 -1
  45. package/dist/src/headers.js +25 -23
  46. package/dist/src/headers.js.map +1 -1
  47. package/dist/src/index.d.ts +4 -3
  48. package/dist/src/index.d.ts.map +1 -1
  49. package/dist/src/index.js +2 -2
  50. package/dist/src/index.js.map +1 -1
  51. package/dist/src/keywords.d.ts +2 -4
  52. package/dist/src/keywords.d.ts.map +1 -1
  53. package/dist/src/keywords.js +6 -5
  54. package/dist/src/keywords.js.map +1 -1
  55. package/dist/src/language.d.ts +3 -4
  56. package/dist/src/language.d.ts.map +1 -1
  57. package/dist/src/language.js +123 -60
  58. package/dist/src/language.js.map +1 -1
  59. package/dist/src/lex.d.ts +1 -1
  60. package/dist/src/lex.d.ts.map +1 -1
  61. package/dist/src/lex.js +3 -5
  62. package/dist/src/lex.js.map +1 -1
  63. package/dist/src/parse.d.ts +3 -1
  64. package/dist/src/parse.d.ts.map +1 -1
  65. package/dist/src/parse.js +234 -22
  66. package/dist/src/parse.js.map +1 -1
  67. package/dist/src/std-bundle.d.ts +2 -1
  68. package/dist/src/std-bundle.d.ts.map +1 -1
  69. package/dist/src/std-bundle.js +16 -15
  70. package/dist/src/std-bundle.js.map +1 -1
  71. package/dist/src/template-guide.d.ts +3 -9
  72. package/dist/src/template-guide.d.ts.map +1 -1
  73. package/dist/src/template-guide.js +16 -23
  74. package/dist/src/template-guide.js.map +1 -1
  75. package/dist/src/toolchain.d.ts +23 -0
  76. package/dist/src/toolchain.d.ts.map +1 -0
  77. package/dist/src/toolchain.js +29 -0
  78. package/dist/src/toolchain.js.map +1 -0
  79. package/docs/README.md +69 -28
  80. package/examples/camera-rental.hsx +0 -1
  81. package/examples/cards.hsx +0 -1
  82. package/examples/collections.hsx +0 -2
  83. package/examples/escrow.hsx +0 -1
  84. package/examples/financing.hsx +0 -1
  85. package/examples/insurance.hsx +0 -2
  86. package/examples/lending.hsx +0 -3
  87. package/examples/library.hsx +0 -3
  88. package/examples/marketplace.hsx +0 -2
  89. package/examples/money.hsx +0 -1
  90. package/examples/rental-hire.hsx +0 -1
  91. package/examples/reporting.hsx +0 -2
  92. package/examples/savings.hsx +0 -1
  93. package/examples/serviced.hsx +0 -4
  94. package/examples/wallet.hsx +0 -1
  95. package/package.json +4 -4
  96. package/src/ast.ts +56 -3
  97. package/src/bases-bundle.ts +11 -11
  98. package/src/catalog-program.ts +0 -13
  99. package/src/checks.ts +386 -0
  100. package/src/cli.ts +6 -25
  101. package/src/compile.ts +583 -438
  102. package/src/diagnostics.ts +49 -1
  103. package/src/examples-bundle.ts +15 -15
  104. package/src/header-source.ts +187 -11
  105. package/src/headers.ts +31 -32
  106. package/src/index.ts +10 -4
  107. package/src/keywords.ts +6 -5
  108. package/src/language.ts +153 -68
  109. package/src/lex.ts +3 -5
  110. package/src/parse.ts +216 -24
  111. package/src/std-bundle.ts +17 -15
  112. package/src/template-guide.ts +17 -34
  113. package/src/toolchain.ts +51 -0
  114. package/std/booking.hsx +14 -1
  115. package/std/collections.hsx +12 -2
  116. package/std/financing.hsx +10 -16
  117. package/std/money.hsx +2 -3
  118. package/std/reporting.hsx +10 -1
  119. package/dist/src/binding-contract.d.ts +0 -22
  120. package/dist/src/binding-contract.d.ts.map +0 -1
  121. package/dist/src/binding-contract.js +0 -80
  122. package/dist/src/binding-contract.js.map +0 -1
  123. package/dist/src/std-library.d.ts +0 -5
  124. package/dist/src/std-library.d.ts.map +0 -1
  125. package/dist/src/std-library.js +0 -5
  126. package/dist/src/std-library.js.map +0 -1
  127. package/src/binding-contract.ts +0 -111
  128. package/src/std-library.ts +0 -7
package/src/index.ts CHANGED
@@ -1,17 +1,23 @@
1
1
  export {
2
2
  compile,
3
3
  type CompileDiagnostic,
4
- type CompileOptions,
5
4
  type CompileResult,
6
5
  type CompileWarning,
7
6
  type CompileOriginMapEntry,
8
- type AdapterBindingTarget,
7
+ type CompileTerm,
8
+ type CompileTermOverride,
9
9
  } from "./compile.ts";
10
+ export type { CompiledCheck, CompiledCheckStep } from "./checks.ts";
11
+ export {
12
+ defaultToolchain,
13
+ toolchain,
14
+ type AdapterBindingTarget,
15
+ type Toolchain,
16
+ } from "./toolchain.ts";
10
17
  export type { ProviderAdapter } from "@hyperscale0/adl";
11
18
  export { parseProgram } from "./parse.ts";
12
19
  export { lex, KEYWORDS } from "./lex.ts";
13
20
  export { format } from "./format.ts";
14
- export { bundledStandardLibrary, type StandardLibrary } from "./std-library.ts";
15
21
  export { buildUdlCostManifest, type UdlCostManifest } from "./cost.ts";
16
22
  export type {
17
23
  Program,
@@ -24,7 +30,7 @@ export type {
24
30
  Diagnostic,
25
31
  } from "./ast.ts";
26
32
 
27
- export { headerManifest, HEADER_NAMES } from "./headers.ts";
33
+ export { headerManifest, HEADER_NAMES, namedHeaders } from "./headers.ts";
28
34
  export {
29
35
  templateGuide,
30
36
  templateIndex,
package/src/keywords.ts CHANGED
@@ -7,7 +7,6 @@ export const KEYWORD_HELP = {
7
7
  "Product contract",
8
8
  ],
9
9
  header: ["Names a reusable library of instruments."],
10
- use: ["Makes a header's instruments available to this program."],
11
10
  party: [
12
11
  "Declares a person, business or staff party. Staff authority requires a permission role.",
13
12
  "Parties",
@@ -31,7 +30,6 @@ export const KEYWORD_HELP = {
31
30
  "Makes an attached action available under a public name.",
32
31
  "Object action bindings",
33
32
  ],
34
- hide: ["Removes an action from the program's public actions."],
35
33
  as: ["Gives an exposed action its public name."],
36
34
  cap: ["Limits a percentage charge to a maximum money amount.", "Capped rate"],
37
35
  of: [
@@ -40,8 +38,8 @@ export const KEYWORD_HELP = {
40
38
  when: [
41
39
  "Includes clauses for a selected enum value or a field present on a bound reference.",
42
40
  ],
43
- constraints: [
44
- "Requires parameter values to agree with each other before the program can be used.",
41
+ checks: [
42
+ "Rules each attachment's tunables must pass, each with its own message and fix.",
45
43
  ],
46
44
  requires: [
47
45
  "Rejects an action unless the stated condition holds.",
@@ -66,7 +64,10 @@ export const KEYWORD_HELP = {
66
64
  is: ["Selects rules for one named parameter choice."],
67
65
  has: ["Selects clauses when a bound reference declares the named field."],
68
66
  family: ["Names an instrument family or the family of an evidence check."],
69
- check: ["Names the provider check whose evidence the action requires."],
67
+ check: [
68
+ "Declares a Build check: customers, steps and the balances they end on. Inside evidence, names the provider check the action requires.",
69
+ "Build checks",
70
+ ],
70
71
  result: ["Names the required outcome of an evidence check."],
71
72
  maxAge: ["Limits how old the required evidence may be."],
72
73
  instruction: ["Binds evidence to the captured boundary instruction."],
package/src/language.ts CHANGED
@@ -1,10 +1,10 @@
1
- import type { Entry, Expr, Span } from "./ast.ts";
1
+ import type { CheckDecl, Entry, Expr, Span } from "./ast.ts";
2
+ import { compile, type CompileTerm } from "./compile.ts";
2
3
  import { headerManifest } from "./headers.ts";
3
4
  import { KEYWORD_HELP } from "./keywords.ts";
4
5
  import { KEYWORDS, scan, type Token } from "./lex.ts";
5
6
  import { parseProgram } from "./parse.ts";
6
- import { bundledStandardLibrary, type StandardLibrary } from "./std-library.ts";
7
- export type { StandardLibrary } from "./std-library.ts";
7
+ import { defaultToolchain, type Toolchain } from "./toolchain.ts";
8
8
 
9
9
  export type HsxTokenClass =
10
10
  | "keyword"
@@ -44,6 +44,24 @@ export interface HsxHover {
44
44
  type Help = Omit<HsxHover, "span">;
45
45
  type Header = ReturnType<typeof headerManifest>["headers"][number];
46
46
  const keywords = new Set<string>(KEYWORDS);
47
+ const CHECK_WORDS = new Set([
48
+ "customer",
49
+ "organization",
50
+ "funded",
51
+ "binds",
52
+ "clock",
53
+ "until",
54
+ "record",
55
+ "close",
56
+ "remember",
57
+ "status",
58
+ "balances",
59
+ "expect",
60
+ "held",
61
+ "pending",
62
+ ]);
63
+ const CHECK_HELP =
64
+ "A check step. Promote runs every check in an isolated world and refuses a Build whose check fails.";
47
65
  const types = new Set([
48
66
  "money",
49
67
  "account",
@@ -59,20 +77,20 @@ const types = new Set([
59
77
  "list",
60
78
  "policy",
61
79
  ]);
62
- // Cache by source bytes, not library identity: callers can edit their own headers.
80
+ // Cache by source bytes, not toolchain identity: callers can edit their own headers.
63
81
  const headerCache = new Map<
64
82
  string,
65
83
  { source: string; value: Header | undefined }
66
84
  >();
67
- function header(name: string, library: StandardLibrary): Header | undefined {
85
+ function header(name: string, toolchain: Toolchain): Header | undefined {
68
86
  try {
69
- const source = library.source(name);
87
+ const source = toolchain.std.get(name);
70
88
  if (!source) return;
71
89
  const cached = headerCache.get(name);
72
90
  if (cached?.source === source) return cached.value;
73
91
  let value: Header | undefined;
74
92
  try {
75
- value = headerManifest({ source: () => source }, [name]).headers[0];
93
+ value = headerManifest(new Map([[name, source]]), [name]).headers[0];
76
94
  } catch {
77
95
  /* Half-written headers have no metadata yet. */
78
96
  }
@@ -105,6 +123,10 @@ function instrumentHelp(
105
123
  label: a.name,
106
124
  value: `${a.summary} Actor: ${a.actor}`,
107
125
  })),
126
+ ...object.checks.map((check) => ({
127
+ label: "check",
128
+ value: `${check.rule}${check.when ? ` when ${check.when.selector} is ${check.when.is}` : ""}: ${check.message}`,
129
+ })),
108
130
  ],
109
131
  };
110
132
  }
@@ -119,14 +141,26 @@ interface Analysis {
119
141
  highlights: HsxHighlight[];
120
142
  hovers: Map<number, HsxHover>;
121
143
  }
122
- function analyze(source: string, library: StandardLibrary): Analysis {
144
+ function analyze(source: string, toolchain: Toolchain): Analysis {
123
145
  const all = scan(source).tokens.filter((t) => t.kind !== "eof");
124
146
  const tokens = all.filter((t) => t.kind !== "comment");
125
147
  const helps = new Map<number, Help>();
126
148
  const classes = new Map<number, HsxTokenClass>();
127
149
  const bindings = new Map<string, Binding[]>();
128
- const imports = new Map<string, Header>();
129
- const headerHelp = new Map<string, Help>();
150
+ // A qualified name such as booking.reservation names its header directly.
151
+ const headerHelp = (value: Header): Help => ({
152
+ kind: "header",
153
+ title: value.name,
154
+ header: value.name,
155
+ summary: value.objects
156
+ .map((o) => o.summary)
157
+ .slice(0, 2)
158
+ .join(" "),
159
+ details: value.objects.map((o) => ({
160
+ label: o.qualifiedName,
161
+ value: o.summary,
162
+ })),
163
+ });
130
164
  const whole = { start: 0, end: source.length };
131
165
  const text = (span: Span) => source.slice(span.start, span.end);
132
166
  const mark = (token: Token | undefined, kind: HsxTokenClass, help?: Help) => {
@@ -177,31 +211,6 @@ function analyze(source: string, library: StandardLibrary): Analysis {
177
211
  for (let i = 0; i < tokens.length; i++) {
178
212
  const token = tokens[i]!;
179
213
  const previous = tokens[i - 1]?.text;
180
- if (previous === "use") {
181
- const value = header(token.text, library);
182
- if (value) imports.set(token.text, value);
183
- mark(
184
- token,
185
- "header",
186
- value
187
- ? {
188
- kind: "header",
189
- title: value.name,
190
- header: value.name,
191
- summary: value.objects
192
- .map((o) => o.summary)
193
- .slice(0, 2)
194
- .join(" "),
195
- details: value.objects.map((o) => ({
196
- label: o.qualifiedName,
197
- value: o.summary,
198
- })),
199
- }
200
- : undefined,
201
- );
202
- const help = helps.get(token.span.start);
203
- if (help) headerHelp.set(token.text, help);
204
- }
205
214
  if (
206
215
  previous === "program" ||
207
216
  previous === "object" ||
@@ -240,7 +249,6 @@ function analyze(source: string, library: StandardLibrary): Analysis {
240
249
  previous === "action" ||
241
250
  previous === "attach" ||
242
251
  previous === "expose" ||
243
- previous === "hide" ||
244
252
  previous === "as"
245
253
  )
246
254
  mark(
@@ -266,9 +274,9 @@ function analyze(source: string, library: StandardLibrary): Analysis {
266
274
  }
267
275
  const attachment = (target: string, scope: Span) => {
268
276
  const [owner, name] = target.split(".");
269
- const object = imports
270
- .get(owner ?? "")
271
- ?.objects.find((o) => o.name === name);
277
+ const object = header(owner ?? "", toolchain)?.objects.find(
278
+ (o) => o.name === name,
279
+ );
272
280
  if (!object) return;
273
281
  for (const parameter of object.tunables)
274
282
  bind(
@@ -425,6 +433,42 @@ function analyze(source: string, library: StandardLibrary): Analysis {
425
433
  walk(expr.cap, scope);
426
434
  }
427
435
  };
436
+ const at = (span: Span) => tokens[atStart.get(span.start) ?? -1];
437
+ // A check's step words are keywords inside the check alone.
438
+ const checkHelp = (check: CheckDecl) => {
439
+ for (const token of tokens)
440
+ if (
441
+ token.span.start > check.span.start &&
442
+ token.span.end < check.span.end &&
443
+ CHECK_WORDS.has(token.text)
444
+ )
445
+ mark(token, "keyword", {
446
+ kind: "keyword",
447
+ title: token.text,
448
+ summary: CHECK_HELP,
449
+ });
450
+ for (const statement of check.statements) {
451
+ if (statement.kind === "customer")
452
+ mark(
453
+ at(statement.id.span),
454
+ "party",
455
+ declared(
456
+ statement.id.name,
457
+ "party",
458
+ check.span,
459
+ statement.id.span,
460
+ `customer ${statement.id.name}`,
461
+ `${statement.title}, a customer of check "${check.name}".`,
462
+ ),
463
+ );
464
+ if (statement.kind === "action") {
465
+ mark(at(statement.action.span), "action");
466
+ if (statement.state) mark(at(statement.state.span), "state");
467
+ }
468
+ if (statement.kind === "clock" && statement.until)
469
+ mark(at(statement.until.state.span), "state");
470
+ }
471
+ };
428
472
  // The parser owns declarations and scopes. A parse failure leaves lexical context intact.
429
473
  try {
430
474
  const parsed = parseProgram(source);
@@ -476,6 +520,7 @@ function analyze(source: string, library: StandardLibrary): Analysis {
476
520
  walk(decl.body, decl.span);
477
521
  }
478
522
  }
523
+ for (const check of parsed.program.checks) checkHelp(check);
479
524
  } catch {
480
525
  /* Arbitrary editor input must not interrupt typing. */
481
526
  }
@@ -486,12 +531,12 @@ function analyze(source: string, library: StandardLibrary): Analysis {
486
531
  const previous = tokens[i - 1]?.text;
487
532
  const next = tokens[i + 1]?.text;
488
533
  const owner = previous === "." ? tokens[i - 2]?.text : undefined;
489
- const imported = owner ? imports.get(owner) : undefined;
534
+ const imported = owner ? header(owner, toolchain) : undefined;
490
535
  const object = imported?.objects.find((o) => o.name === token.text);
536
+ const named = next === "." ? header(token.text, toolchain) : undefined;
491
537
  if (object && owner)
492
538
  mark(token, "instrument", instrumentHelp(object, owner));
493
- else if (imports.has(token.text) && next === ".")
494
- mark(token, "header", headerHelp.get(token.text));
539
+ else if (named) mark(token, "header", headerHelp(named));
495
540
  else if (!helps.has(token.span.start)) {
496
541
  const candidates = bindings
497
542
  .get(token.text)
@@ -514,7 +559,6 @@ function analyze(source: string, library: StandardLibrary): Analysis {
514
559
  !keywords.has(token.text) ||
515
560
  previous === "." ||
516
561
  previous === "expose" ||
517
- previous === "hide" ||
518
562
  next === ":" ||
519
563
  [":", "=", "fee", "moves", "from", "to", "(", ",", "["].includes(
520
564
  previous ?? "",
@@ -583,48 +627,89 @@ function analyze(source: string, library: StandardLibrary): Analysis {
583
627
  return { highlights, hovers };
584
628
  }
585
629
  // One editor document is retained. Hovering never reparses the same keystroke.
586
- let last:
587
- | { source: string; library: StandardLibrary; result: Analysis }
588
- | undefined;
589
- function analysis(source: string, library: StandardLibrary): Analysis {
590
- // Custom libraries may change without changing identity; only the bundled library is immutable.
591
- if (
592
- library === bundledStandardLibrary &&
593
- last?.source === source &&
594
- last.library === library
595
- )
630
+ let last: { source: string; result: Analysis } | undefined;
631
+ function analysis(source: string, toolchain: Toolchain): Analysis {
632
+ // A test toolchain may change its headers in place; the default never does.
633
+ if (toolchain === defaultToolchain && last?.source === source)
596
634
  return last.result;
597
- const result = analyze(source, library);
598
- if (library === bundledStandardLibrary) last = { source, library, result };
635
+ const result = analyze(source, toolchain);
636
+ if (toolchain === defaultToolchain) last = { source, result };
599
637
  return result;
600
638
  }
601
639
  /** Total, sorted, non-overlapping UTF-16 spans, including incomplete source. */
602
640
  export function highlight(
603
641
  source: string,
604
- library: StandardLibrary = bundledStandardLibrary,
642
+ toolchain: Toolchain = defaultToolchain,
605
643
  ): HsxHighlight[] {
606
- return analysis(source, library).highlights.map((span) => ({ ...span }));
644
+ return analysis(source, toolchain).highlights.map((span) => ({ ...span }));
645
+ }
646
+ // The terms of the attach line around an offset, from the last valid compile.
647
+ let compiled:
648
+ | {
649
+ source: string;
650
+ toolchain: Toolchain;
651
+ terms: (offset: number) => CompileTerm[] | undefined;
652
+ }
653
+ | undefined;
654
+ function termsAt(
655
+ source: string,
656
+ offset: number,
657
+ toolchain: Toolchain,
658
+ ): CompileTerm[] | undefined {
659
+ if (compiled?.source !== source || compiled.toolchain !== toolchain) {
660
+ const origins = compile(source, toolchain).artifacts?.originMap ?? [];
661
+ compiled = {
662
+ source,
663
+ toolchain,
664
+ // A record shares its attach line's span; the attach comes first.
665
+ terms: (at) =>
666
+ origins.find(
667
+ (entry) =>
668
+ entry.terms && entry.span.start <= at && at < entry.span.end,
669
+ )?.terms,
670
+ };
671
+ }
672
+ return compiled.terms(offset);
607
673
  }
674
+ const inForce = (term: CompileTerm) =>
675
+ `${term.text} (${term.from === "std" ? `${term.source} default` : term.from === "party" ? "the party of that name" : "set by the program"})`;
608
676
  /** Offsets use half-open UTF-16 spans. Whitespace and out-of-range offsets return null. */
609
677
  export function describe(
610
678
  source: string,
611
679
  offset: number,
612
- library: StandardLibrary = bundledStandardLibrary,
680
+ toolchain: Toolchain = defaultToolchain,
613
681
  ): HsxHover | null {
614
682
  if (!Number.isInteger(offset) || offset < 0 || offset >= source.length)
615
683
  return null;
616
- const result = analysis(source, library);
684
+ const result = analysis(source, toolchain);
617
685
  const span = result.highlights.find(
618
686
  (s) => s.start <= offset && offset < s.end,
619
687
  );
620
688
  const hover = span && result.hovers.get(span.start);
621
- return hover
622
- ? {
623
- ...hover,
624
- span: { ...hover.span },
625
- ...(hover.details
626
- ? { details: hover.details.map((d) => ({ ...d })) }
627
- : {}),
628
- }
629
- : null;
689
+ if (!hover) return null;
690
+ const details = hover.details?.map((d) => ({ ...d }));
691
+ // A std tunable and an attach line show the value in force and who set it.
692
+ const terms =
693
+ (hover.kind === "parameter" && hover.header) ||
694
+ (hover.kind === "instrument" &&
695
+ source.lastIndexOf("attach", offset) > source.lastIndexOf("{", offset))
696
+ ? termsAt(source, offset, toolchain)
697
+ : undefined;
698
+ const term = terms?.find((t) => t.name === hover.title);
699
+ const added =
700
+ hover.kind === "parameter"
701
+ ? term
702
+ ? [{ label: "In force", value: inForce(term) }]
703
+ : []
704
+ : (terms ?? []).map((t) => ({
705
+ label: `${t.name} in force`,
706
+ value: inForce(t),
707
+ }));
708
+ return {
709
+ ...hover,
710
+ span: { ...hover.span },
711
+ ...(details || added.length
712
+ ? { details: [...(details ?? []), ...added] }
713
+ : {}),
714
+ };
630
715
  }
package/src/lex.ts CHANGED
@@ -2,7 +2,6 @@ import type { Diagnostic, Span } from "./ast.ts";
2
2
  export const KEYWORDS = [
3
3
  "program",
4
4
  "header",
5
- "use",
6
5
  "party",
7
6
  "role",
8
7
  "currency",
@@ -11,12 +10,11 @@ export const KEYWORDS = [
11
10
  "lifecycle",
12
11
  "action",
13
12
  "expose",
14
- "hide",
15
13
  "as",
16
14
  "cap",
17
15
  "of",
18
16
  "when",
19
- "constraints",
17
+ "checks",
20
18
  "requires",
21
19
  "invariants",
22
20
  "moves",
@@ -131,10 +129,10 @@ export function scan(
131
129
  }
132
130
  kind = "string";
133
131
  text = quoted[0];
134
- } else if (/^(==|!=|<=|>=)/.test(tail)) {
132
+ } else if (/^(==|!=|<=|>=|->)/.test(tail)) {
135
133
  kind = "punct";
136
134
  text = tail.slice(0, 2);
137
- } else if (/^[{}()[\]:,;=<>?.|]/.test(tail)) {
135
+ } else if (/^[{}()[\]:,;=<>?.|+]/.test(tail)) {
138
136
  kind = "punct";
139
137
  text = tail[0]!;
140
138
  } else {