Skip to content

Handle expanded generator-call stack slots in Python 3.13 and 3.14 - #2

Open
EiNSTeiN- wants to merge 5 commits into
ejfkdev:mainfrom
EiNSTeiN-:fix/generator-expanded-call-slot
Open

EiNSTeiN- wants to merge 5 commits into
ejfkdev:mainfrom
EiNSTeiN-:fix/generator-expanded-call-slot

Conversation

@EiNSTeiN-

@EiNSTeiN- EiNSTeiN- commented Oct 13, 2026 •

Copy link
Copy Markdown

I am opening this PR to fix expanded calls inside generator expressions in pycdc. The code below fails to decompile correctly from Python 3.13 and 3.14 bytecode and succeeds with this change:

def select(rows, factory):
    return tuple(factory(**dict(row)) for row in rows)

The same stack distinction applies to factory(*row) and factory(*args, **kwargs): an absent keyword mapping is a NULL marker, not another source argument. The generator expression simulator decides whether to pop the keyword slot solely from the low flag bit of CALL_FUNCTION_EX. The 3.14 convention has a slot even when it represents no mapping. The fix consumes the slot for that convention and omits its NULL marker from the AST, keeping the callable and positional iterable in their actual positions.

The adjacent callable/NULL check also needs its version boundary corrected. CPython changes the callable/NULL ordering in 3.13, while the unconditional keyword slot begins in 3.14. These are separate version checks: older interpreters retain their flag-dependent keyword slot. The layouts are defined in CPython's 3.12 implementation, 3.13 implementation, and 3.14 implementation.

docs/LIMITATIONS.md now distinguishes these working simple expanded calls from the remaining nested-comprehension stack issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant