Web page for IU Compiler Course for Fall 2020
View the Project on GitHub IUCompilerCourse/IU-P423-P523-E313-E513-Fall-2020
Example program:
(let ([sum 0])
  (let ([i 5])
    (begin
      (while (> i 0)
        (begin
          (set! sum (+ sum i))
          (set! i (- i 1))))
      sum)))
An example that involves lambda:
(let ([x 0])
  (let ([y 0])
    (let ([z 20])
      (let ([f (lambda: ([a : Integer]) : Integer (+ a (+ x z)))])
        (begin
          (set! x 10)
          (set! y 12)
          (f y))))))
Yet another example:
(define (f [x : Integer]) : (Vector ( -> Integer) ( -> Void))
  (vector
   (lambda: () : Integer x)
   (lambda: () : Void (set! x (+ 1 x)))))
(let ([counter (f 0)])
  (let ([get (vector-ref counter 0)])
    (let ([inc (vector-ref counter 1)])
      (begin
        (inc)
        (get)))))
To extend the lifetime of variables, we can “box” them, that is, put them on the heap.
If a variable is never on the LHS of a set!, then there is no need
to box it. We can copy its value into a closure to extend its life.
If a variable is not free in any lambda, then there is also no need
to box it, even if it is assigned-to. We can translate set! into
assignment in C7.
So for this example, we box x but not y, z, and a.
(let ([x 0])
  (let ([y 0])
    (let ([z 20])
      (let ([f (lambda: ([a : Integer]) : Integer (+ a (+ x z)))])
        (begin
          (set! x 10)
          (set! y 12)
          (f y))))))
==>
(define (main) : Integer
  (let ([x0 (vector 0)])
    (let ([y1 0])
      (let ([z2 20])
        (let ([f4 (lambda: ([a3 : Integer]) : Integer
                      (+ a3 (+ (vector-ref x0 0) z2)))])
          (begin 
            (vector-set! x0 0 10)
            (set! y1 12)
            (f4 y1)))))))
To determine which variables to box, create a auxiliary function
assigned&free that returns the set of variables that are
assigned-to, the set of variables that are free-in-a-lambda, and an
updated expression in which the bound variables that are both
assigned-to and free-in-a-lambda have been marked with the
AssignedFree AST node.
Recipe for boxing a variable:
initialize the variable with a one-element vector containing the original initializer.
 (Let (AssignedFree x) e body)
 ==>
 (Let x (Prim 'vector (list e')) body')
change uses of the variable to vector-ref.
 (Var x)
 ==>
 (Prim 'vector-ref (list (Var x) (Int 0)))
change set! with the variable on the LHS to a vector-set!.
 (SetBang x e)
 ==>
 (Prim 'vector-set! (list (Var x) (Int 0) e'))
The while, set!, and begin expressions are all complex,
so they should be let-bound to temporary variables.
Their subexpressions are allowed to be complex.
(let ([x0 10])
  (let ([y1 0])
    (+ (+ (begin (set! y1 (read)) x0)
           (begin (set! x0 (read)) y1))
       x0)))
==>
(let ([x0 10])
  (let ([y1 0])
    (let ([tmp1 (begin (set! y1 (read)) x0)])         ;; GOOD!
      (let ([tmp2 (begin (set! x0 (read)) y1)])
        (+ (+ tmp1 tmp2)
           x0)))))
or??
(let ([x0 10])
  (let ([y1 0])
    (begin
      (set! y1 (read))      ;;; WRONG!
      (set! x0 (read))
      (+ (+ x0 y1) x0))))
(rco-atom (Begin es body))
=
(values (Var tmp) 
        (tmp . (Begin es^ body^)))
where
es^ = (map rco-exp es)
body^ = (rco-exp body)
To handle begin, we need a new auxiliary function:
explicate-effect.  It takes an expression and a continuation block
and produces a block that performs the effects in the expression
followed by the block.
(explicate-effect (Int n) cont)
==>
cont
(explicate-effect (SetBang x e) cont)
==>
(explicate-assign x e cont)
(explicate-effect (Begin es body) cont)
==>
es'
where
body' = (explicate-effect body cont)
and es' is the reslult of applying explicate-effect to each
expression in es, back-to-front, using body' as the initial
continuation. (Hint: use for/foldr.)
(explicate-tail (Begin es body))
===>
body^ = (explicate-tail body)
(for/foldr ([cont body^]) ([e es])
   (explicate-effect e cont))
(explicate-effect (Call e es) cont)
==>
(Seq (Call e es) (force cont))
There are three new kinds of statements in C7:
Callreadvector-set!(explicate-effect (Prim '+ args) cont)
===>
cont
Add cases for the three new statements: Call, read, and
vector-set! by adapting the code generation for those forms in
assignment position.
Use dataflow analysis in uncover-live.