@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,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
|
+
}
|
package/vitest.config.ts
ADDED
|
@@ -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
|
+
});
|