; -- Convert to imperative form ----------------------
; -- This puts it into a form where all of the ---------
; -- recursion can be replaced by assignments and "goto"s

(load "chez-init.ss")
(define any? (lambda (x) #t))

(define-datatype continuation continuation?  ; no changes
  [init-k]
  [append-k (a any?) (k continuation?)]
  [rev1-k (car-L any?) (k continuation?)]
  [rev2-k (reversed-cdr (list-of any?)) (k continuation?)])

; global variables take the place of parameters of
; substantial procedures.
(define L)  ; current list
(define k)  ; current continuation
(define a)  ; used for append
(define b)  ; used for append
(define v)  ; 2nd parameter of apply-k application

; The next 3 procedures are from the previous file. 
; Convert them.

(define apply-k
  (lambda () ; k v
    (trace-it "apply-k   ")
    (cases continuation k
      [init-k () (printf "answer: ~s~n" v)]
      [append-k (a k1)
		(set! v (cons (car a) v))
		(set! k k1)
		(apply-k)]
      [rev1-k (car-L k1)
	      (if (pair? car-L)
		  (begin
		    (set! L car-L)
		    (set! k (rev2-k v k1))
		    (reverse*-cps))
		  (begin
		    (set! a v)
		    (set! b (list car-L))
		    (set! k k1)
		    (append-cps)))]
      [rev2-k (reversed-cdr k1)
	      (set! a reversed-cdr)
	      (set! b (list v))
	      (set! k k1)
	      (append-cps)])))

(define reverse*-cps
  (lambda () ; L k
    (trace-it "reverse*  ")
    (if (null? L)
        (begin
	  (set! v '()) ; no need to change k
	  (apply-k))
	(begin
	  (set! k (rev1-k (car L) k))
	  (set! L (cdr L))
          (reverse*-cps)))))

(define append-cps
  (lambda () ; a b k
    (trace-it "append    ")
    (if (null? a)
	(begin
	  (set! v b)
          (apply-k))
	(begin
	  (set! k (append-k a k))
	  (set! a (cdr a))
          (append-cps)))))

; This driver procedure isn't really substantial,
; So it's okay for it to have a parameter.
(define test-reverse
  (lambda (slist)
    (set! L slist)
    (set! k (init-k))
    (reverse*-cps)))

'(test-reverse
  '(1 ((2 3) () (((4))))))

(define *tracing* #t)

(define trace-it
  (lambda (str)
    (when *tracing*
      (printf "~a " str)
      (printf "L=~s" L)
      (printf "  a=~s" a)
      (printf "  b=~s" b)
      (printf "  v=~s~%" v)
      (printf "           k=~s~%" k))))