the header, and processing before the loop. May declare some new variables
the condition, when to stop the loop.
the actual loop body. It changes some of the header's variables and/or the parameters passed in.
the tailtail; what happens after the loop and return result.
Et voilà; a tail recursive version of any loop. breaks and continues in the loop body will still have to be replaced with return tail and return foo_recursion(params, modified_header_vars) as needed but that is simple enough.
Going the other way is more complicated; in part because there can be multiple recursive calls. This means that each time we pop a stack frame there can be multiple places where we need to continue. Also there may be variables that we need to save across the recursive call and the original parameters of the call.
We can use a switch to work around that:
bar_recurse(params){
if(baseCase){
finalize
return
}
body1
bar_recurse(mod_params)
body2
bar_recurse(mod_params)
body3
}
bar_iterative(params){
stack.push({init, params})
while(!stack.empty){
stackFrame = stack.pop()
switch(stackFrame.resumPoint){
case init:
if(baseCase){
finalize
break;
}
body1
stack.push({resum1, params, variables})
stack.push({init, modified_params})
break;
case resum1:
body2
stack.push({resum2, params, variables})
stack.push({init, modified_params})
break;
case resum2:
body3
break;
}
}
}