If you can define an equality operation over zippers, then you walk from foo#1 to def foo#1, and from foo#2 to def foo#2, and then test if the zipper focused at def foo#1 is equal to the zipper focused at def foo#2.
The challenge, of course, is defining that innocuous equality function. A naive implementation would recurse through the upward triangle of the parse tree twice for each equality check, which is... suboptimal. One way to speed this equality check up is by interning zipper items, in which case you only need to check whether the unique ids are equal (hence the paths are equal, hence they're the same def). This is essentially the same thing as preprocessing to get unique ids, though with minor implementation differences for where the computations get pushed off to.
The language I'm working on now does interning automagically so I wasn't thinking about the fact that it'd have to be implemented for the problem in question. One nice thing about the interning approach is that the "preprocessing" only happens as you're walking over the tree and hence is interleaved with other computations. If you're only ever interested in def nodes, then interning zippers will label too much; but if you're interested in other sites as well, you may want those labels.
Not so drunk thinking...
The challenge, of course, is defining that innocuous equality function. A naive implementation would recurse through the upward triangle of the parse tree twice for each equality check, which is... suboptimal. One way to speed this equality check up is by interning zipper items, in which case you only need to check whether the unique ids are equal (hence the paths are equal, hence they're the same def). This is essentially the same thing as preprocessing to get unique ids, though with minor implementation differences for where the computations get pushed off to.
The language I'm working on now does interning automagically so I wasn't thinking about the fact that it'd have to be implemented for the problem in question. One nice thing about the interning approach is that the "preprocessing" only happens as you're walking over the tree and hence is interleaved with other computations. If you're only ever interested in def nodes, then interning zippers will label too much; but if you're interested in other sites as well, you may want those labels.