Skip to content

Preserve independent loop lookup guards and comparison polarity - #26

Open
EiNSTeiN- wants to merge 2 commits into
ejfkdev:mainfrom
EiNSTeiN-:fix/independent-loop-lookup-guards
Open

EiNSTeiN- wants to merge 2 commits into
ejfkdev:mainfrom
EiNSTeiN-:fix/independent-loop-lookup-guards

Conversation

@EiNSTeiN-

Copy link
Copy Markdown

I am opening this PR to keep independent loop rejection guards from moving a return outside the assignment it depends on. The code below currently decompiles incorrectly:

def select(values):
    for value in values:
        if not value.rating < 10:
            continue
        coordinator = value.coordinator
        if coordinator is None:
            continue
        return coordinator

For Python 3.14, pycdc currently emits:

def select(values):
    for value in values:
        if value.rating < 10:
            coordinator = value.coordinator
            if not coordinator is not None:
                continue
        return coordinator

The return now runs for rejected rows, where coordinator has not been assigned. The generic success-suite reconstruction closes at the later independent rejection guard and ejects the dependent return. This change reconstructs the first rejection as if ...: continue, keeping the lookup and return on the accepted path.

The same pattern occurs in dictionary lookups:

def select(rows):
    for row in rows:
        if not isinstance(row, dict):
            continue
        coordinator = row.get("coordinator")
        if coordinator is None:
            continue
        return coordinator

The recognizer proves the exact fallthrough back edge, assignment, None test and return of that same local. It applies only outside inline comprehensions and only to functions with no exception-table entries. Other shapes retain their existing reconstruction.

The comparison remains not (value.rating < 10): replacing it with value.rating >= 10 changes NaN behavior and dispatches to a different user-defined comparison method. Only proved None identity comparisons may invert their identity operator. A leading if row is None: continue is also supported, and the retrieved value is tested by identity, preserving valid false-valued results such as 0 and False.

This reconstruction applies to Python 3.12+, where the compiler uses the POP_JUMP_IF_NONE / POP_JUMP_IF_NOT_NONE layout matched here. Python 3.11's direction-specific None jumps remain on the existing path.

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