@thomasfosterau/effect-parse 0.4.1 → 0.6.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 (157) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/README.md +56 -14
  3. package/dist/Ascii.d.ts +11 -4
  4. package/dist/Ascii.d.ts.map +1 -1
  5. package/dist/Ascii.js +12 -4
  6. package/dist/Ascii.js.map +1 -1
  7. package/dist/Binary.d.ts +5 -2
  8. package/dist/Binary.d.ts.map +1 -1
  9. package/dist/Binary.js +83 -37
  10. package/dist/Binary.js.map +1 -1
  11. package/dist/Bits.d.ts.map +1 -1
  12. package/dist/Bits.js +11 -4
  13. package/dist/Bits.js.map +1 -1
  14. package/dist/Compiler.d.ts +74 -2
  15. package/dist/Compiler.d.ts.map +1 -1
  16. package/dist/Compiler.js +78 -1
  17. package/dist/Compiler.js.map +1 -1
  18. package/dist/Expression.d.ts.map +1 -1
  19. package/dist/Expression.js +86 -74
  20. package/dist/Expression.js.map +1 -1
  21. package/dist/Input.d.ts +56 -5
  22. package/dist/Input.d.ts.map +1 -1
  23. package/dist/Input.js +70 -1
  24. package/dist/Input.js.map +1 -1
  25. package/dist/Nom.d.ts +5 -15
  26. package/dist/Nom.d.ts.map +1 -1
  27. package/dist/Nom.js.map +1 -1
  28. package/dist/ParseError.d.ts +69 -11
  29. package/dist/ParseError.d.ts.map +1 -1
  30. package/dist/ParseError.js +129 -28
  31. package/dist/ParseError.js.map +1 -1
  32. package/dist/Parser.d.ts +375 -29
  33. package/dist/Parser.d.ts.map +1 -1
  34. package/dist/Parser.js +394 -37
  35. package/dist/Parser.js.map +1 -1
  36. package/dist/ParserSchema.d.ts.map +1 -1
  37. package/dist/ParserSchema.js +2 -3
  38. package/dist/ParserSchema.js.map +1 -1
  39. package/dist/ParserStream.d.ts +122 -14
  40. package/dist/ParserStream.d.ts.map +1 -1
  41. package/dist/ParserStream.js +293 -62
  42. package/dist/ParserStream.js.map +1 -1
  43. package/dist/Syntax.d.ts +23 -5
  44. package/dist/Syntax.d.ts.map +1 -1
  45. package/dist/Syntax.js +1 -1
  46. package/dist/Syntax.js.map +1 -1
  47. package/dist/Text.d.ts.map +1 -1
  48. package/dist/Text.js +21 -15
  49. package/dist/Text.js.map +1 -1
  50. package/dist/Token.d.ts +65 -11
  51. package/dist/Token.d.ts.map +1 -1
  52. package/dist/Token.js +73 -26
  53. package/dist/Token.js.map +1 -1
  54. package/dist/internal/compiler/closure.d.ts +1 -1
  55. package/dist/internal/compiler/closure.d.ts.map +1 -1
  56. package/dist/internal/compiler/closure.js +263 -113
  57. package/dist/internal/compiler/closure.js.map +1 -1
  58. package/dist/internal/compiler/entries.d.ts +3 -1
  59. package/dist/internal/compiler/entries.d.ts.map +1 -1
  60. package/dist/internal/compiler/entries.js +3 -2
  61. package/dist/internal/compiler/entries.js.map +1 -1
  62. package/dist/internal/compiler/first.d.ts.map +1 -1
  63. package/dist/internal/compiler/first.js +9 -2
  64. package/dist/internal/compiler/first.js.map +1 -1
  65. package/dist/internal/compiler/graph.d.ts +39 -0
  66. package/dist/internal/compiler/graph.d.ts.map +1 -0
  67. package/dist/internal/compiler/graph.js +78 -0
  68. package/dist/internal/compiler/graph.js.map +1 -0
  69. package/dist/internal/compiler/jit.d.ts +5 -0
  70. package/dist/internal/compiler/jit.d.ts.map +1 -1
  71. package/dist/internal/compiler/jit.js +208 -106
  72. package/dist/internal/compiler/jit.js.map +1 -1
  73. package/dist/internal/compiler/registry.d.ts +11 -3
  74. package/dist/internal/compiler/registry.d.ts.map +1 -1
  75. package/dist/internal/compiler/registry.js.map +1 -1
  76. package/dist/internal/compiler/search.d.ts +32 -0
  77. package/dist/internal/compiler/search.d.ts.map +1 -0
  78. package/dist/internal/compiler/search.js +68 -0
  79. package/dist/internal/compiler/search.js.map +1 -0
  80. package/dist/internal/compiler/sets.d.ts.map +1 -1
  81. package/dist/internal/compiler/sets.js +1 -1
  82. package/dist/internal/compiler/sets.js.map +1 -1
  83. package/dist/internal/compiler/wasm.d.ts +8 -0
  84. package/dist/internal/compiler/wasm.d.ts.map +1 -0
  85. package/dist/internal/compiler/wasm.js +2840 -0
  86. package/dist/internal/compiler/wasm.js.map +1 -0
  87. package/dist/internal/compiler/wasmAsm.d.ts +199 -0
  88. package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
  89. package/dist/internal/compiler/wasmAsm.js +427 -0
  90. package/dist/internal/compiler/wasmAsm.js.map +1 -0
  91. package/dist/internal/entries.d.ts +3 -1
  92. package/dist/internal/entries.d.ts.map +1 -1
  93. package/dist/internal/entries.js.map +1 -1
  94. package/dist/internal/node.d.ts +77 -3
  95. package/dist/internal/node.d.ts.map +1 -1
  96. package/dist/internal/node.js +54 -10
  97. package/dist/internal/node.js.map +1 -1
  98. package/dist/internal/numbers.d.ts.map +1 -1
  99. package/dist/internal/numbers.js.map +1 -1
  100. package/dist/internal/run.d.ts +14 -0
  101. package/dist/internal/run.d.ts.map +1 -1
  102. package/dist/internal/run.js +53 -11
  103. package/dist/internal/run.js.map +1 -1
  104. package/dist/internal/stack.d.ts +14 -0
  105. package/dist/internal/stack.d.ts.map +1 -1
  106. package/dist/internal/stack.js +24 -2
  107. package/dist/internal/stack.js.map +1 -1
  108. package/dist/internal/syntax.d.ts +4 -4
  109. package/dist/internal/syntax.d.ts.map +1 -1
  110. package/dist/internal/syntax.js +18 -10
  111. package/dist/internal/syntax.js.map +1 -1
  112. package/dist/internal/text.d.ts +32 -0
  113. package/dist/internal/text.d.ts.map +1 -1
  114. package/dist/internal/text.js +68 -14
  115. package/dist/internal/text.js.map +1 -1
  116. package/dist/internal/tokens.d.ts +20 -0
  117. package/dist/internal/tokens.d.ts.map +1 -1
  118. package/dist/internal/tokens.js +72 -39
  119. package/dist/internal/tokens.js.map +1 -1
  120. package/dist/internal/tuple.d.ts +6 -0
  121. package/dist/internal/tuple.d.ts.map +1 -0
  122. package/dist/internal/tuple.js +170 -0
  123. package/dist/internal/tuple.js.map +1 -0
  124. package/package.json +18 -10
  125. package/src/Ascii.ts +47 -12
  126. package/src/Binary.ts +174 -73
  127. package/src/Bits.ts +16 -6
  128. package/src/Compiler.ts +101 -10
  129. package/src/Expression.ts +94 -81
  130. package/src/Input.ts +99 -7
  131. package/src/Nom.ts +15 -5
  132. package/src/ParseError.ts +209 -52
  133. package/src/Parser.ts +684 -143
  134. package/src/ParserSchema.ts +1 -2
  135. package/src/ParserStream.ts +361 -68
  136. package/src/Syntax.ts +60 -36
  137. package/src/Text.ts +32 -27
  138. package/src/Token.ts +152 -34
  139. package/src/internal/compiler/closure.ts +371 -153
  140. package/src/internal/compiler/entries.ts +4 -2
  141. package/src/internal/compiler/first.ts +16 -0
  142. package/src/internal/compiler/graph.ts +96 -0
  143. package/src/internal/compiler/jit.ts +319 -169
  144. package/src/internal/compiler/registry.ts +10 -2
  145. package/src/internal/compiler/search.ts +68 -0
  146. package/src/internal/compiler/sets.ts +7 -3
  147. package/src/internal/compiler/wasm.ts +3276 -0
  148. package/src/internal/compiler/wasmAsm.ts +484 -0
  149. package/src/internal/entries.ts +8 -2
  150. package/src/internal/node.ts +103 -7
  151. package/src/internal/numbers.ts +3 -1
  152. package/src/internal/run.ts +73 -12
  153. package/src/internal/stack.ts +25 -1
  154. package/src/internal/syntax.ts +39 -18
  155. package/src/internal/text.ts +97 -9
  156. package/src/internal/tokens.ts +106 -14
  157. package/src/internal/tuple.ts +141 -0
@@ -3,17 +3,20 @@ import * as Result from "effect/Result";
3
3
  import { Fail } from "../../Input.js";
4
4
  import { floatScan, floatTexts, scanFloatBytes, scanFloatString, toFloat } from "../numbers.js";
5
5
  import { Key } from "../key.js";
6
+ import { Defer, NodeId, nodeOf, scansFloat } from "../node.js";
6
7
  import * as Resume from "../resume.js";
7
8
  import { compileAny } from "../tokens.js";
8
9
  import { backend as backend$1, createClosureCompiler } from "./closure.js";
9
10
  import * as Option from "effect/Option";
10
- import { charOf, fastLimit, latin1, string, utf16be, utf16le, utf8, validate } from "../text.js";
11
+ import { ShortText, charOf, fastLimit, latin1, string, textIn, utf16be, utf16le, utf8, utf8Text, validate } from "../text.js";
11
12
  import * as Arr from "effect/Array";
12
13
  import { addEntry, flushEntries, fromEntries, isPlainKey } from "../entries.js";
13
- import { children, nodeOf, scansFloat } from "../node.js";
14
+ import * as Stack from "../stack.js";
14
15
  import { buildsEntries, pairOf } from "./entries.js";
15
16
  import { Strict, planAlt } from "./first.js";
17
+ import { SearchHead, StopCache, nextStop, stopChars } from "./search.js";
16
18
  import { TableSize, acceptTable, kindOfEncoding, reachesAbove, textSet, tokenSet } from "./sets.js";
19
+ import { countInlined, countRefs, isLeaf, isLetter, isSmall, lowerAscii, selectorOf } from "./graph.js";
17
20
  // src/internal/compiler/jit.ts
18
21
  /**
19
22
  * The JIT: emits JavaScript source for a parser's description and builds
@@ -33,11 +36,15 @@ import { TableSize, acceptTable, kindOfEncoding, reachesAbove, textSet, tokenSet
33
36
  */
34
37
  /** Helpers available to generated code as `R`. */
35
38
  const runtime = {
39
+ StopCache,
40
+ nextStop,
36
41
  take: Resume.take,
37
42
  save: Resume.save,
38
43
  Done: Resume.Done,
39
44
  /** Records the result of a resumed repetition (see `Resume.done`). */
40
45
  done: (state, key, entry, value, pos) => Resume.save(state, key, entry, new Resume.Done(value, pos)),
46
+ isStackOverflow: Stack.isStackOverflow,
47
+ tooDeep: Stack.tooDeep,
41
48
  some: Option.some,
42
49
  none: Option.none,
43
50
  charOf,
@@ -56,8 +63,9 @@ const runtime = {
56
63
  s.mode = "Backtrack";
57
64
  return Fail;
58
65
  }
59
- return enc.text(input, start, end);
60
- }
66
+ return textIn(enc, s, start, end);
67
+ },
68
+ utf8Text
61
69
  };
62
70
  let checked;
63
71
  let supported = false;
@@ -87,22 +95,6 @@ const Margin = 4;
87
95
  var Fn = class {
88
96
  vars = [];
89
97
  };
90
- const isLeaf = (node) => {
91
- switch (node._tag) {
92
- case "Succeed":
93
- case "Fail":
94
- case "Eof":
95
- case "Location":
96
- case "RestLen":
97
- case "Any":
98
- case "Literal":
99
- case "OneOf":
100
- case "TakeWhile": return true;
101
- default: return false;
102
- }
103
- };
104
- const lowerAscii = (c) => c >= 65 && c <= 90 ? c + 32 : c;
105
- const isLetter = (c) => c >= 65 && c <= 90 || c >= 97 && c <= 122;
106
98
  /** The inclusive ranges of 1s in a table. */
107
99
  const runsOf = (table) => {
108
100
  const out = [];
@@ -160,7 +152,9 @@ var Emitter = class {
160
152
  constantIndex = /* @__PURE__ */ new Map();
161
153
  functions = [];
162
154
  rules = [/* @__PURE__ */ new Map(), /* @__PURE__ */ new Map()];
163
- refs = /* @__PURE__ */ new Map();
155
+ refs;
156
+ /** How many parsers have been inlined (see `countInlined`). */
157
+ inlined = 0;
164
158
  closure;
165
159
  next = 0;
166
160
  constructor(root, kind, resumable = false) {
@@ -168,24 +162,11 @@ var Emitter = class {
168
162
  this.kind = kind;
169
163
  this.resumable = resumable;
170
164
  this.closure = createClosureCompiler(kind, resumable);
171
- this.countRefs(root);
165
+ this.refs = countRefs(root);
172
166
  }
173
167
  get fallbacks() {
174
168
  return this.closure.fallbacks;
175
169
  }
176
- /** Counts the distinct parents of each parser. */
177
- countRefs(root) {
178
- const seen = /* @__PURE__ */ new Set();
179
- const stack = [root];
180
- for (let p = stack.pop(); p !== void 0; p = stack.pop()) {
181
- if (seen.has(p)) continue;
182
- seen.add(p);
183
- for (const c of new Set(children(nodeOf(p)))) {
184
- this.refs.set(c, (this.refs.get(c) ?? 0) + 1);
185
- stack.push(c);
186
- }
187
- }
188
- }
189
170
  const(value) {
190
171
  let i = this.constantIndex.get(value);
191
172
  if (i === void 0) {
@@ -195,6 +176,21 @@ var Emitter = class {
195
176
  }
196
177
  return `C[${i}]`;
197
178
  }
179
+ /** The text of `[start, p)` in `enc`: UTF-8 decodes through the state's ASCII run (see `utf8Text`). */
180
+ text(enc, start) {
181
+ const text = `${this.const(enc.text)}(I,${start},p)`;
182
+ return enc === utf8 ? `(p-${start}>${ShortText}?R.utf8Text($S,${start},p):${text})` : text;
183
+ }
184
+ /**
185
+ * A count or bound as source text. Every number a description contributes
186
+ * to the generated source is written here, so nothing but a non-negative
187
+ * integer can reach it: a bound is a `number` only in the types, and a
188
+ * string written as given would run as code (#121).
189
+ */
190
+ num(n) {
191
+ if (!Number.isSafeInteger(n) || n < 0) throw new TypeError("effect-parse: a compiled bound must be a non-negative integer");
192
+ return String(n);
193
+ }
198
194
  /** A JavaScript literal for simple values, otherwise a constant. */
199
195
  lit(value) {
200
196
  if (value === void 0) return "void 0";
@@ -257,19 +253,9 @@ var Emitter = class {
257
253
  gen(p, used, out, fail, fn, depth) {
258
254
  const node = nodeOf(p);
259
255
  if (Predicate.isTagged(node, "Suspend")) return this.call(this.rule(node.resolve(), used), out, fail);
260
- if (!isLeaf(node) && ((this.refs.get(p) ?? 0) > 1 && !this.small(p) || depth > 32)) return this.call(this.rule(p, used), out, fail);
256
+ if (!isLeaf(node) && ((this.refs.get(p) ?? 0) > 1 && !isSmall(p) || depth > 32)) return this.call(this.rule(p, used), out, fail);
261
257
  return this.inline(p, used, out, fail, fn, depth);
262
258
  }
263
- /** Whether a parser is small enough to inline wherever it is used. */
264
- small(p) {
265
- let budget = 6;
266
- const visit = (q) => {
267
- const node = nodeOf(q);
268
- if (--budget < 0 || Predicate.isTagged(node, "Suspend") || Predicate.isTagged(node, "Escaped") || Predicate.isTagged(node, "Dispatch")) return false;
269
- return children(node).every(visit);
270
- };
271
- return visit(p);
272
- }
273
259
  /**
274
260
  * In a resumable build: token code (which fails by breaking out of `bad`)
275
261
  * that read within `lookahead` units of the end of a partial input re-runs
@@ -316,12 +302,12 @@ var Emitter = class {
316
302
  return `if(p>=E){${BT}${fail}}${out === null ? "" : `${out}=I[p];`}p++;`;
317
303
  }
318
304
  arrayOneOf(node, out, fail) {
319
- return `if(p>=E||${this.const(compileAny(node.set).forCode.token)}(I[p])===${node.negate}){${BT}${fail}}${out === null ? "" : `${out}=I[p];`}p++;`;
305
+ return `if(p>=E||${this.const(compileAny(node.set).forCode.token)}(I[p])===${node.negate === true}){${BT}${fail}}${out === null ? "" : `${out}=I[p];`}p++;`;
320
306
  }
321
307
  arrayTakeWhile(node, out, fail, fn) {
322
308
  const m = this.const(compileAny(node.set).forCode.token);
323
309
  const st = this.v(fn);
324
- return `${st}=p;while(p<E${node.max === Infinity ? "" : `&&p-${st}<${node.max}`}&&${m}(I[p])!==${node.negate})p++;` + (node.min > 0 ? `if(p-${st}<${node.min}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=I.slice(${st},p);`);
310
+ return `${st}=p;while(p<E${node.max === Infinity ? "" : `&&p-${st}<${this.num(node.max)}`}&&${m}(I[p])!==${node.negate === true})p++;` + (node.min > 0 ? `if(p-${st}<${this.num(node.min)}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=I.slice(${st},p);`);
325
311
  }
326
312
  call(name, out, fail) {
327
313
  if (out === null) return `if(${name}(p)===F){${fail}}p=P;`;
@@ -337,6 +323,7 @@ var Emitter = class {
337
323
  return enc === void 0 ? this.kind !== 2 : kindOfEncoding(enc) === this.kind;
338
324
  }
339
325
  inline(p, used, out, fail, fn, depth) {
326
+ this.inlined = countInlined(this.inlined);
340
327
  const node = nodeOf(p);
341
328
  const set = (value) => out === null ? "" : `${out}=${value};`;
342
329
  const d = depth + 1;
@@ -344,7 +331,7 @@ var Emitter = class {
344
331
  case "Succeed": return set(this.lit(node.value));
345
332
  case "Sync": return used ? set(`${this.const(node.evaluate)}()`) : "";
346
333
  case "Fail": return `$S.mode=${JSON.stringify(node.mode)};${fail}`;
347
- case "Eof": return `if(p<E){${BT}${fail}}` + (this.resumable ? `if($S.partial){$S.mode="Incomplete";${fail}}` : "") + set("void 0");
334
+ case "Eof": return `if(p<E){${BT}${fail}}` + (this.resumable ? `if($S.partial){$S.incomplete(1);${fail}}` : "") + set("void 0");
348
335
  case "Location": return set("p");
349
336
  case "RestLen": return set("E-p");
350
337
  case "Suspend": return this.call(this.rule(node.resolve(), used), out, fail);
@@ -367,7 +354,7 @@ var Emitter = class {
367
354
  const code = this.float(node, out, fail, fn, d);
368
355
  if (code !== void 0) return code;
369
356
  }
370
- if (node.f === fromEntries && out !== null && !this.resumable && buildsEntries(node.self)) return this.entries(node.self, out, fail, fn, d);
357
+ if (node.f === fromEntries && out !== null && buildsEntries(node.self)) return this.entries(node.self, out, fail, fn, d);
371
358
  const t = this.v(fn);
372
359
  return this.gen(node.self, true, t, fail, fn, d) + set(`${this.const(node.f)}(${t})`);
373
360
  }
@@ -383,6 +370,17 @@ var Emitter = class {
383
370
  const [tag, field] = Predicate.isTagged(node, "TryMap") ? ["Success", "success"] : ["Some", "value"];
384
371
  return this.gen(node.self, true, t, fail, fn, d) + `${r}=${this.const(node.f)}(${t});if(${r}._tag!=="${tag}"){${BT}${fail}}${set(`${r}.${field}`)}`;
385
372
  }
373
+ case "FastPath": {
374
+ const st = this.v(fn);
375
+ const t = out ?? this.v(fn);
376
+ const done = this.label();
377
+ return `${st}=p;$S.pos=p;${t}=${this.const(node.fast)}($S);${done}:{if(${t}!==${this.const(Defer)}){p=$S.pos;break ${done}}p=${st};${this.gen(node.self, used, out, fail, fn, d)}}`;
378
+ }
379
+ case "MapOrFail": {
380
+ const t = this.v(fn);
381
+ const r = out ?? this.v(fn);
382
+ return this.gen(node.self, true, t, fail, fn, d) + `${r}=${this.const(node.f)}(${t});if(${r}===F){${BT}${fail}}`;
383
+ }
386
384
  case "Filter": {
387
385
  const t = out ?? this.v(fn);
388
386
  return this.gen(node.self, true, t, fail, fn, d) + `if(!${this.const(node.predicate)}(${t})){${BT}${fail}}`;
@@ -409,6 +407,12 @@ var Emitter = class {
409
407
  const extra = Predicate.isTagged(node, "WithSpan") ? `{start:${st},end:p}` : `$S.slice(${st},p)`;
410
408
  return `${st}=p;` + this.gen(node.self, true, t, fail, fn, d) + set(`[${t},${extra}]`);
411
409
  }
410
+ case "MapSpan": {
411
+ if (!used) return this.gen(node.self, false, null, fail, fn, d);
412
+ const st = this.v(fn);
413
+ const t = this.v(fn);
414
+ return `${st}=p;` + this.gen(node.self, true, t, fail, fn, d) + set(`${this.const(node.f)}(${t},${st},p)`);
415
+ }
412
416
  case "Span": {
413
417
  const st = this.v(fn);
414
418
  return `${st}=p;` + this.gen(node.self, false, null, fail, fn, d) + set(`{start:${st},end:p}`);
@@ -420,6 +424,7 @@ var Emitter = class {
420
424
  }
421
425
  case "Context":
422
426
  case "Expected":
427
+ case "Quiet":
423
428
  case "MapError":
424
429
  case "OrFail":
425
430
  case "Trace":
@@ -458,6 +463,11 @@ var Emitter = class {
458
463
  if (node.keys.includes("__proto__")) return code + `${out}={};` + node.keys.map((k, i) => `${out}[${JSON.stringify(k)}]=${vars[i]};`).join("");
459
464
  return code + `${out}={${node.keys.map((k, i) => `${JSON.stringify(k)}:${vars[i]}`).join(",")}};`;
460
465
  }
466
+ case "SeqWith": {
467
+ if (out === null) return node.parsers.map((q) => this.gen(q, false, null, fail, fn, d)).join("");
468
+ const vars = node.parsers.map(() => this.v(fn));
469
+ return node.parsers.map((q, i) => this.gen(q, true, vars[i], fail, fn, d)).join("") + `${out}=${this.const(node.f)}(${vars.join(",")});`;
470
+ }
461
471
  case "ZipWith": {
462
472
  if (out === null) return this.gen(node.self, false, null, fail, fn, d) + this.gen(node.that, false, null, fail, fn, d);
463
473
  const x = this.v(fn);
@@ -467,8 +477,13 @@ var Emitter = class {
467
477
  case "Alt": return this.alt(node, used, out, fail, fn, d);
468
478
  case "Dispatch": return this.dispatch(p, node, used, out, fail, fn, d);
469
479
  case "Repeat":
470
- case "Fold": return this.repeat(node, used, out, fail, fn, d);
480
+ case "Fold": return (out === null && Predicate.isTagged(node, "Repeat") ? this.repeatRun(p, node, fail, fn, d) : void 0) ?? this.repeat(node, used, out, fail, fn, d);
471
481
  case "Separated": return this.separated(node, used, out, fail, fn, d);
482
+ case "Fixed": {
483
+ if (this.kind !== 1) return this.delegate(p, used, out, fail, fn);
484
+ const read = used ? `${out ?? this.v(fn)}=${this.const(node.read)}(I,p,$S);` : "";
485
+ return `if(E-p>=${this.num(node.size)}){${read}p+=${this.num(node.size)}}else{${this.delegate(p, used, out, fail, fn)}}`;
486
+ }
472
487
  default: return this.delegate(p, used, out, fail, fn);
473
488
  }
474
489
  }
@@ -552,9 +567,7 @@ var Emitter = class {
552
567
  const r = out ?? this.v(fn);
553
568
  return code + `default:{$S.pos=p;${r}=${q}.step($S);if(${r}===F){${fail}}p=$S.pos;}}`;
554
569
  };
555
- let sel = nodeOf(node.selector);
556
- const peek = Predicate.isTagged(sel, "Peek");
557
- if (peek) sel = nodeOf(sel.self);
570
+ const { node: sel, peek } = selectorOf(node.selector);
558
571
  if (!Predicate.isTagged(sel, "Any") || !this.native(sel.encoding)) return general(true);
559
572
  const enc = sel.encoding;
560
573
  const r = enc === void 0 ? void 0 : this.reader(enc);
@@ -577,6 +590,57 @@ var Emitter = class {
577
590
  code += `case -1:{${BT}${fail}}default:{if(${u}<${size}){${BT}${fail}}${general(false)}}}`;
578
591
  return code;
579
592
  }
593
+ /**
594
+ * A repetition whose elements are not kept, rewritten to scan a run of a
595
+ * character set in one loop instead of one element at a time (#79):
596
+ *
597
+ * - `repeat(oneOf(S), range)` matches what `takeWhile(S, range)` matches,
598
+ * stopping, failing and reporting `Incomplete` where it does, so it
599
+ * compiles as that `takeWhile`, with the repetition's own step as the
600
+ * fallback near the end of a partial input.
601
+ * - `repeat(alt(oneOf(S), ...rest))` with `min` at most 1 and no `max`
602
+ * matches what `repeat(alt(takeWhile(S, { min: 1 }), ...rest))` matches:
603
+ * a run of `S` is a run of one-character elements, and the counts that
604
+ * differ only matter for other ranges. The first branch is a synthetic
605
+ * `takeWhile` node; outside resumable builds, which never run its step.
606
+ *
607
+ * Returns `undefined` when neither applies.
608
+ */
609
+ repeatRun(p, node, fail, fn, d) {
610
+ if (this.kind === 2) return void 0;
611
+ const element = nodeOf(node.self);
612
+ if (Predicate.isTagged(element, "OneOf") && this.native(element.encoding)) {
613
+ const { encoding, negate, set } = element;
614
+ return this.leaf(p, {
615
+ _tag: "TakeWhile",
616
+ set,
617
+ negate,
618
+ encoding,
619
+ min: node.min,
620
+ max: node.max
621
+ }, false, null, fail, fn);
622
+ }
623
+ if (this.resumable || node.min > 1 || node.max !== Infinity || !Predicate.isTagged(element, "Alt")) return void 0;
624
+ const [first, ...rest] = element.parsers;
625
+ const head = first === void 0 ? void 0 : nodeOf(first);
626
+ if (head === void 0 || !Predicate.isTagged(head, "OneOf") || !this.native(head.encoding) || Arr.isReadonlyArrayEmpty(rest)) return;
627
+ const run = synthetic({
628
+ _tag: "TakeWhile",
629
+ set: head.set,
630
+ negate: head.negate,
631
+ encoding: head.encoding,
632
+ min: 1,
633
+ max: Infinity
634
+ }, node.self.step);
635
+ const alt = synthetic({
636
+ _tag: "Alt",
637
+ parsers: [run, ...rest]
638
+ }, node.self.step);
639
+ return this.repeat({
640
+ ...node,
641
+ self: alt
642
+ }, false, null, fail, fn, d);
643
+ }
580
644
  repeat(node, used, out, fail, fn, d, collect) {
581
645
  const { max, min } = node;
582
646
  const loop = this.label();
@@ -600,14 +664,15 @@ var Emitter = class {
600
664
  add = `${acc}.push(${x});`;
601
665
  }
602
666
  }
603
- const check = max === Infinity ? `if(p===${st}){$S.mode="Cut";${fail}}` : "";
604
- const bound = max === Infinity ? "" : `${n}<${max}`;
667
+ const check = `if(p===${st}){$S.mode="Cut";${fail}}`;
668
+ const bound = max === Infinity ? "" : `${n}<${this.num(max)}`;
605
669
  const r = this.resumable ? this.resumePoint(fn) : void 0;
606
- const save = r === void 0 ? "" : `if($S.mode==="Incomplete"&&$S.resume!==void 0)R.save($S,${r.key},${r.entry},{acc:${acc},count:${n},pos:${st}});`;
670
+ const held = collect?.value ?? acc;
671
+ const save = r === void 0 ? "" : `if($S.mode==="Incomplete"&&$S.resume!==void 0)R.save($S,${r.key},${r.entry},{acc:${held},${collect?.saved ?? ""}count:${n},pos:${st}});`;
607
672
  const element = collect === void 0 ? `${this.gen(node.self, tracked, x, `break ${bad};`, fn, d)}${check}${add}` : collect.element(`break ${bad};`, check);
608
- const body = `${loop}:for(;${bound};${n}++){${cond === void 0 ? "" : `if(${min > 0 ? `${n}>=${min}&&` : ""}!${this.const(cond)}(${acc}))break ${loop};`}${st}=p;${bad}:{${element}continue ${loop};}${save}if($S.mode!=="Backtrack"${min > 0 ? `||${n}<${min}` : ""}){${fail}}p=${st};break ${loop};}`;
673
+ const body = `${loop}:for(;${bound};${n}++){${cond === void 0 ? "" : `if(${min > 0 ? `${n}>=${this.num(min)}&&` : ""}!${this.const(cond)}(${acc}))break ${loop};`}${st}=p;${bad}:{${element}continue ${loop};}${save}if($S.mode!=="Backtrack"${min > 0 ? `||${n}<${this.num(min)}` : ""}){${fail}}p=${st};break ${loop};}`;
609
674
  if (r === void 0) return `${init}${n}=0;${body}${collect?.finish ?? ""}`;
610
- return r.wrap(acc, `${acc}=cp.acc;${n}=cp.count;p=cp.pos;`, `${init}${n}=0;`, body);
675
+ return r.wrap(held, `${held}=cp.acc;${collect?.restore ?? ""}${n}=cp.count;p=cp.pos;`, `${init}${n}=0;`, `${body}${collect?.finish ?? ""}`);
611
676
  }
612
677
  /**
613
678
  * In a resumable build, a repetition entered at `entry` may restart from a
@@ -638,7 +703,8 @@ var Emitter = class {
638
703
  const loop = this.label();
639
704
  const push = keep ? `${acc}.push(${x});` : "";
640
705
  const r = this.resumable ? this.resumePoint(fn) : void 0;
641
- const save = r === void 0 ? "" : `if($S.mode==="Incomplete"&&$S.resume!==void 0)R.save($S,${r.key},${r.entry},{acc:${acc},count:${n},pos:${st}});`;
706
+ const held = collect?.value ?? acc;
707
+ const save = r === void 0 ? "" : `if($S.mode==="Incomplete"&&$S.resume!==void 0)R.save($S,${r.key},${r.entry},{acc:${held},${collect?.saved ?? ""}count:${n},pos:${st}});`;
642
708
  const attempt = (body, success, fatal, checkpoint) => {
643
709
  const ok = this.label();
644
710
  const bad = this.label();
@@ -646,11 +712,11 @@ var Emitter = class {
646
712
  };
647
713
  const self = (f) => collect === void 0 ? this.gen(node.self, keep, x, f, fn, d) : collect.element(f, "");
648
714
  const sep = (f) => this.gen(node.separator, false, null, f, fn, d);
649
- const check = max === Infinity ? `if(p===${st}){$S.mode="Cut";${fail}}` : "";
715
+ const check = `if(p===${st}){$S.mode="Cut";${fail}}`;
650
716
  const first = `${collect?.init ?? (keep ? `${acc}=[];` : "")}${n}=0;${st}=p;` + attempt(self, `${push}${n}++;`, min > 0 ? "||true" : "", "");
651
- const rest = `${loop}:while(${max === Infinity ? "true" : `${n}<${max}`}){${st}=p;` + attempt(sep, "", `||${n}<${min}`, save) + check + attempt(self, `${push}${n}++;continue ${loop};`, `||${n}<${min}`, save) + `}`;
717
+ const rest = `${loop}:while(${max === Infinity ? "true" : `${n}<${this.num(max)}`}){${st}=p;` + attempt(sep, "", `||${n}<${this.num(min)}`, save) + check + attempt(self, `${push}${n}++;continue ${loop};`, `||${n}<${this.num(min)}`, save) + `}`;
652
718
  if (r === void 0) return `${done}:{${first}${rest}}${collect?.finish ?? ""}`;
653
- return r.wrap(acc, `${acc}=cp.acc;${n}=cp.count;p=cp.pos;`, "", `${done}:{if(!${r.resumed}){${first}}${rest}}`);
719
+ return r.wrap(held, `${held}=cp.acc;${collect?.restore ?? ""}${n}=cp.count;p=cp.pos;`, "", `${done}:{if(!${r.resumed}){${first}}${rest}}${collect?.finish ?? ""}`);
654
720
  }
655
721
  /**
656
722
  * `map(self, Object.fromEntries)`, where `buildsEntries(self)`: builds the
@@ -661,35 +727,35 @@ var Emitter = class {
661
727
  */
662
728
  entries(p, out, fail, fn, d) {
663
729
  const node = nodeOf(p);
664
- switch (node._tag) {
665
- case "Mode": {
666
- const ok = this.label();
667
- const bad = this.label();
668
- return `${ok}:{${bad}:{${this.entries(node.self, out, `break ${bad};`, fn, d)}break ${ok};}if($S.mode===${JSON.stringify(node.from)})$S.mode=${JSON.stringify(node.to)};${fail}}`;
669
- }
670
- case "Seq": {
671
- const i = node.output;
672
- return node.parsers.map((q, j) => j === i ? this.entries(q, out, fail, fn, d) : this.gen(q, false, null, fail, fn, d)).join("");
673
- }
674
- case "Repeat":
675
- case "Separated": {
676
- const pair = pairOf(node.self);
677
- if (pair === void 0) {
678
- const t = this.v(fn);
679
- return this.gen(p, true, t, fail, fn, d) + `${out}=${this.const(fromEntries)}(${t});`;
680
- }
681
- const deferred = this.v(fn);
682
- const key = this.v(fn);
683
- const value = this.v(fn);
684
- const collect = {
685
- init: `${out}={};${deferred}=void 0;`,
686
- element: (f, check) => pair.parsers.map((q, j) => this.gen(q, j === pair.key || j === pair.value, j === pair.key ? key : j === pair.value ? value : null, f, fn, d)).join("") + check + `if(${deferred}===void 0&&R.isPlainKey(${key}))${out}[${key}]=${value};else ${deferred}=R.addEntry(${out},${deferred},${key},${value});`,
687
- finish: `if(${deferred}!==void 0)R.flushEntries(${out},${deferred});`
688
- };
689
- return Predicate.isTagged(node, "Repeat") ? this.repeat(node, true, out, fail, fn, d, collect) : this.separated(node, true, out, fail, fn, d, collect);
730
+ if (Predicate.isTagged(node, "Mode")) {
731
+ const ok = this.label();
732
+ const bad = this.label();
733
+ return `${ok}:{${bad}:{${this.entries(node.self, out, `break ${bad};`, fn, d)}break ${ok};}if($S.mode===${JSON.stringify(node.from)})$S.mode=${JSON.stringify(node.to)};${fail}}`;
734
+ }
735
+ if (Predicate.isTagged(node, "Seq")) {
736
+ const i = node.output;
737
+ return node.parsers.map((q, j) => j === i ? this.entries(q, out, fail, fn, d) : this.gen(q, false, null, fail, fn, d)).join("");
738
+ }
739
+ if (Predicate.isTagged(node, "Repeat") || Predicate.isTagged(node, "Separated")) {
740
+ const pair = pairOf(node.self);
741
+ if (pair === void 0) {
742
+ const t = this.v(fn);
743
+ return this.gen(p, true, t, fail, fn, d) + `${out}=${this.const(fromEntries)}(${t});`;
690
744
  }
691
- default: return this.entries(node.self, out, fail, fn, d);
745
+ const deferred = this.v(fn);
746
+ const key = this.v(fn);
747
+ const value = this.v(fn);
748
+ const collect = {
749
+ init: `${out}={};${deferred}=void 0;`,
750
+ element: (f, check) => pair.parsers.map((q, j) => this.gen(q, j === pair.key || j === pair.value, j === pair.key ? key : j === pair.value ? value : null, f, fn, d)).join("") + check + `if(${deferred}===void 0&&R.isPlainKey(${key}))${out}[${key}]=${value};else ${deferred}=R.addEntry(${out},${deferred},${key},${value});`,
751
+ finish: `if(${deferred}!==void 0)R.flushEntries(${out},${deferred});`,
752
+ value: out,
753
+ saved: `def:${deferred},`,
754
+ restore: `${deferred}=cp.def;`
755
+ };
756
+ return Predicate.isTagged(node, "Repeat") ? this.repeat(node, true, out, fail, fn, d, collect) : this.separated(node, true, out, fail, fn, d, collect);
692
757
  }
758
+ return this.entries(node.self, out, fail, fn, d);
693
759
  }
694
760
  /** An expression: is the unit `c`, known to be below `size` (at most `TableSize`), accepted? */
695
761
  member(accept, c, size = TableSize) {
@@ -745,9 +811,10 @@ var Emitter = class {
745
811
  return this.literalUnits(Predicate.isString(encoded) ? unitsOf(encoded) : Array.from(encoded), false, fail) + set(this.lit(lit));
746
812
  }
747
813
  const literalKind = Predicate.isString(lit) ? 0 : lit instanceof Uint8Array ? 1 : 2;
748
- if (kind === 0 && literalKind !== 0) return void 0;
749
- if (literalKind === 2) return void 0;
750
- const codes = kind === 0 ? unitsOf(lit) : Array.from(literalKind === 0 ? new TextEncoder().encode(lit) : lit);
814
+ let codes;
815
+ if (Predicate.isString(lit)) codes = kind === 0 ? unitsOf(lit) : Array.from(new TextEncoder().encode(lit));
816
+ else if (kind === 1 && lit instanceof Uint8Array) codes = Array.from(lit);
817
+ else return void 0;
751
818
  const len = codes.length;
752
819
  const value = !node.caseless && literalKind === kind ? this.lit(lit) : kind === 0 ? `I.slice(p-${len},p)` : `I.subarray(p-${len},p)`;
753
820
  return this.literalUnits(codes, node.caseless, fail) + set(value);
@@ -800,9 +867,9 @@ var Emitter = class {
800
867
  const loop = this.label();
801
868
  const counted = max !== Infinity || min > 1;
802
869
  const count = counted ? `${n}++;` : "";
803
- const bound = max !== Infinity ? `&&${n}<${max}` : "";
804
- const slice = enc !== void 0 ? `${this.const(enc.text)}(I,${st},p)` : kind === 0 ? `I.slice(${st},p)` : `I.subarray(${st},p)`;
805
- const finish = (min > 0 ? `if(${counted ? n : `p-${st}`}<${min}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=${slice};`);
870
+ const bound = max !== Infinity ? `&&${n}<${this.num(max)}` : "";
871
+ const slice = enc !== void 0 ? this.text(enc, st) : kind === 0 ? `I.slice(${st},p)` : `I.subarray(${st},p)`;
872
+ const finish = (min > 0 ? `if(${counted ? n : `p-${st}`}<${this.num(min)}){${BT}${fail}}` : "") + (out === null ? "" : `${out}=${slice};`);
806
873
  const head = `${st}=p;${counted ? `${n}=0;` : ""}${loop}:while(p<E${bound}){${c}=${this.unit("p")};`;
807
874
  const member = this.member(accept, c);
808
875
  if (kind === 1 && (enc === void 0 || fastLimit(enc) >= TableSize)) return `${head}if(!(${member}))break;p++;${count}}${finish}`;
@@ -811,6 +878,8 @@ var Emitter = class {
811
878
  const guard = r.width === 1 ? "" : `${r.guard("p")}&&`;
812
879
  return `${st}=p;${counted ? `${n}=0;` : ""}${loop}:while(p<E${bound}){` + (r.fast > 0 ? `if(${guard}(${c}=${r.unit("p")})<${r.fast}){if(!${this.textAccepts(r, cs, accept, negate, c)})break ${loop};p+=${r.width}}else` : "") + `{${c}=${this.const(enc.decode)}(I,p,E);if(${c}<0||${this.textRejectsDecoded(enc, r, cs, negate, c)})break ${loop};p+=${this.const(enc.width)}(${c})}${count}}${finish}`;
813
880
  }
881
+ const stops = negate && !counted ? stopChars(cs) : void 0;
882
+ if (stops !== void 0) return this.stopSearch(stops, st, c, finish, fn);
814
883
  const fast = 55296;
815
884
  const small = TableSize;
816
885
  const highTest = (v) => this.memberHigh(cs, negate, v);
@@ -820,6 +889,21 @@ var Emitter = class {
820
889
  return `${head}if(${c}<${small}){if(!(${member}))break;p++}else ${never && !negate ? `break;` : always && !counted ? `p++;` : `if(${c}<${fast}||${c}>56319){if(!(${highTest(c)}))break ${loop};p++}else{${cp}=${c};if(p+1<I.length){const d=I.charCodeAt(p+1);if((d&64512)===56320)${cp}=((${c}-55296)<<10)+(d-56320)+65536}if(!(${highTest(cp)}))break ${loop};p+=${cp}>65535?2:1}`}${count}}${finish}`;
821
890
  }
822
891
  /**
892
+ * `Token.takeTill` on a string, of one to `MaxStops` characters that are
893
+ * whole code points: the set accepts every other unit, surrogates
894
+ * included, so the run ends at the first stop character. The first
895
+ * `SearchHead` units are tested one at a time, which beats a native
896
+ * search on short runs; a longer run ends at the next occurrence that
897
+ * `nextStop` finds with `indexOf` (#75).
898
+ */
899
+ stopSearch(stops, st, c, finish, fn) {
900
+ const h = this.v(fn);
901
+ const test = stops.map((u) => `${c}!==${u}`).join("&&");
902
+ const search = stops.length === 1 ? `{p=I.indexOf(${JSON.stringify(String.fromCharCode(stops[0]))},p);if(p<0)p=E}` : `p=R.nextStop(${this.const(new StopCache(stops.map((u) => String.fromCharCode(u))))},$S,p);`;
903
+ const head = stops.length === 1 ? SearchHead : 2 * SearchHead;
904
+ return `${st}=p;${h}=p+${head}<E?p+${head}:E;while(p<${h}&&(${c}=I.charCodeAt(p),${test}))p++;if(p===${h}&&p<E&&(${c}=I.charCodeAt(p),${test}))${search}${finish}`;
905
+ }
906
+ /**
823
907
  * `escaped`. In a resumable build it keeps the closure compiler's
824
908
  * checkpoints: where the next segment starts and, unless raw, the text
825
909
  * so far, saved when a segment or an escape runs out of input.
@@ -843,37 +927,54 @@ var Emitter = class {
843
927
  const normal = this.gen(node.normal, !raw, x, `break ${bad};`, fn, d);
844
928
  const escape = this.gen(node.escape, !raw, x, `${save(b)}${fail}`, fn, d);
845
929
  const onNormal = raw ? `if(p===${b}){$S.mode="Cut";${fail}}continue ${loop};` : `if(p!==${b}){${acc}+=${x};continue ${loop}}`;
846
- const slice = enc !== void 0 ? `${this.const(enc.text)}(I,${st},p)` : this.kind === 0 ? `I.slice(${st},p)` : `I.subarray(${st},p)`;
847
- const ctrlTest = rd === void 0 ? `p<E&&${this.unit("p")}===${ctrl}` : `${rd.guard("p")}&&${rd.unit("p")}===${ctrl}`;
930
+ const slice = enc !== void 0 ? this.text(enc, st) : this.kind === 0 ? `I.slice(${st},p)` : `I.subarray(${st},p)`;
931
+ const ctrlTest = rd === void 0 ? `p<E&&${this.unit("p")}===${this.num(ctrl)}` : `${rd.guard("p")}&&${rd.unit("p")}===${this.num(ctrl)}`;
848
932
  const stop = r === void 0 ? loop : this.label();
849
933
  const loopCode = `${loop}:while(p<E){${b}=p;${okv}=false;${bad}:{${normal}${okv}=true;}if(${okv}){${onNormal}}else{if($S.mode!=="Backtrack"){${save(b)}${fail}}p=${b}}if(${ctrlTest}){p+=${rd?.width ?? 1};${escape}${raw ? "" : `${acc}+=${x};`}}else break ${stop};}`;
850
- const body = r === void 0 ? loopCode : `${stop}:{${loopCode}if($S.partial){$S.mode="Incomplete";${save("p")}${fail}}}`;
934
+ const body = r === void 0 ? loopCode : `${stop}:{${loopCode}if($S.partial){$S.incomplete(0);${save("p")}${fail}}}`;
851
935
  if (r === void 0) return `${raw ? `${st}=p;` : `${acc}="";`}${body}${raw && out !== null ? `${out}=${slice};` : ""}`;
852
936
  if (acc !== null) return r.wrap(acc, `${acc}=cp.out;p=cp.pos;`, `${acc}="";`, body);
853
937
  const value = out ?? this.v(fn);
854
938
  return r.wrap(value, "p=cp;", "", `${body}${value}=${out === null ? "void 0" : slice};`);
855
939
  }
856
940
  };
941
+ /**
942
+ * A parser that exists only as a description, for the rewrites of
943
+ * `Emitter.repeatRun`. `step` is never run on the paths they compile (the
944
+ * token code of a native `takeWhile`, and alternatives inline), so it is
945
+ * the step of the repetition's element, which describes the same language
946
+ * when its value is unused.
947
+ */
948
+ const synthetic = (node, step) => {
949
+ return {
950
+ step,
951
+ name: void 0,
952
+ [NodeId]: node
953
+ };
954
+ };
857
955
  /** The UTF-16 code units of a string. */
858
956
  const unitsOf = (s) => Array.from({ length: s.length }, (_, i) => s.charCodeAt(i));
859
957
  /** Generates the source of a compiled parser, without building it. */
860
958
  const generate = (root, kind, resumable = false) => {
861
959
  const e = new Emitter(root, kind, resumable);
862
960
  const main = e.rule(root, true);
961
+ let closure;
962
+ const short = e.const((state) => (closure ??= createClosureCompiler(kind, resumable).compile(root, true))(state));
863
963
  return {
864
- source: `"use strict";let $I,$E,$S,P;${e.functions.join("\n")}\nreturn function run(state){const sI=$I,sE=$E,sS=$S,sP=P;$I=state.input;$E=state.end;$S=state;try{const v=${main}(state.pos);if(v!==F)state.pos=P;return v}finally{$I=sI;$E=sE;$S=sS;P=sP}}`,
964
+ source: `"use strict";let $I,$E,$S,P;${e.functions.join("\n")}\nreturn function run(state){if(state.end!==state.input.length)return ${short}(state);const sI=$I,sE=$E,sS=$S,sP=P;$I=state.input;$E=state.end;$S=state;try{const v=${main}(state.pos);if(v!==F)state.pos=P;return v}catch(e){if(!R.isStackOverflow(e))throw e;return R.tooDeep(state)}finally{$I=sI;$E=sE;$S=sS;P=sP}}`,
865
965
  constants: e.constants,
866
966
  fallbacks: e.fallbacks
867
967
  };
868
968
  };
869
- /** Compiles a root parser for one input kind with `new Function`. */
969
+ /**
970
+ * Compiles a root parser for one input kind with `new Function`. The step
971
+ * is the generated entry, which handles every state and reports call-stack
972
+ * overflows itself.
973
+ */
870
974
  const compileJit = (root, kind, resumable = false) => {
871
975
  const { constants, fallbacks, source } = generate(root, kind, resumable);
872
- const run = globalThis.Function("C", "F", "R", source)(constants, Fail, runtime);
873
- let closure;
874
- const step = (state) => state.end === state.input.length ? run(state) : (closure ??= createClosureCompiler(kind, resumable).compile(root, true))(state);
875
976
  return {
876
- step,
977
+ step: globalThis.Function("C", "F", "R", source)(constants, Fail, runtime),
877
978
  fallbacks,
878
979
  source
879
980
  };
@@ -888,6 +989,7 @@ const backend = { build: (p, kind, resumable) => {
888
989
  onSuccess: ({ fallbacks, source, step }) => ({
889
990
  backend: "jit",
890
991
  step,
992
+ guarded: true,
891
993
  fallbacks,
892
994
  error: void 0,
893
995
  source
@@ -898,6 +1000,6 @@ const backend = { build: (p, kind, resumable) => {
898
1000
  })
899
1001
  });
900
1002
  } };
901
- export { backend };
1003
+ export { backend, jitSupported };
902
1004
 
903
1005
  //# sourceMappingURL=jit.js.map