@lewin671/python-vm 0.1.0
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/.claude/settings.local.json +3 -0
- package/.prettierrc +7 -0
- package/Agents.md +66 -0
- package/README.md +93 -0
- package/README_zh-CN.md +93 -0
- package/SETUP.md +171 -0
- package/dist/compiler.d.ts +20 -0
- package/dist/compiler.js +91 -0
- package/dist/compiler_module/compiler.d.ts +8 -0
- package/dist/compiler_module/compiler.js +22 -0
- package/dist/compiler_module/index.d.ts +2 -0
- package/dist/compiler_module/index.js +6 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +67 -0
- package/dist/lexer/index.d.ts +2 -0
- package/dist/lexer/index.js +6 -0
- package/dist/lexer/lexer.d.ts +16 -0
- package/dist/lexer/lexer.js +403 -0
- package/dist/parser/expressions.d.ts +30 -0
- package/dist/parser/expressions.js +483 -0
- package/dist/parser/index.d.ts +2 -0
- package/dist/parser/index.js +6 -0
- package/dist/parser/parser.d.ts +63 -0
- package/dist/parser/parser.js +129 -0
- package/dist/parser/statements.d.ts +20 -0
- package/dist/parser/statements.js +388 -0
- package/dist/parser/targets.d.ts +6 -0
- package/dist/parser/targets.js +75 -0
- package/dist/types/ast.d.ts +63 -0
- package/dist/types/ast.js +60 -0
- package/dist/types/bytecode.d.ts +38 -0
- package/dist/types/bytecode.js +35 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.js +20 -0
- package/dist/types/token.d.ts +34 -0
- package/dist/types/token.js +39 -0
- package/dist/vm/builtins.d.ts +4 -0
- package/dist/vm/builtins.js +269 -0
- package/dist/vm/callable.d.ts +8 -0
- package/dist/vm/callable.js +161 -0
- package/dist/vm/execution.d.ts +15 -0
- package/dist/vm/execution.js +283 -0
- package/dist/vm/expression-generator.d.ts +3 -0
- package/dist/vm/expression-generator.js +70 -0
- package/dist/vm/expressions.d.ts +13 -0
- package/dist/vm/expressions.js +390 -0
- package/dist/vm/imports.d.ts +7 -0
- package/dist/vm/imports.js +99 -0
- package/dist/vm/index.d.ts +3 -0
- package/dist/vm/index.js +21 -0
- package/dist/vm/operations.d.ts +16 -0
- package/dist/vm/operations.js +439 -0
- package/dist/vm/runtime-types.d.ts +84 -0
- package/dist/vm/runtime-types.js +290 -0
- package/dist/vm/statements.d.ts +7 -0
- package/dist/vm/statements.js +381 -0
- package/dist/vm/truthy.d.ts +4 -0
- package/dist/vm/truthy.js +47 -0
- package/dist/vm/value-utils.d.ts +28 -0
- package/dist/vm/value-utils.js +225 -0
- package/dist/vm/vm.d.ts +56 -0
- package/dist/vm/vm.js +75 -0
- package/examples/assert_testing.py +38 -0
- package/examples/big_int_precision.py +2 -0
- package/examples/boolean_logic.py +35 -0
- package/examples/break_continue.py +43 -0
- package/examples/classes_objects.py +43 -0
- package/examples/compiler_killer_async.py +6 -0
- package/examples/compiler_killer_bigint.py +3 -0
- package/examples/compiler_killer_bool_int_dict_key.py +5 -0
- package/examples/compiler_killer_bool_len.py +9 -0
- package/examples/compiler_killer_floor_division.py +4 -0
- package/examples/compiler_killer_is_identity.py +3 -0
- package/examples/compiler_killer_list_sort_return.py +3 -0
- package/examples/compiler_killer_match.py +13 -0
- package/examples/compiler_killer_negative_repeat.py +3 -0
- package/examples/compiler_killer_negative_zero_repr.py +3 -0
- package/examples/compiler_killer_rounding.py +4 -0
- package/examples/compiler_killer_slice_assign.py +3 -0
- package/examples/comprehensions.py +28 -0
- package/examples/conditions.py +13 -0
- package/examples/context_manager.py +35 -0
- package/examples/decorators.py +50 -0
- package/examples/exceptions.py +40 -0
- package/examples/fibonacci.py +10 -0
- package/examples/functions.py +38 -0
- package/examples/generator.py +51 -0
- package/examples/global_nonlocal.py +48 -0
- package/examples/hello.py +3 -0
- package/examples/itertools_example.py +33 -0
- package/examples/lists_dicts.py +29 -0
- package/examples/loops.py +19 -0
- package/examples/math_ops.py +15 -0
- package/examples/nan_set.py +6 -0
- package/examples/numbers_operators.py +51 -0
- package/examples/sets.py +36 -0
- package/examples/slicing.py +29 -0
- package/examples/starred_unpacking.py +3 -0
- package/examples/string_formatting.py +36 -0
- package/examples/strings.py +22 -0
- package/examples/tuples.py +45 -0
- package/examples/type_conversion.py +41 -0
- package/jest.config.js +15 -0
- package/notes/iterations/compiler-runtime/compiler-runtime_2025-09-16.md +25 -0
- package/notes/iterations/compiler-runtime/compiler-runtime_2026-01-16.md +24 -0
- package/notes/iterations/compiler-runtime/compiler-runtime_test_2026-01-16.md +21 -0
- package/notes/iterations/floor-division/floor-division_2026-01-16.md +29 -0
- package/package.json +36 -0
- package/prompts/commit.txt +9 -0
- package/prompts/task.txt +21 -0
- package/prompts/test.txt +23 -0
- package/scripts/codex-loop.js +215 -0
- package/scripts/verify.sh +12 -0
- package/src/compiler.ts +58 -0
- package/src/compiler_module/compiler.ts +19 -0
- package/src/compiler_module/index.ts +1 -0
- package/src/index.ts +39 -0
- package/src/lexer/index.ts +1 -0
- package/src/lexer/lexer.ts +402 -0
- package/src/parser/expressions.ts +462 -0
- package/src/parser/index.ts +1 -0
- package/src/parser/parser.ts +102 -0
- package/src/parser/statements.ts +366 -0
- package/src/parser/targets.ts +71 -0
- package/src/types/ast.ts +64 -0
- package/src/types/bytecode.ts +50 -0
- package/src/types/index.ts +3 -0
- package/src/types/token.ts +44 -0
- package/src/vm/builtins.ts +237 -0
- package/src/vm/callable.ts +154 -0
- package/src/vm/execution.ts +251 -0
- package/src/vm/expression-generator.ts +65 -0
- package/src/vm/expressions.ts +373 -0
- package/src/vm/imports.ts +61 -0
- package/src/vm/index.ts +2 -0
- package/src/vm/operations.ts +414 -0
- package/src/vm/runtime-types.ts +292 -0
- package/src/vm/statements.ts +358 -0
- package/src/vm/truthy.ts +36 -0
- package/src/vm/value-utils.ts +173 -0
- package/src/vm/vm.ts +80 -0
- package/tests/compiler.test.ts +111 -0
- package/tsconfig.json +20 -0
- package/vitest.config.ts +16 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyBinary = applyBinary;
|
|
4
|
+
exports.formatPercent = formatPercent;
|
|
5
|
+
exports.getSubscript = getSubscript;
|
|
6
|
+
exports.computeSliceBounds = computeSliceBounds;
|
|
7
|
+
exports.computeSliceIndices = computeSliceIndices;
|
|
8
|
+
exports.normalizeSliceStep = normalizeSliceStep;
|
|
9
|
+
exports.getAttribute = getAttribute;
|
|
10
|
+
exports.setAttribute = setAttribute;
|
|
11
|
+
exports.findClassAttribute = findClassAttribute;
|
|
12
|
+
const types_1 = require("../types");
|
|
13
|
+
const runtime_types_1 = require("./runtime-types");
|
|
14
|
+
const value_utils_1 = require("./value-utils");
|
|
15
|
+
function applyBinary(op, left, right) {
|
|
16
|
+
if ((0, value_utils_1.isComplex)(left) || (0, value_utils_1.isComplex)(right)) {
|
|
17
|
+
const a = (0, value_utils_1.toComplex)(left);
|
|
18
|
+
const b = (0, value_utils_1.toComplex)(right);
|
|
19
|
+
switch (op) {
|
|
20
|
+
case '+':
|
|
21
|
+
return { __complex__: true, re: a.re + b.re, im: a.im + b.im };
|
|
22
|
+
case '-':
|
|
23
|
+
return { __complex__: true, re: a.re - b.re, im: a.im - b.im };
|
|
24
|
+
case '*':
|
|
25
|
+
return {
|
|
26
|
+
__complex__: true,
|
|
27
|
+
re: a.re * b.re - a.im * b.im,
|
|
28
|
+
im: a.re * b.im + a.im * b.re,
|
|
29
|
+
};
|
|
30
|
+
default:
|
|
31
|
+
throw new runtime_types_1.PyException('TypeError', `unsupported complex operator ${op}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
switch (op) {
|
|
35
|
+
case '+':
|
|
36
|
+
if (Array.isArray(left) && Array.isArray(right)) {
|
|
37
|
+
const result = [...left, ...right];
|
|
38
|
+
if (left.__tuple__ && right.__tuple__) {
|
|
39
|
+
result.__tuple__ = true;
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
if ((0, value_utils_1.isFloatLike)(left) || (0, value_utils_1.isFloatLike)(right)) {
|
|
44
|
+
return new Number((0, value_utils_1.toNumber)(left) + (0, value_utils_1.toNumber)(right));
|
|
45
|
+
}
|
|
46
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
47
|
+
return (0, value_utils_1.toBigIntValue)(left) + (0, value_utils_1.toBigIntValue)(right);
|
|
48
|
+
}
|
|
49
|
+
return left + right;
|
|
50
|
+
case '-':
|
|
51
|
+
if (left instanceof Set && right instanceof Set) {
|
|
52
|
+
const result = new Set(left);
|
|
53
|
+
for (const item of right.values())
|
|
54
|
+
result.delete(item);
|
|
55
|
+
return result;
|
|
56
|
+
}
|
|
57
|
+
if ((0, value_utils_1.isFloatLike)(left) || (0, value_utils_1.isFloatLike)(right)) {
|
|
58
|
+
return new Number((0, value_utils_1.toNumber)(left) - (0, value_utils_1.toNumber)(right));
|
|
59
|
+
}
|
|
60
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
61
|
+
return (0, value_utils_1.toBigIntValue)(left) - (0, value_utils_1.toBigIntValue)(right);
|
|
62
|
+
}
|
|
63
|
+
return left - right;
|
|
64
|
+
case '*':
|
|
65
|
+
if (typeof left === 'string' && (0, value_utils_1.isIntLike)(right)) {
|
|
66
|
+
const count = (0, value_utils_1.toNumber)(right);
|
|
67
|
+
if (count <= 0)
|
|
68
|
+
return '';
|
|
69
|
+
return left.repeat(count);
|
|
70
|
+
}
|
|
71
|
+
if (typeof right === 'string' && (0, value_utils_1.isIntLike)(left)) {
|
|
72
|
+
const count = (0, value_utils_1.toNumber)(left);
|
|
73
|
+
if (count <= 0)
|
|
74
|
+
return '';
|
|
75
|
+
return right.repeat(count);
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(left) && (0, value_utils_1.isIntLike)(right)) {
|
|
78
|
+
const count = (0, value_utils_1.toNumber)(right);
|
|
79
|
+
if (count <= 0) {
|
|
80
|
+
const result = [];
|
|
81
|
+
if (left.__tuple__) {
|
|
82
|
+
result.__tuple__ = true;
|
|
83
|
+
}
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
const result = Array(count).fill(null).flatMap(() => left);
|
|
87
|
+
if (left.__tuple__) {
|
|
88
|
+
result.__tuple__ = true;
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
if ((0, value_utils_1.isFloatLike)(left) || (0, value_utils_1.isFloatLike)(right)) {
|
|
93
|
+
return new Number((0, value_utils_1.toNumber)(left) * (0, value_utils_1.toNumber)(right));
|
|
94
|
+
}
|
|
95
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
96
|
+
return (0, value_utils_1.toBigIntValue)(left) * (0, value_utils_1.toBigIntValue)(right);
|
|
97
|
+
}
|
|
98
|
+
return left * right;
|
|
99
|
+
case '/':
|
|
100
|
+
if (right === 0 || right === 0n)
|
|
101
|
+
throw new runtime_types_1.PyException('ZeroDivisionError', 'division by zero');
|
|
102
|
+
return new Number((0, value_utils_1.toNumber)(left) / (0, value_utils_1.toNumber)(right));
|
|
103
|
+
case '//':
|
|
104
|
+
if (right === 0 || right === 0n)
|
|
105
|
+
throw new runtime_types_1.PyException('ZeroDivisionError', 'division by zero');
|
|
106
|
+
if ((0, value_utils_1.isFloatLike)(left) || (0, value_utils_1.isFloatLike)(right)) {
|
|
107
|
+
return new Number(Math.floor((0, value_utils_1.toNumber)(left) / (0, value_utils_1.toNumber)(right)));
|
|
108
|
+
}
|
|
109
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
110
|
+
return (0, value_utils_1.bigIntFloorDiv)((0, value_utils_1.toBigIntValue)(left), (0, value_utils_1.toBigIntValue)(right));
|
|
111
|
+
}
|
|
112
|
+
return Math.floor(left / right);
|
|
113
|
+
case '%':
|
|
114
|
+
if (typeof left === 'string') {
|
|
115
|
+
return this.formatPercent(left, right);
|
|
116
|
+
}
|
|
117
|
+
return (0, value_utils_1.pythonModulo)(left, right);
|
|
118
|
+
case '**':
|
|
119
|
+
if ((0, value_utils_1.isIntLike)(left) && (0, value_utils_1.isIntLike)(right) && !(0, value_utils_1.isFloatLike)(left) && !(0, value_utils_1.isFloatLike)(right)) {
|
|
120
|
+
const exponentNum = (0, value_utils_1.toNumber)(right);
|
|
121
|
+
if (Number.isInteger(exponentNum) && exponentNum >= 0) {
|
|
122
|
+
const approx = Math.pow((0, value_utils_1.toNumber)(left), exponentNum);
|
|
123
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right) || !Number.isSafeInteger(approx)) {
|
|
124
|
+
return (0, value_utils_1.toBigIntValue)(left) ** (0, value_utils_1.toBigIntValue)(right);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
129
|
+
const exponent = (0, value_utils_1.toBigIntValue)(right);
|
|
130
|
+
if (exponent < 0n) {
|
|
131
|
+
return new Number(Math.pow((0, value_utils_1.toNumber)(left), (0, value_utils_1.toNumber)(right)));
|
|
132
|
+
}
|
|
133
|
+
return (0, value_utils_1.toBigIntValue)(left) ** exponent;
|
|
134
|
+
}
|
|
135
|
+
return Math.pow((0, value_utils_1.toNumber)(left), (0, value_utils_1.toNumber)(right));
|
|
136
|
+
case '&':
|
|
137
|
+
if (left instanceof Set && right instanceof Set) {
|
|
138
|
+
const result = new Set();
|
|
139
|
+
for (const item of left.values()) {
|
|
140
|
+
if (right.has(item))
|
|
141
|
+
result.add(item);
|
|
142
|
+
}
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
146
|
+
return (0, value_utils_1.toBigIntValue)(left) & (0, value_utils_1.toBigIntValue)(right);
|
|
147
|
+
}
|
|
148
|
+
return left & right;
|
|
149
|
+
case '|':
|
|
150
|
+
if (left instanceof Set && right instanceof Set) {
|
|
151
|
+
const result = new Set(left);
|
|
152
|
+
for (const item of right.values())
|
|
153
|
+
result.add(item);
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
157
|
+
return (0, value_utils_1.toBigIntValue)(left) | (0, value_utils_1.toBigIntValue)(right);
|
|
158
|
+
}
|
|
159
|
+
return left | right;
|
|
160
|
+
case '^':
|
|
161
|
+
if (left instanceof Set && right instanceof Set) {
|
|
162
|
+
const result = new Set();
|
|
163
|
+
for (const item of left.values()) {
|
|
164
|
+
if (!right.has(item))
|
|
165
|
+
result.add(item);
|
|
166
|
+
}
|
|
167
|
+
for (const item of right.values()) {
|
|
168
|
+
if (!left.has(item))
|
|
169
|
+
result.add(item);
|
|
170
|
+
}
|
|
171
|
+
return result;
|
|
172
|
+
}
|
|
173
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
174
|
+
return (0, value_utils_1.toBigIntValue)(left) ^ (0, value_utils_1.toBigIntValue)(right);
|
|
175
|
+
}
|
|
176
|
+
return left ^ right;
|
|
177
|
+
case '<<':
|
|
178
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
179
|
+
return (0, value_utils_1.toBigIntValue)(left) << (0, value_utils_1.toBigIntValue)(right);
|
|
180
|
+
}
|
|
181
|
+
return left << right;
|
|
182
|
+
case '>>':
|
|
183
|
+
if ((0, value_utils_1.shouldUseBigInt)(left, right)) {
|
|
184
|
+
return (0, value_utils_1.toBigIntValue)(left) >> (0, value_utils_1.toBigIntValue)(right);
|
|
185
|
+
}
|
|
186
|
+
return left >> right;
|
|
187
|
+
default:
|
|
188
|
+
throw new runtime_types_1.PyException('TypeError', `unsupported operator ${op}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function formatPercent(format, value) {
|
|
192
|
+
const values = Array.isArray(value) ? value : [value];
|
|
193
|
+
let index = 0;
|
|
194
|
+
return format.replace(/%[sdfo]/g, (match) => {
|
|
195
|
+
const val = values[index++];
|
|
196
|
+
if (match === '%d')
|
|
197
|
+
return typeof val === 'bigint' ? val.toString() : String(parseInt(val, 10));
|
|
198
|
+
if (match === '%f')
|
|
199
|
+
return String(parseFloat(val));
|
|
200
|
+
return String(val);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function getSubscript(obj, index) {
|
|
204
|
+
if (index && index.type === types_1.ASTNodeType.SLICE) {
|
|
205
|
+
const start = index.start !== null && index.start !== undefined ? index.start : null;
|
|
206
|
+
const end = index.end !== null && index.end !== undefined ? index.end : null;
|
|
207
|
+
const step = index.step !== null && index.step !== undefined ? index.step : 1;
|
|
208
|
+
const indices = this.computeSliceIndices(obj.length, start, end, step);
|
|
209
|
+
const result = [];
|
|
210
|
+
for (const idx of indices)
|
|
211
|
+
result.push(obj[idx]);
|
|
212
|
+
if (typeof obj === 'string')
|
|
213
|
+
return result.join('');
|
|
214
|
+
if (Array.isArray(obj) && obj.__tuple__) {
|
|
215
|
+
result.__tuple__ = true;
|
|
216
|
+
}
|
|
217
|
+
return result;
|
|
218
|
+
}
|
|
219
|
+
if (Array.isArray(obj) || typeof obj === 'string') {
|
|
220
|
+
let idx = index;
|
|
221
|
+
if ((0, value_utils_1.isIntLike)(idx) && (0, value_utils_1.toNumber)(idx) < 0) {
|
|
222
|
+
idx = obj.length + (0, value_utils_1.toNumber)(idx);
|
|
223
|
+
}
|
|
224
|
+
if ((0, value_utils_1.isIntLike)(idx)) {
|
|
225
|
+
idx = (0, value_utils_1.toNumber)(idx);
|
|
226
|
+
}
|
|
227
|
+
return obj[idx];
|
|
228
|
+
}
|
|
229
|
+
if (obj instanceof runtime_types_1.PyDict) {
|
|
230
|
+
return obj.get(index);
|
|
231
|
+
}
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
function computeSliceBounds(length, start, end, step) {
|
|
235
|
+
const stepValue = this.normalizeSliceStep(step);
|
|
236
|
+
const startProvided = start !== null && start !== undefined;
|
|
237
|
+
const endProvided = end !== null && end !== undefined;
|
|
238
|
+
let startValue = startProvided ? (0, value_utils_1.toNumber)(start) : null;
|
|
239
|
+
let endValue = endProvided ? (0, value_utils_1.toNumber)(end) : null;
|
|
240
|
+
if (startValue === null)
|
|
241
|
+
startValue = stepValue < 0 ? length - 1 : 0;
|
|
242
|
+
if (endValue === null)
|
|
243
|
+
endValue = stepValue < 0 ? -1 : length;
|
|
244
|
+
if (startProvided && startValue < 0)
|
|
245
|
+
startValue = length + startValue;
|
|
246
|
+
if (endProvided && endValue < 0)
|
|
247
|
+
endValue = length + endValue;
|
|
248
|
+
return { start: startValue, end: endValue, step: stepValue };
|
|
249
|
+
}
|
|
250
|
+
function computeSliceIndices(length, start, end, step) {
|
|
251
|
+
const bounds = this.computeSliceBounds(length, start, end, step);
|
|
252
|
+
const indices = [];
|
|
253
|
+
for (let i = bounds.start; bounds.step > 0 ? i < bounds.end : i > bounds.end; i += bounds.step) {
|
|
254
|
+
indices.push(i);
|
|
255
|
+
}
|
|
256
|
+
return indices;
|
|
257
|
+
}
|
|
258
|
+
function normalizeSliceStep(step) {
|
|
259
|
+
const stepValue = step !== null && step !== undefined ? (0, value_utils_1.toNumber)(step) : 1;
|
|
260
|
+
if (stepValue === 0) {
|
|
261
|
+
throw new runtime_types_1.PyException('ValueError', 'slice step cannot be zero');
|
|
262
|
+
}
|
|
263
|
+
return stepValue;
|
|
264
|
+
}
|
|
265
|
+
function getAttribute(obj, name, scope) {
|
|
266
|
+
if (obj && obj.__moduleScope__) {
|
|
267
|
+
if (obj.__moduleScope__.values.has(name)) {
|
|
268
|
+
return obj.__moduleScope__.values.get(name);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (obj instanceof runtime_types_1.PyInstance) {
|
|
272
|
+
if (obj.attributes.has(name))
|
|
273
|
+
return obj.attributes.get(name);
|
|
274
|
+
const attr = this.findClassAttribute(obj.klass, name);
|
|
275
|
+
if (attr instanceof runtime_types_1.PyFunction) {
|
|
276
|
+
return (...args) => this.callFunction(attr, [obj, ...args], scope);
|
|
277
|
+
}
|
|
278
|
+
return attr;
|
|
279
|
+
}
|
|
280
|
+
if (obj instanceof runtime_types_1.PyClass) {
|
|
281
|
+
const attr = this.findClassAttribute(obj, name);
|
|
282
|
+
return attr;
|
|
283
|
+
}
|
|
284
|
+
if (obj instanceof runtime_types_1.PyFile) {
|
|
285
|
+
const value = obj[name];
|
|
286
|
+
if (typeof value === 'function')
|
|
287
|
+
return value.bind(obj);
|
|
288
|
+
return value;
|
|
289
|
+
}
|
|
290
|
+
if (obj instanceof runtime_types_1.PyGenerator) {
|
|
291
|
+
const value = obj[name];
|
|
292
|
+
if (typeof value === 'function')
|
|
293
|
+
return value.bind(obj);
|
|
294
|
+
return value;
|
|
295
|
+
}
|
|
296
|
+
if ((0, value_utils_1.isComplex)(obj)) {
|
|
297
|
+
if (name === 'real')
|
|
298
|
+
return new Number(obj.re);
|
|
299
|
+
if (name === 'imag')
|
|
300
|
+
return new Number(obj.im);
|
|
301
|
+
}
|
|
302
|
+
if (typeof obj === 'string') {
|
|
303
|
+
if (name === 'upper')
|
|
304
|
+
return () => obj.toUpperCase();
|
|
305
|
+
if (name === 'replace')
|
|
306
|
+
return (a, b) => {
|
|
307
|
+
return obj.replace(a, b);
|
|
308
|
+
};
|
|
309
|
+
if (name === 'format')
|
|
310
|
+
return (...args) => {
|
|
311
|
+
let kwargs = {};
|
|
312
|
+
if (args.length > 0) {
|
|
313
|
+
const last = args[args.length - 1];
|
|
314
|
+
if (last && last.__kwargs__) {
|
|
315
|
+
kwargs = last.__kwargs__;
|
|
316
|
+
args = args.slice(0, -1);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
let autoIndex = 0;
|
|
320
|
+
return obj.replace(/\{([^{}]*)\}/g, (_match, key) => {
|
|
321
|
+
if (key === '') {
|
|
322
|
+
const value = args[autoIndex++];
|
|
323
|
+
return (0, value_utils_1.pyStr)(value);
|
|
324
|
+
}
|
|
325
|
+
if (/^\d+$/.test(key)) {
|
|
326
|
+
const value = args[parseInt(key, 10)];
|
|
327
|
+
return (0, value_utils_1.pyStr)(value);
|
|
328
|
+
}
|
|
329
|
+
if (key in kwargs) {
|
|
330
|
+
return (0, value_utils_1.pyStr)(kwargs[key]);
|
|
331
|
+
}
|
|
332
|
+
return '';
|
|
333
|
+
});
|
|
334
|
+
};
|
|
335
|
+
if (name === 'count')
|
|
336
|
+
return (ch) => obj.split(ch).length - 1;
|
|
337
|
+
}
|
|
338
|
+
if (Array.isArray(obj)) {
|
|
339
|
+
if (name === 'append')
|
|
340
|
+
return (value) => obj.push(value);
|
|
341
|
+
if (name === 'count')
|
|
342
|
+
return (value) => obj.filter((item) => item === value).length;
|
|
343
|
+
if (name === 'index')
|
|
344
|
+
return (value) => obj.indexOf(value);
|
|
345
|
+
if (name === 'sort') {
|
|
346
|
+
return (...args) => {
|
|
347
|
+
let kwargs = {};
|
|
348
|
+
if (args.length > 0) {
|
|
349
|
+
const last = args[args.length - 1];
|
|
350
|
+
if (last && last.__kwargs__) {
|
|
351
|
+
kwargs = last.__kwargs__;
|
|
352
|
+
args = args.slice(0, -1);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
let keyFn = args.length > 0 ? args[0] : null;
|
|
356
|
+
if ('key' in kwargs)
|
|
357
|
+
keyFn = kwargs.key;
|
|
358
|
+
const reverse = 'reverse' in kwargs ? Boolean(kwargs.reverse) : false;
|
|
359
|
+
if (keyFn) {
|
|
360
|
+
const keyed = obj.map((item) => ({
|
|
361
|
+
item,
|
|
362
|
+
key: this.callFunction(keyFn, [item], scope),
|
|
363
|
+
}));
|
|
364
|
+
keyed.sort((a, b) => {
|
|
365
|
+
if ((0, value_utils_1.isNumericLike)(a.key) && (0, value_utils_1.isNumericLike)(b.key)) {
|
|
366
|
+
return (0, value_utils_1.toNumber)(a.key) - (0, value_utils_1.toNumber)(b.key);
|
|
367
|
+
}
|
|
368
|
+
return String(a.key).localeCompare(String(b.key));
|
|
369
|
+
});
|
|
370
|
+
obj.length = 0;
|
|
371
|
+
obj.push(...keyed.map((entry) => entry.item));
|
|
372
|
+
}
|
|
373
|
+
else if (obj.every((value) => (0, value_utils_1.isNumericLike)(value))) {
|
|
374
|
+
obj.sort((a, b) => (0, value_utils_1.toNumber)(a) - (0, value_utils_1.toNumber)(b));
|
|
375
|
+
}
|
|
376
|
+
else {
|
|
377
|
+
obj.sort();
|
|
378
|
+
}
|
|
379
|
+
if (reverse)
|
|
380
|
+
obj.reverse();
|
|
381
|
+
return null;
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
if (obj instanceof runtime_types_1.PyDict) {
|
|
386
|
+
if (name === 'items')
|
|
387
|
+
return () => Array.from(obj.entries()).map(([k, v]) => {
|
|
388
|
+
const tup = [k, v];
|
|
389
|
+
tup.__tuple__ = true;
|
|
390
|
+
return tup;
|
|
391
|
+
});
|
|
392
|
+
const value = obj[name];
|
|
393
|
+
if (typeof value === 'function')
|
|
394
|
+
return value.bind(obj);
|
|
395
|
+
return value;
|
|
396
|
+
}
|
|
397
|
+
if (obj instanceof Set) {
|
|
398
|
+
if (name === 'add')
|
|
399
|
+
return (value) => obj.add(value);
|
|
400
|
+
if (name === 'update')
|
|
401
|
+
return (values) => {
|
|
402
|
+
const items = Array.isArray(values) ? values : Array.from(values);
|
|
403
|
+
for (const item of items)
|
|
404
|
+
obj.add(item);
|
|
405
|
+
};
|
|
406
|
+
if (name === 'remove')
|
|
407
|
+
return (value) => obj.delete(value);
|
|
408
|
+
}
|
|
409
|
+
if (obj && typeof obj === 'object' && obj.__typeName__) {
|
|
410
|
+
if (name === '__name__')
|
|
411
|
+
return obj.__typeName__;
|
|
412
|
+
}
|
|
413
|
+
if (obj && obj.__typeName__ === undefined && name === '__name__') {
|
|
414
|
+
return obj.name;
|
|
415
|
+
}
|
|
416
|
+
return obj[name];
|
|
417
|
+
}
|
|
418
|
+
function setAttribute(obj, name, value) {
|
|
419
|
+
if (obj && obj.__moduleScope__) {
|
|
420
|
+
obj.__moduleScope__.values.set(name, value);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if (obj instanceof runtime_types_1.PyInstance) {
|
|
424
|
+
obj.attributes.set(name, value);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
obj[name] = value;
|
|
428
|
+
}
|
|
429
|
+
function findClassAttribute(klass, name) {
|
|
430
|
+
if (klass.attributes.has(name))
|
|
431
|
+
return klass.attributes.get(name);
|
|
432
|
+
for (const base of klass.bases) {
|
|
433
|
+
const attr = findClassAttribute(base, name);
|
|
434
|
+
if (attr !== undefined)
|
|
435
|
+
return attr;
|
|
436
|
+
}
|
|
437
|
+
return undefined;
|
|
438
|
+
}
|
|
439
|
+
//# sourceMappingURL=operations.js.map
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export type ScopeValue = any;
|
|
2
|
+
export declare class ReturnSignal {
|
|
3
|
+
value: any;
|
|
4
|
+
constructor(value: any);
|
|
5
|
+
}
|
|
6
|
+
export declare class BreakSignal {
|
|
7
|
+
}
|
|
8
|
+
export declare class ContinueSignal {
|
|
9
|
+
}
|
|
10
|
+
export declare class PyException extends Error {
|
|
11
|
+
pyType: string;
|
|
12
|
+
pyValue: any;
|
|
13
|
+
constructor(pyType: string, message?: string, pyValue?: any);
|
|
14
|
+
}
|
|
15
|
+
export declare class Scope {
|
|
16
|
+
values: Map<string, ScopeValue>;
|
|
17
|
+
parent: Scope | null;
|
|
18
|
+
globals: Set<string>;
|
|
19
|
+
nonlocals: Set<string>;
|
|
20
|
+
constructor(parent?: Scope | null);
|
|
21
|
+
get(name: string): ScopeValue;
|
|
22
|
+
set(name: string, value: ScopeValue): void;
|
|
23
|
+
root(): Scope;
|
|
24
|
+
findScopeWith(name: string): Scope | null;
|
|
25
|
+
}
|
|
26
|
+
export declare class PyFunction {
|
|
27
|
+
name: string;
|
|
28
|
+
params: any[];
|
|
29
|
+
body: any[];
|
|
30
|
+
closure: Scope;
|
|
31
|
+
isGenerator: boolean;
|
|
32
|
+
constructor(name: string, params: any[], body: any[], closure: Scope, isGenerator: boolean);
|
|
33
|
+
}
|
|
34
|
+
export declare class PyClass {
|
|
35
|
+
name: string;
|
|
36
|
+
bases: PyClass[];
|
|
37
|
+
attributes: Map<string, any>;
|
|
38
|
+
isException: boolean;
|
|
39
|
+
constructor(name: string, bases: PyClass[], attributes: Map<string, any>, isException?: boolean);
|
|
40
|
+
}
|
|
41
|
+
export declare class PyInstance {
|
|
42
|
+
klass: PyClass;
|
|
43
|
+
attributes: Map<string, any>;
|
|
44
|
+
constructor(klass: PyClass);
|
|
45
|
+
}
|
|
46
|
+
export declare class PyGenerator {
|
|
47
|
+
private iterator;
|
|
48
|
+
constructor(iterator: Generator<any, any, any>);
|
|
49
|
+
next(value?: any): any;
|
|
50
|
+
send(value?: any): any;
|
|
51
|
+
[Symbol.iterator](): Generator<any, any, any>;
|
|
52
|
+
}
|
|
53
|
+
export type DictEntry = {
|
|
54
|
+
key: any;
|
|
55
|
+
value: any;
|
|
56
|
+
};
|
|
57
|
+
export declare class PyDict {
|
|
58
|
+
private primitiveStore;
|
|
59
|
+
private objectStore;
|
|
60
|
+
get size(): number;
|
|
61
|
+
set(key: any, value: any): this;
|
|
62
|
+
get(key: any): any;
|
|
63
|
+
has(key: any): boolean;
|
|
64
|
+
delete(key: any): boolean;
|
|
65
|
+
entries(): IterableIterator<[any, any]>;
|
|
66
|
+
keys(): IterableIterator<any>;
|
|
67
|
+
values(): IterableIterator<any>;
|
|
68
|
+
[Symbol.iterator](): IterableIterator<[any, any]>;
|
|
69
|
+
private keyInfo;
|
|
70
|
+
private normalizeNumericKey;
|
|
71
|
+
}
|
|
72
|
+
export declare class PyFile {
|
|
73
|
+
path: string;
|
|
74
|
+
mode: string;
|
|
75
|
+
handle: number | null;
|
|
76
|
+
constructor(path: string, mode: string);
|
|
77
|
+
open(): void;
|
|
78
|
+
write(data: string): void;
|
|
79
|
+
read(): string;
|
|
80
|
+
close(): void;
|
|
81
|
+
__enter__(): this;
|
|
82
|
+
__exit__(): boolean;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=runtime-types.d.ts.map
|