@hyperscale0/hsx 1.0.0-beta.1 → 1.0.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.
Files changed (255) hide show
  1. package/CHANGELOG.md +58 -9
  2. package/LICENSING.md +3 -3
  3. package/README.md +39 -149
  4. package/TRADEMARKS.md +4 -4
  5. package/bin/hsx.ts +2 -0
  6. package/dist/bin/hsx.js +2 -0
  7. package/dist/bin/hsx.js.map +1 -1
  8. package/dist/src/ast.d.ts +135 -10
  9. package/dist/src/ast.d.ts.map +1 -1
  10. package/dist/src/ast.js +24 -0
  11. package/dist/src/ast.js.map +1 -1
  12. package/dist/src/cli.d.ts +4 -1
  13. package/dist/src/cli.d.ts.map +1 -1
  14. package/dist/src/cli.js +172 -16
  15. package/dist/src/cli.js.map +1 -1
  16. package/dist/src/compile.d.ts +42 -7
  17. package/dist/src/compile.d.ts.map +1 -1
  18. package/dist/src/compile.js +82 -16
  19. package/dist/src/compile.js.map +1 -1
  20. package/dist/src/cost.d.ts +78 -0
  21. package/dist/src/cost.d.ts.map +1 -0
  22. package/dist/src/cost.js +369 -0
  23. package/dist/src/cost.js.map +1 -0
  24. package/dist/src/diagnostics.d.ts +11 -0
  25. package/dist/src/diagnostics.d.ts.map +1 -0
  26. package/dist/src/diagnostics.js +420 -0
  27. package/dist/src/diagnostics.js.map +1 -0
  28. package/dist/src/emit.d.ts +34 -0
  29. package/dist/src/emit.d.ts.map +1 -0
  30. package/dist/src/emit.js +137 -0
  31. package/dist/src/emit.js.map +1 -0
  32. package/dist/src/entry-overrides.d.ts +17 -3
  33. package/dist/src/entry-overrides.d.ts.map +1 -1
  34. package/dist/src/entry-overrides.js +180 -35
  35. package/dist/src/entry-overrides.js.map +1 -1
  36. package/dist/src/format.d.ts +10 -0
  37. package/dist/src/format.d.ts.map +1 -0
  38. package/dist/src/format.js +183 -0
  39. package/dist/src/format.js.map +1 -0
  40. package/dist/src/index.d.ts +11 -4
  41. package/dist/src/index.d.ts.map +1 -1
  42. package/dist/src/index.js +10 -3
  43. package/dist/src/index.js.map +1 -1
  44. package/dist/src/ir.d.ts +66 -0
  45. package/dist/src/ir.d.ts.map +1 -0
  46. package/dist/src/ir.js +15 -0
  47. package/dist/src/ir.js.map +1 -0
  48. package/dist/src/lex.d.ts +9 -1
  49. package/dist/src/lex.d.ts.map +1 -1
  50. package/dist/src/lex.js +50 -4
  51. package/dist/src/lex.js.map +1 -1
  52. package/dist/src/limits.d.ts +2 -3
  53. package/dist/src/limits.d.ts.map +1 -1
  54. package/dist/src/limits.js +2 -3
  55. package/dist/src/limits.js.map +1 -1
  56. package/dist/src/lsp/server.d.ts +32 -0
  57. package/dist/src/lsp/server.d.ts.map +1 -0
  58. package/dist/src/lsp/server.js +391 -0
  59. package/dist/src/lsp/server.js.map +1 -0
  60. package/dist/src/modules.d.ts +38 -0
  61. package/dist/src/modules.d.ts.map +1 -0
  62. package/dist/src/modules.js +368 -0
  63. package/dist/src/modules.js.map +1 -0
  64. package/dist/src/parse.d.ts.map +1 -1
  65. package/dist/src/parse.js +590 -17
  66. package/dist/src/parse.js.map +1 -1
  67. package/dist/src/std-bundle.d.ts +2 -0
  68. package/dist/src/std-bundle.d.ts.map +1 -0
  69. package/dist/src/std-bundle.js +88 -0
  70. package/dist/src/std-bundle.js.map +1 -0
  71. package/dist/src/std-library.d.ts +5 -0
  72. package/dist/src/std-library.d.ts.map +1 -0
  73. package/dist/src/std-library.js +9 -0
  74. package/dist/src/std-library.js.map +1 -0
  75. package/dist/src/typecheck.d.ts +8 -0
  76. package/dist/src/typecheck.d.ts.map +1 -0
  77. package/dist/src/typecheck.js +2958 -0
  78. package/dist/src/typecheck.js.map +1 -0
  79. package/dist/src/version.d.ts +4 -15
  80. package/dist/src/version.d.ts.map +1 -1
  81. package/dist/src/version.js +4 -15
  82. package/dist/src/version.js.map +1 -1
  83. package/docs/README.md +26 -0
  84. package/docs/guide/01-first-program.md +24 -0
  85. package/docs/guide/02-money.md +25 -0
  86. package/docs/guide/03-instruments.md +22 -0
  87. package/docs/guide/04-lifecycles.md +25 -0
  88. package/docs/guide/05-fees-and-splits.md +45 -0
  89. package/docs/guide/06-schedules.md +22 -0
  90. package/docs/guide/07-composition.md +46 -0
  91. package/docs/guide/08-writing-a-module.md +26 -0
  92. package/docs/guide/09-cost.md +24 -0
  93. package/docs/guide/10-diagnostics.md +27 -0
  94. package/docs/llms-full.txt +1739 -0
  95. package/docs/llms.txt +45 -0
  96. package/docs/playground.md +54 -0
  97. package/docs/reference/cli.md +35 -0
  98. package/docs/reference/diagnostics.md +619 -0
  99. package/docs/reference/grammar.md +39 -0
  100. package/docs/reference/std/advance.md +35 -0
  101. package/docs/reference/std/cancellable_booking.md +35 -0
  102. package/docs/reference/std/captured_payment.md +43 -0
  103. package/docs/reference/std/conditional_disbursement.md +33 -0
  104. package/docs/reference/std/credit_facility.md +35 -0
  105. package/docs/reference/std/held_payment.md +64 -0
  106. package/docs/reference/std/instant_transfer.md +30 -0
  107. package/docs/reference/std/metered.md +27 -0
  108. package/docs/reference/std/pooled_split.md +26 -0
  109. package/docs/reference/std/premium_forward.md +39 -0
  110. package/docs/reference/std/reconciled_payout.md +33 -0
  111. package/docs/reference/std/recurring_collection.md +25 -0
  112. package/docs/reference/std/rotating_pool.md +42 -0
  113. package/docs/reference/std/scheduled.md +51 -0
  114. package/docs/reference/std/security_deposit.md +46 -0
  115. package/docs/reference/std/settlement_batch.md +42 -0
  116. package/docs/reference/std/swap.md +46 -0
  117. package/docs/reference/std/threshold_pool.md +47 -0
  118. package/docs/reference/std/weighted_distribution.md +39 -0
  119. package/docs/reference/types.md +20 -0
  120. package/docs/reference/udl-output.md +13 -0
  121. package/docs/sessions/2026-09-02-two-instruments.hsx +21 -0
  122. package/docs/sessions/2026-09-02-two-instruments.md +41 -0
  123. package/examples/01-first-program/README.md +45 -0
  124. package/examples/01-first-program/tip-jar.hsx +17 -0
  125. package/examples/02-imports-and-archetypes/README.md +96 -0
  126. package/examples/02-imports-and-archetypes/photo-booth.hsx +37 -0
  127. package/examples/03-diagnostics/README.md +68 -0
  128. package/examples/03-diagnostics/corner-shop-fixed.hsx +22 -0
  129. package/examples/03-diagnostics/corner-shop.hsx +19 -0
  130. package/examples/04-complete-product/README.md +84 -0
  131. package/examples/04-complete-product/study-hall.hsx +67 -0
  132. package/examples/05-watch-club/README.md +9 -0
  133. package/examples/05-watch-club/watch-club.hsx +124 -0
  134. package/examples/README.md +18 -0
  135. package/examples/advance/README.md +3 -0
  136. package/examples/advance/advance.hsx +13 -0
  137. package/examples/advance/advance.udl +339 -0
  138. package/examples/cancellable_booking/README.md +3 -0
  139. package/examples/cancellable_booking/cancellable_booking.hsx +14 -0
  140. package/examples/cancellable_booking/cancellable_booking.udl +391 -0
  141. package/examples/captured_payment/README.md +3 -0
  142. package/examples/captured_payment/captured_payment.hsx +21 -0
  143. package/examples/captured_payment/captured_payment.udl +677 -0
  144. package/examples/conditional_disbursement/README.md +3 -0
  145. package/examples/conditional_disbursement/conditional_disbursement.hsx +17 -0
  146. package/examples/conditional_disbursement/conditional_disbursement.udl +412 -0
  147. package/examples/cost-table.json +386 -0
  148. package/examples/credit_facility/README.md +3 -0
  149. package/examples/credit_facility/credit_facility.hsx +27 -0
  150. package/examples/credit_facility/credit_facility.udl +1373 -0
  151. package/examples/held_payment/README.md +3 -0
  152. package/examples/held_payment/held_payment.hsx +13 -0
  153. package/examples/held_payment/held_payment.udl +507 -0
  154. package/examples/instant_transfer/README.md +3 -0
  155. package/examples/instant_transfer/instant_transfer.hsx +16 -0
  156. package/examples/instant_transfer/instant_transfer.udl +364 -0
  157. package/examples/metered/README.md +3 -0
  158. package/examples/metered/metered.hsx +13 -0
  159. package/examples/metered/metered.udl +247 -0
  160. package/examples/pooled_split/README.md +3 -0
  161. package/examples/pooled_split/pooled_split.hsx +15 -0
  162. package/examples/pooled_split/pooled_split.udl +425 -0
  163. package/examples/premium_forward/README.md +3 -0
  164. package/examples/premium_forward/premium_forward.hsx +19 -0
  165. package/examples/premium_forward/premium_forward.udl +594 -0
  166. package/examples/reconciled_payout/README.md +3 -0
  167. package/examples/reconciled_payout/reconciled_payout.hsx +13 -0
  168. package/examples/reconciled_payout/reconciled_payout.udl +303 -0
  169. package/examples/recurring_collection/README.md +3 -0
  170. package/examples/recurring_collection/recurring_collection.hsx +21 -0
  171. package/examples/recurring_collection/recurring_collection.udl +1130 -0
  172. package/examples/rotating_pool/README.md +3 -0
  173. package/examples/rotating_pool/rotating_pool.hsx +18 -0
  174. package/examples/rotating_pool/rotating_pool.udl +4352 -0
  175. package/examples/scheduled/README.md +3 -0
  176. package/examples/scheduled/scheduled.hsx +12 -0
  177. package/examples/scheduled/scheduled.udl +335 -0
  178. package/examples/security_deposit/README.md +3 -0
  179. package/examples/security_deposit/security_deposit.hsx +21 -0
  180. package/examples/security_deposit/security_deposit.udl +293 -0
  181. package/examples/settlement_batch/README.md +3 -0
  182. package/examples/settlement_batch/settlement_batch.hsx +19 -0
  183. package/examples/settlement_batch/settlement_batch.udl +753 -0
  184. package/examples/swap/README.md +3 -0
  185. package/examples/swap/swap.hsx +19 -0
  186. package/examples/swap/swap.udl +876 -0
  187. package/examples/threshold_pool/README.md +3 -0
  188. package/examples/threshold_pool/threshold_pool.hsx +16 -0
  189. package/examples/threshold_pool/threshold_pool.udl +667 -0
  190. package/examples/weighted_distribution/README.md +3 -0
  191. package/examples/weighted_distribution/weighted_distribution.hsx +20 -0
  192. package/examples/weighted_distribution/weighted_distribution.udl +337 -0
  193. package/package.json +27 -6
  194. package/skills/hsx/SKILL.md +483 -0
  195. package/src/ast.ts +193 -9
  196. package/src/cli.ts +191 -20
  197. package/src/compile.ts +160 -23
  198. package/src/cost.ts +579 -0
  199. package/src/diagnostics.ts +442 -0
  200. package/src/emit.ts +201 -0
  201. package/src/entry-overrides.ts +263 -48
  202. package/src/format.ts +261 -0
  203. package/src/index.ts +34 -4
  204. package/src/ir.ts +99 -0
  205. package/src/lex.ts +59 -4
  206. package/src/limits.ts +2 -3
  207. package/src/lsp/server.ts +460 -0
  208. package/src/modules.ts +446 -0
  209. package/src/parse.ts +655 -21
  210. package/src/std-bundle.ts +91 -0
  211. package/src/std-library.ts +12 -0
  212. package/src/typecheck.ts +3876 -0
  213. package/src/version.ts +4 -16
  214. package/std/SEMANTICS.md +130 -0
  215. package/std/settlements/advance.hsx +177 -0
  216. package/std/settlements/cancellable_booking.hsx +87 -0
  217. package/std/settlements/captured_payment.hsx +144 -0
  218. package/std/settlements/conditional_disbursement.hsx +185 -0
  219. package/std/settlements/credit_facility.hsx +167 -0
  220. package/std/settlements/held_payment.hsx +578 -0
  221. package/std/settlements/index.hsx +3 -0
  222. package/std/settlements/instant_transfer.hsx +190 -0
  223. package/std/settlements/metered.hsx +67 -0
  224. package/std/settlements/pooled_split.hsx +68 -0
  225. package/std/settlements/premium_forward.hsx +257 -0
  226. package/std/settlements/reconciled_payout.hsx +77 -0
  227. package/std/settlements/recurring_collection.hsx +27 -0
  228. package/std/settlements/rotating_pool.hsx +252 -0
  229. package/std/settlements/scheduled.hsx +641 -0
  230. package/std/settlements/security_deposit.hsx +166 -0
  231. package/std/settlements/settlement_batch.hsx +122 -0
  232. package/std/settlements/swap.hsx +1114 -0
  233. package/std/settlements/threshold_pool.hsx +221 -0
  234. package/std/settlements/weighted_distribution.hsx +141 -0
  235. package/dist/src/archetypes.d.ts +0 -17
  236. package/dist/src/archetypes.d.ts.map +0 -1
  237. package/dist/src/archetypes.js +0 -327
  238. package/dist/src/archetypes.js.map +0 -1
  239. package/dist/src/check.d.ts +0 -12
  240. package/dist/src/check.d.ts.map +0 -1
  241. package/dist/src/check.js +0 -1910
  242. package/dist/src/check.js.map +0 -1
  243. package/dist/src/lower.d.ts +0 -146
  244. package/dist/src/lower.d.ts.map +0 -1
  245. package/dist/src/lower.js +0 -4570
  246. package/dist/src/lower.js.map +0 -1
  247. package/dist/src/model.d.ts +0 -467
  248. package/dist/src/model.d.ts.map +0 -1
  249. package/dist/src/model.js +0 -15
  250. package/dist/src/model.js.map +0 -1
  251. package/spec/hsx-ir.schema.json +0 -920
  252. package/src/archetypes.ts +0 -340
  253. package/src/check.ts +0 -2938
  254. package/src/lower.ts +0 -5416
  255. package/src/model.ts +0 -519
package/src/compile.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * The HSX compiler driver: source text in, three-verdict result out.
3
3
  *
4
- * - `valid`: the program lowers cleanly; the IR document and frame are ready
4
+ * - `valid`: the program lowers cleanly; the IR document is ready
5
5
  * for the independent checker.
6
6
  * - `warning`: the program lowers, and the compiler's lint voice has notes
7
7
  * the author should read (the artifacts are still present and usable).
@@ -11,31 +11,73 @@
11
11
  * Every diagnostic points at SOURCE coordinates, never at lowered IR paths.
12
12
  */
13
13
 
14
+ import type { UdlIssueCode } from "@hyperscale0/udl";
14
15
  import { lineColIn, lineIndex } from "./ast.ts";
15
- import { checkProgram } from "./check.ts";
16
- import { lowerProgram } from "./lower.ts";
16
+ import {
17
+ buildCostManifest,
18
+ type UdlCostManifest,
19
+ type UdlCostTable,
20
+ } from "./cost.ts";
21
+ import { lowerGeneralProgram, type OriginMapEntry } from "./emit.ts";
22
+ import {
23
+ resolveProgramModules,
24
+ type HsxCompilerHost,
25
+ type ModuleOrigin,
26
+ } from "./modules.ts";
17
27
  import { parseProgram } from "./parse.ts";
28
+ import { checkGeneralProgram } from "./typecheck.ts";
18
29
 
19
30
  type Json = Record<string, unknown>;
20
31
 
21
32
  type CompileVerdict = "invalid" | "valid" | "warning";
22
33
 
23
- interface CompileDiagnostic {
34
+ export interface CompileDiagnostic {
24
35
  /** 1-indexed source column. */
25
36
  readonly column: number;
37
+ /** Imported module file when the diagnostic belongs to module source. */
38
+ readonly file?: string;
26
39
  /** 1-indexed source line. */
27
40
  readonly line: number;
28
41
  readonly message: string;
42
+ /** Source offsets in UTF-16 code units, matching parser and checker spans. */
43
+ readonly span: { readonly end: number; readonly start: number };
44
+ readonly code?: string;
45
+ readonly fix?: string;
46
+ /** Canonical UDL path when lowering rejected an emitted clause. */
47
+ readonly path?: string;
48
+ /** UDL validator category when the emitter rejected its candidate document. */
49
+ readonly udlCode?: UdlIssueCode;
29
50
  readonly severity: "error" | "warning";
30
51
  /** The stage that raised it: parse, check, or lower. */
31
- readonly stage: "check" | "lower" | "parse";
52
+ readonly stage: "bind" | "check" | "lower" | "parse" | "typecheck";
32
53
  }
33
54
 
34
55
  interface CompileArtifacts {
35
- /** The lowered HSX-JSON IR document, for the independent checker. */
56
+ /** The canonical UDL document. */
36
57
  readonly document: Json;
37
- /** The congruent Business Frame. */
38
- readonly frame: Json;
58
+ /** Canonical UDL paths bound to their narrowest authored source terms. */
59
+ readonly originMap: readonly CompileOriginMapEntry[];
60
+ /** Deterministic compile-time cost, pinned to one versioned table. */
61
+ readonly costManifest: UdlCostManifest;
62
+ }
63
+
64
+ export interface CompileOptions extends HsxCompilerHost {
65
+ readonly composesCatalogBlueprint?: boolean;
66
+ readonly costTable?: UdlCostTable;
67
+ }
68
+
69
+ export interface CompileOriginMapEntry {
70
+ readonly path: string;
71
+ readonly span: {
72
+ /** Exclusive UTF-8 byte offset. */
73
+ readonly end: number;
74
+ /** 1-indexed source column. */
75
+ readonly column: number;
76
+ /** 1-indexed source line. */
77
+ readonly line: number;
78
+ /** Inclusive UTF-8 byte offset. */
79
+ readonly start: number;
80
+ };
39
81
  }
40
82
 
41
83
  export interface CompileResult {
@@ -45,23 +87,37 @@ export interface CompileResult {
45
87
  readonly verdict: CompileVerdict;
46
88
  }
47
89
 
48
- export function compile(source: string): CompileResult {
90
+ export function compile(
91
+ source: string,
92
+ options: CompileOptions = {},
93
+ ): CompileResult {
49
94
  const diagnostics: CompileDiagnostic[] = [];
50
95
  // Scanned once here rather than per diagnostic: a source can carry one
51
96
  // diagnostic per two bytes, and rescanning from offset zero for each one
52
97
  // made a 128 KB file cost 2.4 seconds of coordinate arithmetic.
53
98
  const lines = lineIndex(source);
99
+ const byteOffsets = utf8OffsetIndex(source);
54
100
  const at = (
55
101
  stage: CompileDiagnostic["stage"],
56
102
  severity: CompileDiagnostic["severity"],
57
103
  message: string,
58
- offset: number,
104
+ span: { readonly end: number; readonly start: number },
105
+ details?: {
106
+ readonly code: string;
107
+ readonly fix: string;
108
+ readonly path?: string;
109
+ readonly udlCode?: UdlIssueCode;
110
+ },
111
+ origin?: ModuleOrigin,
59
112
  ): void => {
60
- const position = lineColIn(lines, offset);
113
+ const position = origin ?? lineColIn(lines, span.start);
61
114
  diagnostics.push({
62
115
  column: position.column,
116
+ ...(origin ? { file: origin.moduleName } : {}),
63
117
  line: position.line,
64
118
  message,
119
+ span: { ...span },
120
+ ...(details ? details : {}),
65
121
  severity,
66
122
  stage,
67
123
  });
@@ -69,34 +125,115 @@ export function compile(source: string): CompileResult {
69
125
 
70
126
  const parsed = parseProgram(source);
71
127
  for (const diagnostic of parsed.diagnostics) {
72
- at("parse", "error", diagnostic.message, diagnostic.span.start);
128
+ at(
129
+ "parse",
130
+ "error",
131
+ diagnostic.message,
132
+ diagnostic.span,
133
+ diagnostic.code && diagnostic.fix
134
+ ? { code: diagnostic.code, fix: diagnostic.fix }
135
+ : undefined,
136
+ );
73
137
  }
74
138
  if (parsed.diagnostics.length > 0) {
75
139
  return { diagnostics, verdict: "invalid" };
76
140
  }
77
141
 
78
- const checked = checkProgram(parsed.program);
142
+ const resolved = resolveProgramModules(parsed.program, options);
143
+ if (!resolved.ok) {
144
+ for (const issue of resolved.issues) {
145
+ at("bind", "error", issue.message, issue.span, {
146
+ code: issue.code,
147
+ fix: issue.fix,
148
+ });
149
+ }
150
+ return { diagnostics, verdict: "invalid" };
151
+ }
152
+ const checked = checkGeneralProgram(
153
+ resolved.program,
154
+ options.publishedCatalog
155
+ ? { publishedCatalog: options.publishedCatalog }
156
+ : {},
157
+ );
79
158
  for (const diagnostic of checked.diagnostics) {
80
- at("check", diagnostic.severity, diagnostic.message, diagnostic.span.start);
159
+ const moduleOrigin = resolved.origins.get(diagnostic.span);
160
+ at(
161
+ diagnostic.code === "HSX1001" ? "bind" : "typecheck",
162
+ diagnostic.severity,
163
+ diagnostic.message,
164
+ diagnostic.span,
165
+ { code: diagnostic.code, fix: diagnostic.fix },
166
+ moduleOrigin,
167
+ );
81
168
  }
82
- if (!checked.program) {
169
+ if (!checked.program) return { diagnostics, verdict: "invalid" };
170
+ const cost = buildCostManifest(
171
+ checked.program,
172
+ options.costTable,
173
+ options.composesCatalogBlueprint ?? false,
174
+ );
175
+ if (!cost.ok) {
176
+ for (const diagnostic of cost.diagnostics) {
177
+ at(
178
+ "typecheck",
179
+ diagnostic.severity,
180
+ diagnostic.message,
181
+ diagnostic.span,
182
+ { code: diagnostic.code, fix: diagnostic.fix },
183
+ );
184
+ }
83
185
  return { diagnostics, verdict: "invalid" };
84
186
  }
85
-
86
- const loweredResult = lowerProgram(checked.program);
87
- if (!loweredResult.ok) {
88
- for (const issue of loweredResult.issues) {
89
- at("lower", "error", issue.message, issue.span.start);
187
+ const lowered = lowerGeneralProgram(checked.program);
188
+ if (!lowered.ok) {
189
+ for (const issue of lowered.issues) {
190
+ at("lower", "error", issue.message, issue.span, {
191
+ code: issue.code,
192
+ fix: issue.fix,
193
+ path: issue.path,
194
+ ...(issue.udlCode ? { udlCode: issue.udlCode } : {}),
195
+ });
90
196
  }
91
197
  return { diagnostics, verdict: "invalid" };
92
198
  }
93
-
199
+ const compileOrigin = (entry: OriginMapEntry): CompileOriginMapEntry => {
200
+ const position = lineColIn(lines, entry.span.start);
201
+ return {
202
+ path: entry.path,
203
+ span: {
204
+ column: position.column,
205
+ end:
206
+ byteOffsets[entry.span.end] ?? byteOffsets[byteOffsets.length - 1]!,
207
+ line: position.line,
208
+ start: byteOffsets[entry.span.start] ?? 0,
209
+ },
210
+ };
211
+ };
94
212
  return {
95
213
  artifacts: {
96
- document: loweredResult.value.document,
97
- frame: loweredResult.value.frame,
214
+ document: lowered.value.document,
215
+ costManifest: cost.manifest,
216
+ originMap: lowered.value.originMap.map(compileOrigin),
98
217
  },
99
218
  diagnostics,
100
219
  verdict: diagnostics.length > 0 ? "warning" : "valid",
101
220
  };
102
221
  }
222
+
223
+ function utf8OffsetIndex(source: string): Uint32Array {
224
+ const offsets = new Uint32Array(source.length + 1);
225
+ let bytes = 0;
226
+ for (let index = 0; index < source.length; index += 1) {
227
+ offsets[index] = bytes;
228
+ const codePoint = source.codePointAt(index) as number;
229
+ if (codePoint > 0xffff) {
230
+ offsets[index + 1] = bytes;
231
+ bytes += 4;
232
+ index += 1;
233
+ } else if (codePoint > 0x7ff) bytes += 3;
234
+ else if (codePoint > 0x7f) bytes += 2;
235
+ else bytes += 1;
236
+ }
237
+ offsets[source.length] = bytes;
238
+ return offsets;
239
+ }