@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
package/.prettierrc
ADDED
package/Agents.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Python Compiler Architecture (TypeScript)
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This project is a Python compiler + interpreter written in TypeScript.
|
|
6
|
+
It follows a classic 4-stage pipeline:
|
|
7
|
+
|
|
8
|
+
**Lex → Parse → Compile → Execute**
|
|
9
|
+
|
|
10
|
+
Goal: keep the system **modular, testable, and easy to extend.**
|
|
11
|
+
|
|
12
|
+
## Architecture
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
Python Source
|
|
16
|
+
↓
|
|
17
|
+
Lexer → Tokens
|
|
18
|
+
↓
|
|
19
|
+
Parser → AST
|
|
20
|
+
↓
|
|
21
|
+
Compiler → Bytecode
|
|
22
|
+
↓
|
|
23
|
+
VM → Result
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Each stage must:
|
|
27
|
+
|
|
28
|
+
* Do one job only
|
|
29
|
+
* Have clear input/output types
|
|
30
|
+
* Avoid cross-stage coupling
|
|
31
|
+
|
|
32
|
+
## Engineering Rules
|
|
33
|
+
|
|
34
|
+
### 1. 500-Line Rule
|
|
35
|
+
|
|
36
|
+
* **Hard limit:** No `.ts` file over **500 lines**
|
|
37
|
+
* **Refactor early:** At **400 lines**, start splitting
|
|
38
|
+
* **Why:**
|
|
39
|
+
|
|
40
|
+
* Easier to read and review
|
|
41
|
+
* Faster debugging
|
|
42
|
+
* Better AI/code-assist context
|
|
43
|
+
|
|
44
|
+
### 2. Modularity
|
|
45
|
+
|
|
46
|
+
* One file = one main responsibility
|
|
47
|
+
* No “god files”
|
|
48
|
+
* Shared logic goes into `utils/` or `common/`
|
|
49
|
+
|
|
50
|
+
### 3. Stage Isolation
|
|
51
|
+
|
|
52
|
+
* Lexer never touches AST
|
|
53
|
+
* Parser never emits bytecode
|
|
54
|
+
* Compiler never executes
|
|
55
|
+
* VM never parses
|
|
56
|
+
|
|
57
|
+
Each layer talks only through well-defined data structures.
|
|
58
|
+
|
|
59
|
+
### 4. Test by Stage
|
|
60
|
+
|
|
61
|
+
* Unit test each stage independently:
|
|
62
|
+
|
|
63
|
+
* Lexer → tokens
|
|
64
|
+
* Parser → AST
|
|
65
|
+
* Compiler → bytecode
|
|
66
|
+
* VM → runtime result
|
package/README.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @lewin671/python-vm
|
|
2
|
+
|
|
3
|
+
A Python compiler and interpreter implemented in TypeScript. The compiler currently packages the AST into a bytecode container that the VM executes.
|
|
4
|
+
|
|
5
|
+
[简体中文](README_zh-CN.md)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- [x] CLI entry point for running `.py` files
|
|
10
|
+
- [x] Lexer with indentation handling, numbers, strings (including f-strings), keywords, and operators
|
|
11
|
+
- [x] Parser that builds ASTs for statements and expressions (functions, classes, loops, comprehensions, exceptions, and more)
|
|
12
|
+
- [x] Bytecode compiler scaffold that passes ASTs to the VM
|
|
13
|
+
- [x] AST-based virtual machine with scopes, control flow, functions, classes, generators, context managers, and exceptions
|
|
14
|
+
- [x] Python data structures including lists, tuples, dicts, sets, slicing, and comprehensions
|
|
15
|
+
- [x] Built-ins:
|
|
16
|
+
- Type/conversion: int, float, str, bool, list, tuple, set, type, isinstance
|
|
17
|
+
- Iteration: range, enumerate, zip, sorted, reversed, map, filter, next
|
|
18
|
+
- Math/util: abs, round, sum, min, max
|
|
19
|
+
- I/O: print, open
|
|
20
|
+
- [x] Example scripts and Vitest suite that compare output against system Python
|
|
21
|
+
|
|
22
|
+
## Getting Started
|
|
23
|
+
|
|
24
|
+
### Requirements
|
|
25
|
+
|
|
26
|
+
- Node.js 18+
|
|
27
|
+
- npm
|
|
28
|
+
- Python 3 available on your PATH for tests (set `PYTHON=python3` if needed)
|
|
29
|
+
|
|
30
|
+
### Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Build
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm run build
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Test
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm test
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If the tests cannot find Python, set the environment variable before running them, for example: `export PYTHON=python3`.
|
|
49
|
+
|
|
50
|
+
### Run
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm run build
|
|
54
|
+
npm start -- examples/hello.py
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Or run directly:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
node dist/index.js examples/hello.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Use in TypeScript
|
|
64
|
+
|
|
65
|
+
After `npm run build`, you can call the compiler from TypeScript. When consuming the package, import from `@lewin671/python-vm`. For local development in this repo, import from `./dist` instead.
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { PythonCompiler } from '@lewin671/python-vm';
|
|
69
|
+
|
|
70
|
+
const compiler = new PythonCompiler();
|
|
71
|
+
const result = compiler.run('print("Hello from TypeScript")');
|
|
72
|
+
|
|
73
|
+
console.log(result);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Project Structure
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
@lewin671/python-vm/
|
|
80
|
+
├── dist/ # Compiled output
|
|
81
|
+
├── examples/ # Sample Python programs used by tests
|
|
82
|
+
├── src/
|
|
83
|
+
│ ├── compiler.ts # Public PythonCompiler API
|
|
84
|
+
│ ├── compiler_module/ # Bytecode compiler scaffold
|
|
85
|
+
│ ├── index.ts # CLI entry + exports
|
|
86
|
+
│ ├── lexer/ # Tokenizer
|
|
87
|
+
│ ├── parser/ # AST parser
|
|
88
|
+
│ ├── types/ # Tokens, AST, bytecode types
|
|
89
|
+
│ └── vm/ # AST interpreter (virtual machine)
|
|
90
|
+
├── tests/ # Vitest suites comparing against CPython
|
|
91
|
+
├── package.json
|
|
92
|
+
└── tsconfig.json
|
|
93
|
+
```
|
package/README_zh-CN.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @lewin671/python-vm
|
|
2
|
+
|
|
3
|
+
一个使用 TypeScript 实现的 Python 编译器与解释器。目前编译器会将 AST 打包到字节码容器中,由虚拟机执行。
|
|
4
|
+
|
|
5
|
+
[English](README.md)
|
|
6
|
+
|
|
7
|
+
## 功能特性
|
|
8
|
+
|
|
9
|
+
- [x] CLI 入口,用于运行 `.py` 文件
|
|
10
|
+
- [x] 具备缩进处理、数字/字符串(含 f-string)、关键字与运算符的词法分析器
|
|
11
|
+
- [x] 语法分析器生成 AST,覆盖函数、类、循环、推导式、异常等语句与表达式
|
|
12
|
+
- [x] 字节码编译器框架,将 AST 交给虚拟机执行
|
|
13
|
+
- [x] 基于 AST 的虚拟机,支持作用域、控制流、函数、类、生成器、上下文管理器与异常
|
|
14
|
+
- [x] Python 数据结构支持:list、tuple、dict、set、切片与推导式
|
|
15
|
+
- [x] 内置函数:
|
|
16
|
+
- 类型/转换:int、float、str、bool、list、tuple、set、type、isinstance
|
|
17
|
+
- 迭代相关:range、enumerate、zip、sorted、reversed、map、filter、next
|
|
18
|
+
- 数值/工具:abs、round、sum、min、max
|
|
19
|
+
- 输入输出:print、open
|
|
20
|
+
- [x] 示例脚本与 Vitest 测试,输出对比系统 Python
|
|
21
|
+
|
|
22
|
+
## 快速开始
|
|
23
|
+
|
|
24
|
+
### 环境要求
|
|
25
|
+
|
|
26
|
+
- Node.js 18+
|
|
27
|
+
- npm
|
|
28
|
+
- Python 3(运行测试需要,确保在 PATH 中;必要时设置 `PYTHON=python3`)
|
|
29
|
+
|
|
30
|
+
### 安装依赖
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 构建
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm run build
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 测试
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm test
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
如果测试无法找到 Python,可先设置环境变量,例如:`export PYTHON=python3`。
|
|
49
|
+
|
|
50
|
+
### 运行
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
npm run build
|
|
54
|
+
npm start -- examples/hello.py
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
或直接运行:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
node dist/index.js examples/hello.py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 在 TypeScript 中调用
|
|
64
|
+
|
|
65
|
+
运行 `npm run build` 后,可以在 TypeScript 中这样调用。作为依赖使用时请从 `@lewin671/python-vm` 导入,本仓库本地开发时则从 `./dist` 导入。
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
import { PythonCompiler } from '@lewin671/python-vm';
|
|
69
|
+
|
|
70
|
+
const compiler = new PythonCompiler();
|
|
71
|
+
const result = compiler.run('print("Hello from TypeScript")');
|
|
72
|
+
|
|
73
|
+
console.log(result);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## 项目结构
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
@lewin671/python-vm/
|
|
80
|
+
├── dist/ # 编译输出
|
|
81
|
+
├── examples/ # 测试用 Python 示例
|
|
82
|
+
├── src/
|
|
83
|
+
│ ├── compiler.ts # PythonCompiler 公共 API
|
|
84
|
+
│ ├── compiler_module/ # 字节码编译器框架
|
|
85
|
+
│ ├── index.ts # CLI 入口 + 导出
|
|
86
|
+
│ ├── lexer/ # 词法分析器
|
|
87
|
+
│ ├── parser/ # 语法分析器
|
|
88
|
+
│ ├── types/ # Token/AST/字节码类型
|
|
89
|
+
│ └── vm/ # AST 解释执行器
|
|
90
|
+
├── tests/ # 与 CPython 对比的 Vitest 测试
|
|
91
|
+
├── package.json
|
|
92
|
+
└── tsconfig.json
|
|
93
|
+
```
|
package/SETUP.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# 项目设置和测试说明
|
|
2
|
+
|
|
3
|
+
## 项目概览
|
|
4
|
+
|
|
5
|
+
这是一个用 TypeScript 实现的 Python 编译器项目。目前编译器核心功能尚未完全实现,使用方法壳来定义接口。
|
|
6
|
+
|
|
7
|
+
## 当前状态
|
|
8
|
+
|
|
9
|
+
### ✅ 已完成
|
|
10
|
+
- 项目结构搭建
|
|
11
|
+
- 配置文件(TypeScript, Jest, ESLint, Prettier)
|
|
12
|
+
- 编译器接口定义(方法壳)
|
|
13
|
+
- 完整的测试用例
|
|
14
|
+
- Python 示例脚本(可在 shell 中正常运行)
|
|
15
|
+
|
|
16
|
+
### 🚧 待实现
|
|
17
|
+
- 词法分析器(Tokenizer)
|
|
18
|
+
- 语法分析器(Parser)
|
|
19
|
+
- 编译器(Compiler)
|
|
20
|
+
- 虚拟机(VM)
|
|
21
|
+
|
|
22
|
+
## 快速开始
|
|
23
|
+
|
|
24
|
+
### 安装依赖
|
|
25
|
+
```bash
|
|
26
|
+
npm install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### 编译项目
|
|
30
|
+
```bash
|
|
31
|
+
npm run build
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 运行测试
|
|
35
|
+
```bash
|
|
36
|
+
npm test
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**注意:** 测试预期会失败,因为编译器核心功能尚未实现。所有 24 个测试都会报错:
|
|
40
|
+
```
|
|
41
|
+
Error: Tokenizer not implemented yet
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
这是正常的!这表明:
|
|
45
|
+
1. 测试框架正常工作
|
|
46
|
+
2. 测试用例正确配置
|
|
47
|
+
3. 编译器接口定义完整
|
|
48
|
+
4. 现在可以开始实现各个模块
|
|
49
|
+
|
|
50
|
+
## 验证 Python 脚本
|
|
51
|
+
|
|
52
|
+
所有示例 Python 脚本都可以在 shell 中正常运行:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# Hello World
|
|
56
|
+
python3 examples/hello.py
|
|
57
|
+
|
|
58
|
+
# 数学运算
|
|
59
|
+
python3 examples/math.py
|
|
60
|
+
|
|
61
|
+
# 斐波那契数列
|
|
62
|
+
python3 examples/fibonacci.py
|
|
63
|
+
|
|
64
|
+
# 条件语句
|
|
65
|
+
python3 examples/conditions.py
|
|
66
|
+
|
|
67
|
+
# 循环
|
|
68
|
+
python3 examples/loops.py
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## 项目结构
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
python-compiler-ts/
|
|
75
|
+
├── src/
|
|
76
|
+
│ ├── compiler.ts # 编译器主类(方法壳)
|
|
77
|
+
│ └── index.ts # CLI 入口
|
|
78
|
+
├── tests/
|
|
79
|
+
│ └── compiler.test.ts # 24 个测试用例
|
|
80
|
+
├── examples/ # Python 示例脚本
|
|
81
|
+
│ ├── hello.py # Hello World
|
|
82
|
+
│ ├── math.py # 数学运算
|
|
83
|
+
│ ├── fibonacci.py # 递归函数
|
|
84
|
+
│ ├── conditions.py # 条件语句
|
|
85
|
+
│ └── loops.py # 循环语句
|
|
86
|
+
├── dist/ # 编译输出(npm run build)
|
|
87
|
+
├── package.json
|
|
88
|
+
├── tsconfig.json
|
|
89
|
+
├── jest.config.js
|
|
90
|
+
└── README.md
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 测试覆盖范围
|
|
94
|
+
|
|
95
|
+
测试用例涵盖以下 Python 特性:
|
|
96
|
+
|
|
97
|
+
1. **Hello World** (2 tests)
|
|
98
|
+
- 简单的 print 语句
|
|
99
|
+
- 运行 hello.py 文件
|
|
100
|
+
|
|
101
|
+
2. **变量和算术运算** (3 tests)
|
|
102
|
+
- 变量赋值
|
|
103
|
+
- 基本算术运算
|
|
104
|
+
- 运行 math.py 文件
|
|
105
|
+
|
|
106
|
+
3. **函数** (4 tests)
|
|
107
|
+
- 函数定义
|
|
108
|
+
- 函数调用
|
|
109
|
+
- 递归函数
|
|
110
|
+
- 运行 fibonacci.py 文件
|
|
111
|
+
|
|
112
|
+
4. **控制流** (3 tests)
|
|
113
|
+
- if 语句
|
|
114
|
+
- if-elif-else 语句
|
|
115
|
+
- 运行 conditions.py 文件
|
|
116
|
+
|
|
117
|
+
5. **循环** (4 tests)
|
|
118
|
+
- for 循环(range)
|
|
119
|
+
- while 循环
|
|
120
|
+
- 列表迭代
|
|
121
|
+
- 运行 loops.py 文件
|
|
122
|
+
|
|
123
|
+
6. **数据类型** (5 tests)
|
|
124
|
+
- 整数
|
|
125
|
+
- 浮点数
|
|
126
|
+
- 字符串
|
|
127
|
+
- 布尔值
|
|
128
|
+
- 列表
|
|
129
|
+
|
|
130
|
+
7. **运算符** (3 tests)
|
|
131
|
+
- 算术运算符(+, -, *, /, %, **)
|
|
132
|
+
- 比较运算符(==, !=, <, >, <=, >=)
|
|
133
|
+
- 逻辑运算符(and, or, not)
|
|
134
|
+
|
|
135
|
+
**总计:24 个测试用例,全部预期失败**
|
|
136
|
+
|
|
137
|
+
## 下一步
|
|
138
|
+
|
|
139
|
+
1. 实现 `tokenize()` 方法 - 词法分析
|
|
140
|
+
2. 实现 `parse()` 方法 - 语法分析
|
|
141
|
+
3. 实现 `compile()` 方法 - 编译到字节码
|
|
142
|
+
4. 实现 `execute()` 方法 - 虚拟机执行
|
|
143
|
+
5. 逐步通过测试用例
|
|
144
|
+
|
|
145
|
+
## 开发命令
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# 开发模式(监听文件变化)
|
|
149
|
+
npm run dev
|
|
150
|
+
|
|
151
|
+
# 运行测试(监听模式)
|
|
152
|
+
npm run test:watch
|
|
153
|
+
|
|
154
|
+
# 测试覆盖率
|
|
155
|
+
npm run test:coverage
|
|
156
|
+
|
|
157
|
+
# 代码检查
|
|
158
|
+
npm run lint
|
|
159
|
+
|
|
160
|
+
# 代码格式化
|
|
161
|
+
npm run format
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 贡献指南
|
|
165
|
+
|
|
166
|
+
1. 从简单的功能开始实现(如:整数字面量、变量赋值)
|
|
167
|
+
2. 确保每次实现后运行测试
|
|
168
|
+
3. 逐步增加复杂度
|
|
169
|
+
4. 保持代码整洁和文档更新
|
|
170
|
+
|
|
171
|
+
祝你编码愉快!🚀
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Python Compiler - 主入口
|
|
3
|
+
* 用于编译和执行 Python 代码
|
|
4
|
+
*/
|
|
5
|
+
export declare class PythonCompiler {
|
|
6
|
+
/**
|
|
7
|
+
* 编译并运行 Python 代码
|
|
8
|
+
* @param code Python 源代码
|
|
9
|
+
* @returns 执行结果
|
|
10
|
+
*/
|
|
11
|
+
run(code: string): any;
|
|
12
|
+
/**
|
|
13
|
+
* 运行 Python 文件
|
|
14
|
+
* @param filePath 文件路径
|
|
15
|
+
* @returns 执行结果
|
|
16
|
+
*/
|
|
17
|
+
runFile(filePath: string): any;
|
|
18
|
+
}
|
|
19
|
+
export * from './types';
|
|
20
|
+
//# sourceMappingURL=compiler.d.ts.map
|
package/dist/compiler.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Python Compiler - 主入口
|
|
4
|
+
* 用于编译和执行 Python 代码
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
40
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.PythonCompiler = void 0;
|
|
44
|
+
const lexer_1 = require("./lexer");
|
|
45
|
+
const parser_1 = require("./parser");
|
|
46
|
+
const compiler_module_1 = require("./compiler_module");
|
|
47
|
+
const vm_1 = require("./vm");
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
class PythonCompiler {
|
|
50
|
+
/**
|
|
51
|
+
* 编译并运行 Python 代码
|
|
52
|
+
* @param code Python 源代码
|
|
53
|
+
* @returns 执行结果
|
|
54
|
+
*/
|
|
55
|
+
run(code) {
|
|
56
|
+
// 1. 词法分析
|
|
57
|
+
const lexer = new lexer_1.Lexer(code);
|
|
58
|
+
const tokens = lexer.tokenize();
|
|
59
|
+
// 2. 语法分析
|
|
60
|
+
const parser = new parser_1.Parser(tokens);
|
|
61
|
+
const ast = parser.parse();
|
|
62
|
+
// 3. 编译到字节码
|
|
63
|
+
const compiler = new compiler_module_1.Compiler();
|
|
64
|
+
const bytecode = compiler.compile(ast);
|
|
65
|
+
// 4. 执行字节码
|
|
66
|
+
const vm = new vm_1.VirtualMachine([process.cwd()]);
|
|
67
|
+
const result = vm.execute(bytecode);
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* 运行 Python 文件
|
|
72
|
+
* @param filePath 文件路径
|
|
73
|
+
* @returns 执行结果
|
|
74
|
+
*/
|
|
75
|
+
runFile(filePath) {
|
|
76
|
+
const fs = require('fs');
|
|
77
|
+
const code = fs.readFileSync(filePath, 'utf-8');
|
|
78
|
+
const lexer = new lexer_1.Lexer(code);
|
|
79
|
+
const tokens = lexer.tokenize();
|
|
80
|
+
const parser = new parser_1.Parser(tokens);
|
|
81
|
+
const ast = parser.parse();
|
|
82
|
+
const compiler = new compiler_module_1.Compiler();
|
|
83
|
+
const bytecode = compiler.compile(ast);
|
|
84
|
+
const vm = new vm_1.VirtualMachine([path.dirname(filePath), process.cwd()]);
|
|
85
|
+
return vm.execute(bytecode);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.PythonCompiler = PythonCompiler;
|
|
89
|
+
// 重新导出类型,供外部使用
|
|
90
|
+
__exportStar(require("./types"), exports);
|
|
91
|
+
//# sourceMappingURL=compiler.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Compiler = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/**
|
|
6
|
+
* 编译器 - 将 AST 编译为字节码
|
|
7
|
+
*/
|
|
8
|
+
class Compiler {
|
|
9
|
+
compile(ast) {
|
|
10
|
+
if (ast.type !== types_1.ASTNodeType.PROGRAM) {
|
|
11
|
+
throw new Error(`Expected Program node, got ${ast.type}`);
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
instructions: [],
|
|
15
|
+
constants: [],
|
|
16
|
+
names: [],
|
|
17
|
+
ast
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.Compiler = Compiler;
|
|
22
|
+
//# sourceMappingURL=compiler.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Compiler = void 0;
|
|
4
|
+
var compiler_1 = require("./compiler");
|
|
5
|
+
Object.defineProperty(exports, "Compiler", { enumerable: true, get: function () { return compiler_1.Compiler; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.PythonCompiler = void 0;
|
|
38
|
+
const compiler_1 = require("./compiler");
|
|
39
|
+
Object.defineProperty(exports, "PythonCompiler", { enumerable: true, get: function () { return compiler_1.PythonCompiler; } });
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
function main() {
|
|
42
|
+
const args = process.argv.slice(2);
|
|
43
|
+
if (args.length === 0) {
|
|
44
|
+
console.error('Usage: PyVM <file.py>');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const filePath = args[0];
|
|
48
|
+
if (!fs.existsSync(filePath)) {
|
|
49
|
+
console.error(`Error: File '${filePath}' not found`);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
const compiler = new compiler_1.PythonCompiler();
|
|
53
|
+
try {
|
|
54
|
+
const result = compiler.runFile(filePath);
|
|
55
|
+
if (result !== undefined) {
|
|
56
|
+
console.log(result);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error('Error:', error instanceof Error ? error.message : error);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (require.main === module) {
|
|
65
|
+
main();
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Lexer = void 0;
|
|
4
|
+
var lexer_1 = require("./lexer");
|
|
5
|
+
Object.defineProperty(exports, "Lexer", { enumerable: true, get: function () { return lexer_1.Lexer; } });
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Token } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* 词法分析器 - 将源代码转换为 token 流
|
|
4
|
+
*/
|
|
5
|
+
export declare class Lexer {
|
|
6
|
+
private code;
|
|
7
|
+
private pos;
|
|
8
|
+
private line;
|
|
9
|
+
private column;
|
|
10
|
+
private tokens;
|
|
11
|
+
private indentStack;
|
|
12
|
+
private atLineStart;
|
|
13
|
+
constructor(code: string);
|
|
14
|
+
tokenize(): Token[];
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=lexer.d.ts.map
|