@kernlang/python 3.5.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/LICENSE +678 -0
- package/README.md +26 -0
- package/dist/codegen-body-python.d.ts +152 -0
- package/dist/codegen-body-python.js +1648 -0
- package/dist/codegen-body-python.js.map +1 -0
- package/dist/codegen-helpers.d.ts +21 -0
- package/dist/codegen-helpers.js +352 -0
- package/dist/codegen-helpers.js.map +1 -0
- package/dist/codegen-python.d.ts +17 -0
- package/dist/codegen-python.js +106 -0
- package/dist/codegen-python.js.map +1 -0
- package/dist/fastapi-middleware.d.ts +8 -0
- package/dist/fastapi-middleware.js +87 -0
- package/dist/fastapi-middleware.js.map +1 -0
- package/dist/fastapi-portable.d.ts +9 -0
- package/dist/fastapi-portable.js +295 -0
- package/dist/fastapi-portable.js.map +1 -0
- package/dist/fastapi-raw-handler.d.ts +28 -0
- package/dist/fastapi-raw-handler.js +282 -0
- package/dist/fastapi-raw-handler.js.map +1 -0
- package/dist/fastapi-response.d.ts +13 -0
- package/dist/fastapi-response.js +150 -0
- package/dist/fastapi-response.js.map +1 -0
- package/dist/fastapi-route.d.ts +12 -0
- package/dist/fastapi-route.js +629 -0
- package/dist/fastapi-route.js.map +1 -0
- package/dist/fastapi-types.d.ts +39 -0
- package/dist/fastapi-types.js +5 -0
- package/dist/fastapi-types.js.map +1 -0
- package/dist/fastapi-utils.d.ts +16 -0
- package/dist/fastapi-utils.js +99 -0
- package/dist/fastapi-utils.js.map +1 -0
- package/dist/fastapi-websocket.d.ts +6 -0
- package/dist/fastapi-websocket.js +77 -0
- package/dist/fastapi-websocket.js.map +1 -0
- package/dist/generators/core.d.ts +23 -0
- package/dist/generators/core.js +906 -0
- package/dist/generators/core.js.map +1 -0
- package/dist/generators/data.d.ts +15 -0
- package/dist/generators/data.js +443 -0
- package/dist/generators/data.js.map +1 -0
- package/dist/generators/ground.d.ts +20 -0
- package/dist/generators/ground.js +333 -0
- package/dist/generators/ground.js.map +1 -0
- package/dist/generators/infra.d.ts +8 -0
- package/dist/generators/infra.js +109 -0
- package/dist/generators/infra.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/ir-semantics/python-leg.d.ts +45 -0
- package/dist/ir-semantics/python-leg.js +291 -0
- package/dist/ir-semantics/python-leg.js.map +1 -0
- package/dist/python-stdlib-preamble.d.ts +32 -0
- package/dist/python-stdlib-preamble.js +86 -0
- package/dist/python-stdlib-preamble.js.map +1 -0
- package/dist/transpiler-fastapi.d.ts +8 -0
- package/dist/transpiler-fastapi.js +593 -0
- package/dist/transpiler-fastapi.js.map +1 -0
- package/dist/type-map.d.ts +14 -0
- package/dist/type-map.js +288 -0
- package/dist/type-map.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python emitter leg — Phase 1 PR-3b.
|
|
3
|
+
*
|
|
4
|
+
* Council-approved design (6-engine agon brainstorm, run 1778871685720):
|
|
5
|
+
*
|
|
6
|
+
* - **(A) Fresh `python3 -u` subprocess per fixture.** Clean isolation;
|
|
7
|
+
* ~50-100ms overhead × 19 fixtures = ~1-2s test cost; no shared state.
|
|
8
|
+
* `-u` flag forces unbuffered stdio so short-lived fixtures cannot
|
|
9
|
+
* drop trace events to a half-flushed buffer.
|
|
10
|
+
* - **(ii) Dedicated FD 3 for trace transport.** stdout is reserved for
|
|
11
|
+
* emitted-code `print()` calls; FD3 carries one JSON event per line.
|
|
12
|
+
* This keeps user output from polluting the trace channel.
|
|
13
|
+
* - **(B1) Codegen hook injected in production Python emitter** behind
|
|
14
|
+
* `BodyEmitOptions.traceHooks.eachIterNext` (opt-in only; production
|
|
15
|
+
* callers never set it). Symmetric with TS leg's hook contract.
|
|
16
|
+
* - **(P1) Sentinel exception classes** `_KernReturn`/`_KernThrow`
|
|
17
|
+
* defined in the prelude. Lowered `throw` body-stmts raise them;
|
|
18
|
+
* a wrapping `async def __kern_run()` catches and resolves them
|
|
19
|
+
* into [[CompletionRecord]]s. Symmetric with TS sentinel approach.
|
|
20
|
+
*
|
|
21
|
+
* Council-flagged mitigations applied:
|
|
22
|
+
* - Deterministic JSON: `sort_keys=True` on Python side; we already do
|
|
23
|
+
* key-sorted serialization on TS side via `serializeValue`.
|
|
24
|
+
* - Unbuffered stdio: `python3 -u`.
|
|
25
|
+
* - Async-aware timeout: subprocess SIGKILLed after 10s if it hasn't
|
|
26
|
+
* exited; surfaces as PythonLegError.
|
|
27
|
+
*
|
|
28
|
+
* Fixture authors: do NOT use Python `print()` inside fixture bodies — the
|
|
29
|
+
* harness writes the completion record to stdout. Use `__trace` events with
|
|
30
|
+
* `op: 'stdout'` if you need to observe stdout-style output through the
|
|
31
|
+
* trace channel (FD 3).
|
|
32
|
+
*/
|
|
33
|
+
import { spawn } from 'node:child_process';
|
|
34
|
+
import { lowerFixtureForTarget } from '@kernlang/core';
|
|
35
|
+
import { emitNativeKernBodyPythonWithImports } from '../codegen-body-python.js';
|
|
36
|
+
const PYTHON_LEG_TIMEOUT_MS = 10_000;
|
|
37
|
+
/**
|
|
38
|
+
* Serialise a fixture binding into a Python literal expression. Mirrors
|
|
39
|
+
* `serializeValue` from `@kernlang/core/ir/semantics/fixture-lowering`
|
|
40
|
+
* but with `target='python'` semantics so booleans, null, etc. map to
|
|
41
|
+
* their Python equivalents.
|
|
42
|
+
*/
|
|
43
|
+
function pyLiteral(value) {
|
|
44
|
+
if (value === null || value === undefined)
|
|
45
|
+
return 'None';
|
|
46
|
+
if (typeof value === 'boolean')
|
|
47
|
+
return value ? 'True' : 'False';
|
|
48
|
+
if (typeof value === 'number') {
|
|
49
|
+
if (!Number.isFinite(value)) {
|
|
50
|
+
throw new Error(`pyLiteral: ${value} is not cross-target portable`);
|
|
51
|
+
}
|
|
52
|
+
return String(value);
|
|
53
|
+
}
|
|
54
|
+
if (typeof value === 'string')
|
|
55
|
+
return JSON.stringify(value);
|
|
56
|
+
if (Array.isArray(value))
|
|
57
|
+
return `[${value.map(pyLiteral).join(', ')}]`;
|
|
58
|
+
if (value instanceof Map) {
|
|
59
|
+
// Python dict (3.7+) preserves insertion order; emit in Map iteration
|
|
60
|
+
// order to keep `.keys()` / `.values()` / `.items()` iteration semantics
|
|
61
|
+
// aligned with the reference runner (which uses `Map` insertion order).
|
|
62
|
+
const pairs = Array.from(value.entries()).map(([k, v]) => `${JSON.stringify(String(k))}: ${pyLiteral(v)}`);
|
|
63
|
+
return `{${pairs.join(', ')}}`;
|
|
64
|
+
}
|
|
65
|
+
if (typeof value === 'object') {
|
|
66
|
+
// Preserve JS object insertion order — Python dict iteration mirrors it.
|
|
67
|
+
// Sort-keys here would silently reorder entry-mode iteration.
|
|
68
|
+
const pairs = Object.entries(value).map(([k, v]) => `${JSON.stringify(k)}: ${pyLiteral(v)}`);
|
|
69
|
+
return `{${pairs.join(', ')}}`;
|
|
70
|
+
}
|
|
71
|
+
throw new Error(`pyLiteral: unsupported type "${typeof value}"`);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Python prelude — injected as the first statements in the spawned
|
|
75
|
+
* subprocess. Defines the sentinel classes the lowered IR raises, the
|
|
76
|
+
* trace sink that writes one JSON event per line to FD 3, and the
|
|
77
|
+
* async wrapper that converts sentinel exceptions into CompletionRecords.
|
|
78
|
+
*/
|
|
79
|
+
function buildPrelude() {
|
|
80
|
+
return [
|
|
81
|
+
'import asyncio',
|
|
82
|
+
'import json',
|
|
83
|
+
'import os',
|
|
84
|
+
'import sys',
|
|
85
|
+
'',
|
|
86
|
+
'class _KernReturn(Exception):',
|
|
87
|
+
' def __init__(self, value):',
|
|
88
|
+
' self.value = value',
|
|
89
|
+
'',
|
|
90
|
+
'class _KernThrow(Exception):',
|
|
91
|
+
' def __init__(self, kind):',
|
|
92
|
+
' self.kind = kind',
|
|
93
|
+
'',
|
|
94
|
+
'_kern_trace_fd = 3',
|
|
95
|
+
'',
|
|
96
|
+
'def _kern_trace(event):',
|
|
97
|
+
' line = json.dumps(event, sort_keys=True)',
|
|
98
|
+
' os.write(_kern_trace_fd, (line + "\\n").encode("utf-8"))',
|
|
99
|
+
'',
|
|
100
|
+
].join('\n');
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Wrap the emitted body in an async function that returns a JSON
|
|
104
|
+
* CompletionRecord on stdout, catching the sentinel exceptions.
|
|
105
|
+
*
|
|
106
|
+
* `helpers` are emitted at module scope ABOVE the env bindings so they're
|
|
107
|
+
* visible from inside `__kern_run`. This matches production codegen: helpers
|
|
108
|
+
* (`_kern_pairs`, `_kern_async_pairs`) are module-level defs, not nested
|
|
109
|
+
* inside the running function.
|
|
110
|
+
*/
|
|
111
|
+
function buildProgram(bodyCode, envBindings, helpers) {
|
|
112
|
+
const bindingLines = envBindings.map(([name, value]) => `${name} = ${pyLiteral(value)}`);
|
|
113
|
+
const indented = bodyCode
|
|
114
|
+
.split('\n')
|
|
115
|
+
.map((line) => (line.length === 0 ? '' : ` ${line}`))
|
|
116
|
+
.join('\n');
|
|
117
|
+
const helperBlock = helpers.length > 0 ? `${helpers.join('\n\n')}\n` : '';
|
|
118
|
+
return [
|
|
119
|
+
buildPrelude(),
|
|
120
|
+
helperBlock,
|
|
121
|
+
...bindingLines,
|
|
122
|
+
'',
|
|
123
|
+
'async def __kern_run():',
|
|
124
|
+
' try:',
|
|
125
|
+
indented || ' pass',
|
|
126
|
+
` return {"kind": "normal"}`,
|
|
127
|
+
' except _KernReturn as r:',
|
|
128
|
+
' return {"kind": "return", "value": r.value}',
|
|
129
|
+
' except _KernThrow as t:',
|
|
130
|
+
' return {"kind": "throw", "error": {"kind": t.kind}}',
|
|
131
|
+
'',
|
|
132
|
+
'_completion = asyncio.run(__kern_run())',
|
|
133
|
+
'sys.stdout.write(json.dumps(_completion, sort_keys=True))',
|
|
134
|
+
'sys.stdout.flush()',
|
|
135
|
+
].join('\n');
|
|
136
|
+
}
|
|
137
|
+
export class PythonLegError extends Error {
|
|
138
|
+
constructor(message) {
|
|
139
|
+
super(message);
|
|
140
|
+
this.name = 'PythonLegError';
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function runPython(program) {
|
|
144
|
+
return new Promise((resolve, reject) => {
|
|
145
|
+
let child;
|
|
146
|
+
try {
|
|
147
|
+
child = spawn('python3', ['-u', '-c', program], {
|
|
148
|
+
stdio: ['ignore', 'pipe', 'pipe', 'pipe'],
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
reject(new PythonLegError(`python3 spawn failed: ${err.message}`));
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
// Single-settle guard — `error` and `close` can both fire; we want
|
|
156
|
+
// exactly one terminal resolution.
|
|
157
|
+
let settled = false;
|
|
158
|
+
const settle = (action) => {
|
|
159
|
+
if (settled)
|
|
160
|
+
return;
|
|
161
|
+
settled = true;
|
|
162
|
+
action();
|
|
163
|
+
};
|
|
164
|
+
let stdout = '';
|
|
165
|
+
let stderr = '';
|
|
166
|
+
let fd3 = '';
|
|
167
|
+
child.stdout?.on('data', (chunk) => {
|
|
168
|
+
stdout += chunk.toString();
|
|
169
|
+
});
|
|
170
|
+
child.stderr?.on('data', (chunk) => {
|
|
171
|
+
stderr += chunk.toString();
|
|
172
|
+
});
|
|
173
|
+
// FD 3 is the trace channel. Parent's view is Readable because the child
|
|
174
|
+
// writes to FD 3 via `os.write(3, ...)`.
|
|
175
|
+
const fd3Stream = child.stdio[3];
|
|
176
|
+
if (fd3Stream && typeof fd3Stream.on === 'function') {
|
|
177
|
+
fd3Stream.on('data', (chunk) => {
|
|
178
|
+
fd3 += chunk.toString();
|
|
179
|
+
});
|
|
180
|
+
fd3Stream.on('error', (err) => {
|
|
181
|
+
settle(() => {
|
|
182
|
+
clearTimeout(killTimer);
|
|
183
|
+
reject(new PythonLegError(`fd3 stream error: ${err.message}`));
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const killTimer = setTimeout(() => {
|
|
188
|
+
child.kill('SIGKILL');
|
|
189
|
+
settle(() => reject(new PythonLegError(`python3 timed out after ${PYTHON_LEG_TIMEOUT_MS}ms`)));
|
|
190
|
+
}, PYTHON_LEG_TIMEOUT_MS);
|
|
191
|
+
killTimer.unref?.();
|
|
192
|
+
child.on('error', (err) => {
|
|
193
|
+
settle(() => {
|
|
194
|
+
clearTimeout(killTimer);
|
|
195
|
+
reject(new PythonLegError(`python3 process error: ${err.message}`));
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
// Resolve on `close` — fires only after ALL stdio streams have closed,
|
|
199
|
+
// so stdout/stderr/FD3 buffers are fully drained. `exit` races stdio
|
|
200
|
+
// drain (claude + codex agreed in PR-3b review).
|
|
201
|
+
child.on('close', (code) => {
|
|
202
|
+
settle(() => {
|
|
203
|
+
clearTimeout(killTimer);
|
|
204
|
+
resolve({ stdout, fd3, stderr, exitCode: code });
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function parseTraceEvents(fd3) {
|
|
210
|
+
const events = [];
|
|
211
|
+
for (const raw of fd3.split('\n')) {
|
|
212
|
+
const line = raw.trim();
|
|
213
|
+
if (line.length === 0)
|
|
214
|
+
continue;
|
|
215
|
+
try {
|
|
216
|
+
events.push(JSON.parse(line));
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
throw new PythonLegError(`malformed trace line on FD3: ${line.slice(0, 200)}`);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return events;
|
|
223
|
+
}
|
|
224
|
+
function isCompletion(value) {
|
|
225
|
+
if (!value || typeof value !== 'object')
|
|
226
|
+
return false;
|
|
227
|
+
const k = value.kind;
|
|
228
|
+
return k === 'normal' || k === 'return' || k === 'throw';
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Run the Python emitter leg of the differential harness.
|
|
232
|
+
*
|
|
233
|
+
* Error model mirrors `runTsEmitterLeg`: ONLY the sentinel-resolved
|
|
234
|
+
* completions count as fixture-comparable; any other failure (spawn
|
|
235
|
+
* error, non-zero exit, malformed FD3 output) is thrown so the harness
|
|
236
|
+
* records `leg-error`.
|
|
237
|
+
*/
|
|
238
|
+
export async function runPythonEmitterLeg(fixture, env) {
|
|
239
|
+
const lowered = lowerFixtureForTarget(fixture.ir, 'python');
|
|
240
|
+
const handlerWrapper = {
|
|
241
|
+
type: 'handler',
|
|
242
|
+
props: { lang: 'kern' },
|
|
243
|
+
children: [lowered],
|
|
244
|
+
};
|
|
245
|
+
let bodyCode;
|
|
246
|
+
let bodyHelpers;
|
|
247
|
+
try {
|
|
248
|
+
const result = emitNativeKernBodyPythonWithImports(handlerWrapper, {
|
|
249
|
+
traceHooks: { eachIterNext: true },
|
|
250
|
+
});
|
|
251
|
+
if (result.imports.size > 0) {
|
|
252
|
+
// Differential fixtures don't exercise stdlib-import codegen (math, etc.);
|
|
253
|
+
// if a future fixture does, this leg will need an import-emission
|
|
254
|
+
// strategy. Fail loud rather than silently producing broken Python.
|
|
255
|
+
const list = [...result.imports].sort().join(', ');
|
|
256
|
+
throw new PythonLegError(`fixture body requires Python imports [${list}] — unsupported by harness`);
|
|
257
|
+
}
|
|
258
|
+
bodyCode = result.code;
|
|
259
|
+
bodyHelpers = [...result.helpers];
|
|
260
|
+
}
|
|
261
|
+
catch (err) {
|
|
262
|
+
if (err instanceof PythonLegError)
|
|
263
|
+
throw err;
|
|
264
|
+
throw new PythonLegError(`emitNativeKernBodyPythonWithImports failed: ${err.message}`);
|
|
265
|
+
}
|
|
266
|
+
const program = buildProgram(bodyCode, Array.from(env.bindings.entries()), bodyHelpers);
|
|
267
|
+
const result = await runPython(program);
|
|
268
|
+
if (result.exitCode !== 0) {
|
|
269
|
+
throw new PythonLegError(`python3 exited with code ${result.exitCode}; stderr=${result.stderr.slice(0, 1000)}`);
|
|
270
|
+
}
|
|
271
|
+
const events = parseTraceEvents(result.fd3);
|
|
272
|
+
let completion;
|
|
273
|
+
try {
|
|
274
|
+
const parsed = JSON.parse(result.stdout);
|
|
275
|
+
if (!isCompletion(parsed)) {
|
|
276
|
+
throw new Error(`unexpected completion shape: ${result.stdout.slice(0, 500)}`);
|
|
277
|
+
}
|
|
278
|
+
completion = parsed;
|
|
279
|
+
// Canonicalise error: Python sends `{"kind": "throw", "error": {"kind": "TypeError"}}`.
|
|
280
|
+
// The CompletionRecord shape matches our reference; nothing more to do.
|
|
281
|
+
if (completion.kind === 'throw' && completion.error) {
|
|
282
|
+
const canonical = { kind: completion.error.kind };
|
|
283
|
+
completion = { kind: 'throw', error: canonical };
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
throw new PythonLegError(`failed to parse Python completion JSON: ${err.message}; stdout=${result.stdout.slice(0, 500)}`);
|
|
288
|
+
}
|
|
289
|
+
return { events, completion };
|
|
290
|
+
}
|
|
291
|
+
//# sourceMappingURL=python-leg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-leg.js","sourceRoot":"","sources":["../../src/ir-semantics/python-leg.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAA4B,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAIrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,mCAAmC,EAAE,MAAM,2BAA2B,CAAC;AAEhF,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAErC;;;;;GAKG;AACH,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC;IACzD,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;IAChE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,cAAc,KAAK,+BAA+B,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC5D,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACxE,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;QACzB,sEAAsE;QACtE,yEAAyE;QACzE,wEAAwE;QACxE,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3G,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACjC,CAAC;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,yEAAyE;QACzE,8DAA8D;QAC9D,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAgC,CAAC,CAAC,GAAG,CAChE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CACpD,CAAC;QACF,OAAO,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;IACjC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,gCAAgC,OAAO,KAAK,GAAG,CAAC,CAAC;AACnE,CAAC;AAED;;;;;GAKG;AACH,SAAS,YAAY;IACnB,OAAO;QACL,gBAAgB;QAChB,aAAa;QACb,WAAW;QACX,YAAY;QACZ,EAAE;QACF,+BAA+B;QAC/B,gCAAgC;QAChC,4BAA4B;QAC5B,EAAE;QACF,8BAA8B;QAC9B,+BAA+B;QAC/B,0BAA0B;QAC1B,EAAE;QACF,oBAAoB;QACpB,EAAE;QACF,yBAAyB;QACzB,8CAA8C;QAC9C,8DAA8D;QAC9D,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CACnB,QAAgB,EAChB,WAA6C,EAC7C,OAA8B;IAE9B,MAAM,YAAY,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,MAAM,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzF,MAAM,QAAQ,GAAG,QAAQ;SACtB,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;SAC3D,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1E,OAAO;QACL,YAAY,EAAE;QACd,WAAW;QACX,GAAG,YAAY;QACf,EAAE;QACF,yBAAyB;QACzB,UAAU;QACV,QAAQ,IAAI,cAAc;QAC1B,mCAAmC;QACnC,8BAA8B;QAC9B,qDAAqD;QACrD,6BAA6B;QAC7B,6DAA6D;QAC7D,EAAE;QACF,yCAAyC;QACzC,2DAA2D;QAC3D,oBAAoB;KACrB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AASD,SAAS,SAAS,CAAC,OAAe;IAChC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,IAAI,KAAmF,CAAC;QACxF,IAAI,CAAC;YACH,KAAK,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;gBAC9C,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;aAC1C,CAA4F,CAAC;QAChG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,IAAI,cAAc,CAAC,yBAA0B,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC9E,OAAO;QACT,CAAC;QAED,mEAAmE;QACnE,mCAAmC;QACnC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,MAAM,MAAM,GAAG,CAAC,MAAkB,EAAQ,EAAE;YAC1C,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,MAAM,EAAE,CAAC;QACX,CAAC,CAAC;QAEF,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,GAAG,GAAG,EAAE,CAAC;QAEb,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QAEH,yEAAyE;QACzE,yCAAyC;QACzC,MAAM,SAAS,GAAI,KAAK,CAAC,KAA2C,CAAC,CAAC,CAAC,CAAC;QACxE,IAAI,SAAS,IAAI,OAAO,SAAS,CAAC,EAAE,KAAK,UAAU,EAAE,CAAC;YACpD,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAsB,EAAE,EAAE;gBAC9C,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YAC1B,CAAC,CAAC,CAAC;YACH,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAU,EAAE,EAAE;gBACnC,MAAM,CAAC,GAAG,EAAE;oBACV,YAAY,CAAC,SAAS,CAAC,CAAC;oBACxB,MAAM,CAAC,IAAI,cAAc,CAAC,qBAAqB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBACjE,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;YAChC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtB,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,2BAA2B,qBAAqB,IAAI,CAAC,CAAC,CAAC,CAAC;QACjG,CAAC,EAAE,qBAAqB,CAAC,CAAC;QAC1B,SAAS,CAAC,KAAK,EAAE,EAAE,CAAC;QAEpB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,MAAM,CAAC,GAAG,EAAE;gBACV,YAAY,CAAC,SAAS,CAAC,CAAC;gBACxB,MAAM,CAAC,IAAI,cAAc,CAAC,0BAA0B,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACtE,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,uEAAuE;QACvE,qEAAqE;QACrE,iDAAiD;QACjD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,MAAM,CAAC,GAAG,EAAE;gBACV,YAAY,CAAC,SAAS,CAAC,CAAC;gBACxB,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACnD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAChC,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAe,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,cAAc,CAAC,gCAAgC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,YAAY,CAAC,KAAc;IAClC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAI,KAA4B,CAAC,IAAI,CAAC;IAC7C,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,OAAO,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAoB,EAAE,GAAgB;IAC9E,MAAM,OAAO,GAAG,qBAAqB,CAAC,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC5D,MAAM,cAAc,GAAG;QACrB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACvB,QAAQ,EAAE,CAAC,OAAO,CAAC;KACpB,CAAC;IAEF,IAAI,QAAgB,CAAC;IACrB,IAAI,WAAkC,CAAC;IACvC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,mCAAmC,CAAC,cAAc,EAAE;YACjE,UAAU,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;SACnC,CAAC,CAAC;QACH,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAC5B,2EAA2E;YAC3E,kEAAkE;YAClE,oEAAoE;YACpE,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnD,MAAM,IAAI,cAAc,CAAC,yCAAyC,IAAI,4BAA4B,CAAC,CAAC;QACtG,CAAC;QACD,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC;QACvB,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,cAAc;YAAE,MAAM,GAAG,CAAC;QAC7C,MAAM,IAAI,cAAc,CAAC,+CAAgD,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IACpG,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC;IAExF,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAExC,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,cAAc,CAAC,4BAA4B,MAAM,CAAC,QAAQ,YAAY,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;IAClH,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IAE5C,IAAI,UAA4B,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,UAAU,GAAG,MAAM,CAAC;QACpB,wFAAwF;QACxF,wEAAwE;QACxE,IAAI,UAAU,CAAC,IAAI,KAAK,OAAO,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;YACpD,MAAM,SAAS,GAAmB,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAClE,UAAU,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,cAAc,CACtB,2CAA4C,GAAa,CAAC,OAAO,YAAY,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAC3G,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/** Slice 4 follow-up — Python equivalent of the TS `kernStdlibPreamble`.
|
|
2
|
+
*
|
|
3
|
+
* When a KERN module references the reserved type names `Result<T, E>`
|
|
4
|
+
* or `Option<T>` AND the compile target is FastAPI, the generated
|
|
5
|
+
* `main.py` needs the corresponding type aliases + frozen-dataclass
|
|
6
|
+
* wrappers in scope. Without them, `Result[User, ParseError]` in a fn
|
|
7
|
+
* signature would resolve to an undefined name at runtime.
|
|
8
|
+
*
|
|
9
|
+
* Spec: docs/language/result-option-spec.md (per-target table). The
|
|
10
|
+
* spec calls for **frozen dataclass** wrappers — NOT `Optional[T]` —
|
|
11
|
+
* so `Some(None)` and `None_()` round-trip distinctly through Pydantic
|
|
12
|
+
* and the discriminant `kind` field stays uniform across all targets.
|
|
13
|
+
*
|
|
14
|
+
* Detection reuses `detectKernStdlibUsage` from @kernlang/core, the same
|
|
15
|
+
* scanner the TS-family targets consume. Insertion is performed by the
|
|
16
|
+
* FastAPI transpiler entry between the `import …` block and the first
|
|
17
|
+
* emitted core node. */
|
|
18
|
+
import type { IRNode, KernStdlibUsage } from '@kernlang/core';
|
|
19
|
+
/** Module-level imports the preamble needs. The transpiler merges these
|
|
20
|
+
* into its existing `serverImports` set so duplicates are deduped. */
|
|
21
|
+
export declare const PYTHON_STDLIB_IMPORTS: string[];
|
|
22
|
+
/** Build the preamble lines. Returns an empty array when neither Result
|
|
23
|
+
* nor Option is detected so the FastAPI output stays unchanged for
|
|
24
|
+
* modules that don't use the compact form. */
|
|
25
|
+
export declare function pythonStdlibPreamble(usage: KernStdlibUsage): string[];
|
|
26
|
+
/** Convenience wrapper that pairs detection + emission. The transpiler
|
|
27
|
+
* calls this once per build to know whether to merge the imports and
|
|
28
|
+
* what lines to insert ahead of the first core artifact. */
|
|
29
|
+
export declare function buildPythonStdlibPreamble(root: IRNode): {
|
|
30
|
+
imports: string[];
|
|
31
|
+
lines: string[];
|
|
32
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Slice 4 follow-up — Python equivalent of the TS `kernStdlibPreamble`.
|
|
2
|
+
*
|
|
3
|
+
* When a KERN module references the reserved type names `Result<T, E>`
|
|
4
|
+
* or `Option<T>` AND the compile target is FastAPI, the generated
|
|
5
|
+
* `main.py` needs the corresponding type aliases + frozen-dataclass
|
|
6
|
+
* wrappers in scope. Without them, `Result[User, ParseError]` in a fn
|
|
7
|
+
* signature would resolve to an undefined name at runtime.
|
|
8
|
+
*
|
|
9
|
+
* Spec: docs/language/result-option-spec.md (per-target table). The
|
|
10
|
+
* spec calls for **frozen dataclass** wrappers — NOT `Optional[T]` —
|
|
11
|
+
* so `Some(None)` and `None_()` round-trip distinctly through Pydantic
|
|
12
|
+
* and the discriminant `kind` field stays uniform across all targets.
|
|
13
|
+
*
|
|
14
|
+
* Detection reuses `detectKernStdlibUsage` from @kernlang/core, the same
|
|
15
|
+
* scanner the TS-family targets consume. Insertion is performed by the
|
|
16
|
+
* FastAPI transpiler entry between the `import …` block and the first
|
|
17
|
+
* emitted core node. */
|
|
18
|
+
import { detectKernStdlibUsage } from '@kernlang/core';
|
|
19
|
+
/** Module-level imports the preamble needs. The transpiler merges these
|
|
20
|
+
* into its existing `serverImports` set so duplicates are deduped. */
|
|
21
|
+
export const PYTHON_STDLIB_IMPORTS = [
|
|
22
|
+
'from dataclasses import dataclass',
|
|
23
|
+
'from typing import Generic, Literal, TypeAlias, TypeVar, Union',
|
|
24
|
+
];
|
|
25
|
+
/** TypeVars used by both Result and Option. Kern-namespaced names avoid
|
|
26
|
+
* collisions with user-defined `T` / `E` TypeVars in the same module. */
|
|
27
|
+
const TYPE_VARS = ['_T_kern = TypeVar("_T_kern")', '_E_kern = TypeVar("_E_kern")'];
|
|
28
|
+
/** Frozen-dataclass wrappers for Result. `value` / `error` come first
|
|
29
|
+
* (no defaults); `kind` last with a default literal so constructors can
|
|
30
|
+
* be called as `Ok(value=user)` without restating the discriminant. */
|
|
31
|
+
const RESULT_TYPES = [
|
|
32
|
+
'@dataclass(frozen=True)',
|
|
33
|
+
'class Ok(Generic[_T_kern]):',
|
|
34
|
+
' value: _T_kern',
|
|
35
|
+
' kind: Literal["ok"] = "ok"',
|
|
36
|
+
'',
|
|
37
|
+
'@dataclass(frozen=True)',
|
|
38
|
+
'class Err(Generic[_E_kern]):',
|
|
39
|
+
' error: _E_kern',
|
|
40
|
+
' kind: Literal["err"] = "err"',
|
|
41
|
+
'',
|
|
42
|
+
'Result: TypeAlias = Union[Ok[_T_kern], Err[_E_kern]]',
|
|
43
|
+
];
|
|
44
|
+
const OPTION_TYPES = [
|
|
45
|
+
'@dataclass(frozen=True)',
|
|
46
|
+
'class Some(Generic[_T_kern]):',
|
|
47
|
+
' value: _T_kern',
|
|
48
|
+
' kind: Literal["some"] = "some"',
|
|
49
|
+
'',
|
|
50
|
+
// `None_` (trailing underscore) — Python `None` is reserved as a
|
|
51
|
+
// singleton/null literal, so the spec uses `None_` for the "absent"
|
|
52
|
+
// variant of Option. Frozen + parameterless to model the unit case.
|
|
53
|
+
'@dataclass(frozen=True)',
|
|
54
|
+
'class None_:',
|
|
55
|
+
' kind: Literal["none"] = "none"',
|
|
56
|
+
'',
|
|
57
|
+
'Option: TypeAlias = Union[Some[_T_kern], None_]',
|
|
58
|
+
];
|
|
59
|
+
/** Build the preamble lines. Returns an empty array when neither Result
|
|
60
|
+
* nor Option is detected so the FastAPI output stays unchanged for
|
|
61
|
+
* modules that don't use the compact form. */
|
|
62
|
+
export function pythonStdlibPreamble(usage) {
|
|
63
|
+
if (!usage.result && !usage.option)
|
|
64
|
+
return [];
|
|
65
|
+
const lines = ['# ── KERN stdlib (auto-emitted) ──────────────────────────────────────', ...TYPE_VARS, ''];
|
|
66
|
+
if (usage.result) {
|
|
67
|
+
lines.push(...RESULT_TYPES);
|
|
68
|
+
lines.push('');
|
|
69
|
+
}
|
|
70
|
+
if (usage.option) {
|
|
71
|
+
lines.push(...OPTION_TYPES);
|
|
72
|
+
lines.push('');
|
|
73
|
+
}
|
|
74
|
+
return lines;
|
|
75
|
+
}
|
|
76
|
+
/** Convenience wrapper that pairs detection + emission. The transpiler
|
|
77
|
+
* calls this once per build to know whether to merge the imports and
|
|
78
|
+
* what lines to insert ahead of the first core artifact. */
|
|
79
|
+
export function buildPythonStdlibPreamble(root) {
|
|
80
|
+
const usage = detectKernStdlibUsage(root);
|
|
81
|
+
const lines = pythonStdlibPreamble(usage);
|
|
82
|
+
if (lines.length === 0)
|
|
83
|
+
return { imports: [], lines: [] };
|
|
84
|
+
return { imports: PYTHON_STDLIB_IMPORTS, lines };
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=python-stdlib-preamble.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"python-stdlib-preamble.js","sourceRoot":"","sources":["../src/python-stdlib-preamble.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;yBAgByB;AAGzB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEvD;uEACuE;AACvE,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,mCAAmC;IACnC,gEAAgE;CACjE,CAAC;AAEF;0EAC0E;AAC1E,MAAM,SAAS,GAAG,CAAC,8BAA8B,EAAE,8BAA8B,CAAC,CAAC;AAEnF;;wEAEwE;AACxE,MAAM,YAAY,GAAG;IACnB,yBAAyB;IACzB,6BAA6B;IAC7B,oBAAoB;IACpB,gCAAgC;IAChC,EAAE;IACF,yBAAyB;IACzB,8BAA8B;IAC9B,oBAAoB;IACpB,kCAAkC;IAClC,EAAE;IACF,sDAAsD;CACvD,CAAC;AAEF,MAAM,YAAY,GAAG;IACnB,yBAAyB;IACzB,+BAA+B;IAC/B,oBAAoB;IACpB,oCAAoC;IACpC,EAAE;IACF,iEAAiE;IACjE,oEAAoE;IACpE,oEAAoE;IACpE,yBAAyB;IACzB,cAAc;IACd,oCAAoC;IACpC,EAAE;IACF,iDAAiD;CAClD,CAAC;AAEF;;+CAE+C;AAC/C,MAAM,UAAU,oBAAoB,CAAC,KAAsB;IACzD,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAE9C,MAAM,KAAK,GAAa,CAAC,wEAAwE,EAAE,GAAG,SAAS,EAAE,EAAE,CAAC,CAAC;IACrH,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,KAAK,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;6DAE6D;AAC7D,MAAM,UAAU,yBAAyB,CAAC,IAAY;IACpD,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAC1D,OAAO,EAAE,OAAO,EAAE,qBAAqB,EAAE,KAAK,EAAE,CAAC;AACnD,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @kernlang/python — FastAPI Python backend transpiler
|
|
3
|
+
*
|
|
4
|
+
* IR → Python/FastAPI multi-file output.
|
|
5
|
+
* Blueprint: transpiler-express.ts — same IR nodes, same multi-file pattern, Python output.
|
|
6
|
+
*/
|
|
7
|
+
import type { IRNode, ResolvedKernConfig, TranspileResult } from '@kernlang/core';
|
|
8
|
+
export declare function transpileFastAPI(root: IRNode, _config?: ResolvedKernConfig): TranspileResult;
|