You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
MicroPython's own .pyi stubs (micropython-rp2-stubs, the parity suite's reference) mark
every C-implemented function and most method setters as positional-only, using PEP 3102's / marker: def sleep(seconds, /) -> None: .... This layer's real Python source can never
match that shape, because neither PyMCU frontend parses /:
The hand-written C# parser (src/compiler/Frontend/Parser.cs, ParseParameters()) has no
branch for TokenType.Slash; def f(a, /, b=0): is a hard parse error there today
("Expected parameter name", pointing at the /).
The CPython-ast frontend (PYMCU_PY_PARSER=1, Frontend/PyParser/pymcu_translate.py)
parses / without erroring, but silently merges posonlyargs into the ordinary
positional list (no flag is ever emitted), so the restriction is a no-op even there.
Param (src/compiler/Frontend/Ast.cs) has no positional-only flag at all, and call
binding (src/compiler/IR/IRGenerator/Call.cs) matches keywords purely by name.
Since the default frontend is the C# parser, / cannot be used in this repo's source without
breaking the build for anyone not setting PYMCU_PY_PARSER=1.
What this blocks
tests/parity/ compares this layer's real (CPython-importable) function signatures against
the stub via inspect.signature, which correctly reports POSITIONAL_ONLY for stub params
before /. Every one of the symbols below differs from its stub only in that kind (name,
default and required-ness already agree, or agree once the harmless renames below are made);
none of them can be closed until the compiler accepts /.
time.sleep, time.sleep_ms, time.sleep_us, time.ticks_add, time.ticks_diff
(and the utime aliases of all five)
micropython.const (stub param is named expr, ours value)
micropython.native, micropython.viper (stub param is named _func, ours f)
machine.enable_irq
machine.UART.readinto (name already matches: buf)
machine.UART.write (stub param is named buf, ours data)
machine.PWM.duty_ns, machine.PWM.duty_u16, machine.PWM.freq (each already has a
real no-arg getter and a one-arg setter @inline overload, matching arity; only the
setter's positional-only value blocks an exact match)
machine.time_pulse_us (also needs timeout_us widened past uint16: the stub's
default is 1 000 000 µs (1 s, MicroPython's convention), which does not fit the
16-bit parameter this HAL currently uses)
Add / support to src/compiler/Frontend/Parser.cs (ParseParameters(), mirroring the
existing bare-* handling), a positional-only flag on Param, and the matching change in pymcu_translate.py/PythonAstReader.cs so both frontends agree. This is a compiler-repo
change (PyMCU/PyMCU); tracked here because it blocks this layer's own parity suite
(tests/parity/, allowlisted tracked:#<this issue>).
What happens
MicroPython's own
.pyistubs (micropython-rp2-stubs, the parity suite's reference) markevery C-implemented function and most method setters as positional-only, using PEP 3102's
/marker:def sleep(seconds, /) -> None: .... This layer's real Python source can nevermatch that shape, because neither PyMCU frontend parses
/:src/compiler/Frontend/Parser.cs,ParseParameters()) has nobranch for
TokenType.Slash;def f(a, /, b=0):is a hard parse error there today("Expected parameter name", pointing at the
/).PYMCU_PY_PARSER=1,Frontend/PyParser/pymcu_translate.py)parses
/without erroring, but silently mergesposonlyargsinto the ordinarypositional list (no flag is ever emitted), so the restriction is a no-op even there.
Param(src/compiler/Frontend/Ast.cs) has no positional-only flag at all, and callbinding (
src/compiler/IR/IRGenerator/Call.cs) matches keywords purely by name.Since the default frontend is the C# parser,
/cannot be used in this repo's source withoutbreaking the build for anyone not setting
PYMCU_PY_PARSER=1.What this blocks
tests/parity/compares this layer's real (CPython-importable) function signatures againstthe stub via
inspect.signature, which correctly reportsPOSITIONAL_ONLYfor stub paramsbefore
/. Every one of the symbols below differs from its stub only in that kind (name,default and required-ness already agree, or agree once the harmless renames below are made);
none of them can be closed until the compiler accepts
/.time.sleep,time.sleep_ms,time.sleep_us,time.ticks_add,time.ticks_diff(and the
utimealiases of all five)micropython.const(stub param is namedexpr, oursvalue)micropython.native,micropython.viper(stub param is named_func, oursf)machine.enable_irqmachine.UART.readinto(name already matches:buf)machine.UART.write(stub param is namedbuf, oursdata)machine.UART.irq(added 2026-09-15, UART init/deinit/flush/sendbreak/txdone need new HAL primitives (PyMCU/PyMCU#451); irq() done #16:handler/trigger/hardare all positional-only in the stub,
(self, handler=None, trigger=0, hard=False, /);names, defaults and required-ness already agree)
machine.Pin.value,machine.Pin.mode,machine.Signal.value(their setter overload'sxis positional-only,(self, x, /); the getter overload already matches exactly,closed 2026-09-15 in Pin.value()/Pin.mode()/Signal.value() encode "read" as the sentinel value 255, which collides with the legal value 255 #13)
machine.PWM.duty_ns,machine.PWM.duty_u16,machine.PWM.freq(each already has areal no-arg getter and a one-arg setter
@inlineoverload, matching arity; only thesetter's positional-only
valueblocks an exact match)machine.time_pulse_us(also needstimeout_uswidened pastuint16: the stub'sdefault is 1 000 000 µs (1 s, MicroPython's convention), which does not fit the
16-bit parameter this HAL currently uses)
machine.I2C/machine.SoftI2C'swrite,readinto,writeto,readfrom_into,writeto_mem,readfrom_mem_into(added 2026-09-15, I2C/SoftI2C stop= done; buffer-vs-heap shapes documented #14/I2C/SoftI2C primitives mostly done; init/deinit need PyMCU/PyMCU#455, writevto/I2CTarget remain #15:each matches the real stub in every param name, kind and default except the trailing
/)machine.SPI.write,SPI.write_readinto,SPI.readinto(added 2026-09-15,I2C/SoftI2C stop= done; buffer-vs-heap shapes documented #14: same, blocked only by
/)Fix
Add
/support tosrc/compiler/Frontend/Parser.cs(ParseParameters(), mirroring theexisting bare-
*handling), a positional-only flag onParam, and the matching change inpymcu_translate.py/PythonAstReader.csso both frontends agree. This is a compiler-repochange (PyMCU/PyMCU); tracked here because it blocks this layer's own parity suite
(
tests/parity/, allowlistedtracked:#<this issue>).