This fits inbetween checking (+monomorphization) and compilation, but we'll need to modify checking (specifically check_call and synthesize_call) to build the callgraph.
The intervening analysis phase uses a graph library to identify cycles (connected components); all functions in a CC will have the same effects. Effects of unannotated functions can then be calculated by a tree traversal (union of effects in the body of a function/cycle plus those in any callee outside of the cycle).
Whether we should error on finding a call from a max_effects= function to one that's unannotated is debateable - we could add a strict_effects=<bool> flag but we can probably allow this and instead enforce that every @guppy.declare is explicitly annotated along with every library export (otherwise it's very easy to introduce breaking changes).
This fits inbetween checking (+monomorphization) and compilation, but we'll need to modify checking (specifically
check_callandsynthesize_call) to build the callgraph.The intervening analysis phase uses a graph library to identify cycles (connected components); all functions in a CC will have the same effects. Effects of unannotated functions can then be calculated by a tree traversal (union of effects in the body of a function/cycle plus those in any callee outside of the cycle).
Whether we should error on finding a call from a
max_effects=function to one that's unannotated is debateable - we could add astrict_effects=<bool>flag but we can probably allow this and instead enforce that every@guppy.declareis explicitly annotated along with every library export (otherwise it's very easy to introduce breaking changes).