Skip to content

Fix Python nested function call resolution - #3410

Open
hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:investigate/3405-python-call-resolution
Open

Fix Python nested function call resolution#3410
hopstreax wants to merge 1 commit into
Graphify-Labs:v8from
hopstreax:investigate/3405-python-call-resolution

Conversation

@hopstreax

Copy link
Copy Markdown
Contributor

Summary

Fixes Python nested-function extraction and lexical call resolution for issue #3405.

Changes

  • Extract nested Python functions as proper Graphify function nodes.
  • Add contains edges between parent and nested functions.
  • Resolve unqualified calls using lexical scope.
  • Correctly handle nested-function shadowing of module-level functions.
  • Support nested sibling calls, recursion, async nested functions, and deeper nesting.
  • Prevent local non-callable variables from being incorrectly emitted as unresolved calls.

Tests

Added coverage for:

  • Nested function extraction and node IDs
  • Parent → nested contains relationships
  • Outer → nested function calls
  • Lexical shadowing
  • Nested sibling calls
  • Recursive nested functions
  • Async nested functions
  • Deeply nested functions
  • Local non-callable suppression

Existing Python, confidence-rubric, and JavaScript nested-function tests also pass.

Issue: #3405

@graphify-labs graphify-labs Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Graphify reviewed this change.

Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.

Formal verification. No changes could be formally verified in this run.


Graphify review — findings

Adds Python lexical-scope resolution for nested functions (#3405): _scan_python_nested_function_declarations emits nodes and contains edges for functions nested inside other functions, tracking each one's body, its bound names, and a scope_parents/lexical_nids_by_scope hierarchy. Unqualified Python calls now resolve by walking outward from the caller's scope through those maps before falling back to the module-level label lookup, and nested-function names no longer clobber module-level entries in label_to_nid. Unqualified calls that name a local non-callable variable or parameter are dropped rather than queued for cross-file resolution, and the self-call guard tgt_nid != caller_nid is removed so recursive calls emit an edge.

Worth a look

  • Direct self-call suppression removed from emitted call edgesgraphify/extractors/engine.py:5773 · Escalate · medium
    • agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification

Impact & health

Graphify review

Impact — 669 functions depend on the 228 functions this change touches.

Health — this change adds coupling hotspots:

  • new: _extract_generic() — 18 callers, 26 callees
  • new: extract_js() — 85 callers, 4 callees
  • new: extract_xaml() — 19 callers, 17 callees
  • new: extract_objc() — 27 callers, 9 callees
  • new: extract_julia() — 17 callers, 7 callees
  • new: extract_cpp() — 27 callers, 3 callees
  • new: extract_vue() — 10 callers, 7 callees
  • new: walk() — 1 callers, 59 callees
  • …and 8 more — each is listed as a finding

Verification — 669 functions in the blast radius were not formally verified this run (proofs are advisory here).

Gate & verification

graphify gate

PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.

Advisory (not blocking):

  • verification_scope: 609 function(s) in the blast radius were not formally verified this run

Formal verification

Could not verify: Could not verify \_extract\_generic.

The verifier did not have enough to check \_extract\_generic, so it is saying so rather than guessing. No false assurance is the whole point.

Guarantee: No guarantee either way, this is an honest abstention, not a pass.

Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set

· 16 more finding(s) on lines outside this diff (see the check run).

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