@@ -204,14 +204,14 @@ def emit_l3_body(
204204 :func:`build_function_pdgs` (syntactic oracle), this writes onto the
205205 matching ``PyCallable`` in ``app``'s symbol table:
206206
207- * ``body`` — one node per CFG node, keyed by its ordinal id
208- (``<can:// id>@entry``/``@ exit`` for the synthetic bookends,
209- ``<can:// id>@line:col`` for real statements ). A statement position an
210- L1 pass already materialized as a ``call`` node keeps its ``call`` kind
211- and L2-resolved ``callee``; it is only re-keyed onto its ordinal id (so
212- the edge lists resolve to it and it is not duplicated) and given the
213- byte-offset ``span`` L1 could not compute.
214- * ``cfg`` — one ``CfgEdge`` per CFG edge, endpoints as ordinal ids.
207+ * ``body`` — one node per CFG node, keyed by its LOCAL id (``"@entry"``/
208+ ``"@ exit" `` for the synthetic bookends, ``"line:col"`` for real
209+ statements — the same key format L1 uses ). A statement position an L1
210+ pass already materialized as a ``call`` node lands on the SAME local key,
211+ so it keeps its ``call`` kind and L2-resolved ``callee`` in place (no
212+ re-keying, no duplication) and is only given the byte-offset ``span`` L1
213+ could not compute.
214+ * ``cfg`` — one ``CfgEdge`` per CFG edge, endpoints as local ids.
215215 * ``cdg`` — the PDG's control-dependence edges.
216216 * ``ddg`` — the PDG's syntactic def-use edges, each with ``prov=["ssa"]``
217217 (no points-to provenance at L3; that is the L4 delta).
@@ -261,50 +261,45 @@ def _span_of(source: str, node) -> Optional["Span"]:
261261 im = IdentityMap .for_function (callable_id , pdg )
262262
263263 for node in pdg .cfg .nodes :
264- ordinal = im .ordinal (node .id )
264+ local = im .local (node .id )
265265 if node .id == pdg .cfg .entry_id :
266- pycallable .body [ordinal ] = BodyNode (kind = "entry" )
266+ pycallable .body [local ] = BodyNode (kind = "entry" )
267267 continue
268268 if node .id == pdg .cfg .exit_id :
269- pycallable .body [ordinal ] = BodyNode (kind = "exit" )
269+ pycallable .body [local ] = BodyNode (kind = "exit" )
270270 continue
271271 span = _span_of (source , node )
272- # An L1 `call` node was keyed by its "line:col"; if this CFG node
273- # sits at the same position, keep that node's `call` kind and
274- # resolved `callee` and merely re-key it onto the ordinal id
275- # (dedup + endpoint resolution), filling any missing span.
276- existing = pycallable .body .get (ordinal )
277- if existing is None :
278- existing = pycallable .body .pop (
279- f"{ node .start_line } :{ node .start_column } " , None
280- )
272+ # An L1 `call` node was keyed by its LOCAL "line:col"; this CFG
273+ # node at the same position lands on the SAME key, so keep the
274+ # node's `call` kind and L2-resolved `callee` in place and just
275+ # fill any missing span — never re-key or duplicate it.
276+ existing = pycallable .body .get (local )
281277 if existing is not None :
282278 if existing .span is None and span is not None :
283279 existing .span = span
284- pycallable .body [ordinal ] = existing
285280 continue
286- pycallable .body [ordinal ] = BodyNode (kind = node .kind , span = span )
281+ pycallable .body [local ] = BodyNode (kind = node .kind , span = span )
287282
288283 if want_cfg :
289284 pycallable .cfg = [
290285 CfgEdge (
291- src = im .ordinal (e .source ),
292- dst = im .ordinal (e .target ),
286+ src = im .local (e .source ),
287+ dst = im .local (e .target ),
293288 kind = e .kind ,
294289 )
295290 for e in pdg .cfg .edges
296291 ]
297292 if want_pdg :
298293 pycallable .cdg = [
299- CdgEdge (src = im .ordinal (e .source ), dst = im .ordinal (e .target ))
294+ CdgEdge (src = im .local (e .source ), dst = im .local (e .target ))
300295 for e in pdg .edges
301296 if e .type == "CDG"
302297 ]
303298 if want_ddg :
304299 pycallable .ddg = [
305300 DdgEdge (
306- src = im .ordinal (e .source ),
307- dst = im .ordinal (e .target ),
301+ src = im .local (e .source ),
302+ dst = im .local (e .target ),
308303 var = e .var ,
309304 prov = ["ssa" ],
310305 )
0 commit comments