@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,111 @@
1
+ import { PythonCompiler } from '../src/index';
2
+ import { execFileSync } from 'child_process';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+
6
+ const pythonCommandCandidates = [
7
+ process.env.PYTHON,
8
+ 'python3',
9
+ 'python',
10
+ ].filter(Boolean) as string[];
11
+
12
+ const runPythonFile = (filePath: string): string => {
13
+ const errors: { cmd: string; error: string }[] = [];
14
+
15
+ for (const cmd of pythonCommandCandidates) {
16
+ try {
17
+ return execFileSync(cmd, [filePath], { encoding: 'utf8' });
18
+ } catch (error) {
19
+ const errorMsg = error instanceof Error ? error.message : String(error);
20
+ errors.push({ cmd, error: errorMsg });
21
+ }
22
+ }
23
+
24
+ const errorDetails = errors
25
+ .map(({ cmd, error }) => ` • ${cmd}: ${error}`)
26
+ .join('\n');
27
+
28
+ throw new Error(
29
+ `āŒ Python interpreter not found\n\n` +
30
+ `Attempted commands:\n${errorDetails}\n\n` +
31
+ `Please ensure Python 3 is installed and in your PATH, or set the PYTHON environment variable.`
32
+ );
33
+ };
34
+
35
+ const captureOutput = (fn: () => void): string => {
36
+ const outputChunks: string[] = [];
37
+ const originalWrite = process.stdout.write;
38
+
39
+ process.stdout.write = ((chunk: any) => {
40
+ const normalized =
41
+ typeof chunk === 'string' ? chunk : chunk.toString('utf8');
42
+ outputChunks.push(normalized);
43
+ return true;
44
+ }) as any;
45
+
46
+ try {
47
+ fn();
48
+ } finally {
49
+ process.stdout.write = originalWrite;
50
+ }
51
+
52
+ return outputChunks.join('');
53
+ };
54
+
55
+ describe('PythonCompiler - Public API Tests', () => {
56
+ let compiler: PythonCompiler;
57
+
58
+ beforeEach(() => {
59
+ compiler = new PythonCompiler();
60
+ });
61
+
62
+ describe('runFile() method', () => {
63
+ const examplesDir = path.join(__dirname, '../examples');
64
+ const exampleFiles = fs
65
+ .readdirSync(examplesDir)
66
+ .filter((file) => file.endsWith('.py'))
67
+ .sort();
68
+
69
+ it('should match output for example files', () => {
70
+ const failedTests: Array<{ file: string; expected: string; actual: string }> = [];
71
+
72
+ for (const fileName of exampleFiles) {
73
+ const filePath = path.join(examplesDir, fileName);
74
+ const expectedOutput = runPythonFile(filePath);
75
+ const actualOutput = captureOutput(() => {
76
+ compiler.runFile(filePath);
77
+ });
78
+
79
+ if (actualOutput !== expectedOutput) {
80
+ failedTests.push({
81
+ file: fileName,
82
+ expected: expectedOutput,
83
+ actual: actualOutput,
84
+ });
85
+ }
86
+ }
87
+
88
+ if (failedTests.length > 0) {
89
+ const failureDetails = failedTests
90
+ .map(({ file, expected, actual }) => {
91
+ return (
92
+ `\nšŸ“„ ${file}\n` +
93
+ ` Expected:\n${expected
94
+ .split('\n')
95
+ .map((l) => ` ${l}`)
96
+ .join('\n')}\n` +
97
+ ` Actual:\n${actual
98
+ .split('\n')
99
+ .map((l) => ` ${l}`)
100
+ .join('\n')}`
101
+ );
102
+ })
103
+ .join('\n');
104
+
105
+ throw new Error(
106
+ `āŒ ${failedTests.length} test(s) failed:${failureDetails}`
107
+ );
108
+ }
109
+ });
110
+ });
111
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020"],
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
+ "resolveJsonModule": true,
13
+ "declaration": true,
14
+ "declarationMap": true,
15
+ "sourceMap": true,
16
+ "moduleResolution": "node"
17
+ },
18
+ "include": ["src/**/*"],
19
+ "exclude": ["node_modules", "dist", "tests"]
20
+ }
@@ -0,0 +1,16 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ environment: 'node',
7
+ include: ['tests/**/*.test.ts'],
8
+ coverage: {
9
+ provider: 'v8',
10
+ reporter: ['text', 'json', 'html'],
11
+ include: ['src/**/*.ts'],
12
+ exclude: ['src/**/*.d.ts'],
13
+ },
14
+ testTimeout: 10000,
15
+ },
16
+ });