@kernlang/python 3.5.6-canary.199.1.c927d232 → 3.5.6-canary.202.1.31706b95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/django.d.ts +49 -0
- package/dist/adapters/django.js +151 -0
- package/dist/adapters/django.js.map +1 -0
- package/dist/adapters/fastapi.d.ts +43 -0
- package/dist/adapters/fastapi.js +139 -0
- package/dist/adapters/fastapi.js.map +1 -0
- package/dist/codegen-body-python.d.ts +51 -2
- package/dist/codegen-body-python.js +281 -26
- package/dist/codegen-body-python.js.map +1 -1
- package/dist/codegen-python.d.ts +1 -0
- package/dist/codegen-python.js +1 -1
- package/dist/codegen-python.js.map +1 -1
- package/dist/core/emit-imports.d.ts +11 -0
- package/dist/core/emit-imports.js +166 -0
- package/dist/core/emit-imports.js.map +1 -0
- package/dist/core/emit-models.d.ts +14 -0
- package/dist/core/emit-models.js +86 -0
- package/dist/core/emit-models.js.map +1 -0
- package/dist/core/expr/helpers.d.ts +5 -0
- package/dist/core/expr/helpers.js +62 -0
- package/dist/core/expr/helpers.js.map +1 -0
- package/dist/core/expr/index.d.ts +9 -0
- package/dist/core/expr/index.js +2046 -0
- package/dist/core/expr/index.js.map +1 -0
- package/dist/core/fence-diagnostics.d.ts +17 -0
- package/dist/core/fence-diagnostics.js +86 -0
- package/dist/core/fence-diagnostics.js.map +1 -0
- package/dist/core/handlers/index.d.ts +74 -0
- package/dist/core/handlers/index.js +462 -0
- package/dist/core/handlers/index.js.map +1 -0
- package/dist/core/index.d.ts +3 -0
- package/dist/core/index.js +4 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/type-mapper.d.ts +4 -0
- package/dist/core/type-mapper.js +8 -0
- package/dist/core/type-mapper.js.map +1 -0
- package/dist/fastapi-portable.d.ts +7 -1
- package/dist/fastapi-portable.js +97 -74
- package/dist/fastapi-portable.js.map +1 -1
- package/dist/fastapi-response.d.ts +0 -4
- package/dist/fastapi-response.js +1 -1868
- package/dist/fastapi-response.js.map +1 -1
- package/dist/fastapi-route.js +24 -3
- package/dist/fastapi-route.js.map +1 -1
- package/dist/fastapi-utils.d.ts +2 -1
- package/dist/fastapi-utils.js +2 -58
- package/dist/fastapi-utils.js.map +1 -1
- package/dist/generators/data.d.ts +3 -1
- package/dist/generators/data.js +28 -1
- package/dist/generators/data.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/ir-semantics/python-leg.js +5 -0
- package/dist/ir-semantics/python-leg.js.map +1 -1
- package/dist/targets/python.d.ts +32 -0
- package/dist/targets/python.js +176 -0
- package/dist/targets/python.js.map +1 -0
- package/dist/transpiler-fastapi.js +23 -66
- package/dist/transpiler-fastapi.js.map +1 -1
- package/package.json +2 -2
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
* relative indent on the `return __k_tN` line; the wrapper prepends the
|
|
40
40
|
* surrounding indent so the post-emit result nests correctly. */
|
|
41
41
|
import { applyTemplate, isPostfixMutationOperator, isSupportedAssignOperator, KERN_STDLIB_MODULES, lookupStdlib, needsArgParens, needsBinaryParens, parseExpression, suggestStdlibMethod, } from '@kernlang/core';
|
|
42
|
+
import { KERN_FMT_HELPER_PY, KERN_I32_HELPER_PY, KERN_PAIR_HELPERS_PY, KERN_TMOD_HELPER_PY, } from './core/expr/index.js';
|
|
42
43
|
const INDENT_STEP = ' ';
|
|
43
44
|
function freshCtx(options) {
|
|
44
45
|
return {
|
|
@@ -49,6 +50,7 @@ function freshCtx(options) {
|
|
|
49
50
|
shadowedSymbols: new Set(),
|
|
50
51
|
localScopes: [],
|
|
51
52
|
regexScopes: [],
|
|
53
|
+
renameStack: [],
|
|
52
54
|
propagateStyle: options?.propagateStyle ?? 'value',
|
|
53
55
|
usedPropagation: false,
|
|
54
56
|
tryDepth: 0,
|
|
@@ -74,18 +76,6 @@ function freshCtx(options) {
|
|
|
74
76
|
* async iterable; sync data is wrapped at iteration entry).
|
|
75
77
|
*
|
|
76
78
|
* Both helpers are pure functions on the input; no captures, no globals. */
|
|
77
|
-
export const KERN_PAIR_HELPERS_PY = [
|
|
78
|
-
'def _kern_pairs(__k_v):',
|
|
79
|
-
' return __k_v.items() if hasattr(__k_v, "items") else iter(__k_v)',
|
|
80
|
-
'',
|
|
81
|
-
'async def _kern_async_pairs(__k_v):',
|
|
82
|
-
' if hasattr(__k_v, "__aiter__"):',
|
|
83
|
-
' async for __k_item in __k_v:',
|
|
84
|
-
' yield __k_item',
|
|
85
|
-
' else:',
|
|
86
|
-
' for __k_item in _kern_pairs(__k_v):',
|
|
87
|
-
' yield __k_item',
|
|
88
|
-
].join('\n');
|
|
89
79
|
/** KERN-canonical interpolation formatter for `fmt` / template literals.
|
|
90
80
|
* Python `f"{v}"` uses `str()`, which gives `True`/`False`/`None` — diverging
|
|
91
81
|
* from KERN's canonical lowercase `true`/`false`/`null` that TS template
|
|
@@ -97,14 +87,6 @@ export const KERN_PAIR_HELPERS_PY = [
|
|
|
97
87
|
* `True` → `"True"`. Co-located with the codegen so the production emitter and
|
|
98
88
|
* the differential harness use byte-identical defs; emitted at module scope
|
|
99
89
|
* via `BodyEmitResult.helpers` whenever an interpolation is wrapped. */
|
|
100
|
-
export const KERN_FMT_HELPER_PY = [
|
|
101
|
-
'def _kern_fmt(__k_v):',
|
|
102
|
-
' if isinstance(__k_v, bool):',
|
|
103
|
-
" return 'true' if __k_v else 'false'",
|
|
104
|
-
' if __k_v is None:',
|
|
105
|
-
" return 'null'",
|
|
106
|
-
' return str(__k_v)',
|
|
107
|
-
].join('\n');
|
|
108
90
|
/** Emit the body of a native KERN handler as Python source. Returns the
|
|
109
91
|
* joined body text. Each top-level line is unindented; nested `if`-bodies
|
|
110
92
|
* carry one level of 4-space indent per level of nesting.
|
|
@@ -148,8 +130,31 @@ export function emitNativeKernBodyPython(handlerNode, options) {
|
|
|
148
130
|
* when `propagateStyle: 'http-exception'` is in effect. */
|
|
149
131
|
export function emitNativeKernBodyPythonWithImports(handlerNode, options) {
|
|
150
132
|
const ctx = freshCtx(options);
|
|
151
|
-
|
|
152
|
-
|
|
133
|
+
// Push the param/outer-binding scope ABOVE the function-body scope so an
|
|
134
|
+
// inner-block `let x` that shadows a param is detected by
|
|
135
|
+
// `maybeRenameOnShadow` (nero red-team Challenge 2). `emitChildrenPy`
|
|
136
|
+
// pushes its own scope on top; we pop ours after it returns.
|
|
137
|
+
const outerBindings = options?.outerBindings ?? [];
|
|
138
|
+
if (outerBindings.length > 0) {
|
|
139
|
+
ctx.localScopes.push(new Map(outerBindings.map((n) => [n, 'const'])));
|
|
140
|
+
// `null` is the existing "no active regex binding" sentinel — consumed
|
|
141
|
+
// by `lookupRegexBinding` (returns null when the scope has the name but
|
|
142
|
+
// no regex literal was assigned to it). Mirroring it here keeps regex
|
|
143
|
+
// and local-binding scope stacks index-aligned.
|
|
144
|
+
ctx.regexScopes.push(new Map(outerBindings.map((n) => [n, null])));
|
|
145
|
+
ctx.renameStack.push(new Map());
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const code = emitChildrenPy(handlerNode.children ?? [], ctx, '').join('\n');
|
|
149
|
+
return { code, imports: ctx.imports, usedPropagation: ctx.usedPropagation, helpers: ctx.helpers };
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
if (outerBindings.length > 0) {
|
|
153
|
+
ctx.localScopes.pop();
|
|
154
|
+
ctx.regexScopes.pop();
|
|
155
|
+
ctx.renameStack.pop();
|
|
156
|
+
}
|
|
157
|
+
}
|
|
153
158
|
}
|
|
154
159
|
/** Body-statement node types that map to a SINGLE emitted line and may carry
|
|
155
160
|
* an inline same-line trailing comment captured by the migrator into a
|
|
@@ -169,6 +174,7 @@ function emitChildrenPy(children, ctx, indent, initialBindings = []) {
|
|
|
169
174
|
const lines = [];
|
|
170
175
|
ctx.localScopes.push(new Map(initialBindings));
|
|
171
176
|
ctx.regexScopes.push(new Map(initialBindings.map(([name]) => [name, null])));
|
|
177
|
+
ctx.renameStack.push(new Map());
|
|
172
178
|
try {
|
|
173
179
|
for (let i = 0; i < children.length; i++) {
|
|
174
180
|
const child = children[i];
|
|
@@ -530,9 +536,43 @@ function emitChildrenPy(children, ctx, indent, initialBindings = []) {
|
|
|
530
536
|
finally {
|
|
531
537
|
ctx.localScopes.pop();
|
|
532
538
|
ctx.regexScopes.pop();
|
|
539
|
+
ctx.renameStack.pop();
|
|
533
540
|
}
|
|
534
541
|
return lines;
|
|
535
542
|
}
|
|
543
|
+
/** Returns the rename for `name` from the innermost scope that has one, else
|
|
544
|
+
* `name` itself. Consulted in ident emission and at `let`/`assign` LHS
|
|
545
|
+
* rendering so a shadowed inner `let x` (emitted as `__k_shadow_x_N`) and
|
|
546
|
+
* its references inside the block resolve consistently, while outer
|
|
547
|
+
* references after the block still see the user-facing name. */
|
|
548
|
+
function resolveLocalRename(ctx, name) {
|
|
549
|
+
for (let i = ctx.renameStack.length - 1; i >= 0; i--) {
|
|
550
|
+
const scope = ctx.renameStack[i];
|
|
551
|
+
const renamed = scope.get(name);
|
|
552
|
+
if (renamed !== undefined)
|
|
553
|
+
return renamed;
|
|
554
|
+
}
|
|
555
|
+
return name;
|
|
556
|
+
}
|
|
557
|
+
/** Returns the renamed name if `let name=` here would shadow a binding in
|
|
558
|
+
* any OUTER scope; otherwise returns `name` unchanged. Used by `emitLetPy`
|
|
559
|
+
* to give an inner-block shadow a unique Python name + record the rename
|
|
560
|
+
* in the current scope so within-block references resolve to it. Returns
|
|
561
|
+
* `name` for function-body lets (no outer scope to shadow) and for
|
|
562
|
+
* non-shadowing inner lets (so unrelated locals stay user-friendly). */
|
|
563
|
+
function maybeRenameOnShadow(ctx, name) {
|
|
564
|
+
// Only the inner-most CURRENT scope is the "newcomer"; check OUTER scopes.
|
|
565
|
+
if (ctx.localScopes.length < 2)
|
|
566
|
+
return name;
|
|
567
|
+
for (let i = ctx.localScopes.length - 2; i >= 0; i--) {
|
|
568
|
+
if (ctx.localScopes[i].has(name)) {
|
|
569
|
+
const renamed = `__k_shadow_${name}_${++ctx.gensymCounter}`;
|
|
570
|
+
ctx.renameStack.at(-1)?.set(name, renamed);
|
|
571
|
+
return renamed;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return name;
|
|
575
|
+
}
|
|
536
576
|
function emitRangeForPy(node, ctx, indent) {
|
|
537
577
|
const props = (node.props ?? {});
|
|
538
578
|
const name = String(props.name ?? '');
|
|
@@ -797,15 +837,22 @@ function emitSetPy(node, ctx) {
|
|
|
797
837
|
}
|
|
798
838
|
function emitLetPy(node, ctx) {
|
|
799
839
|
const props = (node.props ?? {});
|
|
800
|
-
const
|
|
840
|
+
const userName = String(props.name ?? '_');
|
|
801
841
|
validateBodyLetKind(props.kind);
|
|
802
|
-
declareLocalBinding(ctx,
|
|
842
|
+
declareLocalBinding(ctx, userName, props.kind === 'let' ? 'let' : 'const');
|
|
843
|
+
// Block-scope fix: an inner `let` that shadows an outer binding gets a
|
|
844
|
+
// gensym'd Python name so TS `let x=1; if(c){let x=2}; return x` (returns 1)
|
|
845
|
+
// doesn't degrade to Python's flat scoping (would return 2). The rename is
|
|
846
|
+
// stored in the current scope's renameStack and resolved by every ident
|
|
847
|
+
// emission inside this block; outer references after the block see the
|
|
848
|
+
// user-facing name (no entry in any in-scope rename map).
|
|
849
|
+
const name = maybeRenameOnShadow(ctx, userName);
|
|
803
850
|
const rawValue = props.value;
|
|
804
851
|
if (rawValue === undefined || rawValue === '') {
|
|
805
852
|
return [`${name} = None`];
|
|
806
853
|
}
|
|
807
854
|
const valueIR = parseExpression(String(rawValue));
|
|
808
|
-
setRegexBinding(ctx,
|
|
855
|
+
setRegexBinding(ctx, userName, valueIR.kind === 'regexLit' ? valueIR : null);
|
|
809
856
|
if (valueIR.kind === 'propagate' && valueIR.op === '?') {
|
|
810
857
|
rejectPropagationInsideTry(ctx);
|
|
811
858
|
const tmp = `__k_t${++ctx.gensymCounter}`;
|
|
@@ -1250,13 +1297,23 @@ function emitPyExprCtx(node, ctx) {
|
|
|
1250
1297
|
case 'regexLit':
|
|
1251
1298
|
ctx.imports.add('re');
|
|
1252
1299
|
return `__k_re.compile(${pyRegexPattern(node)}, ${pyRegexFlags(node.flags, { allowGlobal: true })})`;
|
|
1253
|
-
case 'ident':
|
|
1300
|
+
case 'ident': {
|
|
1301
|
+
// Block-scope rename takes precedence — an inner `let x` that shadows
|
|
1302
|
+
// an outer binding was emitted with a gensym (`__k_shadow_x_N`) and
|
|
1303
|
+
// every in-block reference must use the same gensym. Walk renameStack
|
|
1304
|
+
// top-to-bottom (most-inner scope wins); after the inner block ends
|
|
1305
|
+
// its scope is popped, so post-block references naturally see the
|
|
1306
|
+
// outer user-facing name again.
|
|
1307
|
+
const blockRename = resolveLocalRename(ctx, node.name);
|
|
1308
|
+
if (blockRename !== node.name)
|
|
1309
|
+
return blockRename;
|
|
1254
1310
|
// Slice 3a — apply symbol-map rename so KERN-form `userId` becomes
|
|
1255
1311
|
// Python-form `user_id`. Identifiers not in the map (locals, globals,
|
|
1256
1312
|
// module names) pass through unchanged.
|
|
1257
1313
|
if (ctx.shadowedSymbols.has(node.name))
|
|
1258
1314
|
return node.name;
|
|
1259
1315
|
return ctx.symbolMap[node.name] ?? node.name;
|
|
1316
|
+
}
|
|
1260
1317
|
case 'member':
|
|
1261
1318
|
case 'call':
|
|
1262
1319
|
case 'index': {
|
|
@@ -1302,6 +1359,16 @@ function emitPyExprCtx(node, ctx) {
|
|
|
1302
1359
|
return out;
|
|
1303
1360
|
}
|
|
1304
1361
|
case 'binary': {
|
|
1362
|
+
if (node.op === '|' ||
|
|
1363
|
+
node.op === '&' ||
|
|
1364
|
+
node.op === '^' ||
|
|
1365
|
+
node.op === '<<' ||
|
|
1366
|
+
node.op === '>>' ||
|
|
1367
|
+
node.op === '%') {
|
|
1368
|
+
const transformed = lowerBitwiseAndModuloAST(node);
|
|
1369
|
+
registerHelpers(transformed, ctx);
|
|
1370
|
+
return emitPyExprCtx(transformed, ctx);
|
|
1371
|
+
}
|
|
1305
1372
|
// Slice 2c — arithmetic / comparison / logical lowering for Python.
|
|
1306
1373
|
// Use precedence-aware paren-wrapping so `a + b * c` doesn't redundantly
|
|
1307
1374
|
// wrap the right side (`a + (b * c)`) — same rule as the TS side.
|
|
@@ -1359,6 +1426,11 @@ function emitPyExprCtx(node, ctx) {
|
|
|
1359
1426
|
return `${lp} ${op} ${rp}`;
|
|
1360
1427
|
}
|
|
1361
1428
|
case 'unary': {
|
|
1429
|
+
if (node.op === '~') {
|
|
1430
|
+
const transformed = lowerBitwiseAndModuloAST(node);
|
|
1431
|
+
registerHelpers(transformed, ctx);
|
|
1432
|
+
return emitPyExprCtx(transformed, ctx);
|
|
1433
|
+
}
|
|
1362
1434
|
// Slice 2c — `!x` → `not x`, `-x` → `-x`.
|
|
1363
1435
|
// Slice typeof — expose the now-eligible native KERN `typeof` shape on
|
|
1364
1436
|
// Python too. Dynamic Python values are an approximation of JS typeof:
|
|
@@ -1828,4 +1900,187 @@ function lowerListLambdaPython(moduleName, methodName, call, ctx) {
|
|
|
1828
1900
|
ctx.shadowedSymbols = previous;
|
|
1829
1901
|
}
|
|
1830
1902
|
}
|
|
1903
|
+
export function lowerBitwiseAndModuloAST(node) {
|
|
1904
|
+
switch (node.kind) {
|
|
1905
|
+
case 'binary': {
|
|
1906
|
+
const left = lowerBitwiseAndModuloAST(node.left);
|
|
1907
|
+
const right = lowerBitwiseAndModuloAST(node.right);
|
|
1908
|
+
if (node.op === '|' || node.op === '&' || node.op === '^' || node.op === '<<' || node.op === '>>') {
|
|
1909
|
+
let rewrittenRight = right;
|
|
1910
|
+
if (node.op === '<<' || node.op === '>>') {
|
|
1911
|
+
const i32Right = wrapInI32(right);
|
|
1912
|
+
rewrittenRight = {
|
|
1913
|
+
kind: 'binary',
|
|
1914
|
+
op: '&',
|
|
1915
|
+
left: i32Right,
|
|
1916
|
+
right: { kind: 'numLit', value: 31, raw: '31' },
|
|
1917
|
+
};
|
|
1918
|
+
}
|
|
1919
|
+
else {
|
|
1920
|
+
rewrittenRight = wrapInI32(right);
|
|
1921
|
+
}
|
|
1922
|
+
const i32Left = wrapInI32(left);
|
|
1923
|
+
const bitwiseNode = {
|
|
1924
|
+
kind: 'binary',
|
|
1925
|
+
op: node.op,
|
|
1926
|
+
left: i32Left,
|
|
1927
|
+
right: rewrittenRight,
|
|
1928
|
+
};
|
|
1929
|
+
return wrapInI32(bitwiseNode);
|
|
1930
|
+
}
|
|
1931
|
+
else if (node.op === '%') {
|
|
1932
|
+
return {
|
|
1933
|
+
kind: 'call',
|
|
1934
|
+
callee: { kind: 'ident', name: '_tmod' },
|
|
1935
|
+
args: [left, right],
|
|
1936
|
+
optional: false,
|
|
1937
|
+
};
|
|
1938
|
+
}
|
|
1939
|
+
return { ...node, left, right };
|
|
1940
|
+
}
|
|
1941
|
+
case 'unary': {
|
|
1942
|
+
const argument = lowerBitwiseAndModuloAST(node.argument);
|
|
1943
|
+
if (node.op === '~') {
|
|
1944
|
+
const i32Arg = wrapInI32(argument);
|
|
1945
|
+
const unaryNode = {
|
|
1946
|
+
kind: 'unary',
|
|
1947
|
+
op: '~',
|
|
1948
|
+
argument: i32Arg,
|
|
1949
|
+
};
|
|
1950
|
+
return wrapInI32(unaryNode);
|
|
1951
|
+
}
|
|
1952
|
+
return { ...node, argument };
|
|
1953
|
+
}
|
|
1954
|
+
case 'tmplLit':
|
|
1955
|
+
return { ...node, expressions: node.expressions.map(lowerBitwiseAndModuloAST) };
|
|
1956
|
+
case 'member':
|
|
1957
|
+
return { ...node, object: lowerBitwiseAndModuloAST(node.object) };
|
|
1958
|
+
case 'index':
|
|
1959
|
+
return { ...node, object: lowerBitwiseAndModuloAST(node.object), index: lowerBitwiseAndModuloAST(node.index) };
|
|
1960
|
+
case 'call':
|
|
1961
|
+
return {
|
|
1962
|
+
...node,
|
|
1963
|
+
callee: lowerBitwiseAndModuloAST(node.callee),
|
|
1964
|
+
args: node.args.map(lowerBitwiseAndModuloAST),
|
|
1965
|
+
};
|
|
1966
|
+
case 'lambda':
|
|
1967
|
+
return { ...node, body: lowerBitwiseAndModuloAST(node.body) };
|
|
1968
|
+
case 'spread':
|
|
1969
|
+
return { ...node, argument: lowerBitwiseAndModuloAST(node.argument) };
|
|
1970
|
+
case 'await':
|
|
1971
|
+
return { ...node, argument: lowerBitwiseAndModuloAST(node.argument) };
|
|
1972
|
+
case 'new':
|
|
1973
|
+
return { ...node, argument: lowerBitwiseAndModuloAST(node.argument) };
|
|
1974
|
+
case 'typeAssert':
|
|
1975
|
+
return { ...node, expression: lowerBitwiseAndModuloAST(node.expression) };
|
|
1976
|
+
case 'nonNull':
|
|
1977
|
+
return { ...node, expression: lowerBitwiseAndModuloAST(node.expression) };
|
|
1978
|
+
case 'propagate':
|
|
1979
|
+
return { ...node, argument: lowerBitwiseAndModuloAST(node.argument) };
|
|
1980
|
+
case 'objectLit':
|
|
1981
|
+
return {
|
|
1982
|
+
...node,
|
|
1983
|
+
entries: node.entries.map((e) => 'kind' in e && e.kind === 'spread'
|
|
1984
|
+
? { kind: 'spread', argument: lowerBitwiseAndModuloAST(e.argument) }
|
|
1985
|
+
: { ...e, value: lowerBitwiseAndModuloAST(e.value) }),
|
|
1986
|
+
};
|
|
1987
|
+
case 'arrayLit':
|
|
1988
|
+
return { ...node, items: node.items.map(lowerBitwiseAndModuloAST) };
|
|
1989
|
+
case 'conditional':
|
|
1990
|
+
return {
|
|
1991
|
+
...node,
|
|
1992
|
+
test: lowerBitwiseAndModuloAST(node.test),
|
|
1993
|
+
consequent: lowerBitwiseAndModuloAST(node.consequent),
|
|
1994
|
+
alternate: lowerBitwiseAndModuloAST(node.alternate),
|
|
1995
|
+
};
|
|
1996
|
+
default:
|
|
1997
|
+
return node;
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
function wrapInI32(node) {
|
|
2001
|
+
return {
|
|
2002
|
+
kind: 'call',
|
|
2003
|
+
callee: { kind: 'ident', name: '_i32' },
|
|
2004
|
+
args: [node],
|
|
2005
|
+
optional: false,
|
|
2006
|
+
};
|
|
2007
|
+
}
|
|
2008
|
+
export function registerHelpers(node, ctx) {
|
|
2009
|
+
switch (node.kind) {
|
|
2010
|
+
case 'call':
|
|
2011
|
+
if (node.callee.kind === 'ident') {
|
|
2012
|
+
if (node.callee.name === '_i32') {
|
|
2013
|
+
ctx.helpers.add(KERN_I32_HELPER_PY);
|
|
2014
|
+
}
|
|
2015
|
+
else if (node.callee.name === '_tmod') {
|
|
2016
|
+
ctx.helpers.add(KERN_TMOD_HELPER_PY);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
registerHelpers(node.callee, ctx);
|
|
2020
|
+
for (const arg of node.args) {
|
|
2021
|
+
registerHelpers(arg, ctx);
|
|
2022
|
+
}
|
|
2023
|
+
break;
|
|
2024
|
+
case 'binary':
|
|
2025
|
+
registerHelpers(node.left, ctx);
|
|
2026
|
+
registerHelpers(node.right, ctx);
|
|
2027
|
+
break;
|
|
2028
|
+
case 'unary':
|
|
2029
|
+
registerHelpers(node.argument, ctx);
|
|
2030
|
+
break;
|
|
2031
|
+
case 'tmplLit':
|
|
2032
|
+
for (const expr of node.expressions) {
|
|
2033
|
+
registerHelpers(expr, ctx);
|
|
2034
|
+
}
|
|
2035
|
+
break;
|
|
2036
|
+
case 'member':
|
|
2037
|
+
registerHelpers(node.object, ctx);
|
|
2038
|
+
break;
|
|
2039
|
+
case 'index':
|
|
2040
|
+
registerHelpers(node.object, ctx);
|
|
2041
|
+
registerHelpers(node.index, ctx);
|
|
2042
|
+
break;
|
|
2043
|
+
case 'lambda':
|
|
2044
|
+
registerHelpers(node.body, ctx);
|
|
2045
|
+
break;
|
|
2046
|
+
case 'spread':
|
|
2047
|
+
registerHelpers(node.argument, ctx);
|
|
2048
|
+
break;
|
|
2049
|
+
case 'await':
|
|
2050
|
+
registerHelpers(node.argument, ctx);
|
|
2051
|
+
break;
|
|
2052
|
+
case 'new':
|
|
2053
|
+
registerHelpers(node.argument, ctx);
|
|
2054
|
+
break;
|
|
2055
|
+
case 'typeAssert':
|
|
2056
|
+
registerHelpers(node.expression, ctx);
|
|
2057
|
+
break;
|
|
2058
|
+
case 'nonNull':
|
|
2059
|
+
registerHelpers(node.expression, ctx);
|
|
2060
|
+
break;
|
|
2061
|
+
case 'propagate':
|
|
2062
|
+
registerHelpers(node.argument, ctx);
|
|
2063
|
+
break;
|
|
2064
|
+
case 'objectLit':
|
|
2065
|
+
for (const e of node.entries) {
|
|
2066
|
+
if ('kind' in e && e.kind === 'spread') {
|
|
2067
|
+
registerHelpers(e.argument, ctx);
|
|
2068
|
+
}
|
|
2069
|
+
else {
|
|
2070
|
+
registerHelpers(e.value, ctx);
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
break;
|
|
2074
|
+
case 'arrayLit':
|
|
2075
|
+
for (const item of node.items) {
|
|
2076
|
+
registerHelpers(item, ctx);
|
|
2077
|
+
}
|
|
2078
|
+
break;
|
|
2079
|
+
case 'conditional':
|
|
2080
|
+
registerHelpers(node.test, ctx);
|
|
2081
|
+
registerHelpers(node.consequent, ctx);
|
|
2082
|
+
registerHelpers(node.alternate, ctx);
|
|
2083
|
+
break;
|
|
2084
|
+
}
|
|
2085
|
+
}
|
|
1831
2086
|
//# sourceMappingURL=codegen-body-python.js.map
|