parseman 0.48.1 → 0.50.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.
- package/dist/analysis/commitment.d.ts +2 -1
- package/dist/analysis/commitment.d.ts.map +1 -1
- package/dist/analysis/diagnostics.js +1931 -861
- package/dist/analysis/diagnostics.js.map +3 -3
- package/dist/analysis/rebuild.d.ts.map +1 -1
- package/dist/cli/index.js +1236 -164
- package/dist/cli/index.js.map +3 -3
- package/dist/combinators/trivia-skip.d.ts +1 -1
- package/dist/combinators/trivia-skip.d.ts.map +1 -1
- package/dist/compiler/build-arity.d.ts +16 -0
- package/dist/compiler/build-arity.d.ts.map +1 -1
- package/dist/compiler/degradation.d.ts +0 -2
- package/dist/compiler/degradation.d.ts.map +1 -1
- package/dist/compiler/ir-serialize.d.ts.map +1 -1
- package/dist/compiler/linker.d.ts.map +1 -1
- package/dist/compiler/token-alphabet.d.ts +11 -0
- package/dist/compiler/token-alphabet.d.ts.map +1 -1
- package/dist/compiler/token-capability.js +185 -20
- package/dist/compiler/token-capability.js.map +1 -1
- package/dist/cst/capture-buffer.d.ts +5 -1
- package/dist/cst/capture-buffer.d.ts.map +1 -1
- package/dist/index.js +1354 -278
- package/dist/index.js.map +3 -3
- package/dist/language-service/index.js +2 -1
- package/dist/language-service/index.js.map +1 -1
- package/dist/plugin/direct-builder-static.d.ts +20 -0
- package/dist/plugin/direct-builder-static.d.ts.map +1 -1
- package/dist/plugin/entry-supercompiler.d.ts +48 -0
- package/dist/plugin/entry-supercompiler.d.ts.map +1 -0
- package/dist/plugin/evaluator.d.ts +13 -0
- package/dist/plugin/evaluator.d.ts.map +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +2118 -376
- package/dist/plugin/index.js.map +3 -3
- package/dist/run/index.js +2 -1
- package/dist/run/index.js.map +1 -1
- package/dist/spec/index.js +29 -7
- package/dist/spec/index.js.map +1 -1
- package/dist/table/assemble.d.ts.map +1 -1
- package/dist/table/compile-rule-map.d.ts +6 -5
- package/dist/table/compile-rule-map.d.ts.map +1 -1
- package/dist/table/emit-assembly.d.ts +6 -1
- package/dist/table/emit-assembly.d.ts.map +1 -1
- package/dist/table/encode.d.ts.map +1 -1
- package/dist/table/index.js +1298 -231
- package/dist/table/index.js.map +3 -3
- package/dist/table/ops.d.ts +3 -2
- package/dist/table/ops.d.ts.map +1 -1
- package/dist/table/program.d.ts +15 -1
- package/dist/table/program.d.ts.map +1 -1
- package/dist/table/scalar-terminal.d.ts +30 -0
- package/dist/table/scalar-terminal.d.ts.map +1 -1
- package/dist/table/site-labels.d.ts +8 -0
- package/dist/table/site-labels.d.ts.map +1 -1
- package/dist/types.d.ts +8 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/analysis/commitment.ts +19 -8
- package/src/analysis/rebuild.ts +1 -0
- package/src/combinators/trivia-skip.ts +2 -2
- package/src/compiler/build-arity.ts +50 -0
- package/src/compiler/degradation.ts +0 -6
- package/src/compiler/ir-serialize.ts +17 -3
- package/src/compiler/linker.ts +14 -1
- package/src/compiler/token-alphabet.ts +322 -28
- package/src/cst/capture-buffer.ts +34 -11
- package/src/plugin/direct-builder-static.ts +116 -12
- package/src/plugin/entry-supercompiler.ts +567 -0
- package/src/plugin/evaluator.ts +60 -2
- package/src/plugin/index.ts +147 -4
- package/src/table/assemble.ts +125 -42
- package/src/table/compile-rule-map.ts +8 -7
- package/src/table/compile.ts +7 -8
- package/src/table/emit-assembly.ts +646 -126
- package/src/table/emit.ts +1 -1
- package/src/table/encode.ts +132 -7
- package/src/table/ops.ts +3 -2
- package/src/table/program.ts +44 -3
- package/src/table/scalar-terminal.ts +213 -1
- package/src/table/site-labels.ts +22 -9
- package/src/types.ts +1 -1
- package/src/version.ts +1 -1
|
@@ -8,6 +8,13 @@ import { parseSync } from 'oxc-parser'
|
|
|
8
8
|
const STATIC_BUILDER_GLOBALS = new Set([
|
|
9
9
|
'Array', 'Boolean', 'Date', 'JSON', 'Math', 'NaN', 'Number', 'Object', 'String',
|
|
10
10
|
'Infinity', 'parseFloat', 'parseInt', 'undefined',
|
|
11
|
+
// Frozen intrinsic error constructors. Reducers pervasively `throw new TypeError(…)`;
|
|
12
|
+
// once the statement walker walks a `throw` argument these surface as free names, and
|
|
13
|
+
// refusing them would re-refuse the very productions the block-body lift clears. They
|
|
14
|
+
// carry no closure state, so admitting them cannot make an unanalyzable builder
|
|
15
|
+
// analyzable by accident. A MODULE-SCOPE custom error stays a free name (rescued by
|
|
16
|
+
// provenance or refused) — unchanged.
|
|
17
|
+
'Error', 'TypeError', 'RangeError', 'SyntaxError',
|
|
11
18
|
])
|
|
12
19
|
|
|
13
20
|
type Ast = { type: string; [key: string]: unknown }
|
|
@@ -33,30 +40,70 @@ function unwrapCallbackExpression(node: Ast | undefined): Ast | undefined {
|
|
|
33
40
|
* AST binding check, never a source-text heuristic: property names and plain
|
|
34
41
|
* object keys are not lexical reads. The result becomes inert metadata on the
|
|
35
42
|
* macro-produced node and is enforced later by the runtime IR re-lowerer.
|
|
43
|
+
*
|
|
44
|
+
* Kept as the combined `structural ++ free` list so every existing caller and the
|
|
45
|
+
* standalone unit gate see one flat array. `directBuilderBindings` exposes the
|
|
46
|
+
* split the provenance path needs.
|
|
36
47
|
*/
|
|
37
48
|
export function directBuilderUnsupportedBindings(src: string): string[] {
|
|
49
|
+
const r = directBuilderBindings(src)
|
|
50
|
+
return [...r.structural, ...r.free]
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The analysis, SPLIT into two kinds of unsupported binding:
|
|
55
|
+
*
|
|
56
|
+
* - `structural` — a refusal no provenance can rescue: an un-analyzable node
|
|
57
|
+
* kind, a non-Identifier parameter, `this` / `arguments`, an async or generator
|
|
58
|
+
* reducer. These fail closed and fall back to the interpreter.
|
|
59
|
+
* - `free` — a plain lexical read of a name declared OUTSIDE the builder. Such a
|
|
60
|
+
* name is a refusal on its own, but it CAN be re-bound in a downstream module if
|
|
61
|
+
* that module re-emits the import it came from. The evaluator resolves each free
|
|
62
|
+
* name against the authoring module's imports: one that resolves is carried as
|
|
63
|
+
* import provenance; one that does not stays a refusal.
|
|
64
|
+
*/
|
|
65
|
+
export function directBuilderBindings(src: string): { structural: string[]; free: string[] } {
|
|
38
66
|
let init: Ast | undefined
|
|
39
67
|
try {
|
|
40
68
|
const parsed = parseSync('parseman-direct-builder.ts', `const _direct = (${src})`)
|
|
41
|
-
if (parsed.errors.length > 0) return ['invalid callback source']
|
|
69
|
+
if (parsed.errors.length > 0) return { structural: ['invalid callback source'], free: [] }
|
|
42
70
|
const program = parsed.program as unknown as Ast
|
|
43
|
-
const
|
|
44
|
-
const declaration = (
|
|
71
|
+
const statementNode = (program.body as Ast[] | undefined)?.[0]
|
|
72
|
+
const declaration = (statementNode?.declarations as Ast[] | undefined)?.[0]
|
|
45
73
|
init = unwrapCallbackExpression(declaration?.init as Ast | undefined)
|
|
46
74
|
} catch {
|
|
47
|
-
return ['invalid callback source']
|
|
75
|
+
return { structural: ['invalid callback source'], free: [] }
|
|
48
76
|
}
|
|
49
|
-
|
|
77
|
+
// A direct builder is an arrow OR a resolved `function` reducer (a bare reference
|
|
78
|
+
// to a top-level `function foldOperation(…) {…}` resolves to a FunctionExpression
|
|
79
|
+
// here). Both inline verbatim into the fused table. An async or generator reducer
|
|
80
|
+
// is NOT a pure synchronous builder and stays refused.
|
|
81
|
+
if (init === undefined) return { structural: ['unsupported callback shape'], free: [] }
|
|
82
|
+
const isCallable = init.type === 'ArrowFunctionExpression'
|
|
83
|
+
|| init.type === 'FunctionExpression'
|
|
84
|
+
|| init.type === 'FunctionDeclaration'
|
|
85
|
+
if (!isCallable || !Array.isArray(init.params)) return { structural: ['unsupported callback shape'], free: [] }
|
|
86
|
+
if (init.async === true || init.generator === true) return { structural: ['unsupported callback shape'], free: [] }
|
|
50
87
|
const allowed = new Set(STATIC_BUILDER_GLOBALS)
|
|
51
88
|
for (const param of init.params as Ast[]) {
|
|
52
|
-
if (param.type !== 'Identifier' || typeof param.name !== 'string') return ['unsupported parameter pattern']
|
|
89
|
+
if (param.type !== 'Identifier' || typeof param.name !== 'string') return { structural: ['unsupported parameter pattern'], free: [] }
|
|
53
90
|
allowed.add(param.name)
|
|
54
91
|
}
|
|
55
|
-
|
|
56
|
-
|
|
92
|
+
// A named function expression binds its own name inside its body (recursion), so
|
|
93
|
+
// an inlined `function foldOperation(…) { … foldOperation(…) … }` is self-contained.
|
|
94
|
+
const selfName = astChild(init.id)
|
|
95
|
+
if (selfName?.type === 'Identifier' && typeof selfName.name === 'string') allowed.add(selfName.name)
|
|
96
|
+
|
|
97
|
+
const structural = new Set<string>()
|
|
98
|
+
const free = new Set<string>()
|
|
99
|
+
const reportUnsupportedNode = (ast: Ast): void => { structural.add(`unsupported ${ast.type}`) }
|
|
57
100
|
const read = (ast: Ast, allowedNames: ReadonlySet<string>): void => {
|
|
58
101
|
if (typeof ast.name === 'string' && allowedNames.has(ast.name)) return
|
|
59
|
-
|
|
102
|
+
// `arguments` is a function-only binding that no import can supply; refuse it
|
|
103
|
+
// structurally rather than letting it masquerade as a rescuable free name.
|
|
104
|
+
if (ast.name === 'arguments') { structural.add('unsupported arguments'); return }
|
|
105
|
+
if (typeof ast.name === 'string') free.add(ast.name)
|
|
106
|
+
else structural.add('unsupported identifier')
|
|
60
107
|
}
|
|
61
108
|
const expression = (node: unknown, allowedNames: ReadonlySet<string>): void => {
|
|
62
109
|
const ast = astChild(node)
|
|
@@ -89,14 +136,71 @@ export function directBuilderUnsupportedBindings(src: string): string[] {
|
|
|
89
136
|
if (param.type !== 'Identifier' || typeof param.name !== 'string') { reportUnsupportedNode(param); continue }
|
|
90
137
|
nested.add(param.name)
|
|
91
138
|
}
|
|
92
|
-
|
|
139
|
+
// A nested arrow with a block body is carried as source and inlined verbatim,
|
|
140
|
+
// exactly like the top-level builder — walk it, do not refuse it.
|
|
141
|
+
const nestedBody = astChild(ast.body)
|
|
142
|
+
if (nestedBody?.type === 'BlockStatement') { statement(nestedBody, nested); return }
|
|
93
143
|
expression(ast.body, nested)
|
|
94
144
|
return
|
|
95
145
|
}
|
|
96
146
|
default: reportUnsupportedNode(ast); return
|
|
97
147
|
}
|
|
98
148
|
}
|
|
99
|
-
|
|
149
|
+
// A block body is not a SERIALIZATION limit — `buildSrc` is carried as text and
|
|
150
|
+
// inlined verbatim downstream, so a statement inlines exactly as an expression
|
|
151
|
+
// does. The refusal was an ANALYZER gap: the walker only knew expressions. Walk
|
|
152
|
+
// statements too and the refusal disappears for the shapes grammar reducers use.
|
|
153
|
+
const statement = (node: unknown, names: Set<string>): void => {
|
|
154
|
+
const ast = astChild(node)
|
|
155
|
+
if (!ast) return
|
|
156
|
+
switch (ast.type) {
|
|
157
|
+
case 'VariableDeclaration':
|
|
158
|
+
for (const d of astArray(ast.declarations)) {
|
|
159
|
+
expression(d.init, names)
|
|
160
|
+
const idAst = astChild(d.id)
|
|
161
|
+
if (idAst?.type === 'Identifier' && typeof idAst.name === 'string') names.add(idAst.name)
|
|
162
|
+
else reportUnsupportedNode(idAst ?? ast)
|
|
163
|
+
}
|
|
164
|
+
return
|
|
165
|
+
case 'ReturnStatement': expression(ast.argument, names); return
|
|
166
|
+
case 'ExpressionStatement': expression(ast.expression, names); return
|
|
167
|
+
case 'ThrowStatement': expression(ast.argument, names); return
|
|
168
|
+
case 'IfStatement':
|
|
169
|
+
expression(ast.test, names)
|
|
170
|
+
statement(ast.consequent, new Set(names))
|
|
171
|
+
if (ast.alternate) statement(ast.alternate, new Set(names))
|
|
172
|
+
return
|
|
173
|
+
case 'ForStatement': {
|
|
174
|
+
// The init's bindings (`index`) are visible to test / update / body but must
|
|
175
|
+
// not leak to the enclosing scope — hence the child set.
|
|
176
|
+
const inner = new Set(names)
|
|
177
|
+
if (ast.init) {
|
|
178
|
+
const initAst = astChild(ast.init)
|
|
179
|
+
if (initAst?.type === 'VariableDeclaration') statement(initAst, inner)
|
|
180
|
+
else expression(initAst, inner)
|
|
181
|
+
}
|
|
182
|
+
if (ast.test) expression(ast.test, inner)
|
|
183
|
+
if (ast.update) expression(ast.update, inner)
|
|
184
|
+
statement(ast.body, inner)
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
case 'ForOfStatement': case 'ForInStatement': {
|
|
188
|
+
// The iterable (`ast.right`) is read in the OUTER scope; the loop variable is
|
|
189
|
+
// in scope only for the body. A non-declaration target (`for (x of …)`, a
|
|
190
|
+
// destructuring or member target) is refused by the statement walker.
|
|
191
|
+
const inner = new Set(names)
|
|
192
|
+
statement(ast.left, inner)
|
|
193
|
+
expression(ast.right, names)
|
|
194
|
+
statement(ast.body, inner)
|
|
195
|
+
return
|
|
196
|
+
}
|
|
197
|
+
case 'BlockStatement': { const inner = new Set(names); for (const s of astArray(ast.body)) statement(s, inner); return }
|
|
198
|
+
case 'BreakStatement': case 'ContinueStatement': case 'EmptyStatement': return
|
|
199
|
+
default: reportUnsupportedNode(ast); return
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const bodyAst = astChild(init.body)
|
|
203
|
+
if (bodyAst?.type === 'BlockStatement') statement(bodyAst, allowed)
|
|
100
204
|
else expression(init.body, allowed)
|
|
101
|
-
return [...
|
|
205
|
+
return { structural: [...structural], free: [...free] }
|
|
102
206
|
}
|