The goal of this repository is not to fully rewrite CPython from day one. Instead, it first establishes a stable, regression-friendly, and extensible sample suite, then gradually implements the system with a TDD / SDD workflow:
- Python source input
- Compile Python source into
.pyc - Inspect compiled
.pycartifacts - Execute them with a simplified virtual machine
- Verify behavior through regression checks
The entire project is implemented in Python, without using C.
This choice has several direct advantages:
- the code is simpler and the overall structure is clearer
- it is better suited for teaching, reading, and step-by-step experimentation
- iteration is cheaper and changes are faster to make
- it is also more AI-agent-friendly and costs fewer tokens during collaboration
The focus of this project is to understand .pyc, bytecode, parsers, and virtual machines themselves, rather than spending large amounts of effort on C engineering details.
When building a CPython-style interpreter yourself, the easiest way to fail is not "not knowing how to code," but rather:
- not having enough behavioral samples
- not knowing what regressed after a change
- only being able to run extremely simple demos
- being unable to systematically observe the transition from
.pyto.pyc
So in the first phase, this repository prioritizes two things:
- collecting a large number of Python samples that can be compiled, executed, and asserted
- generating
.pycfiles for each sample as input for later parsing and execution work
tests/Stores a collection of small and clear Python samplespy2pyc-parser/Responsible forpy -> pycpyc-vm/Responsible forpyc -> rundis-study/Used to inspectdisoutput, generate.pyc, and save disassembly text
The responsibilities of these three directories are intentionally kept very clear:
dis-study/Uses the standard library to get the.py -> .pyc -> .txtobservation pipeline working first, while preserving the generated artifactspy2pyc-parser/Studies and implements how Python source code is compiled into.pycpyc-vm/Reads.pycand executes it on a handwritten VM
In other words, the current mainline of the project is not "parsing .pyc back into source code," but:
tests/*.pypy2pyc-parserhandlespy -> pycdis-studyis used to inspect.pycanddistextpyc-vmhandlespyc -> run
Already completed:
tests/A large set of regression-friendly Python samples is already in placedis-study/Can already generate and preserve.pycfiles and matchingdistext reliablypyc-vm/Already hasphase1andphase2designs, andphase2runs successfully across the current batch of.pycfiles
Still to be advanced:
py2pyc-parser/Continue making the "Python source to.pyc" layer more handwritten, clearer, and more suitable for teaching
Files under tests/ follow these rules as much as possible:
- each file should express one clear topic
- use normal Python syntax without third-party dependencies
- use
assertdirectly to express expected results - include both basic exercises and more LeetCode-style problems
- prioritize semantic points that interpreters commonly get wrong
Examples include:
- function calls
- recursion
- loops
- conditional branches
- lists, dictionaries, and sets
- string processing
- slicing
- sorting
- binary search
- stacks and queues
- dynamic programming
You can move forward in the following order:
- Write or add one Python sample first
- Compile the corresponding
.pycusing the existing toolchain - Inspect the
disoutput - Gradually study and implement the
py -> pyccompilation path insidepy2pyc-parser/ - Gradually support more opcodes inside
pyc-vm/ - Re-run the sample and confirm the behavior stays consistent
The first phase does not aim for a complete interpreter. It aims for:
- many stable samples
- many
.pycfiles - a clear separation between the compilation layer and the execution layer
- incremental support for basic control flow and data structures
- immediate regression cases whenever a new capability is added
After this batch of foundational samples runs successfully, the next things to add can include:
- closures
- generators
- classes and objects
- exception handling
- the import system
- context managers
Build the "sample library + .pyc sample library" first, and the later interpreter implementation will become much more stable.