mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-11 03:38:07 +00:00
Add createPythonCfgVisitor + python-harvest -- the most structurally divergent target (indentation blocks, elif, for/while-else, with, try/ except/except-group/else/finally, match/case, comprehensions, walrus), confirming the shared CfgBuilder/ControlFlowContext core carries no brace-family assumptions. for/while else-clause sits on the normal- completion edge (not break); with modeled as try/finally dispose; match has no fallthrough. Wire into pythonProvider. Every literal validated against tree-sitter-python via the probe. while True: keeps EXIT reverse-reachable (production CDG probe: 3 edges; fixture: 42 CDG edges). 37 real-parser tests; gate green; no regression (cfg unit 391, tsc clean). Gaps: async/generator suspension, comprehension scope over-approximation. No sites[] (taint substrate, separate). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
125 lines
3.1 KiB
Python
125 lines
3.1 KiB
Python
# Python CFG hazard fixture. Exercises every control-flow construct the Python
|
|
# visitor models, including the EXIT-reachability hazard (`while True:` with no
|
|
# static exit) the CDG soundness gate depends on, plus the structural divergences
|
|
# from the brace family: indentation blocks, elif, for/while-else, with,
|
|
# try/except/except*/else/finally, match/case, comprehensions, and the def shapes
|
|
# (tuple/list unpack, walrus, augmented assign, global/nonlocal, *args/**kwargs).
|
|
|
|
|
|
def if_elif_else(x):
|
|
"""if / elif / else branch senses."""
|
|
if x > 0:
|
|
r = positive()
|
|
elif x < 0:
|
|
r = negative()
|
|
else:
|
|
r = zero()
|
|
return r
|
|
|
|
|
|
def for_else(xs):
|
|
"""for-else: the else runs on NORMAL completion, not on break."""
|
|
found = None
|
|
for i in xs:
|
|
if matches(i):
|
|
found = i
|
|
break
|
|
else:
|
|
found = default()
|
|
return found
|
|
|
|
|
|
def while_else(x):
|
|
"""while-else: same else-on-normal-completion / not-on-break semantics."""
|
|
while x > 0:
|
|
if done(x):
|
|
break
|
|
x -= 1
|
|
else:
|
|
finished()
|
|
return x
|
|
|
|
|
|
def while_true_loop(x):
|
|
"""while True: keeps EXIT reverse-reachable (CDG soundness hazard)."""
|
|
while True:
|
|
if should_stop(x):
|
|
return collect()
|
|
x = step(x)
|
|
|
|
|
|
def with_dispose(path):
|
|
"""with runs __exit__ on BOTH the normal and the exception exit."""
|
|
with open(path) as fh, lock() as l:
|
|
data = fh.read()
|
|
use(l)
|
|
return process(data)
|
|
|
|
|
|
def with_early_return(path):
|
|
"""a return inside a `with` threads through the dispose."""
|
|
with open(path) as fh:
|
|
return fh.read()
|
|
|
|
|
|
def try_except_else_finally(payload):
|
|
"""try / except / except* / else / finally completion edges."""
|
|
try:
|
|
result = parse(payload)
|
|
except ValueError as e:
|
|
result = recover(e)
|
|
except (TypeError, KeyError):
|
|
result = fallback()
|
|
else:
|
|
validate(result)
|
|
finally:
|
|
cleanup()
|
|
return result
|
|
|
|
|
|
def try_except_group(payload):
|
|
"""except* group handler."""
|
|
try:
|
|
body(payload)
|
|
except* ValueError as eg:
|
|
handle_group(eg)
|
|
|
|
|
|
def match_dispatch(command):
|
|
"""match / case: no fallthrough; the no-wildcard path keeps EXIT reachable."""
|
|
match command:
|
|
case "start":
|
|
on_start()
|
|
case ["move", x, y]:
|
|
on_move(x, y)
|
|
case {"kind": k} if k > 0:
|
|
on_kind(k)
|
|
case _:
|
|
on_default()
|
|
return ack()
|
|
|
|
|
|
def defs_and_uses(a, b=1, *args, **kwargs):
|
|
"""tuple/list unpack, walrus, augmented assign, comprehension, global."""
|
|
global COUNTER
|
|
x, y = compute(a, b)
|
|
[p, q] = pair()
|
|
first, *rest = sequence(args)
|
|
if (n := length(kwargs)) > 0:
|
|
total = n + x + y + p + q
|
|
squares = [i * i for i in rest if i > 0]
|
|
COUNTER += 1
|
|
return total if a else squares
|
|
|
|
|
|
def nested_loops_labels(matrix):
|
|
"""nested loops with continue/break and a comprehension target."""
|
|
out = []
|
|
for row in matrix:
|
|
for cell in row:
|
|
if cell is None:
|
|
continue
|
|
if cell < 0:
|
|
break
|
|
out.append(cell)
|
|
return [v for v in out]
|