89 lines
2.3 KiB
Org Mode
89 lines
2.3 KiB
Org Mode
* example
|
|
|
|
#+begin_src scheme
|
|
(letrec ((fac (λ (n)
|
|
(if (zero? n)
|
|
1
|
|
(* n (fac (- n 1)))))))
|
|
(fac 3))
|
|
#+end_src
|
|
|
|
#+begin_src scheme
|
|
(λ (ktail0)
|
|
(letrec ((fac
|
|
(λ (n ktail1)
|
|
(zero?
|
|
n
|
|
(κ (x0)
|
|
(if x0
|
|
(continue ktail1 1)
|
|
(- n 1
|
|
(κ (x1)
|
|
(fac x1
|
|
(κ (x2)
|
|
(* n x2 ktail1)))))))))))
|
|
(fac 3)))
|
|
#+end_src
|
|
|
|
#+begin_example
|
|
n ktail1
|
|
| |
|
|
| | x0
|
|
| | |
|
|
| | ^
|
|
| |
|
|
| | x1
|
|
| | |
|
|
| | ^
|
|
| |
|
|
| | x2
|
|
| | |
|
|
^ ^ ^
|
|
#+end_example
|
|
|
|
#+begin_src scheme
|
|
(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.
|
|
)
|
|
#+end_src
|
|
|