;; Problem: only lifts programs to the most recent bound variable, could be better (optimization wise) to lift them as high as possible
;; For instance if we have a (case contradiction) then we want to lift that as high as possible because the whole code is dead!
;; On the other hand, we will get somewhat of a code explosion because of case statements, so in practice we would want a compromise between these two techniques.
;; To solve this we'll work in two passes, first we will annotate
;; every AST node with its free variables
;; Then in the second pass we use a more *cooperative* continuation protocol:
;; First, every prompt is at a binding site and so when we install, it
;; is associated with a list of variables it binds w
;; Second, when we control, we only get up to the closest prompt, so
;; we need the prompt "handler" to "re-raise" the control if the value
;; that we are lifting would still be well typed.
;; If the value would not be well typed, we insert it *here* and the control is "handled"
;;
;; So when we control, we need to provide enough information, this means we return a list of
;; Exn : FV -> Kont -> CPST
;; where FV are all of the free variables in the term Thk will return
;; Kont is the captured continuation up to the prompt
;; CPST is a function that takes a continuation for a term and returns a term (possibly re-raising later)
;; So when we write control, we also provide the free variables of the term
(define(control-vars-funvarscps)
(controlk2(list'raisevarsk2cps)))
(define-syntax-rule(control-varsvarskt)
(control-vars-funvars(λ(k)t)))
;; So now all of our work is in the "handler"
;; First, we need to install a prompt for our term and insert an implicit "return"