@thomasfosterau/effect-parse 0.4.1 → 0.5.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 (143) hide show
  1. package/README.md +37 -13
  2. package/dist/Ascii.d.ts +11 -4
  3. package/dist/Ascii.d.ts.map +1 -1
  4. package/dist/Ascii.js +7 -1
  5. package/dist/Ascii.js.map +1 -1
  6. package/dist/Binary.d.ts.map +1 -1
  7. package/dist/Binary.js +64 -35
  8. package/dist/Binary.js.map +1 -1
  9. package/dist/Bits.d.ts.map +1 -1
  10. package/dist/Bits.js +7 -4
  11. package/dist/Bits.js.map +1 -1
  12. package/dist/Compiler.d.ts +74 -2
  13. package/dist/Compiler.d.ts.map +1 -1
  14. package/dist/Compiler.js +78 -1
  15. package/dist/Compiler.js.map +1 -1
  16. package/dist/Expression.d.ts.map +1 -1
  17. package/dist/Expression.js +86 -74
  18. package/dist/Expression.js.map +1 -1
  19. package/dist/Input.d.ts +37 -4
  20. package/dist/Input.d.ts.map +1 -1
  21. package/dist/Input.js +42 -0
  22. package/dist/Input.js.map +1 -1
  23. package/dist/Nom.d.ts +5 -15
  24. package/dist/Nom.d.ts.map +1 -1
  25. package/dist/Nom.js.map +1 -1
  26. package/dist/ParseError.d.ts.map +1 -1
  27. package/dist/ParseError.js.map +1 -1
  28. package/dist/Parser.d.ts +366 -26
  29. package/dist/Parser.d.ts.map +1 -1
  30. package/dist/Parser.js +390 -19
  31. package/dist/Parser.js.map +1 -1
  32. package/dist/ParserSchema.js +1 -1
  33. package/dist/ParserStream.d.ts +3 -2
  34. package/dist/ParserStream.d.ts.map +1 -1
  35. package/dist/ParserStream.js +13 -9
  36. package/dist/ParserStream.js.map +1 -1
  37. package/dist/Syntax.d.ts +23 -5
  38. package/dist/Syntax.d.ts.map +1 -1
  39. package/dist/Syntax.js.map +1 -1
  40. package/dist/Text.d.ts.map +1 -1
  41. package/dist/Text.js +9 -9
  42. package/dist/Text.js.map +1 -1
  43. package/dist/Token.d.ts +55 -10
  44. package/dist/Token.d.ts.map +1 -1
  45. package/dist/Token.js +59 -21
  46. package/dist/Token.js.map +1 -1
  47. package/dist/internal/compiler/closure.d.ts.map +1 -1
  48. package/dist/internal/compiler/closure.js +257 -97
  49. package/dist/internal/compiler/closure.js.map +1 -1
  50. package/dist/internal/compiler/entries.d.ts +3 -1
  51. package/dist/internal/compiler/entries.d.ts.map +1 -1
  52. package/dist/internal/compiler/entries.js +3 -2
  53. package/dist/internal/compiler/entries.js.map +1 -1
  54. package/dist/internal/compiler/first.d.ts.map +1 -1
  55. package/dist/internal/compiler/first.js +7 -1
  56. package/dist/internal/compiler/first.js.map +1 -1
  57. package/dist/internal/compiler/graph.d.ts +17 -0
  58. package/dist/internal/compiler/graph.d.ts.map +1 -0
  59. package/dist/internal/compiler/graph.js +56 -0
  60. package/dist/internal/compiler/graph.js.map +1 -0
  61. package/dist/internal/compiler/jit.d.ts +5 -0
  62. package/dist/internal/compiler/jit.d.ts.map +1 -1
  63. package/dist/internal/compiler/jit.js +185 -96
  64. package/dist/internal/compiler/jit.js.map +1 -1
  65. package/dist/internal/compiler/registry.d.ts +10 -2
  66. package/dist/internal/compiler/registry.d.ts.map +1 -1
  67. package/dist/internal/compiler/registry.js.map +1 -1
  68. package/dist/internal/compiler/search.d.ts +32 -0
  69. package/dist/internal/compiler/search.d.ts.map +1 -0
  70. package/dist/internal/compiler/search.js +68 -0
  71. package/dist/internal/compiler/search.js.map +1 -0
  72. package/dist/internal/compiler/sets.d.ts.map +1 -1
  73. package/dist/internal/compiler/sets.js +1 -1
  74. package/dist/internal/compiler/sets.js.map +1 -1
  75. package/dist/internal/compiler/wasm.d.ts +8 -0
  76. package/dist/internal/compiler/wasm.d.ts.map +1 -0
  77. package/dist/internal/compiler/wasm.js +2769 -0
  78. package/dist/internal/compiler/wasm.js.map +1 -0
  79. package/dist/internal/compiler/wasmAsm.d.ts +199 -0
  80. package/dist/internal/compiler/wasmAsm.d.ts.map +1 -0
  81. package/dist/internal/compiler/wasmAsm.js +427 -0
  82. package/dist/internal/compiler/wasmAsm.js.map +1 -0
  83. package/dist/internal/entries.d.ts +3 -1
  84. package/dist/internal/entries.d.ts.map +1 -1
  85. package/dist/internal/entries.js.map +1 -1
  86. package/dist/internal/node.d.ts +58 -2
  87. package/dist/internal/node.d.ts.map +1 -1
  88. package/dist/internal/node.js +13 -3
  89. package/dist/internal/node.js.map +1 -1
  90. package/dist/internal/numbers.d.ts.map +1 -1
  91. package/dist/internal/numbers.js.map +1 -1
  92. package/dist/internal/run.d.ts +12 -0
  93. package/dist/internal/run.d.ts.map +1 -1
  94. package/dist/internal/run.js +51 -11
  95. package/dist/internal/run.js.map +1 -1
  96. package/dist/internal/stack.d.ts +6 -0
  97. package/dist/internal/stack.d.ts.map +1 -1
  98. package/dist/internal/stack.js +8 -2
  99. package/dist/internal/stack.js.map +1 -1
  100. package/dist/internal/syntax.d.ts +4 -4
  101. package/dist/internal/syntax.d.ts.map +1 -1
  102. package/dist/internal/syntax.js +18 -10
  103. package/dist/internal/syntax.js.map +1 -1
  104. package/dist/internal/text.d.ts +32 -0
  105. package/dist/internal/text.d.ts.map +1 -1
  106. package/dist/internal/text.js +68 -14
  107. package/dist/internal/text.js.map +1 -1
  108. package/dist/internal/tokens.d.ts +13 -0
  109. package/dist/internal/tokens.d.ts.map +1 -1
  110. package/dist/internal/tokens.js +59 -39
  111. package/dist/internal/tokens.js.map +1 -1
  112. package/package.json +5 -4
  113. package/src/Ascii.ts +42 -9
  114. package/src/Binary.ts +151 -71
  115. package/src/Bits.ts +12 -6
  116. package/src/Compiler.ts +101 -10
  117. package/src/Expression.ts +94 -81
  118. package/src/Input.ts +65 -6
  119. package/src/Nom.ts +15 -5
  120. package/src/ParseError.ts +3 -0
  121. package/src/Parser.ts +678 -127
  122. package/src/ParserStream.ts +37 -18
  123. package/src/Syntax.ts +60 -36
  124. package/src/Text.ts +16 -15
  125. package/src/Token.ts +138 -29
  126. package/src/internal/compiler/closure.ts +362 -135
  127. package/src/internal/compiler/entries.ts +4 -2
  128. package/src/internal/compiler/first.ts +10 -0
  129. package/src/internal/compiler/graph.ts +68 -0
  130. package/src/internal/compiler/jit.ts +284 -154
  131. package/src/internal/compiler/registry.ts +10 -2
  132. package/src/internal/compiler/search.ts +68 -0
  133. package/src/internal/compiler/sets.ts +7 -3
  134. package/src/internal/compiler/wasm.ts +3203 -0
  135. package/src/internal/compiler/wasmAsm.ts +484 -0
  136. package/src/internal/entries.ts +8 -2
  137. package/src/internal/node.ts +54 -4
  138. package/src/internal/numbers.ts +3 -1
  139. package/src/internal/run.ts +71 -12
  140. package/src/internal/stack.ts +8 -1
  141. package/src/internal/syntax.ts +39 -18
  142. package/src/internal/text.ts +97 -9
  143. package/src/internal/tokens.ts +96 -14
@@ -11,15 +11,23 @@ import type { Fallback, Step } from "./closure.js"
11
11
 
12
12
  /** What was compiled for a parser and an input kind. */
13
13
  export interface Compiled {
14
- /** The compiler actually used. */
15
- readonly backend: "jit" | "closure" | undefined
14
+ /** The compiler actually used: `interpreted` when compilation failed. */
15
+ readonly backend: "wasm" | "jit" | "closure" | "interpreted"
16
16
  readonly step: Step | undefined
17
+ /**
18
+ * Whether `step` reports a call-stack overflow as a `TooDeep` failure
19
+ * itself, as `Stack.run` would (the JIT's generated entry does), so that
20
+ * it runs without that guard.
21
+ */
22
+ readonly guarded: boolean
17
23
  /** Parts of the grammar that run interpreted, and why. */
18
24
  readonly fallbacks: ReadonlyArray<Fallback>
19
25
  /** Why compilation failed, if it did (the parser then runs interpreted). */
20
26
  readonly error: unknown
21
27
  /** Why the JIT failed, if it did (the closure compiler is then used). */
22
28
  readonly jitError?: unknown
29
+ /** Why the WebAssembly compiler failed, if it did (the JIT is then used). */
30
+ readonly wasmError?: unknown
23
31
  /** The generated source, for the JIT. */
24
32
  readonly source?: string
25
33
  }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Searching for the stop characters of `Token.takeTill` on string input
3
+ * (#75): a run is scanned a unit at a time for `SearchHead` units, then
4
+ * found with `indexOf`, which V8 runs much faster on long runs. Both
5
+ * compilers use these; the interpreter scans unit by unit.
6
+ */
7
+ import * as Arr from "effect/Array"
8
+ import type { State } from "../../Input.js"
9
+ import type { CharSet } from "./sets.js"
10
+
11
+ /**
12
+ * How many units a compiled `takeTill` tests one at a time before it
13
+ * searches with `indexOf` (twice as many for several stop characters, whose
14
+ * cached search costs more): short runs, most tokens, are faster scanned.
15
+ */
16
+ export const SearchHead = 8
17
+
18
+ /** The most stop characters a compiled `takeTill` searches for. */
19
+ const MaxStops = 3
20
+
21
+ /**
22
+ * The stop characters of a `takeTill` set, as UTF-16 units, when there are
23
+ * one to `MaxStops` of them, each a whole code point (not a surrogate).
24
+ */
25
+ export const stopChars = (cs: CharSet): ReadonlyArray<number> | undefined => {
26
+ const ranges = cs.ranges
27
+ if (ranges === undefined || Arr.isReadonlyArrayEmpty(ranges) || ranges.length > MaxStops) return undefined
28
+ if (!ranges.every(([a, b]) => a === b && (a < 0xd800 || (a > 0xdfff && a <= 0xffff)))) return undefined
29
+ return ranges.map(([a]) => a)
30
+ }
31
+
32
+ /**
33
+ * The stop characters of one compiled `takeTill`, identifying its search site.
34
+ * The state holds, under this site, where each one next occurs (see
35
+ * `nextStop`).
36
+ */
37
+ export class StopCache {
38
+ constructor(readonly chars: ReadonlyArray<string>) {}
39
+ }
40
+
41
+ /**
42
+ * The first index from `p` of any of `site.chars` in the input of `s`, or
43
+ * `s.end`. The state remembers, for each stop character `i`, the first
44
+ * index at or after `from` where it occurs (`-1` if none), as
45
+ * `[from, at]` at `2 * i` in `s.searches.get(site)`: successive runs over
46
+ * one input then pay a comparison per stop character instead of a search,
47
+ * and one that never occurs is searched for once.
48
+ */
49
+ export const nextStop = (site: StopCache, s: State<string>, p: number): number => {
50
+ const searches = (s.searches ??= new Map())
51
+ let memo = searches.get(site)
52
+ if (memo === undefined) {
53
+ memo = site.chars.flatMap(() => [-1, -1])
54
+ searches.set(site, memo)
55
+ }
56
+ let best = s.end
57
+ for (let i = 0; i < site.chars.length; i++) {
58
+ const from = memo[2 * i]
59
+ let at = memo[2 * i + 1]
60
+ if (from < 0 || p < from || (at >= 0 && at < p)) {
61
+ at = s.input.indexOf(site.chars[i], p)
62
+ memo[2 * i] = p
63
+ memo[2 * i + 1] = at
64
+ }
65
+ if (at >= 0 && at < best) best = at
66
+ }
67
+ return best
68
+ }
@@ -7,6 +7,7 @@ import * as Order from "effect/Order"
7
7
  import * as Predicate from "effect/Predicate"
8
8
  import type { Encoding } from "../../Encoding.js"
9
9
  import { firstCodePoint } from "../text.js"
10
+ import type { TokenRangeLike } from "../tokens.js"
10
11
  import { compile, compileAny, PredicateRanges } from "../tokens.js"
11
12
 
12
13
  /** Size of the membership table: every byte, and the Latin-1 code points. */
@@ -28,8 +29,7 @@ export const acceptTable = (set: CharSet, negate: boolean): Uint8Array => {
28
29
  return t
29
30
  }
30
31
 
31
- const isRange = (u: unknown): u is { readonly from: string | number; readonly to: string | number } =>
32
- Predicate.isObjectOrArray(u) && (u as any)._tag === "TokenRange"
32
+ const isRange = (u: unknown): u is TokenRangeLike => Predicate.isObjectOrArray(u) && Predicate.isTagged(u, "TokenRange")
33
33
 
34
34
  const toCode = (u: string | number): number => (Predicate.isNumber(u) ? u : firstCodePoint(u))
35
35
 
@@ -57,7 +57,11 @@ const rangesOf = (set: unknown): Array<[number, number]> | undefined => {
57
57
  return true
58
58
  }
59
59
  if (Predicate.isFunction(u)) {
60
- const r = (u as any)[PredicateRanges] as ReadonlyArray<readonly [number, number]> | undefined
60
+ // SAFETY: `codePointPredicate` is the only writer of `PredicateRanges`, and it stores the
61
+ // predicate's sorted inclusive code point ranges there (or nothing)
62
+ const r = (u as { readonly [PredicateRanges]?: ReadonlyArray<readonly [number, number]> | undefined })[
63
+ PredicateRanges
64
+ ]
61
65
  if (r === undefined) return false
62
66
  for (const [a, b] of r) out.push([a, b])
63
67
  return true