i think (never played much) that cps is probably not a bad idea if you use it only for control flow and put dataflow somewhere else; cf some of my other comments on ssa-as-ai (cba to find the comments—don’t think i talked about the interesting stuff anyway :). e.g. the substitution optimisation described here; nominally, this is a complete nothing optimisation (allocate the same register to argument and parameter and then the move is a no-op and it’s exactly the same as if you had just substituted it), but, like ‘inlining’ (another kind of halfbaked optimisation), it enables further optimisations within the body. i think applying ssa-as-ai to cps to get a shadow dataflow graph completely subsumes substitution. probably so does sea-of-nodes cps (never looked closely at this either)
of course cps shares the problems of other control-flow-oriented irs (sea of nodes, cfg, probably anf) that control is totally scheduled / you have to sharply distinguish data from control . (the only satisfactory solution i’ve seen is rvsdg. apparently turbofan uses sea of nodes with some unscheduled control, and i don’t know exactly how this works, but i strongly suspect it can’t generalise well; the semantics seem to get really finicky and hard to reason about. because the graph is free form, you have to ensure there are no ‘conflicts’ between distinct control tokens (or pick a semantics for conflicts); rvsdg’s region boundaries make the partitioning explicit. it does schedule somewhat, but only to the extent actually necessary for optimisation—suppose a conditionally evaluated expression is condition-invariant, but you want to apply a conditionally correct optimisation; then you have to schedule it dependently on the conditional to be able to do it with local reasoning.) but it’s nice within that paradigm because control flow is completely uniform in the intermediate representation (you do want to convert between calls at the edges but that’s fine)
i think (never played much) that cps is probably not a bad idea if you use it only for control flow and put dataflow somewhere else; cf some of my other comments on ssa-as-ai (cba to find the comments—don’t think i talked about the interesting stuff anyway :). e.g. the substitution optimisation described here; nominally, this is a complete nothing optimisation (allocate the same register to argument and parameter and then the move is a no-op and it’s exactly the same as if you had just substituted it), but, like ‘inlining’ (another kind of halfbaked optimisation), it enables further optimisations within the body. i think applying ssa-as-ai to cps to get a shadow dataflow graph completely subsumes substitution. probably so does sea-of-nodes cps (never looked closely at this either)
of course cps shares the problems of other control-flow-oriented irs (sea of nodes, cfg, probably anf) that control is totally scheduled / you have to sharply distinguish data from control . (the only satisfactory solution i’ve seen is rvsdg. apparently turbofan uses sea of nodes with some unscheduled control, and i don’t know exactly how this works, but i strongly suspect it can’t generalise well; the semantics seem to get really finicky and hard to reason about. because the graph is free form, you have to ensure there are no ‘conflicts’ between distinct control tokens (or pick a semantics for conflicts); rvsdg’s region boundaries make the partitioning explicit. it does schedule somewhat, but only to the extent actually necessary for optimisation—suppose a conditionally evaluated expression is condition-invariant, but you want to apply a conditionally correct optimisation; then you have to schedule it dependently on the conditional to be able to do it with local reasoning.) but it’s nice within that paradigm because control flow is completely uniform in the intermediate representation (you do want to convert between calls at the edges but that’s fine)
Isn’t CPS basically just generator functions without syntax?
I’m not sure what exactly generator function is, but for me CPS is just multiple stacks made explicit.
That’s an interesting way of putting it. I think the same description could apply equally well to generators in JS and Python