Contributing#
Contributions to PyMCU are welcome. Please read this guide before opening a PR.
Repository layout#
pymcu/
src/compiler/ # C# compiler (pymcuc)
Frontend/ # Lexer, Parser, AST
IR/ # IRGenerator, Optimizer, Tacky IR
Backend/Targets/AVR/ # AVR codegen, peephole, register allocator
lib/src/pymcu/ # Python stdlib (compiled into firmware)
hal/ # GPIO, UART, ADC, Timer, PWM, SPI, I2C
drivers/ # DHT11 and other device drivers
boards/ # Board pin name constants
chips/ # Chip configuration and __CHIP__
src/driver/ # Python CLI driver (pymcu build/flash/new)
tests/integration/ # .NET / AVR8Sharp integration tests
examples/avr/ # Firmware examples (each with a full test suite)
docs/ # This documentation site
Building the compiler#
dotnet publish src/compiler/PyMCU.Compiler.csproj -c Release -o build/bin --nologo
Running integration tests#
dotnet test tests/integration/PyMCU.IntegrationTests.csproj
All tests must stay green. Add a new test in tests/integration/Tests/AVR/ for every new
compiler or HAL feature.
Adding a stdlib module / Driver#
When contributing to the standard library or adding new drivers, please adhere to the following principles:
MicroPython/CircuitPython Compatibility (Crucial): If you are writing a driver for a sensor or exposing an API, it must match the corresponding MicroPython or CircuitPython API if one exists. Do not invent your own API names (e.g., use
machine.Pin, notpymcu.hal.gpio.Pinfor user-facing code). The internal HAL inlib/src/pymcu/halis meant to be wrapped by these compatibility layers.Add the implementation in
lib/src/pymcu/hal/(ordrivers/).Use
@inlinefor all public methods (zero-cost abstraction rule).Use
match __CHIP__.arch:for architecture dispatch.No non-ASCII characters — the compiler lexer is ASCII-only.
No multiline docstrings with code examples — use
# commentsinstead.After editing stdlib, sync to the local virtualenv:
rsync lib/src/pymcu/ .venv/lib/python3.X/site-packages/pymcu/
HAL coding rules#
No em dashes (U+2014) or other non-ASCII characters in any
.pyfile underlib/.No statements after
matchblocks — put defaults incase _:inside the match.Dotted names (
ClassName.ATTR) are value patterns inmatch/case; bare names are capture patterns.@inlinefunctions containingasm()with labels must delegate to a non-inline sub-helper to avoid label duplication across inline expansion sites.Do not use
+=/ augmented assignment inside compile-time unrolledforloops. Useacc = acc + xinstead (known compiler limitation).
Commit format#
PyMCU uses Conventional Commits. Every commit must be:
<type>(<scope>): <short description under 72 chars>
Types: feat, fix, docs, test, refactor, perf, chore, style
Scopes: avr, ir, parser, hal, driver, stdlib, drivers, test, docs, ci
A typical feature implementation splits into 2–5 focused commits:
feat(parser): parse @extern decorator on function definitions
feat(ir): emit Extern IR instruction and register extern symbols
feat(avr): emit .extern and CALL with AVR ABI for @extern
test(avr): add ExternCallTests for @extern C interop
docs: mark @extern as implemented in roadmap and limitations
Each commit must leave the test suite green.
Building this documentation#
cd docs
pip install -r requirements.txt
sphinx-build -b html . _build/html
python -m http.server -d _build/html # preview at http://localhost:8000
For live reload during editing:
pip install sphinx-autobuild
sphinx-autobuild . _build/html
Pull request checklist#
Fork the repository and create your branch from
main.Each commit follows Conventional Commits format.
All integration tests pass (
dotnet test ...).A test is added for any new compiler or HAL feature.
LANGUAGE_ROADMAP.mdanddocs/language/roadmap.mdare updated if applicable.docs/language/limitations.mdis updated if the supported/unsupported status changes.