@pulse-compute/wasm-compiler 0.0.0 → 1.0.0-beta.2

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 (104) hide show
  1. package/README.md +53 -1
  2. package/bin/provider-proof-composition.js +34 -0
  3. package/bin/pulsewasm-extract.js +20 -0
  4. package/package.json +60 -5
  5. package/src/artifacts-dir.js +13 -0
  6. package/src/ast-json.js +52 -0
  7. package/src/build-manifest.js +354 -0
  8. package/src/canonical-api-compiler.js +269 -0
  9. package/src/canonical-native-compiler.js +411 -0
  10. package/src/canonical-native-plan.js +1478 -0
  11. package/src/canonical-project-compiler.js +1224 -0
  12. package/src/canonical-router-compiler.js +25 -0
  13. package/src/cli-intents.js +1235 -0
  14. package/src/cli.js +1927 -0
  15. package/src/codegen/assemblyscript-compile.js +3 -0
  16. package/src/codegen/assemblyscript-core.js +3 -0
  17. package/src/codegen/assemblyscript-shape.js +3 -0
  18. package/src/codegen/assemblyscript-wasm-smoke.js +3 -0
  19. package/src/codegen/backend-capabilities.js +3 -0
  20. package/src/codegen/channel-broadcaster.js +3 -0
  21. package/src/codegen/compiled-handlers.js +3 -0
  22. package/src/codegen/compiled-wasm-runtime.js +3 -0
  23. package/src/codegen/config-references.js +248 -0
  24. package/src/codegen/dispatch-ts.js +145 -0
  25. package/src/codegen/effect-composition.js +331 -0
  26. package/src/codegen/effect-runtime.js +418 -0
  27. package/src/codegen/execution-harness-ts.js +467 -0
  28. package/src/codegen/handler-bindings-ts.js +298 -0
  29. package/src/codegen/handler-library-contracts.js +3 -0
  30. package/src/codegen/host-capabilities.js +3 -0
  31. package/src/codegen/host-runtime-kernel.js +3 -0
  32. package/src/codegen/integrated-compiled-app.js +3 -0
  33. package/src/codegen/json-body.js +3 -0
  34. package/src/codegen/library-sidecars.js +3 -0
  35. package/src/codegen/local-harness-ts.js +453 -0
  36. package/src/codegen/pulse-wrapper.js +217 -0
  37. package/src/codegen/request-result-headers.js +3 -0
  38. package/src/codegen/schema-json-compile.js +3 -0
  39. package/src/codegen/schema-json-sidecar-v2.js +3 -0
  40. package/src/codegen/schema-json-sidecar.js +3 -0
  41. package/src/codegen/streaming-passthrough.js +3 -0
  42. package/src/codegen/wasm-host-abi.js +3 -0
  43. package/src/codegen/wasm-host-bridge.js +3 -0
  44. package/src/compiled-wasm-host-runtime-kv.js +3 -0
  45. package/src/config-resolver.js +813 -0
  46. package/src/crypto-requirement-planner.js +89 -0
  47. package/src/definitions/config-schema.js +14 -0
  48. package/src/definitions/handler-roles.js +14 -0
  49. package/src/definitions/path-grammar.js +14 -0
  50. package/src/definitions/router-api.js +14 -0
  51. package/src/diagnostics/codes.js +14 -0
  52. package/src/diagnostics/reporter.js +14 -0
  53. package/src/diagnostics.js +14 -0
  54. package/src/dispatch-table.js +400 -0
  55. package/src/events/event-emit.js +265 -0
  56. package/src/events/event-topology.js +127 -0
  57. package/src/execution-plan.js +463 -0
  58. package/src/extractor.js +2816 -0
  59. package/src/handler-eval.js +1154 -0
  60. package/src/handler-table.js +326 -0
  61. package/src/index.js +19 -0
  62. package/src/javascript-application-plan.js +181 -0
  63. package/src/kv-provider.js +3 -0
  64. package/src/path-table.js +60 -0
  65. package/src/path.js +14 -0
  66. package/src/patterns/config-define.js +30 -0
  67. package/src/patterns/dependency-call.js +18 -0
  68. package/src/patterns/env-lookup.js +13 -0
  69. package/src/patterns/handler-reference.js +29 -0
  70. package/src/patterns/path-literal.js +35 -0
  71. package/src/patterns/result.js +15 -0
  72. package/src/patterns/router-chain-call.js +50 -0
  73. package/src/patterns/router-construction.js +19 -0
  74. package/src/project/package-reachability.js +782 -0
  75. package/src/project/reachable-graph-builder.js +992 -0
  76. package/src/project/reachable-graph-contract.js +54 -0
  77. package/src/project/reachable-graph-implementation.js +36 -0
  78. package/src/project/router-module-linker.js +710 -0
  79. package/src/project-config-compiler.js +222 -0
  80. package/src/project-target-support.js +500 -0
  81. package/src/provider-toolchain.js +299 -0
  82. package/src/spine/async-surface-normalizer.js +328 -0
  83. package/src/spine/canonical-handler-ir.js +336 -0
  84. package/src/spine/canonical-native-module.js +87 -0
  85. package/src/spine/canonical-native-plan.js +89 -0
  86. package/src/spine/canonical-project.js +76 -0
  87. package/src/spine/canonical-router.js +155 -0
  88. package/src/spine/canonical-source.js +165 -0
  89. package/src/spine/diagnostic-authority.js +290 -0
  90. package/src/spine/equivalence.js +262 -0
  91. package/src/spine/guest-unit-stage.js +87 -0
  92. package/src/spine/handler-ir-emitter.js +455 -0
  93. package/src/spine/handler-ir-managed.js +1598 -0
  94. package/src/spine/handler-ir.js +797 -0
  95. package/src/spine/handler-surface-authority.js +588 -0
  96. package/src/spine/package-operation-seam.js +1015 -0
  97. package/src/spine/pipeline.js +202 -0
  98. package/src/spine/plain-handler-frontend.js +545 -0
  99. package/src/spine/provider-requirement-authority.js +208 -0
  100. package/src/spine/router-control-contract.js +17 -0
  101. package/src/spine/router-handler-frontend.js +514 -0
  102. package/src/spine/router-handler-ir.js +372 -0
  103. package/src/spine/router-topology-frontend.js +638 -0
  104. package/src/stable-id.js +14 -0
@@ -0,0 +1,455 @@
1
+ 'use strict';
2
+
3
+ const ts = require('typescript');
4
+ const { positionFor } = require('./diagnostic-authority.js');
5
+ const {
6
+ HANDLER_IR_VERSION,
7
+ ROUTER_HANDLER_IR_KIND
8
+ } = require('./handler-ir.js');
9
+ const {
10
+ ROUTER_CURSOR_IDENTIFIER: CURSOR,
11
+ ROUTER_MODE_IDENTIFIER: MODE,
12
+ ROUTER_ERROR_IDENTIFIER: ERROR
13
+ } = require('./router-control-contract.js');
14
+
15
+ const HANDLER_IR_EMITTER_VERSION = 'pulse.canonical-handler-ir-emitter.v1';
16
+
17
+ function literalProperty(factory, name, value) {
18
+ return factory.createPropertyAssignment(factory.createIdentifier(name), value);
19
+ }
20
+
21
+ function stringLiteral(factory, value) {
22
+ return factory.createStringLiteral(String(value));
23
+ }
24
+
25
+ function sourceExpression(factory, sourceFile, node) {
26
+ const pos = positionFor(sourceFile, node);
27
+ return factory.createObjectLiteralExpression([
28
+ literalProperty(factory, 'file', stringLiteral(factory, sourceFile.fileName)),
29
+ literalProperty(factory, 'line', factory.createNumericLiteral(pos.line)),
30
+ literalProperty(factory, 'column', factory.createNumericLiteral(pos.column))
31
+ ], false);
32
+ }
33
+
34
+ function fetchEffectExpression(factory, sourceFile, site, chain) {
35
+ const pos = positionFor(sourceFile, chain.fetchCall);
36
+ const init = chain.init || factory.createIdentifier('undefined');
37
+ const properties = [
38
+ literalProperty(factory, 'kind', stringLiteral(factory, 'fetch')),
39
+ literalProperty(factory, 'id', stringLiteral(factory, site.id))
40
+ ];
41
+ if (site.groupKey !== undefined) properties.push(literalProperty(factory, 'groupKey', stringLiteral(factory, site.groupKey)));
42
+ properties.push(
43
+ literalProperty(factory, 'responseMode', stringLiteral(factory, chain.decoder ? 'structured' : 'opaque')),
44
+ literalProperty(factory, 'projection', stringLiteral(factory, chain.decoder || 'response')),
45
+ literalProperty(factory, 'url', chain.url),
46
+ literalProperty(factory, 'init', init),
47
+ literalProperty(factory, 'source', factory.createObjectLiteralExpression([
48
+ literalProperty(factory, 'file', stringLiteral(factory, sourceFile.fileName)),
49
+ literalProperty(factory, 'line', factory.createNumericLiteral(pos.line)),
50
+ literalProperty(factory, 'column', factory.createNumericLiteral(pos.column))
51
+ ], false))
52
+ );
53
+ return factory.createObjectLiteralExpression(properties, false);
54
+ }
55
+
56
+ function providerEffectExpression(factory, sourceFile, site, providerOperation) {
57
+ const properties = [
58
+ literalProperty(factory, 'kind', stringLiteral(factory, providerOperation.kind)),
59
+ literalProperty(factory, 'id', stringLiteral(factory, site.id))
60
+ ];
61
+ if (site.groupKey !== undefined) properties.push(literalProperty(factory, 'groupKey', stringLiteral(factory, site.groupKey)));
62
+ if (providerOperation.kind === 'config.get' || providerOperation.kind === 'secret.get') {
63
+ properties.push(literalProperty(factory, 'name', providerOperation.name));
64
+ } else if (providerOperation.providerKind === 'kv') {
65
+ properties.push(literalProperty(factory, 'store', providerOperation.store));
66
+ properties.push(literalProperty(factory, 'key', providerOperation.key));
67
+ if (providerOperation.generation) properties.push(literalProperty(factory, 'generation', providerOperation.generation));
68
+ if (providerOperation.value) properties.push(literalProperty(factory, 'value', providerOperation.value));
69
+ } else if (providerOperation.kind === 'event.emit') {
70
+ properties.push(literalProperty(factory, 'type', providerOperation.type));
71
+ properties.push(literalProperty(factory, 'emission', providerOperation.emission));
72
+ }
73
+ properties.push(literalProperty(factory, 'source', sourceExpression(factory, sourceFile, providerOperation.call)));
74
+ return factory.createObjectLiteralExpression(properties, false);
75
+ }
76
+
77
+ function staticValueExpression(factory, value) {
78
+ if (value === undefined) return factory.createIdentifier('undefined');
79
+ if (value === null) return factory.createNull();
80
+ if (typeof value === 'string') return factory.createStringLiteral(value);
81
+ if (typeof value === 'number') return factory.createNumericLiteral(Number.isFinite(value) ? value : 0);
82
+ if (typeof value === 'boolean') return value ? factory.createTrue() : factory.createFalse();
83
+ if (Array.isArray(value)) return factory.createArrayLiteralExpression(value.map((entry) => staticValueExpression(factory, entry)), false);
84
+ if (value && typeof value === 'object') {
85
+ return factory.createObjectLiteralExpression(
86
+ Object.entries(value).map(([key, entry]) => factory.createPropertyAssignment(factory.createStringLiteral(key), staticValueExpression(factory, entry))),
87
+ false
88
+ );
89
+ }
90
+ throw new TypeError(`Unsupported canonical package effect literal: ${typeof value}`);
91
+ }
92
+
93
+ function packageEffectSourceExpression(factory, sourceFile, effect, call) {
94
+ const start = effect && effect.loc && effect.loc.start;
95
+ const file = effect && effect.loc && effect.loc.file;
96
+ if (file && start && String(file).replace(/\\/g, '/') !== String(sourceFile.fileName).replace(/\\/g, '/')) {
97
+ return factory.createObjectLiteralExpression([
98
+ literalProperty(factory, 'file', stringLiteral(factory, String(file).replace(/\\/g, '/'))),
99
+ literalProperty(factory, 'line', factory.createNumericLiteral(Number(start.line || 1))),
100
+ literalProperty(factory, 'column', factory.createNumericLiteral(Number(start.column || 1)))
101
+ ], false);
102
+ }
103
+ return sourceExpression(factory, sourceFile, call);
104
+ }
105
+
106
+ function packageEffectExpression(factory, sourceFile, site, effect, call, rewriteExpression = (expression) => expression) {
107
+ const properties = [
108
+ literalProperty(factory, 'kind', stringLiteral(factory, effect.kind)),
109
+ literalProperty(factory, 'id', stringLiteral(factory, site.id))
110
+ ];
111
+ if (site.groupKey !== undefined) properties.push(literalProperty(factory, 'groupKey', stringLiteral(factory, site.groupKey)));
112
+ properties.push(
113
+ literalProperty(factory, 'package', stringLiteral(factory, effect.package)),
114
+ literalProperty(factory, 'contractId', stringLiteral(factory, effect.contractId)),
115
+ literalProperty(factory, 'providerKind', stringLiteral(factory, effect.providerKind || 'package')),
116
+ literalProperty(factory, 'operation', stringLiteral(factory, effect.operation)),
117
+ literalProperty(factory, 'capability', stringLiteral(factory, effect.capability || effect.kind)),
118
+ literalProperty(factory, 'result', stringLiteral(factory, effect.result || 'value')),
119
+ literalProperty(factory, 'resource', staticValueExpression(factory, effect.resource || {})),
120
+ literalProperty(factory, 'payload', staticValueExpression(factory, effect.payload || {}))
121
+ );
122
+ const runtimeInputs = Array.isArray(effect.runtimeInputs) ? effect.runtimeInputs : [];
123
+ if (runtimeInputs.length > 0) {
124
+ properties.push(literalProperty(
125
+ factory,
126
+ 'invocation',
127
+ factory.createObjectLiteralExpression(runtimeInputs.map((input) => {
128
+ const argument = call && call.arguments && call.arguments[Number(input.argumentIndex)];
129
+ return factory.createPropertyAssignment(
130
+ factory.createStringLiteral(String(input.name)),
131
+ rewriteExpression(argument || factory.createIdentifier('undefined'))
132
+ );
133
+ }), false)
134
+ ));
135
+ }
136
+ properties.push(literalProperty(factory, 'source', packageEffectSourceExpression(factory, sourceFile, effect, call)));
137
+ return factory.createObjectLiteralExpression(properties, false);
138
+ }
139
+
140
+ function callPulse(factory, method, args) {
141
+ return factory.createCallExpression(
142
+ factory.createPropertyAccessExpression(factory.createIdentifier('__pulse'), method),
143
+ undefined,
144
+ args
145
+ );
146
+ }
147
+
148
+ function decodedExpression(factory, responseExpression, decoder, decoderArgs = []) {
149
+ if (!decoder) return responseExpression;
150
+ return factory.createCallExpression(factory.createPropertyAccessExpression(responseExpression, decoder), undefined, [...decoderArgs]);
151
+ }
152
+
153
+ function declarationFlags(statement) {
154
+ return statement.declarationList.flags;
155
+ }
156
+
157
+ function parallelMemberEffectExpression(factory, sourceFile, site, member, rewriteExpression) {
158
+ if (member.kind === 'fetch') return fetchEffectExpression(factory, sourceFile, site, member.chain);
159
+ if (member.kind === 'provider') return providerEffectExpression(factory, sourceFile, site, member.operation);
160
+ if (member.kind === 'package') return packageEffectExpression(factory, sourceFile, site, member.effect, member.call, rewriteExpression);
161
+ throw new TypeError(`Unsupported ctx.parallel member kind: ${member.kind}`);
162
+ }
163
+
164
+ function parallelMemberResultExpression(factory, temporary, member) {
165
+ if (member.kind === 'fetch') return decodedExpression(factory, temporary, member.chain.decoder, member.chain.decoderArgs);
166
+ return temporary;
167
+ }
168
+
169
+ function bindingKey(node) {
170
+ if (ts.isIdentifier(node) || ts.isStringLiteral(node)) return node.text;
171
+ return undefined;
172
+ }
173
+
174
+ function parallelResultStatements(factory, candidate, temporaryNames) {
175
+ const binding = candidate.declaration.name;
176
+ if (ts.isObjectBindingPattern(binding)) {
177
+ const memberIndexes = new Map(candidate.members.map((member, index) => [member.key, index]));
178
+ return binding.elements.map((element) => {
179
+ const key = bindingKey(element.propertyName || element.name);
180
+ const index = memberIndexes.get(key);
181
+ if (index === undefined || !ts.isIdentifier(element.name) || element.dotDotDotToken || element.initializer) {
182
+ throw new TypeError('Unsupported ctx.parallel result binding reached canonical emission.');
183
+ }
184
+ const initializer = parallelMemberResultExpression(factory, temporaryNames[index], candidate.members[index]);
185
+ return factory.createVariableStatement(candidate.statement.modifiers, factory.createVariableDeclarationList([
186
+ factory.createVariableDeclaration(element.name, undefined, undefined, initializer)
187
+ ], declarationFlags(candidate.statement)));
188
+ });
189
+ }
190
+ const resultObject = factory.createObjectLiteralExpression(candidate.members.map((member, index) =>
191
+ factory.createPropertyAssignment(
192
+ factory.createStringLiteral(member.key),
193
+ parallelMemberResultExpression(factory, temporaryNames[index], member)
194
+ )), true);
195
+ const declaration = factory.updateVariableDeclaration(
196
+ candidate.declaration,
197
+ candidate.declaration.name,
198
+ undefined,
199
+ candidate.declaration.type,
200
+ resultObject
201
+ );
202
+ return [factory.updateVariableStatement(
203
+ candidate.statement,
204
+ candidate.statement.modifiers,
205
+ factory.updateVariableDeclarationList(candidate.statement.declarationList, [declaration])
206
+ )];
207
+ }
208
+
209
+ function emitCanonicalHandlerGenerator(ir) {
210
+ if (!ir || ir.version !== HANDLER_IR_VERSION) throw new TypeError(`emitCanonicalHandlerGenerator requires ${HANDLER_IR_VERSION}.`);
211
+ const factory = ts.factory;
212
+ const sourceFile = ir.sourceFile;
213
+ const packageIntrinsicsByStart = new Map(
214
+ (ir.packageIntrinsics || []).map((intrinsic) => [Number(intrinsic.range && intrinsic.range.start), intrinsic])
215
+ );
216
+
217
+ function canonicalContextIntrinsic(intrinsic, args) {
218
+ if (intrinsic.intrinsic !== 'request.header') return null;
219
+ return factory.createCallExpression(
220
+ factory.createPropertyAccessExpression(
221
+ factory.createPropertyAccessExpression(
222
+ factory.createIdentifier(ir.ctxName),
223
+ 'req'
224
+ ),
225
+ 'header'
226
+ ),
227
+ undefined,
228
+ args
229
+ );
230
+ }
231
+
232
+ function rewritePackageIntrinsics(node) {
233
+ if (!node || packageIntrinsicsByStart.size === 0) return node;
234
+ const transformed = ts.transform(node, [
235
+ (context) => {
236
+ function visit(current) {
237
+ if (ts.isCallExpression(current)) {
238
+ let start = NaN;
239
+ try { start = current.getStart(sourceFile); } catch {}
240
+ const intrinsic = packageIntrinsicsByStart.get(start);
241
+ if (intrinsic) {
242
+ const indexes = Array.isArray(intrinsic.argumentIndexes) ? intrinsic.argumentIndexes : [];
243
+ const staticArguments = Array.isArray(intrinsic.staticArguments) ? intrinsic.staticArguments : [];
244
+ const args = [
245
+ ...staticArguments.map((argument) => staticValueExpression(factory, argument)),
246
+ ...indexes.map((index) => current.arguments[index]).filter(Boolean).map((argument) => ts.visitNode(argument, visit))
247
+ ];
248
+ const canonicalIntrinsic = canonicalContextIntrinsic(intrinsic, args);
249
+ if (canonicalIntrinsic) return canonicalIntrinsic;
250
+ return factory.createCallExpression(factory.createIdentifier(String(intrinsic.compilerName)), undefined, args);
251
+ }
252
+ }
253
+ return ts.visitEachChild(current, visit, context);
254
+ }
255
+ return (root) => ts.visitNode(root, visit);
256
+ }
257
+ ]);
258
+ const output = transformed.transformed[0];
259
+ transformed.dispose();
260
+ return output;
261
+ }
262
+
263
+ function emitOperation(entry) {
264
+ switch (entry.kind) {
265
+ case 'source-statement':
266
+ return rewritePackageIntrinsics(entry.statement);
267
+ case 'block':
268
+ return factory.updateBlock(entry.statement, entry.statements.flatMap((child) => {
269
+ const emitted = emitOperation(child);
270
+ return Array.isArray(emitted) ? emitted : [emitted];
271
+ }).filter(Boolean));
272
+ case 'if':
273
+ return factory.updateIfStatement(
274
+ entry.statement,
275
+ rewritePackageIntrinsics(entry.expression),
276
+ emitOperation(entry.thenOperation),
277
+ entry.elseOperation ? emitOperation(entry.elseOperation) : undefined
278
+ );
279
+ case 'fetch-single': {
280
+ const { candidate, site, continuation } = entry;
281
+ const marker = fetchEffectExpression(factory, sourceFile, site, candidate.chain);
282
+ const yieldExpression = factory.createYieldExpression(undefined, callPulse(factory, 'effect', [marker, stringLiteral(factory, continuation.id)]));
283
+ const initializer = decodedExpression(factory, factory.createParenthesizedExpression(yieldExpression), candidate.chain.decoder, candidate.chain.decoderArgs);
284
+ const declaration = factory.updateVariableDeclaration(candidate.declaration, candidate.declaration.name, undefined, candidate.declaration.type, initializer);
285
+ return factory.updateVariableStatement(candidate.statement, candidate.statement.modifiers, factory.updateVariableDeclarationList(candidate.statement.declarationList, [declaration]));
286
+ }
287
+ case 'fetch-group': {
288
+ const { candidates, sites, continuation } = entry;
289
+ const tempNames = sites.map((site) => factory.createIdentifier(`__pulse_response_${site.id.replace(/[^a-z0-9_]/gi, '_')}`));
290
+ const binding = factory.createArrayBindingPattern(tempNames.map((name) => factory.createBindingElement(undefined, undefined, name, undefined)));
291
+ const effectsArray = factory.createArrayLiteralExpression(sites.map((site, index) => fetchEffectExpression(factory, sourceFile, site, candidates[index].chain)), false);
292
+ const groupYield = factory.createYieldExpression(undefined, callPulse(factory, 'group', [effectsArray, stringLiteral(factory, continuation.id)]));
293
+ const groupDeclaration = factory.createVariableStatement(undefined, factory.createVariableDeclarationList([
294
+ factory.createVariableDeclaration(binding, undefined, undefined, groupYield)
295
+ ], ts.NodeFlags.Const));
296
+ const declarations = candidates.map((candidate, index) => {
297
+ const initializer = decodedExpression(factory, tempNames[index], candidate.chain.decoder, candidate.chain.decoderArgs);
298
+ return factory.createVariableStatement(candidate.statement.modifiers, factory.createVariableDeclarationList([
299
+ factory.createVariableDeclaration(candidate.declaration.name, undefined, candidate.declaration.type, initializer)
300
+ ], declarationFlags(candidate.statement)));
301
+ });
302
+ return [groupDeclaration, ...declarations];
303
+ }
304
+ case 'parallel-group': {
305
+ const { candidate, sites, continuation } = entry;
306
+ const temporaryNames = sites.map((site) => factory.createIdentifier(`__pulse_parallel_${site.id.replace(/[^a-z0-9_]/gi, '_')}`));
307
+ const binding = factory.createArrayBindingPattern(temporaryNames.map((name) => factory.createBindingElement(undefined, undefined, name, undefined)));
308
+ const effectsArray = factory.createArrayLiteralExpression(
309
+ sites.map((site, index) => parallelMemberEffectExpression(factory, sourceFile, site, candidate.members[index], rewritePackageIntrinsics)),
310
+ false
311
+ );
312
+ const groupYield = factory.createYieldExpression(undefined, callPulse(factory, 'group', [effectsArray, stringLiteral(factory, continuation.id)]));
313
+ if (candidate.discard) return factory.createExpressionStatement(groupYield);
314
+ const groupDeclaration = factory.createVariableStatement(undefined, factory.createVariableDeclarationList([
315
+ factory.createVariableDeclaration(binding, undefined, undefined, groupYield)
316
+ ], ts.NodeFlags.Const));
317
+ return [groupDeclaration, ...parallelResultStatements(factory, candidate, temporaryNames)];
318
+ }
319
+ case 'provider-variable': {
320
+ const { candidate, site, continuation } = entry;
321
+ const marker = providerEffectExpression(factory, sourceFile, site, candidate.operation);
322
+ const initializer = factory.createYieldExpression(undefined, callPulse(factory, 'effect', [marker, stringLiteral(factory, continuation.id)]));
323
+ const declaration = factory.updateVariableDeclaration(candidate.declaration, candidate.declaration.name, undefined, candidate.declaration.type, initializer);
324
+ return factory.updateVariableStatement(candidate.statement, candidate.statement.modifiers, factory.updateVariableDeclarationList(candidate.statement.declarationList, [declaration]));
325
+ }
326
+ case 'provider-expression': {
327
+ const { candidate, site, continuation } = entry;
328
+ const marker = providerEffectExpression(factory, sourceFile, site, candidate.operation);
329
+ return factory.createExpressionStatement(factory.createYieldExpression(undefined, callPulse(factory, 'effect', [marker, stringLiteral(factory, continuation.id)])));
330
+ }
331
+ case 'package-effect': {
332
+ const marker = packageEffectExpression(factory, sourceFile, entry.site, entry.effect, entry.call, rewritePackageIntrinsics);
333
+ const yielded = factory.createYieldExpression(undefined, callPulse(factory, 'effect', [marker, stringLiteral(factory, entry.continuation.id)]));
334
+ return entry.returnResult ? factory.createReturnStatement(yielded) : factory.createExpressionStatement(yielded);
335
+ }
336
+ case 'package-variable': {
337
+ const marker = packageEffectExpression(factory, sourceFile, entry.site, entry.candidate.effect, entry.candidate.call, rewritePackageIntrinsics);
338
+ const yielded = factory.createYieldExpression(undefined, callPulse(factory, 'effect', [marker, stringLiteral(factory, entry.continuation.id)]));
339
+ const declaration = factory.updateVariableDeclaration(entry.candidate.declaration, entry.candidate.declaration.name, undefined, entry.candidate.declaration.type, yielded);
340
+ return factory.updateVariableStatement(entry.candidate.statement, entry.candidate.statement.modifiers, factory.updateVariableDeclarationList(entry.candidate.statement.declarationList, [declaration]));
341
+ }
342
+ case 'package-result-adapter':
343
+ return factory.updateReturnStatement(entry.statement, rewritePackageIntrinsics(entry.resultExpression));
344
+ case 'opaque-fetch-return': {
345
+ const marker = fetchEffectExpression(factory, sourceFile, entry.site, entry.chain);
346
+ return factory.updateReturnStatement(entry.statement, factory.createYieldExpression(undefined, callPulse(factory, 'effect', [marker, stringLiteral(factory, entry.continuation.id)])));
347
+ }
348
+ default:
349
+ throw new TypeError(`Unsupported canonical Handler IR operation during emission: ${entry.kind}`);
350
+ }
351
+ }
352
+
353
+ const transformedBody = emitOperation(ir.body);
354
+ const generator = factory.createFunctionDeclaration(
355
+ undefined,
356
+ factory.createToken(ts.SyntaxKind.AsteriskToken),
357
+ factory.createIdentifier('__pulse_handler'),
358
+ undefined,
359
+ [
360
+ factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier(ir.ctxName), undefined, undefined, undefined),
361
+ factory.createParameterDeclaration(undefined, undefined, factory.createIdentifier('__pulse'), undefined, undefined, undefined)
362
+ ],
363
+ undefined,
364
+ transformedBody
365
+ );
366
+
367
+ return Object.freeze({
368
+ version: HANDLER_IR_EMITTER_VERSION,
369
+ generator,
370
+ ctxName: ir.ctxName,
371
+ effectSites: ir.effectSites,
372
+ continuationSites: ir.continuationSites
373
+ });
374
+ }
375
+
376
+ function assignmentStatement(factory, name, expression) {
377
+ return factory.createExpressionStatement(factory.createBinaryExpression(
378
+ factory.createIdentifier(name),
379
+ factory.createToken(ts.SyntaxKind.EqualsToken),
380
+ expression
381
+ ));
382
+ }
383
+
384
+ function emitCanonicalRouterHandlerBody(ir) {
385
+ if (!ir || ir.version !== HANDLER_IR_VERSION || ir.kind !== ROUTER_HANDLER_IR_KIND) {
386
+ throw new TypeError(`emitCanonicalRouterHandlerBody requires ${HANDLER_IR_VERSION} ${ROUTER_HANDLER_IR_KIND}.`);
387
+ }
388
+ const factory = ts.factory;
389
+
390
+ function emitOperation(entry) {
391
+ switch (entry.kind) {
392
+ case 'source-statement':
393
+ return entry.statement;
394
+ case 'block':
395
+ return factory.createBlock((entry.statements || []).flatMap((child) => {
396
+ const emitted = emitOperation(child);
397
+ return Array.isArray(emitted) ? emitted : [emitted];
398
+ }).filter(Boolean), true);
399
+ case 'if':
400
+ return factory.createIfStatement(
401
+ entry.expression,
402
+ emitOperation(entry.thenOperation),
403
+ entry.elseOperation ? emitOperation(entry.elseOperation) : undefined
404
+ );
405
+ case 'router-transfer': {
406
+ const statements = [];
407
+ if (entry.clearNormalMode) statements.push(assignmentStatement(factory, MODE, factory.createNumericLiteral(0)));
408
+ if (entry.errorExpression) {
409
+ statements.push(assignmentStatement(factory, ERROR, entry.errorExpression));
410
+ statements.push(assignmentStatement(factory, MODE, factory.createNumericLiteral(1)));
411
+ }
412
+ statements.push(assignmentStatement(factory, CURSOR, factory.createNumericLiteral(entry.nextIndex)));
413
+ statements.push(assignmentStatement(factory, entry.transferFlag, factory.createTrue()));
414
+ return statements;
415
+ }
416
+ case 'router-guard':
417
+ return factory.createIfStatement(
418
+ factory.createPrefixUnaryExpression(ts.SyntaxKind.ExclamationToken, factory.createIdentifier(entry.transferFlag)),
419
+ emitOperation(entry.body),
420
+ undefined
421
+ );
422
+ default:
423
+ throw new TypeError(`Unsupported Router Handler IR operation during emission: ${entry.kind}`);
424
+ }
425
+ }
426
+
427
+ const body = emitOperation(ir.body);
428
+ const bodyStatements = body && ts.isBlock(body) ? [...body.statements] : [];
429
+ const transferFlag = ir.transferFlag;
430
+ const statements = ir.role === 'event'
431
+ ? [
432
+ ...bodyStatements,
433
+ ...(ir.summary && ir.summary.flow && ir.summary.flow.mustTerminate
434
+ ? []
435
+ : [factory.createReturnStatement(factory.createIdentifier('undefined'))])
436
+ ]
437
+ : [
438
+ factory.createVariableStatement(undefined, factory.createVariableDeclarationList([
439
+ factory.createVariableDeclaration(factory.createIdentifier(transferFlag), undefined, undefined, factory.createFalse())
440
+ ], ts.NodeFlags.Let)),
441
+ ...bodyStatements
442
+ ];
443
+ const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
444
+ return Object.freeze({
445
+ version: HANDLER_IR_EMITTER_VERSION,
446
+ statements: Object.freeze(statements),
447
+ sourceText: statements.map((statement) => printer.printNode(ts.EmitHint.Unspecified, statement, ir.sourceFile)).join('\n')
448
+ });
449
+ }
450
+
451
+ module.exports = Object.freeze({
452
+ HANDLER_IR_EMITTER_VERSION,
453
+ emitCanonicalHandlerGenerator,
454
+ emitCanonicalRouterHandlerBody
455
+ });