@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.
- package/README.md +53 -1
- package/bin/provider-proof-composition.js +34 -0
- package/bin/pulsewasm-extract.js +20 -0
- package/package.json +60 -5
- package/src/artifacts-dir.js +13 -0
- package/src/ast-json.js +52 -0
- package/src/build-manifest.js +354 -0
- package/src/canonical-api-compiler.js +269 -0
- package/src/canonical-native-compiler.js +411 -0
- package/src/canonical-native-plan.js +1478 -0
- package/src/canonical-project-compiler.js +1224 -0
- package/src/canonical-router-compiler.js +25 -0
- package/src/cli-intents.js +1235 -0
- package/src/cli.js +1927 -0
- package/src/codegen/assemblyscript-compile.js +3 -0
- package/src/codegen/assemblyscript-core.js +3 -0
- package/src/codegen/assemblyscript-shape.js +3 -0
- package/src/codegen/assemblyscript-wasm-smoke.js +3 -0
- package/src/codegen/backend-capabilities.js +3 -0
- package/src/codegen/channel-broadcaster.js +3 -0
- package/src/codegen/compiled-handlers.js +3 -0
- package/src/codegen/compiled-wasm-runtime.js +3 -0
- package/src/codegen/config-references.js +248 -0
- package/src/codegen/dispatch-ts.js +145 -0
- package/src/codegen/effect-composition.js +331 -0
- package/src/codegen/effect-runtime.js +418 -0
- package/src/codegen/execution-harness-ts.js +467 -0
- package/src/codegen/handler-bindings-ts.js +298 -0
- package/src/codegen/handler-library-contracts.js +3 -0
- package/src/codegen/host-capabilities.js +3 -0
- package/src/codegen/host-runtime-kernel.js +3 -0
- package/src/codegen/integrated-compiled-app.js +3 -0
- package/src/codegen/json-body.js +3 -0
- package/src/codegen/library-sidecars.js +3 -0
- package/src/codegen/local-harness-ts.js +453 -0
- package/src/codegen/pulse-wrapper.js +217 -0
- package/src/codegen/request-result-headers.js +3 -0
- package/src/codegen/schema-json-compile.js +3 -0
- package/src/codegen/schema-json-sidecar-v2.js +3 -0
- package/src/codegen/schema-json-sidecar.js +3 -0
- package/src/codegen/streaming-passthrough.js +3 -0
- package/src/codegen/wasm-host-abi.js +3 -0
- package/src/codegen/wasm-host-bridge.js +3 -0
- package/src/compiled-wasm-host-runtime-kv.js +3 -0
- package/src/config-resolver.js +813 -0
- package/src/crypto-requirement-planner.js +89 -0
- package/src/definitions/config-schema.js +14 -0
- package/src/definitions/handler-roles.js +14 -0
- package/src/definitions/path-grammar.js +14 -0
- package/src/definitions/router-api.js +14 -0
- package/src/diagnostics/codes.js +14 -0
- package/src/diagnostics/reporter.js +14 -0
- package/src/diagnostics.js +14 -0
- package/src/dispatch-table.js +400 -0
- package/src/events/event-emit.js +265 -0
- package/src/events/event-topology.js +127 -0
- package/src/execution-plan.js +463 -0
- package/src/extractor.js +2816 -0
- package/src/handler-eval.js +1154 -0
- package/src/handler-table.js +326 -0
- package/src/index.js +19 -0
- package/src/javascript-application-plan.js +181 -0
- package/src/kv-provider.js +3 -0
- package/src/path-table.js +60 -0
- package/src/path.js +14 -0
- package/src/patterns/config-define.js +30 -0
- package/src/patterns/dependency-call.js +18 -0
- package/src/patterns/env-lookup.js +13 -0
- package/src/patterns/handler-reference.js +29 -0
- package/src/patterns/path-literal.js +35 -0
- package/src/patterns/result.js +15 -0
- package/src/patterns/router-chain-call.js +50 -0
- package/src/patterns/router-construction.js +19 -0
- package/src/project/package-reachability.js +782 -0
- package/src/project/reachable-graph-builder.js +992 -0
- package/src/project/reachable-graph-contract.js +54 -0
- package/src/project/reachable-graph-implementation.js +36 -0
- package/src/project/router-module-linker.js +710 -0
- package/src/project-config-compiler.js +222 -0
- package/src/project-target-support.js +500 -0
- package/src/provider-toolchain.js +299 -0
- package/src/spine/async-surface-normalizer.js +328 -0
- package/src/spine/canonical-handler-ir.js +336 -0
- package/src/spine/canonical-native-module.js +87 -0
- package/src/spine/canonical-native-plan.js +89 -0
- package/src/spine/canonical-project.js +76 -0
- package/src/spine/canonical-router.js +155 -0
- package/src/spine/canonical-source.js +165 -0
- package/src/spine/diagnostic-authority.js +290 -0
- package/src/spine/equivalence.js +262 -0
- package/src/spine/guest-unit-stage.js +87 -0
- package/src/spine/handler-ir-emitter.js +455 -0
- package/src/spine/handler-ir-managed.js +1598 -0
- package/src/spine/handler-ir.js +797 -0
- package/src/spine/handler-surface-authority.js +588 -0
- package/src/spine/package-operation-seam.js +1015 -0
- package/src/spine/pipeline.js +202 -0
- package/src/spine/plain-handler-frontend.js +545 -0
- package/src/spine/provider-requirement-authority.js +208 -0
- package/src/spine/router-control-contract.js +17 -0
- package/src/spine/router-handler-frontend.js +514 -0
- package/src/spine/router-handler-ir.js +372 -0
- package/src/spine/router-topology-frontend.js +638 -0
- 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
|
+
});
|