Files
gyehoek-hs/doc/liveness.org
T
2026-08-28 11:39:37 -06:00

2.3 KiB

example

  (letrec ((fac (λ (n)
                (if (zero? n)
                    1
                    (* n (fac (- n 1)))))))
  (fac 3))
  (λ (ktail0)
  (letrec ((fac
            (λ (n ktail1)
              (zero?
               n
               (κ (x0)
                  (if x0
                      (continue ktail1 1)
                      (- n 1
                         (κ (x1)
                            (fac x1
                                 (κ (x2)
                                    (* n x2 ktail1)))))))))))
    (fac 3)))
n ktail1
| |
| | x0
| | |
| | ^
| |
| | x1
| | |
| | ^
| | 
| | x2
| | |
^ ^ ^
  (define $fac-c0
    (pop! %x0 0) ; [ x0 $fac-c0 n $fac ktail1 ]
    (if %x0 ; [ $fac-c0 n $fac ktail1 ]
        ;; every variable but `ktail1' is dead so we pop them all.
        ;; this probably means that `if' should take two continuations
        ;; rather than two blocks.
        (then (pop! %_) ; [ $fac-c0 n $fac ktail1 ]
              (pop! %_) ; [ n $fac ktail1 ]
              (pop! %_) ; [ $fac ktail1 ]
              (push! 1) ; [ ktail1 ]
              (return 1)) ; [ 1 ktail1 ]
        (else (load! %n 1) ; [ $fac-c0 n $fac ktail1 ]
              (prim %x1 (- %n 1)) ; [ $fac-c0 n $fac ktail1 ]
              (push! $fac-c1) ; [ $fac-c0 n $fac ktail1 ]
              (push! $fac) ; [ $fac-c1 $fac-c0 n $fac ktail1 ]
              (push! %x1) ; [ $fac $fac-c1 $fac-c0 n $fac ktail1 ]
              (call 1) ; [ x1 $fac $fac-c1 $fac-c0 n $fac ktail1 ]
              )))

  (define $fac-c1
    (pop! %x2) ; [ x2 $fac-c1 $fac-c0 n $fac ktail1 ]
    (load! %n 3) ; [ $fac-c1 $fac-c0 n $fac ktail1 ]
    (prim %x3 (* %n %x2))
    (push! %x3) ; [ $fac-c1 $fac-c0 n $fac ktail1 ]
    (return 1) ; [ x3 $fac-c1 $fac-c0 n $fac ktail1 ]
    )

  (define $fac
    (load! %ktail1 2) ; [ n $fac ktail1 ]
    (load! %n 0) ; [ n $fac ktail1 ]
    (push! $fac-c0) ; [ n $fac ktail1 ]
    (push! $zero?) ; [ $fac-c0 n $fac ktail1 ]
    (push! %n) ; [ $zero? $fac-c0 n $fac ktail1 ]
    (call 1) ; [ n $zero? $fac-c0 n $fac ktail1 ]
    )

  (define $start
    (push! $fac) ; [ $start ktail0 ]
    (push! 3) ; [ $fac $start ktail0 ]
    (tail-call 1) ; [ 3 $fac $start ktail0 ]
    ;; ↑ `tail-call' knows how to dispose of the caller's stack frame.
    )