@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.
Files changed (144) hide show
  1. package/.claude/settings.local.json +3 -0
  2. package/.prettierrc +7 -0
  3. package/Agents.md +66 -0
  4. package/README.md +93 -0
  5. package/README_zh-CN.md +93 -0
  6. package/SETUP.md +171 -0
  7. package/dist/compiler.d.ts +20 -0
  8. package/dist/compiler.js +91 -0
  9. package/dist/compiler_module/compiler.d.ts +8 -0
  10. package/dist/compiler_module/compiler.js +22 -0
  11. package/dist/compiler_module/index.d.ts +2 -0
  12. package/dist/compiler_module/index.js +6 -0
  13. package/dist/index.d.ts +4 -0
  14. package/dist/index.js +67 -0
  15. package/dist/lexer/index.d.ts +2 -0
  16. package/dist/lexer/index.js +6 -0
  17. package/dist/lexer/lexer.d.ts +16 -0
  18. package/dist/lexer/lexer.js +403 -0
  19. package/dist/parser/expressions.d.ts +30 -0
  20. package/dist/parser/expressions.js +483 -0
  21. package/dist/parser/index.d.ts +2 -0
  22. package/dist/parser/index.js +6 -0
  23. package/dist/parser/parser.d.ts +63 -0
  24. package/dist/parser/parser.js +129 -0
  25. package/dist/parser/statements.d.ts +20 -0
  26. package/dist/parser/statements.js +388 -0
  27. package/dist/parser/targets.d.ts +6 -0
  28. package/dist/parser/targets.js +75 -0
  29. package/dist/types/ast.d.ts +63 -0
  30. package/dist/types/ast.js +60 -0
  31. package/dist/types/bytecode.d.ts +38 -0
  32. package/dist/types/bytecode.js +35 -0
  33. package/dist/types/index.d.ts +4 -0
  34. package/dist/types/index.js +20 -0
  35. package/dist/types/token.d.ts +34 -0
  36. package/dist/types/token.js +39 -0
  37. package/dist/vm/builtins.d.ts +4 -0
  38. package/dist/vm/builtins.js +269 -0
  39. package/dist/vm/callable.d.ts +8 -0
  40. package/dist/vm/callable.js +161 -0
  41. package/dist/vm/execution.d.ts +15 -0
  42. package/dist/vm/execution.js +283 -0
  43. package/dist/vm/expression-generator.d.ts +3 -0
  44. package/dist/vm/expression-generator.js +70 -0
  45. package/dist/vm/expressions.d.ts +13 -0
  46. package/dist/vm/expressions.js +390 -0
  47. package/dist/vm/imports.d.ts +7 -0
  48. package/dist/vm/imports.js +99 -0
  49. package/dist/vm/index.d.ts +3 -0
  50. package/dist/vm/index.js +21 -0
  51. package/dist/vm/operations.d.ts +16 -0
  52. package/dist/vm/operations.js +439 -0
  53. package/dist/vm/runtime-types.d.ts +84 -0
  54. package/dist/vm/runtime-types.js +290 -0
  55. package/dist/vm/statements.d.ts +7 -0
  56. package/dist/vm/statements.js +381 -0
  57. package/dist/vm/truthy.d.ts +4 -0
  58. package/dist/vm/truthy.js +47 -0
  59. package/dist/vm/value-utils.d.ts +28 -0
  60. package/dist/vm/value-utils.js +225 -0
  61. package/dist/vm/vm.d.ts +56 -0
  62. package/dist/vm/vm.js +75 -0
  63. package/examples/assert_testing.py +38 -0
  64. package/examples/big_int_precision.py +2 -0
  65. package/examples/boolean_logic.py +35 -0
  66. package/examples/break_continue.py +43 -0
  67. package/examples/classes_objects.py +43 -0
  68. package/examples/compiler_killer_async.py +6 -0
  69. package/examples/compiler_killer_bigint.py +3 -0
  70. package/examples/compiler_killer_bool_int_dict_key.py +5 -0
  71. package/examples/compiler_killer_bool_len.py +9 -0
  72. package/examples/compiler_killer_floor_division.py +4 -0
  73. package/examples/compiler_killer_is_identity.py +3 -0
  74. package/examples/compiler_killer_list_sort_return.py +3 -0
  75. package/examples/compiler_killer_match.py +13 -0
  76. package/examples/compiler_killer_negative_repeat.py +3 -0
  77. package/examples/compiler_killer_negative_zero_repr.py +3 -0
  78. package/examples/compiler_killer_rounding.py +4 -0
  79. package/examples/compiler_killer_slice_assign.py +3 -0
  80. package/examples/comprehensions.py +28 -0
  81. package/examples/conditions.py +13 -0
  82. package/examples/context_manager.py +35 -0
  83. package/examples/decorators.py +50 -0
  84. package/examples/exceptions.py +40 -0
  85. package/examples/fibonacci.py +10 -0
  86. package/examples/functions.py +38 -0
  87. package/examples/generator.py +51 -0
  88. package/examples/global_nonlocal.py +48 -0
  89. package/examples/hello.py +3 -0
  90. package/examples/itertools_example.py +33 -0
  91. package/examples/lists_dicts.py +29 -0
  92. package/examples/loops.py +19 -0
  93. package/examples/math_ops.py +15 -0
  94. package/examples/nan_set.py +6 -0
  95. package/examples/numbers_operators.py +51 -0
  96. package/examples/sets.py +36 -0
  97. package/examples/slicing.py +29 -0
  98. package/examples/starred_unpacking.py +3 -0
  99. package/examples/string_formatting.py +36 -0
  100. package/examples/strings.py +22 -0
  101. package/examples/tuples.py +45 -0
  102. package/examples/type_conversion.py +41 -0
  103. package/jest.config.js +15 -0
  104. package/notes/iterations/compiler-runtime/compiler-runtime_2025-09-16.md +25 -0
  105. package/notes/iterations/compiler-runtime/compiler-runtime_2026-01-16.md +24 -0
  106. package/notes/iterations/compiler-runtime/compiler-runtime_test_2026-01-16.md +21 -0
  107. package/notes/iterations/floor-division/floor-division_2026-01-16.md +29 -0
  108. package/package.json +36 -0
  109. package/prompts/commit.txt +9 -0
  110. package/prompts/task.txt +21 -0
  111. package/prompts/test.txt +23 -0
  112. package/scripts/codex-loop.js +215 -0
  113. package/scripts/verify.sh +12 -0
  114. package/src/compiler.ts +58 -0
  115. package/src/compiler_module/compiler.ts +19 -0
  116. package/src/compiler_module/index.ts +1 -0
  117. package/src/index.ts +39 -0
  118. package/src/lexer/index.ts +1 -0
  119. package/src/lexer/lexer.ts +402 -0
  120. package/src/parser/expressions.ts +462 -0
  121. package/src/parser/index.ts +1 -0
  122. package/src/parser/parser.ts +102 -0
  123. package/src/parser/statements.ts +366 -0
  124. package/src/parser/targets.ts +71 -0
  125. package/src/types/ast.ts +64 -0
  126. package/src/types/bytecode.ts +50 -0
  127. package/src/types/index.ts +3 -0
  128. package/src/types/token.ts +44 -0
  129. package/src/vm/builtins.ts +237 -0
  130. package/src/vm/callable.ts +154 -0
  131. package/src/vm/execution.ts +251 -0
  132. package/src/vm/expression-generator.ts +65 -0
  133. package/src/vm/expressions.ts +373 -0
  134. package/src/vm/imports.ts +61 -0
  135. package/src/vm/index.ts +2 -0
  136. package/src/vm/operations.ts +414 -0
  137. package/src/vm/runtime-types.ts +292 -0
  138. package/src/vm/statements.ts +358 -0
  139. package/src/vm/truthy.ts +36 -0
  140. package/src/vm/value-utils.ts +173 -0
  141. package/src/vm/vm.ts +80 -0
  142. package/tests/compiler.test.ts +111 -0
  143. package/tsconfig.json +20 -0
  144. package/vitest.config.ts +16 -0
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OpCode = void 0;
4
+ var OpCode;
5
+ (function (OpCode) {
6
+ // Loading and storing
7
+ OpCode[OpCode["LOAD_CONST"] = 0] = "LOAD_CONST";
8
+ OpCode[OpCode["LOAD_NAME"] = 1] = "LOAD_NAME";
9
+ OpCode[OpCode["STORE_NAME"] = 2] = "STORE_NAME";
10
+ // Binary operations
11
+ OpCode[OpCode["BINARY_ADD"] = 3] = "BINARY_ADD";
12
+ OpCode[OpCode["BINARY_SUBTRACT"] = 4] = "BINARY_SUBTRACT";
13
+ OpCode[OpCode["BINARY_MULTIPLY"] = 5] = "BINARY_MULTIPLY";
14
+ OpCode[OpCode["BINARY_DIVIDE"] = 6] = "BINARY_DIVIDE";
15
+ OpCode[OpCode["BINARY_MODULO"] = 7] = "BINARY_MODULO";
16
+ OpCode[OpCode["BINARY_POWER"] = 8] = "BINARY_POWER";
17
+ // Comparison operations
18
+ OpCode[OpCode["COMPARE_EQ"] = 9] = "COMPARE_EQ";
19
+ OpCode[OpCode["COMPARE_NE"] = 10] = "COMPARE_NE";
20
+ OpCode[OpCode["COMPARE_LT"] = 11] = "COMPARE_LT";
21
+ OpCode[OpCode["COMPARE_GT"] = 12] = "COMPARE_GT";
22
+ OpCode[OpCode["COMPARE_LE"] = 13] = "COMPARE_LE";
23
+ OpCode[OpCode["COMPARE_GE"] = 14] = "COMPARE_GE";
24
+ // Logical operations
25
+ OpCode[OpCode["LOGICAL_AND"] = 15] = "LOGICAL_AND";
26
+ OpCode[OpCode["LOGICAL_OR"] = 16] = "LOGICAL_OR";
27
+ OpCode[OpCode["LOGICAL_NOT"] = 17] = "LOGICAL_NOT";
28
+ // Function calls
29
+ OpCode[OpCode["CALL_FUNCTION"] = 18] = "CALL_FUNCTION";
30
+ OpCode[OpCode["RETURN_VALUE"] = 19] = "RETURN_VALUE";
31
+ // Print
32
+ OpCode[OpCode["PRINT_ITEM"] = 20] = "PRINT_ITEM";
33
+ OpCode[OpCode["PRINT_NEWLINE"] = 21] = "PRINT_NEWLINE";
34
+ })(OpCode || (exports.OpCode = OpCode = {}));
35
+ //# sourceMappingURL=bytecode.js.map
@@ -0,0 +1,4 @@
1
+ export * from './token';
2
+ export * from './ast';
3
+ export * from './bytecode';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./token"), exports);
18
+ __exportStar(require("./ast"), exports);
19
+ __exportStar(require("./bytecode"), exports);
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Token 类型定义
3
+ */
4
+ export interface Token {
5
+ type: TokenType;
6
+ value: string;
7
+ line: number;
8
+ column: number;
9
+ }
10
+ export declare enum TokenType {
11
+ KEYWORD = 0,
12
+ IDENTIFIER = 1,
13
+ NUMBER = 2,
14
+ STRING = 3,
15
+ BOOLEAN = 4,
16
+ NONE = 5,
17
+ OPERATOR = 6,
18
+ LPAREN = 7,
19
+ RPAREN = 8,
20
+ LBRACKET = 9,
21
+ RBRACKET = 10,
22
+ LBRACE = 11,
23
+ RBRACE = 12,
24
+ ASSIGN = 13,
25
+ COLON = 14,
26
+ COMMA = 15,
27
+ DOT = 16,
28
+ AT = 17,
29
+ EOF = 18,
30
+ INDENT = 19,
31
+ DEDENT = 20,
32
+ NEWLINE = 21
33
+ }
34
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TokenType = void 0;
4
+ var TokenType;
5
+ (function (TokenType) {
6
+ // Keywords
7
+ TokenType[TokenType["KEYWORD"] = 0] = "KEYWORD";
8
+ // Identifiers
9
+ TokenType[TokenType["IDENTIFIER"] = 1] = "IDENTIFIER";
10
+ // Literals
11
+ TokenType[TokenType["NUMBER"] = 2] = "NUMBER";
12
+ TokenType[TokenType["STRING"] = 3] = "STRING";
13
+ TokenType[TokenType["BOOLEAN"] = 4] = "BOOLEAN";
14
+ TokenType[TokenType["NONE"] = 5] = "NONE";
15
+ // Operators
16
+ TokenType[TokenType["OPERATOR"] = 6] = "OPERATOR";
17
+ // Parentheses
18
+ TokenType[TokenType["LPAREN"] = 7] = "LPAREN";
19
+ TokenType[TokenType["RPAREN"] = 8] = "RPAREN";
20
+ TokenType[TokenType["LBRACKET"] = 9] = "LBRACKET";
21
+ TokenType[TokenType["RBRACKET"] = 10] = "RBRACKET";
22
+ TokenType[TokenType["LBRACE"] = 11] = "LBRACE";
23
+ TokenType[TokenType["RBRACE"] = 12] = "RBRACE";
24
+ // Assignment
25
+ TokenType[TokenType["ASSIGN"] = 13] = "ASSIGN";
26
+ // Colon
27
+ TokenType[TokenType["COLON"] = 14] = "COLON";
28
+ // Comma
29
+ TokenType[TokenType["COMMA"] = 15] = "COMMA";
30
+ TokenType[TokenType["DOT"] = 16] = "DOT";
31
+ TokenType[TokenType["AT"] = 17] = "AT";
32
+ // End of file
33
+ TokenType[TokenType["EOF"] = 18] = "EOF";
34
+ // Indentation
35
+ TokenType[TokenType["INDENT"] = 19] = "INDENT";
36
+ TokenType[TokenType["DEDENT"] = 20] = "DEDENT";
37
+ TokenType[TokenType["NEWLINE"] = 21] = "NEWLINE";
38
+ })(TokenType || (exports.TokenType = TokenType = {}));
39
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1,4 @@
1
+ import type { VirtualMachine } from './vm';
2
+ import { Scope } from './runtime-types';
3
+ export declare function installBuiltins(this: VirtualMachine, scope: Scope): void;
4
+ //# sourceMappingURL=builtins.d.ts.map
@@ -0,0 +1,269 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installBuiltins = installBuiltins;
4
+ const runtime_types_1 = require("./runtime-types");
5
+ const value_utils_1 = require("./value-utils");
6
+ function installBuiltins(scope) {
7
+ const builtins = new Map();
8
+ builtins.set('print', (...args) => {
9
+ let sep = ' ';
10
+ let end = '\n';
11
+ if (args.length > 0) {
12
+ const last = args[args.length - 1];
13
+ if (last && last.__kwargs__) {
14
+ const kwargs = last.__kwargs__;
15
+ sep = kwargs.sep !== undefined ? kwargs.sep : sep;
16
+ end = kwargs.end !== undefined ? kwargs.end : end;
17
+ args = args.slice(0, -1);
18
+ }
19
+ }
20
+ const output = args.map((a) => (0, value_utils_1.pyStr)(a)).join(sep) + end;
21
+ process.stdout.write(output);
22
+ return null;
23
+ });
24
+ builtins.set('len', (value) => {
25
+ if (typeof value === 'string' || Array.isArray(value))
26
+ return value.length;
27
+ if (value instanceof runtime_types_1.PyDict || value instanceof Set)
28
+ return value.size;
29
+ throw new runtime_types_1.PyException('TypeError', 'object has no len()');
30
+ });
31
+ builtins.set('range', (...args) => {
32
+ let start = 0;
33
+ let end = 0;
34
+ let step = 1;
35
+ if (args.length === 1) {
36
+ end = (0, value_utils_1.toNumber)(args[0]);
37
+ }
38
+ else if (args.length === 2) {
39
+ start = (0, value_utils_1.toNumber)(args[0]);
40
+ end = (0, value_utils_1.toNumber)(args[1]);
41
+ }
42
+ else if (args.length >= 3) {
43
+ start = (0, value_utils_1.toNumber)(args[0]);
44
+ end = (0, value_utils_1.toNumber)(args[1]);
45
+ step = (0, value_utils_1.toNumber)(args[2]);
46
+ }
47
+ const result = [];
48
+ if (step === 0)
49
+ throw new runtime_types_1.PyException('ValueError', 'range() arg 3 must not be zero');
50
+ if (step > 0) {
51
+ for (let i = start; i < end; i += step)
52
+ result.push(i);
53
+ }
54
+ else {
55
+ for (let i = start; i > end; i += step)
56
+ result.push(i);
57
+ }
58
+ return result;
59
+ });
60
+ const listFn = (value) => {
61
+ if (Array.isArray(value))
62
+ return [...value];
63
+ if (value instanceof Set)
64
+ return Array.from(value.values());
65
+ if (value && typeof value[Symbol.iterator] === 'function')
66
+ return Array.from(value);
67
+ return [];
68
+ };
69
+ listFn.__typeName__ = 'list';
70
+ builtins.set('list', listFn);
71
+ const tupleFn = (value) => {
72
+ const arr = Array.isArray(value) ? [...value] : value && typeof value[Symbol.iterator] === 'function' ? Array.from(value) : [];
73
+ arr.__tuple__ = true;
74
+ return arr;
75
+ };
76
+ tupleFn.__typeName__ = 'tuple';
77
+ builtins.set('tuple', tupleFn);
78
+ const setFn = (value) => {
79
+ if (value instanceof Set)
80
+ return new Set(value);
81
+ if (Array.isArray(value))
82
+ return new Set(value);
83
+ if (value && typeof value[Symbol.iterator] === 'function')
84
+ return new Set(Array.from(value));
85
+ return new Set();
86
+ };
87
+ setFn.__typeName__ = 'set';
88
+ builtins.set('set', setFn);
89
+ builtins.set('sum', (value) => {
90
+ if (value.some((v) => typeof v === 'bigint')) {
91
+ return value.reduce((acc, v) => acc + (0, value_utils_1.toBigIntValue)(v), 0n);
92
+ }
93
+ return value.reduce((acc, v) => acc + v, 0);
94
+ });
95
+ builtins.set('max', (...args) => {
96
+ const values = args.length === 1 && Array.isArray(args[0]) ? args[0] : args;
97
+ if (values.every((v) => (0, value_utils_1.isNumericLike)(v) && !(0, value_utils_1.isFloatLike)(v))) {
98
+ return values.reduce((acc, v) => ((0, value_utils_1.toBigIntValue)(v) > (0, value_utils_1.toBigIntValue)(acc) ? v : acc));
99
+ }
100
+ return Math.max(...values.map((v) => (0, value_utils_1.toNumber)(v)));
101
+ });
102
+ builtins.set('min', (...args) => {
103
+ const values = args.length === 1 && Array.isArray(args[0]) ? args[0] : args;
104
+ if (values.every((v) => (0, value_utils_1.isNumericLike)(v) && !(0, value_utils_1.isFloatLike)(v))) {
105
+ return values.reduce((acc, v) => ((0, value_utils_1.toBigIntValue)(v) < (0, value_utils_1.toBigIntValue)(acc) ? v : acc));
106
+ }
107
+ return Math.min(...values.map((v) => (0, value_utils_1.toNumber)(v)));
108
+ });
109
+ builtins.set('abs', (value) => {
110
+ if (typeof value === 'bigint')
111
+ return value < 0n ? -value : value;
112
+ return Math.abs((0, value_utils_1.toNumber)(value));
113
+ });
114
+ const roundHalfToEven = (input) => {
115
+ const floored = Math.floor(input);
116
+ const diff = input - floored;
117
+ const epsilon = 1e-12;
118
+ if (diff > 0.5 + epsilon)
119
+ return floored + 1;
120
+ if (diff < 0.5 - epsilon)
121
+ return floored;
122
+ return floored % 2 === 0 ? floored : floored + 1;
123
+ };
124
+ builtins.set('round', (value, digits) => {
125
+ if (digits === undefined)
126
+ return roundHalfToEven(value);
127
+ const factor = Math.pow(10, digits);
128
+ return roundHalfToEven(value * factor) / factor;
129
+ });
130
+ const intFn = (value) => {
131
+ if (typeof value === 'bigint')
132
+ return value;
133
+ const text = typeof value === 'string' ? value.trim() : null;
134
+ if (text && /^[-+]?\\d+$/.test(text)) {
135
+ const big = BigInt(text);
136
+ const maxSafe = BigInt(Number.MAX_SAFE_INTEGER);
137
+ const minSafe = BigInt(Number.MIN_SAFE_INTEGER);
138
+ if (big > maxSafe || big < minSafe) {
139
+ return big;
140
+ }
141
+ }
142
+ const result = parseInt(value, 10);
143
+ if (Number.isNaN(result))
144
+ throw new runtime_types_1.PyException('ValueError', 'Invalid integer');
145
+ const boxed = new Number(result);
146
+ boxed.__int__ = true;
147
+ return boxed;
148
+ };
149
+ intFn.__typeName__ = 'int';
150
+ builtins.set('int', intFn);
151
+ const floatFn = (value) => {
152
+ if (value === undefined)
153
+ return new Number(0);
154
+ if (value instanceof Number)
155
+ return new Number(value.valueOf());
156
+ if (typeof value === 'number')
157
+ return new Number(value);
158
+ if (typeof value === 'boolean')
159
+ return new Number(value ? 1 : 0);
160
+ if (typeof value === 'string') {
161
+ const text = value.trim();
162
+ if (text.length === 0)
163
+ throw new runtime_types_1.PyException('ValueError', 'Invalid float');
164
+ const lower = text.toLowerCase();
165
+ if (lower === 'nan' || lower === '+nan' || lower === '-nan')
166
+ return new Number(NaN);
167
+ if (lower === 'inf' || lower === '+inf' || lower === 'infinity' || lower === '+infinity')
168
+ return new Number(Infinity);
169
+ if (lower === '-inf' || lower === '-infinity')
170
+ return new Number(-Infinity);
171
+ const result = parseFloat(text);
172
+ if (Number.isNaN(result))
173
+ throw new runtime_types_1.PyException('ValueError', 'Invalid float');
174
+ return new Number(result);
175
+ }
176
+ const result = parseFloat(value);
177
+ if (Number.isNaN(result))
178
+ throw new runtime_types_1.PyException('ValueError', 'Invalid float');
179
+ return new Number(result);
180
+ };
181
+ floatFn.__typeName__ = 'float';
182
+ builtins.set('float', floatFn);
183
+ const strFn = (value) => (0, value_utils_1.pyStr)(value);
184
+ strFn.__typeName__ = 'str';
185
+ builtins.set('str', strFn);
186
+ const boolFn = (value) => this.isTruthy(value, scope);
187
+ boolFn.__typeName__ = 'bool';
188
+ builtins.set('bool', boolFn);
189
+ builtins.set('type', (value) => ({ __typeName__: (0, value_utils_1.pyTypeName)(value) }));
190
+ builtins.set('isinstance', (value, typeObj) => {
191
+ if (typeObj && typeObj.__typeName__) {
192
+ return (0, value_utils_1.pyTypeName)(value) === typeObj.__typeName__;
193
+ }
194
+ return false;
195
+ });
196
+ builtins.set('enumerate', (iterable) => {
197
+ const arr = Array.isArray(iterable) ? iterable : Array.from(iterable);
198
+ return arr.map((v, i) => {
199
+ const tup = [i, v];
200
+ tup.__tuple__ = true;
201
+ return tup;
202
+ });
203
+ });
204
+ builtins.set('zip', (...iterables) => {
205
+ const arrays = iterables.map((it) => (Array.isArray(it) ? it : Array.from(it)));
206
+ const length = Math.min(...arrays.map((a) => a.length));
207
+ const result = [];
208
+ for (let i = 0; i < length; i++) {
209
+ const tup = arrays.map((a) => a[i]);
210
+ tup.__tuple__ = true;
211
+ result.push(tup);
212
+ }
213
+ return result;
214
+ });
215
+ builtins.set('sorted', (iterable) => {
216
+ const arr = Array.isArray(iterable) ? [...iterable] : Array.from(iterable);
217
+ if (arr.every((v) => (0, value_utils_1.isNumericLike)(v))) {
218
+ return arr.sort((a, b) => (0, value_utils_1.toNumber)(a) - (0, value_utils_1.toNumber)(b));
219
+ }
220
+ return arr.sort();
221
+ });
222
+ builtins.set('reversed', (iterable) => {
223
+ const arr = Array.isArray(iterable) ? [...iterable] : Array.from(iterable);
224
+ return arr.reverse();
225
+ });
226
+ builtins.set('map', (fn, iterable) => {
227
+ const arr = Array.isArray(iterable) ? iterable : Array.from(iterable);
228
+ return arr.map((value) => this.callFunction(fn, [value], scope));
229
+ });
230
+ builtins.set('filter', (fn, iterable) => {
231
+ const arr = Array.isArray(iterable) ? iterable : Array.from(iterable);
232
+ return arr.filter((value) => this.isTruthy(this.callFunction(fn, [value], scope), scope));
233
+ });
234
+ builtins.set('next', (iterable) => {
235
+ if (iterable instanceof runtime_types_1.PyGenerator) {
236
+ return iterable.next();
237
+ }
238
+ if (iterable && typeof iterable.next === 'function') {
239
+ const result = iterable.next();
240
+ if (result.done)
241
+ throw new runtime_types_1.PyException('StopIteration', 'StopIteration');
242
+ return result.value;
243
+ }
244
+ throw new runtime_types_1.PyException('TypeError', 'object is not an iterator');
245
+ });
246
+ builtins.set('open', (path, mode = 'r') => {
247
+ const file = new runtime_types_1.PyFile(String(path), String(mode));
248
+ try {
249
+ file.open();
250
+ }
251
+ catch (err) {
252
+ throw new runtime_types_1.PyException('FileNotFoundError', 'File not found');
253
+ }
254
+ return file;
255
+ });
256
+ const exceptionClass = (name, base) => {
257
+ const klass = new runtime_types_1.PyClass(name, base ? [base] : [], new Map(), true);
258
+ return klass;
259
+ };
260
+ const ExceptionBase = exceptionClass('Exception');
261
+ builtins.set('Exception', ExceptionBase);
262
+ builtins.set('AssertionError', exceptionClass('AssertionError', ExceptionBase));
263
+ builtins.set('ZeroDivisionError', exceptionClass('ZeroDivisionError', ExceptionBase));
264
+ builtins.set('ValueError', exceptionClass('ValueError', ExceptionBase));
265
+ builtins.set('TypeError', exceptionClass('TypeError', ExceptionBase));
266
+ builtins.set('FileNotFoundError', exceptionClass('FileNotFoundError', ExceptionBase));
267
+ scope.values = new Map([...builtins.entries()]);
268
+ }
269
+ //# sourceMappingURL=builtins.js.map
@@ -0,0 +1,8 @@
1
+ import type { VirtualMachine } from './vm';
2
+ import { Scope } from './runtime-types';
3
+ export declare function callFunction(this: VirtualMachine, func: any, args: any[], scope: Scope, kwargs?: Record<string, any>): any;
4
+ export declare function containsYield(this: VirtualMachine, body: any[]): boolean;
5
+ export declare function evaluateComprehension(this: VirtualMachine, node: any, scope: Scope, emit: () => void): void;
6
+ export declare function generateComprehension(this: VirtualMachine, node: any, scope: Scope, valueFactory: () => any): Generator<any, any, any>;
7
+ export declare function expressionHasYield(this: VirtualMachine, node: any): boolean;
8
+ //# sourceMappingURL=callable.d.ts.map
@@ -0,0 +1,161 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.callFunction = callFunction;
4
+ exports.containsYield = containsYield;
5
+ exports.evaluateComprehension = evaluateComprehension;
6
+ exports.generateComprehension = generateComprehension;
7
+ exports.expressionHasYield = expressionHasYield;
8
+ const types_1 = require("../types");
9
+ const runtime_types_1 = require("./runtime-types");
10
+ function callFunction(func, args, scope, kwargs = {}) {
11
+ if (!kwargs) {
12
+ kwargs = {};
13
+ }
14
+ if (func instanceof runtime_types_1.PyFunction) {
15
+ const callScope = new runtime_types_1.Scope(func.closure);
16
+ for (const param of func.params) {
17
+ if (param.type === 'Param') {
18
+ let argValue;
19
+ if (args.length > 0) {
20
+ argValue = args.shift();
21
+ }
22
+ else if (param.name in kwargs) {
23
+ argValue = kwargs[param.name];
24
+ delete kwargs[param.name];
25
+ }
26
+ else if (param.defaultEvaluated !== undefined) {
27
+ argValue = param.defaultEvaluated;
28
+ }
29
+ else if (param.defaultValue) {
30
+ argValue = this.evaluateExpression(param.defaultValue, scope);
31
+ }
32
+ else {
33
+ argValue = null;
34
+ }
35
+ callScope.set(param.name, argValue);
36
+ }
37
+ else if (param.type === 'VarArg') {
38
+ const varArgs = [...args];
39
+ varArgs.__tuple__ = true;
40
+ callScope.set(param.name, varArgs);
41
+ args = [];
42
+ }
43
+ else if (param.type === 'KwArg') {
44
+ const kwDict = new runtime_types_1.PyDict();
45
+ for (const [key, value] of Object.entries(kwargs)) {
46
+ kwDict.set(key, value);
47
+ }
48
+ callScope.set(param.name, kwDict);
49
+ kwargs = {};
50
+ }
51
+ }
52
+ try {
53
+ if (func.isGenerator) {
54
+ const iterator = this.executeBlockGenerator(func.body, callScope);
55
+ return new runtime_types_1.PyGenerator(iterator);
56
+ }
57
+ const result = this.executeBlock(func.body, callScope);
58
+ return result;
59
+ }
60
+ catch (err) {
61
+ if (err instanceof runtime_types_1.ReturnSignal)
62
+ return err.value;
63
+ throw err;
64
+ }
65
+ }
66
+ if (func instanceof runtime_types_1.PyClass) {
67
+ const instance = new runtime_types_1.PyInstance(func);
68
+ if (func.isException && args.length > 0) {
69
+ instance.attributes.set('message', args[0]);
70
+ }
71
+ const init = this.findClassAttribute(func, '__init__');
72
+ if (init instanceof runtime_types_1.PyFunction) {
73
+ this.callFunction(init, [instance, ...args], scope, kwargs);
74
+ }
75
+ return instance;
76
+ }
77
+ if (typeof func === 'function') {
78
+ if (Object.keys(kwargs).length > 0) {
79
+ return func(...args, { __kwargs__: kwargs });
80
+ }
81
+ return func(...args);
82
+ }
83
+ throw new runtime_types_1.PyException('TypeError', 'object is not callable');
84
+ }
85
+ function containsYield(body) {
86
+ for (const stmt of body) {
87
+ if (stmt.type === types_1.ASTNodeType.YIELD)
88
+ return true;
89
+ if (stmt.expression && this.expressionHasYield(stmt.expression))
90
+ return true;
91
+ if (stmt.value && this.expressionHasYield(stmt.value))
92
+ return true;
93
+ if (stmt.body && Array.isArray(stmt.body) && this.containsYield(stmt.body))
94
+ return true;
95
+ }
96
+ return false;
97
+ }
98
+ function evaluateComprehension(node, scope, emit) {
99
+ const clauses = node.clauses || [];
100
+ const walk = (index) => {
101
+ if (index >= clauses.length) {
102
+ emit();
103
+ return;
104
+ }
105
+ const clause = clauses[index];
106
+ const iterable = this.evaluateExpression(clause.iter, scope);
107
+ const items = Array.isArray(iterable) ? iterable : Array.from(iterable);
108
+ for (const item of items) {
109
+ this.assignTarget(clause.target, item, scope);
110
+ const passes = clause.ifs.every((cond) => this.isTruthy(this.evaluateExpression(cond, scope), scope));
111
+ if (passes) {
112
+ walk(index + 1);
113
+ }
114
+ }
115
+ };
116
+ walk(0);
117
+ }
118
+ function* generateComprehension(node, scope, valueFactory) {
119
+ const clauses = node.clauses || [];
120
+ const walk = (index) => {
121
+ const self = this;
122
+ return (function* () {
123
+ if (index >= clauses.length) {
124
+ yield valueFactory();
125
+ return;
126
+ }
127
+ const clause = clauses[index];
128
+ const iterable = self.evaluateExpression(clause.iter, scope);
129
+ const items = Array.isArray(iterable) ? iterable : Array.from(iterable);
130
+ for (const item of items) {
131
+ self.assignTarget(clause.target, item, scope);
132
+ const passes = clause.ifs.every((cond) => self.isTruthy(self.evaluateExpression(cond, scope), scope));
133
+ if (passes) {
134
+ yield* walk(index + 1);
135
+ }
136
+ }
137
+ })();
138
+ };
139
+ yield* walk(0);
140
+ return null;
141
+ }
142
+ function expressionHasYield(node) {
143
+ if (!node)
144
+ return false;
145
+ if (node.type === types_1.ASTNodeType.YIELD)
146
+ return true;
147
+ for (const key of Object.keys(node)) {
148
+ const value = node[key];
149
+ if (Array.isArray(value)) {
150
+ if (value.some((item) => item && typeof item === 'object' && this.expressionHasYield(item))) {
151
+ return true;
152
+ }
153
+ }
154
+ else if (value && typeof value === 'object') {
155
+ if (this.expressionHasYield(value))
156
+ return true;
157
+ }
158
+ }
159
+ return false;
160
+ }
161
+ //# sourceMappingURL=callable.js.map
@@ -0,0 +1,15 @@
1
+ import type { VirtualMachine } from './vm';
2
+ import { ByteCode } from '../types';
3
+ import { Scope } from './runtime-types';
4
+ export declare function execute(this: VirtualMachine, bytecode: ByteCode): any;
5
+ export declare function executeBlock(this: VirtualMachine, body: any[], scope: Scope): any;
6
+ export declare function iterableToArray(this: VirtualMachine, iterable: any): any[];
7
+ export declare function matchValueEquals(left: any, right: any): boolean;
8
+ export declare function matchPattern(this: VirtualMachine, node: any, value: any, scope: Scope): {
9
+ matched: boolean;
10
+ bindings: Map<string, any>;
11
+ };
12
+ export declare function applyBindings(bindings: Map<string, any>, scope: Scope): void;
13
+ export declare function executeBlockGenerator(this: VirtualMachine, body: any[], scope: Scope): Generator<any, any, any>;
14
+ export declare function executeStatementGenerator(this: VirtualMachine, node: any, scope: Scope): Generator<any, any, any>;
15
+ //# sourceMappingURL=execution.d.ts.map