parseman 0.46.0 → 0.47.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 (316) hide show
  1. package/README.md +8 -3
  2. package/dist/analysis/choice-cost-render.d.ts +12 -4
  3. package/dist/analysis/choice-cost-render.d.ts.map +1 -1
  4. package/dist/analysis/choice-cost.d.ts +2 -2
  5. package/dist/analysis/choice-cost.d.ts.map +1 -1
  6. package/dist/analysis/commitment.d.ts +131 -0
  7. package/dist/analysis/commitment.d.ts.map +1 -0
  8. package/dist/analysis/diagnostics.cjs +9929 -7465
  9. package/dist/analysis/diagnostics.cjs.map +3 -4
  10. package/dist/analysis/diagnostics.d.ts +2 -2
  11. package/dist/analysis/diagnostics.js +9929 -7465
  12. package/dist/analysis/diagnostics.js.map +3 -4
  13. package/dist/analysis/duplication.d.ts.map +1 -1
  14. package/dist/analysis/fix.d.ts +3 -3
  15. package/dist/analysis/fix.d.ts.map +1 -1
  16. package/dist/analysis/format-number.d.ts +23 -0
  17. package/dist/analysis/format-number.d.ts.map +1 -0
  18. package/dist/analysis/gating.d.ts +39 -2
  19. package/dist/analysis/gating.d.ts.map +1 -1
  20. package/dist/analysis/rebuild.d.ts.map +1 -1
  21. package/dist/analysis/terminal.d.ts +5 -2
  22. package/dist/analysis/terminal.d.ts.map +1 -1
  23. package/dist/cli/index.cjs +10865 -8535
  24. package/dist/cli/index.cjs.map +3 -4
  25. package/dist/cli/index.js +10865 -8535
  26. package/dist/cli/index.js.map +3 -4
  27. package/dist/combinators/adjacency.d.ts +100 -0
  28. package/dist/combinators/adjacency.d.ts.map +1 -0
  29. package/dist/combinators/choice.d.ts.map +1 -1
  30. package/dist/combinators/completions.d.ts.map +1 -1
  31. package/dist/combinators/dispatch.d.ts +8 -1
  32. package/dist/combinators/dispatch.d.ts.map +1 -1
  33. package/dist/combinators/expect.d.ts.map +1 -1
  34. package/dist/combinators/first-set.d.ts.map +1 -1
  35. package/dist/combinators/gate.d.ts.map +1 -1
  36. package/dist/combinators/grammar.d.ts +22 -0
  37. package/dist/combinators/grammar.d.ts.map +1 -1
  38. package/dist/combinators/literal.d.ts +8 -0
  39. package/dist/combinators/literal.d.ts.map +1 -1
  40. package/dist/combinators/map.d.ts +0 -1
  41. package/dist/combinators/map.d.ts.map +1 -1
  42. package/dist/combinators/node.d.ts +13 -3
  43. package/dist/combinators/node.d.ts.map +1 -1
  44. package/dist/combinators/parser.d.ts +1 -1
  45. package/dist/combinators/parser.d.ts.map +1 -1
  46. package/dist/combinators/ref.d.ts.map +1 -1
  47. package/dist/combinators/regex.d.ts +1 -16
  48. package/dist/combinators/regex.d.ts.map +1 -1
  49. package/dist/combinators/repeat.d.ts +30 -2
  50. package/dist/combinators/repeat.d.ts.map +1 -1
  51. package/dist/combinators/scanTo.d.ts +71 -1
  52. package/dist/combinators/scanTo.d.ts.map +1 -1
  53. package/dist/combinators/sequence.d.ts.map +1 -1
  54. package/dist/combinators/token.d.ts.map +1 -1
  55. package/dist/combinators/trivia-boundary.d.ts +26 -0
  56. package/dist/combinators/trivia-boundary.d.ts.map +1 -0
  57. package/dist/combinators/trivia-skip.d.ts +40 -1
  58. package/dist/combinators/trivia-skip.d.ts.map +1 -1
  59. package/dist/combinators/withCtx.d.ts.map +1 -1
  60. package/dist/compiler/compile-linkable-table.d.ts +104 -0
  61. package/dist/compiler/compile-linkable-table.d.ts.map +1 -0
  62. package/dist/compiler/degradation.d.ts +0 -2
  63. package/dist/compiler/degradation.d.ts.map +1 -1
  64. package/dist/compiler/fields.d.ts +13 -0
  65. package/dist/compiler/fields.d.ts.map +1 -1
  66. package/dist/compiler/grammar-coverage-ids.d.ts +5 -5
  67. package/dist/compiler/grammar-coverage-ids.d.ts.map +1 -1
  68. package/dist/compiler/ir-serialize.d.ts.map +1 -1
  69. package/dist/compiler/linker.d.ts +47 -53
  70. package/dist/compiler/linker.d.ts.map +1 -1
  71. package/dist/compiler/token-alphabet.d.ts +81 -0
  72. package/dist/compiler/token-alphabet.d.ts.map +1 -0
  73. package/dist/compiler/token-dispatch.d.ts +95 -0
  74. package/dist/compiler/token-dispatch.d.ts.map +1 -0
  75. package/dist/compiler/token-scanner.d.ts +53 -0
  76. package/dist/compiler/token-scanner.d.ts.map +1 -0
  77. package/dist/compiler/value-usage.d.ts.map +1 -1
  78. package/dist/coverage.d.ts +1 -1
  79. package/dist/coverage.d.ts.map +1 -1
  80. package/dist/cst/capture-buffer.d.ts +35 -0
  81. package/dist/cst/capture-buffer.d.ts.map +1 -1
  82. package/dist/cst/reflection-attach.d.ts +8 -0
  83. package/dist/cst/reflection-attach.d.ts.map +1 -0
  84. package/dist/cst/reflection-symbols.d.ts +10 -0
  85. package/dist/cst/reflection-symbols.d.ts.map +1 -0
  86. package/dist/cst/reflection.d.ts +2 -4
  87. package/dist/cst/reflection.d.ts.map +1 -1
  88. package/dist/cst/root-trivia-scope.d.ts +26 -0
  89. package/dist/cst/root-trivia-scope.d.ts.map +1 -0
  90. package/dist/cst/trivia-charscan.d.ts +18 -0
  91. package/dist/cst/trivia-charscan.d.ts.map +1 -0
  92. package/dist/cst/trivia-kinds.d.ts +19 -0
  93. package/dist/cst/trivia-kinds.d.ts.map +1 -1
  94. package/dist/functional/doc.d.ts.map +1 -1
  95. package/dist/functional/run-tabled.d.ts +12 -0
  96. package/dist/functional/run-tabled.d.ts.map +1 -0
  97. package/dist/functional/run.d.ts +25 -42
  98. package/dist/functional/run.d.ts.map +1 -1
  99. package/dist/grammar-metadata.d.ts +3 -0
  100. package/dist/grammar-metadata.d.ts.map +1 -0
  101. package/dist/index.cjs +9224 -7203
  102. package/dist/index.cjs.map +3 -4
  103. package/dist/index.d.ts +18 -9
  104. package/dist/index.d.ts.map +1 -1
  105. package/dist/index.js +9219 -7198
  106. package/dist/index.js.map +3 -4
  107. package/dist/language-service/index.cjs +311 -121
  108. package/dist/language-service/index.cjs.map +3 -4
  109. package/dist/language-service/index.js +311 -121
  110. package/dist/language-service/index.js.map +3 -4
  111. package/dist/oracle/index.cjs.map +0 -1
  112. package/dist/oracle/index.js.map +0 -1
  113. package/dist/parse-context.d.ts +49 -0
  114. package/dist/parse-context.d.ts.map +1 -0
  115. package/dist/plugin/evaluator.d.ts +40 -1
  116. package/dist/plugin/evaluator.d.ts.map +1 -1
  117. package/dist/plugin/index.cjs +11146 -9593
  118. package/dist/plugin/index.cjs.map +3 -4
  119. package/dist/plugin/index.d.ts.map +1 -1
  120. package/dist/plugin/index.js +11146 -9593
  121. package/dist/plugin/index.js.map +3 -4
  122. package/dist/regex/classes.d.ts +28 -0
  123. package/dist/regex/classes.d.ts.map +1 -1
  124. package/dist/regex/first-set.d.ts +14 -0
  125. package/dist/regex/first-set.d.ts.map +1 -1
  126. package/dist/run/index.cjs +136 -51
  127. package/dist/run/index.cjs.map +2 -3
  128. package/dist/run/index.js +136 -51
  129. package/dist/run/index.js.map +2 -3
  130. package/dist/spec/index.cjs +2898 -1623
  131. package/dist/spec/index.cjs.map +3 -4
  132. package/dist/spec/index.js +2898 -1623
  133. package/dist/spec/index.js.map +3 -4
  134. package/dist/spec/model.d.ts +8 -0
  135. package/dist/spec/model.d.ts.map +1 -1
  136. package/dist/table/assemble.d.ts +307 -0
  137. package/dist/table/assemble.d.ts.map +1 -0
  138. package/dist/table/cell.d.ts +42 -0
  139. package/dist/table/cell.d.ts.map +1 -0
  140. package/dist/table/child-slots.d.ts +30 -0
  141. package/dist/table/child-slots.d.ts.map +1 -0
  142. package/dist/table/compile-rule-map.d.ts +136 -0
  143. package/dist/table/compile-rule-map.d.ts.map +1 -0
  144. package/dist/table/compile.d.ts +56 -0
  145. package/dist/table/compile.d.ts.map +1 -0
  146. package/dist/table/duplication-hook.d.ts +32 -0
  147. package/dist/table/duplication-hook.d.ts.map +1 -0
  148. package/dist/table/emit-assembly.d.ts +139 -0
  149. package/dist/table/emit-assembly.d.ts.map +1 -0
  150. package/dist/table/emit.d.ts +113 -0
  151. package/dist/table/emit.d.ts.map +1 -0
  152. package/dist/table/encode-baseline.d.ts +16 -0
  153. package/dist/table/encode-baseline.d.ts.map +1 -0
  154. package/dist/table/encode.d.ts +71 -0
  155. package/dist/table/encode.d.ts.map +1 -0
  156. package/dist/table/exec-baseline.d.ts +9 -0
  157. package/dist/table/exec-baseline.d.ts.map +1 -0
  158. package/dist/table/exec.d.ts +72 -0
  159. package/dist/table/exec.d.ts.map +1 -0
  160. package/dist/table/fold.d.ts +25 -0
  161. package/dist/table/fold.d.ts.map +1 -0
  162. package/dist/table/index.cjs +11375 -0
  163. package/dist/table/index.cjs.map +6 -0
  164. package/dist/table/index.d.ts +100 -0
  165. package/dist/table/index.d.ts.map +1 -0
  166. package/dist/table/index.js +11352 -0
  167. package/dist/table/index.js.map +6 -0
  168. package/dist/table/inspect.d.ts +17 -0
  169. package/dist/table/inspect.d.ts.map +1 -0
  170. package/dist/table/ops.d.ts +446 -0
  171. package/dist/table/ops.d.ts.map +1 -0
  172. package/dist/table/program.d.ts +493 -0
  173. package/dist/table/program.d.ts.map +1 -0
  174. package/dist/table/run-support.d.ts +38 -0
  175. package/dist/table/run-support.d.ts.map +1 -0
  176. package/dist/{compiler/scannable-run.d.ts → table/scan-shapes.d.ts} +14 -13
  177. package/dist/table/scan-shapes.d.ts.map +1 -0
  178. package/dist/table/site-labels.d.ts +58 -0
  179. package/dist/table/site-labels.d.ts.map +1 -0
  180. package/dist/table/stamp.d.ts +70 -0
  181. package/dist/table/stamp.d.ts.map +1 -0
  182. package/dist/types.d.ts +80 -24
  183. package/dist/types.d.ts.map +1 -1
  184. package/dist/version.d.ts +1 -1
  185. package/package.json +25 -2
  186. package/src/analysis/choice-cost-gate.ts +359 -0
  187. package/src/analysis/choice-cost-render.ts +293 -0
  188. package/src/analysis/choice-cost.ts +1008 -0
  189. package/src/analysis/commitment.ts +557 -0
  190. package/src/analysis/corpus.ts +130 -0
  191. package/src/analysis/diagnose-render.ts +625 -0
  192. package/src/analysis/diagnose.ts +317 -0
  193. package/src/analysis/diagnostics.ts +33 -0
  194. package/src/analysis/duplication.ts +1955 -0
  195. package/src/analysis/fix-render.ts +217 -0
  196. package/src/analysis/fix.ts +669 -0
  197. package/src/analysis/format-number.ts +31 -0
  198. package/src/analysis/gating.ts +792 -0
  199. package/src/analysis/grammar.ts +72 -0
  200. package/src/analysis/rebuild.ts +287 -0
  201. package/src/analysis/terminal.ts +336 -0
  202. package/src/cli/index.ts +413 -0
  203. package/src/combinators/adjacency.ts +171 -0
  204. package/src/combinators/attempt.ts +41 -0
  205. package/src/combinators/case-fold.ts +90 -0
  206. package/src/combinators/choice.ts +466 -0
  207. package/src/combinators/completions.ts +64 -0
  208. package/src/combinators/dispatch.ts +358 -0
  209. package/src/combinators/expect.ts +159 -0
  210. package/src/combinators/first-set.ts +322 -0
  211. package/src/combinators/gate.ts +50 -0
  212. package/src/combinators/grammar.ts +272 -0
  213. package/src/combinators/keywords.ts +145 -0
  214. package/src/combinators/literal.ts +102 -0
  215. package/src/combinators/map.ts +106 -0
  216. package/src/combinators/node.ts +345 -0
  217. package/src/combinators/not.ts +55 -0
  218. package/src/combinators/parser.ts +266 -0
  219. package/src/combinators/peek.ts +63 -0
  220. package/src/combinators/probe.ts +25 -0
  221. package/src/combinators/ref.ts +109 -0
  222. package/src/combinators/regex.ts +170 -0
  223. package/src/combinators/repeat.ts +561 -0
  224. package/src/combinators/scanTo.ts +393 -0
  225. package/src/combinators/sequence.ts +221 -0
  226. package/src/combinators/token.ts +120 -0
  227. package/src/combinators/trivia-boundary.ts +48 -0
  228. package/src/combinators/trivia-skip.ts +821 -0
  229. package/src/combinators/withCtx.ts +45 -0
  230. package/src/compiler/build-arity.ts +330 -0
  231. package/src/compiler/compile-linkable-table.ts +209 -0
  232. package/src/compiler/degradation.ts +266 -0
  233. package/src/compiler/fields.ts +191 -0
  234. package/src/compiler/grammar-coverage-ids.ts +129 -0
  235. package/src/compiler/ir-serialize.ts +615 -0
  236. package/src/compiler/linker.ts +954 -0
  237. package/src/compiler/token-alphabet.ts +209 -0
  238. package/src/compiler/token-dispatch.ts +353 -0
  239. package/src/compiler/token-scanner.ts +318 -0
  240. package/src/compiler/value-usage.ts +147 -0
  241. package/src/coverage.ts +383 -0
  242. package/src/cst/capture-buffer.ts +297 -0
  243. package/src/cst/host-mode.ts +69 -0
  244. package/src/cst/reflection-attach.ts +11 -0
  245. package/src/cst/reflection-symbols.ts +9 -0
  246. package/src/cst/reflection.ts +149 -0
  247. package/src/cst/relative-spans.ts +207 -0
  248. package/src/cst/root-trivia-scope.ts +30 -0
  249. package/src/cst/trivia-charscan.ts +312 -0
  250. package/src/cst/trivia-entries.ts +285 -0
  251. package/src/cst/trivia-index.ts +131 -0
  252. package/src/cst/trivia-kinds.ts +358 -0
  253. package/src/cst/types.ts +76 -0
  254. package/src/cst/walk.ts +101 -0
  255. package/src/functional/doc.ts +959 -0
  256. package/src/functional/run-tabled.ts +153 -0
  257. package/src/functional/run.ts +558 -0
  258. package/src/grammar-metadata.ts +2 -0
  259. package/src/index.ts +189 -0
  260. package/src/language-service/index.ts +221 -0
  261. package/src/line-index.ts +131 -0
  262. package/src/oracle/digest.ts +620 -0
  263. package/src/oracle/index.ts +55 -0
  264. package/src/parse-context.ts +91 -0
  265. package/src/plugin/direct-builder-static.ts +102 -0
  266. package/src/plugin/evaluator.ts +1505 -0
  267. package/src/plugin/free-identifiers.ts +338 -0
  268. package/src/plugin/index.ts +2281 -0
  269. package/src/plugin/reducer-resolver.ts +606 -0
  270. package/src/recovery/scan.ts +155 -0
  271. package/src/regex/classes.ts +183 -0
  272. package/src/regex/first-set.ts +316 -0
  273. package/src/run/index.ts +31 -0
  274. package/src/spec/ebnf.ts +128 -0
  275. package/src/spec/index.ts +54 -0
  276. package/src/spec/model.ts +636 -0
  277. package/src/spec/railroad-lib.ts +559 -0
  278. package/src/spec/railroad.ts +256 -0
  279. package/src/table/assemble.ts +2994 -0
  280. package/src/table/cell.ts +42 -0
  281. package/src/table/child-slots.ts +113 -0
  282. package/src/table/compile-rule-map.ts +336 -0
  283. package/src/table/compile.ts +244 -0
  284. package/src/table/duplication-hook.ts +89 -0
  285. package/src/table/emit-assembly.ts +1766 -0
  286. package/src/table/emit.ts +418 -0
  287. package/src/table/encode-baseline.ts +340 -0
  288. package/src/table/encode.ts +1569 -0
  289. package/src/table/exec-baseline.ts +537 -0
  290. package/src/table/exec.ts +1672 -0
  291. package/src/table/fold.ts +38 -0
  292. package/src/table/index.ts +108 -0
  293. package/src/table/inspect.ts +52 -0
  294. package/src/table/ops.ts +459 -0
  295. package/src/table/program.ts +855 -0
  296. package/src/table/run-support.ts +66 -0
  297. package/src/table/scan-shapes.ts +1578 -0
  298. package/src/table/site-labels.ts +228 -0
  299. package/src/table/stamp.ts +229 -0
  300. package/src/types.ts +563 -0
  301. package/src/version.ts +16 -0
  302. package/dist/compiler/codegen.d.ts +0 -334
  303. package/dist/compiler/codegen.d.ts.map +0 -1
  304. package/dist/compiler/inline-build.d.ts +0 -11
  305. package/dist/compiler/inline-build.d.ts.map +0 -1
  306. package/dist/compiler/inline-callback.d.ts +0 -21
  307. package/dist/compiler/inline-callback.d.ts.map +0 -1
  308. package/dist/compiler/line-index.d.ts +0 -2
  309. package/dist/compiler/line-index.d.ts.map +0 -1
  310. package/dist/compiler/module-hoist.d.ts +0 -106
  311. package/dist/compiler/module-hoist.d.ts.map +0 -1
  312. package/dist/compiler/scannable-run.d.ts.map +0 -1
  313. package/dist/compiler/scannable-terminal.d.ts +0 -23
  314. package/dist/compiler/scannable-terminal.d.ts.map +0 -1
  315. package/dist/compiler/trivia-fast-path.d.ts +0 -38
  316. package/dist/compiler/trivia-fast-path.d.ts.map +0 -1
@@ -0,0 +1,91 @@
1
+ import type { ParseContext } from './types.ts'
2
+
3
+ /**
4
+ * THE canonical `ParseContext` literal — the only place in the runtime where one
5
+ * is constructed from scratch.
6
+ *
7
+ * `ctx` is threaded through every combinator call, so it is the single most
8
+ * megamorphism-sensitive object in the system: every `ctx.<field>` load in
9
+ * `choice`/`sequence`/`regex`/`node`/… is an inline cache keyed on its hidden
10
+ * class. Historically the entry points built `ctx` with CONDITIONAL SPREADS
11
+ * (`...(cond ? { x } : {})`), which is a shape hazard, not a cost-free idiom:
12
+ *
13
+ * - `run()` had SIX of them (root trivia, grammar trivia, scan-skip, capture
14
+ * mask, tolerant, instrumentation) — up to 2^6 distinct hidden classes for
15
+ * `ctx` across configurations, all landing on the same ICs.
16
+ * - Fields that appear only inside a spread are ABSENT from the map on the
17
+ * paths that don't take the branch. That is why `ctx._triviaLog = undefined`
18
+ * is not free there: it is a property ADD (a map transition), not a store.
19
+ * And it is why `delete ctx._triviaLog` is expensive on the paths where the
20
+ * field IS present: a transition to dictionary mode.
21
+ *
22
+ * Declaring every field unconditionally — `undefined` when unset — collapses
23
+ * that to ONE realised map. Clearing a field is then a plain in-object store to
24
+ * an existing slot on every path, so `delete` is never needed and neither
25
+ * operation can transition the map.
26
+ *
27
+ * This is safe because absence and `undefined` are already interchangeable
28
+ * throughout the runtime: every reader tests `!== undefined` or truthiness, and
29
+ * none uses `in`, `hasOwnProperty`, or `Object.keys` on a `ParseContext`.
30
+ * `recovery/scan.ts` already restores these exact fields by assigning the saved
31
+ * value, which is `undefined` when the field was absent.
32
+ *
33
+ * Callers assign what they need AFTER construction; because every slot already
34
+ * exists those are in-object stores, and the shape is preserved. Do NOT
35
+ * reintroduce a conditional spread, and do NOT add a field here without also
36
+ * declaring it on `ParseContext`.
37
+ *
38
+ * Key ORDER matters as much as the key set — two literals with the same keys in
39
+ * a different order are two different maps — which is why there is one literal
40
+ * and not one per call site. It follows the declaration order of `ParseContext`.
41
+ */
42
+ export function createParseContext(): ParseContext {
43
+ return {
44
+ trivia: undefined,
45
+ scanSkip: undefined,
46
+ triviaKindLabels: undefined,
47
+ captureTrivia: undefined,
48
+ _triviaCaptureMask: undefined,
49
+ trackLines: false,
50
+ state: undefined,
51
+ build: undefined,
52
+ _errors: undefined,
53
+ _tolerant: undefined,
54
+ _sync: undefined,
55
+ _rec: undefined,
56
+ _fe: undefined,
57
+ _fx: undefined,
58
+ _fc: undefined,
59
+ _probe: undefined,
60
+ _cstChildren: undefined,
61
+ _cstLeaves: undefined,
62
+ _cstRawChildren: undefined,
63
+ _triviaLog: undefined,
64
+ _rootTriviaLog: undefined,
65
+ _rootTriviaKindIndex: undefined,
66
+ _rootTriviaStrictScopes: undefined,
67
+ _rootTriviaCapture: undefined,
68
+ _cstTriviaLog: undefined,
69
+ _fields: undefined,
70
+ _cstBuf: undefined,
71
+ _routed: undefined,
72
+ _lineStarts: undefined,
73
+ _lineIndex: undefined,
74
+ _lineScannedTo: undefined,
75
+ _grammarCoverage: undefined,
76
+ _grammarTrace: undefined,
77
+ }
78
+ }
79
+
80
+ /**
81
+ * A `ctx` for a THROWAWAY sub-parse that must not inherit or pollute any sink —
82
+ * the trailing-trivia probe in `run()`/`doc()`, the trivia-kind classifier, and
83
+ * the no-capture trivia parses in `trivia-skip`. Identical shape to
84
+ * `createParseContext()`; only `trackLines`/`state` are seeded.
85
+ */
86
+ export function createDetachedParseContext(trackLines: boolean, state: unknown): ParseContext {
87
+ const ctx = createParseContext()
88
+ ctx.trackLines = trackLines
89
+ ctx.state = state
90
+ return ctx
91
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Build-time validation for a direct node builder that may cross a compiled
3
+ * artifact boundary. This module deliberately belongs to the macro plugin: the
4
+ * public parser/compiler runtime must not import Oxc or its platform bindings.
5
+ */
6
+ import { parseSync } from 'oxc-parser'
7
+
8
+ const STATIC_BUILDER_GLOBALS = new Set([
9
+ 'Array', 'Boolean', 'Date', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'String',
10
+ 'Infinity', 'parseFloat', 'parseInt', 'undefined',
11
+ ])
12
+
13
+ type Ast = { type: string; [key: string]: unknown }
14
+
15
+ function astArray(value: unknown): Ast[] {
16
+ return Array.isArray(value) ? value as Ast[] : []
17
+ }
18
+
19
+ function astChild(value: unknown): Ast | null {
20
+ return value !== null && typeof value === 'object' && !Array.isArray(value)
21
+ ? value as Ast
22
+ : null
23
+ }
24
+
25
+ function unwrapCallbackExpression(node: Ast | undefined): Ast | undefined {
26
+ let current = node
27
+ while (current?.type === 'ParenthesizedExpression') current = astChild(current.expression) ?? undefined
28
+ return current
29
+ }
30
+
31
+ /**
32
+ * Return lexical reads that cannot cross an artifact boundary. This is an Oxc
33
+ * AST binding check, never a source-text heuristic: property names and plain
34
+ * object keys are not lexical reads. The result becomes inert metadata on the
35
+ * macro-produced node and is enforced later by the runtime IR re-lowerer.
36
+ */
37
+ export function directBuilderUnsupportedBindings(src: string): string[] {
38
+ let init: Ast | undefined
39
+ try {
40
+ const parsed = parseSync('parseman-direct-builder.ts', `const _direct = (${src})`)
41
+ if (parsed.errors.length > 0) return ['invalid callback source']
42
+ const program = parsed.program as unknown as Ast
43
+ const statement = (program.body as Ast[] | undefined)?.[0]
44
+ const declaration = (statement?.declarations as Ast[] | undefined)?.[0]
45
+ init = unwrapCallbackExpression(declaration?.init as Ast | undefined)
46
+ } catch {
47
+ return ['invalid callback source']
48
+ }
49
+ if (init?.type !== 'ArrowFunctionExpression' || !Array.isArray(init.params)) return ['unsupported callback shape']
50
+ const allowed = new Set(STATIC_BUILDER_GLOBALS)
51
+ for (const param of init.params as Ast[]) {
52
+ if (param.type !== 'Identifier' || typeof param.name !== 'string') return ['unsupported parameter pattern']
53
+ allowed.add(param.name)
54
+ }
55
+ const unsupported = new Set<string>()
56
+ const reportUnsupportedNode = (ast: Ast): void => { unsupported.add(`unsupported ${ast.type}`) }
57
+ const read = (ast: Ast, allowedNames: ReadonlySet<string>): void => {
58
+ if (typeof ast.name === 'string' && allowedNames.has(ast.name)) return
59
+ unsupported.add(typeof ast.name === 'string' ? ast.name : 'identifier')
60
+ }
61
+ const expression = (node: unknown, allowedNames: ReadonlySet<string>): void => {
62
+ const ast = astChild(node)
63
+ if (!ast) return
64
+ switch (ast.type) {
65
+ case 'Literal': return
66
+ case 'Identifier': read(ast, allowedNames); return
67
+ case 'ParenthesizedExpression': case 'ChainExpression': case 'TSAsExpression':
68
+ case 'TSTypeAssertion': case 'TSNonNullExpression': expression(ast.expression, allowedNames); return
69
+ case 'ArrayExpression': for (const element of astArray(ast.elements)) expression(element, allowedNames); return
70
+ case 'ObjectExpression':
71
+ for (const property of astArray(ast.properties)) {
72
+ if (property.type === 'SpreadElement') { expression(property.argument, allowedNames); continue }
73
+ if (property.type !== 'Property' || property.method === true || property.kind !== 'init') { reportUnsupportedNode(property); continue }
74
+ if (property.computed === true) expression(property.key, allowedNames)
75
+ expression(property.value, allowedNames)
76
+ }
77
+ return
78
+ case 'MemberExpression': expression(ast.object, allowedNames); if (ast.computed === true) expression(ast.property, allowedNames); return
79
+ case 'CallExpression': case 'NewExpression': expression(ast.callee, allowedNames); for (const argument of astArray(ast.arguments)) expression(argument, allowedNames); return
80
+ case 'UnaryExpression': case 'UpdateExpression': expression(ast.argument, allowedNames); return
81
+ case 'BinaryExpression': case 'LogicalExpression': case 'AssignmentExpression': expression(ast.left, allowedNames); expression(ast.right, allowedNames); return
82
+ case 'ConditionalExpression': expression(ast.test, allowedNames); expression(ast.consequent, allowedNames); expression(ast.alternate, allowedNames); return
83
+ case 'SequenceExpression': for (const value of astArray(ast.expressions)) expression(value, allowedNames); return
84
+ case 'TemplateLiteral': for (const value of astArray(ast.expressions)) expression(value, allowedNames); return
85
+ case 'SpreadElement': expression(ast.argument, allowedNames); return
86
+ case 'ArrowFunctionExpression': {
87
+ const nested = new Set(allowedNames)
88
+ for (const param of astArray(ast.params)) {
89
+ if (param.type !== 'Identifier' || typeof param.name !== 'string') { reportUnsupportedNode(param); continue }
90
+ nested.add(param.name)
91
+ }
92
+ if (astChild(ast.body)?.type === 'BlockStatement') { reportUnsupportedNode(astChild(ast.body)!); return }
93
+ expression(ast.body, nested)
94
+ return
95
+ }
96
+ default: reportUnsupportedNode(ast); return
97
+ }
98
+ }
99
+ if (astChild(init.body)?.type === 'BlockStatement') unsupported.add('unsupported BlockStatement')
100
+ else expression(init.body, allowed)
101
+ return [...unsupported]
102
+ }