@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.
Files changed (63) hide show
  1. package/LICENSE +678 -0
  2. package/README.md +26 -0
  3. package/dist/codegen-body-python.d.ts +152 -0
  4. package/dist/codegen-body-python.js +1648 -0
  5. package/dist/codegen-body-python.js.map +1 -0
  6. package/dist/codegen-helpers.d.ts +21 -0
  7. package/dist/codegen-helpers.js +352 -0
  8. package/dist/codegen-helpers.js.map +1 -0
  9. package/dist/codegen-python.d.ts +17 -0
  10. package/dist/codegen-python.js +106 -0
  11. package/dist/codegen-python.js.map +1 -0
  12. package/dist/fastapi-middleware.d.ts +8 -0
  13. package/dist/fastapi-middleware.js +87 -0
  14. package/dist/fastapi-middleware.js.map +1 -0
  15. package/dist/fastapi-portable.d.ts +9 -0
  16. package/dist/fastapi-portable.js +295 -0
  17. package/dist/fastapi-portable.js.map +1 -0
  18. package/dist/fastapi-raw-handler.d.ts +28 -0
  19. package/dist/fastapi-raw-handler.js +282 -0
  20. package/dist/fastapi-raw-handler.js.map +1 -0
  21. package/dist/fastapi-response.d.ts +13 -0
  22. package/dist/fastapi-response.js +150 -0
  23. package/dist/fastapi-response.js.map +1 -0
  24. package/dist/fastapi-route.d.ts +12 -0
  25. package/dist/fastapi-route.js +629 -0
  26. package/dist/fastapi-route.js.map +1 -0
  27. package/dist/fastapi-types.d.ts +39 -0
  28. package/dist/fastapi-types.js +5 -0
  29. package/dist/fastapi-types.js.map +1 -0
  30. package/dist/fastapi-utils.d.ts +16 -0
  31. package/dist/fastapi-utils.js +99 -0
  32. package/dist/fastapi-utils.js.map +1 -0
  33. package/dist/fastapi-websocket.d.ts +6 -0
  34. package/dist/fastapi-websocket.js +77 -0
  35. package/dist/fastapi-websocket.js.map +1 -0
  36. package/dist/generators/core.d.ts +23 -0
  37. package/dist/generators/core.js +906 -0
  38. package/dist/generators/core.js.map +1 -0
  39. package/dist/generators/data.d.ts +15 -0
  40. package/dist/generators/data.js +443 -0
  41. package/dist/generators/data.js.map +1 -0
  42. package/dist/generators/ground.d.ts +20 -0
  43. package/dist/generators/ground.js +333 -0
  44. package/dist/generators/ground.js.map +1 -0
  45. package/dist/generators/infra.d.ts +8 -0
  46. package/dist/generators/infra.js +109 -0
  47. package/dist/generators/infra.js.map +1 -0
  48. package/dist/index.d.ts +6 -0
  49. package/dist/index.js +7 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/ir-semantics/python-leg.d.ts +45 -0
  52. package/dist/ir-semantics/python-leg.js +291 -0
  53. package/dist/ir-semantics/python-leg.js.map +1 -0
  54. package/dist/python-stdlib-preamble.d.ts +32 -0
  55. package/dist/python-stdlib-preamble.js +86 -0
  56. package/dist/python-stdlib-preamble.js.map +1 -0
  57. package/dist/transpiler-fastapi.d.ts +8 -0
  58. package/dist/transpiler-fastapi.js +593 -0
  59. package/dist/transpiler-fastapi.js.map +1 -0
  60. package/dist/type-map.d.ts +14 -0
  61. package/dist/type-map.js +288 -0
  62. package/dist/type-map.js.map +1 -0
  63. 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;