This doesn't do a whole lot yet other than change the print out produced
by the analysis, but it lays the groundwork for a very major change I'm
working on next: teaching the call graph to actually be a call graph,
modeling *both* the indirect reference graph and the call graph
simultaneously. More details on that in the next patch though.
Here, the biggest qustion I have for reviewers is whether they like the
core interface used by the edge abstraction. Notably, the Edge::Kind
enums end up used broadly in the API of the entire call graph. Better
names or structure for these abstractions would be very interesting.
The rest of this is essentially a bunch of over-engineering that won't be
interesting until the next patch. But this also isolates essentially all of the
churn necessary to introduce the edge abstraction from the very important
behavior change necessary in order to separately model the two graphs. So it
should make review of the subsequent patch a bit easier at the cost of making
this patch seem poorly motivated. ;]
That said, if folks would rather me merge this into the big patch that
makes having this abstraction necessary, I'm happy to do that.
Having a class called edge which doesn't encode the source seems mildly confusing. Possibly OutboundEdge? Decidedly minor and optional.
If you make the change suggested, it might be good to pull enum out as a class enum Edge to keep the use sites descriptive. Edge::Ref is more meaningful that OutgoingEdge::Ref to me. Either way, nit, I'd be fine with either.
A bit more detail about the Function/Node and lazy creation might be useful for context on the accessors below.