Function Call / Execution Model
- Augment the block building monad with state to keep current variables in scope
- Bind all arguments for closure RHS as basic block arguments (this keeps them in scope)
- Keep a mapping of internal variable IDs to currently bound names, and substitute them in when necessary
For dealing with let and let-no-escape, we still need to make sure everything that was captured in the outer scope is still in scope.
- Define everything that is needed by the let binding
- Call into a new basic block with the extra variables in scope
- For let, proceed as normal. For let-no-escape, generate code, ensuring that the last operation is an unconditional branch back to the start of the block.