Now represent environments on stack.  Observe that sole purpose of
loop in apply-ak is to construct list for use by apply-proc.  So
let's just pass the stack to apply-proc and let it sort it out.

apply-proc either pulls out the pieces and passes them to the
primops, or builds an environment for a closure.  So we need to
represent environments on the stack.  An environment
representation will also have to represent a continuation which,
when executed, will clean itself up:

(ep, a) represents ((extend-rec decls env), (cleanup-rec k)) iff
   a[ep] = 'extend-rec
   and a[ep-1] = decls
   and (a[ep-2],a) represents env  [the static link]
   and (ep-3, a) represents k

More interesting:

(ep, a) represents
         ((extend formals args env), (proc-value-cont k))  iff
   a[ep] = 'proc-value-cont
   and a[ep-1] = formals
   and (a[ep-2], a) represents env   [static link]
   and a[ep-3] = bp < ep             [dynamic link]
   and for all i [1 <= i <= (length args))]
       a[bp+2*i] = (car (list-ref args i))
       a[bp+2*i-1] = (cdr (list-ref args i))
   and (bp-2, a) represents k        [bp is really dynamic chain]       

We just use proc-value-cont, since on procedure exit we need to check
that we're returning a legal value AND cleanup the stack.

We can generalize this to say that if args is an args-list, then 

(bp, a) represents args iff
    for all i [1 <= i <= (length args))]
       a[bp+2*i] = (car (list-ref args i))
       a[bp+2*i-1] = (cdr (list-ref args i))

Under this representation, the internal loop in apply-ak is a no-op, since
bp ALREADY represents the entire args-list.  So when we call apply-ak,
we can go immediately to the akp = bp case.

We'll also make (0, a) represent the initial environment

We'll have to go through and change all env's to ep.  Also check our
representations to replace a[j] = env to  (a[j], a) represents
env.

Need to save arguments across call to apply-env in ak.  So
represent proc-cont with args in stack:

(kp, a) represents (proc-cont args k) iff
     a[kp] = 'proc-cont
     and a[kp-1] = bp
     and (bp, a) represents args
     and (bp-2, a) represents k



****************************************************************

Represent value continuations on stack.  Use straightforward
representation, (tag field1 field2 ..fieldn vk) represented by

(a, kp) represents (tag field1 field2 ..fieldn k)
   iff a[kp] = tag
       a[kp-1] = field1
       etc...
       (a, kp-n-1) represents k

Cases:

(final-valcont)
(test-value-cont exp1 exp2 env vk)
(first-arg-cont rands env ak)   -- but watch out for ak.
(proc-value-cont vk)       superceded
%% (proc-cont args vk)     superceded

Represent args continuations without tags.  Two kinds of ak's:  

(all-args-cont rator rands vk)

(other-args-cont arg arg-env ak)

So an ak is a sequence of other-args-cont's, terminated by an
all-args-cont.   Since there is only one builder, we don't need a
tag, but we do need to find the end of the list.  We do this with
another pointer (the "base pointer"):

(a, akp, bp) represents (all-args-cont rator env vk) iff
      akp = bp and a[akp] = rator
               and (a[akp-1], a) represents env   <<--- CHANGED
               and (a, kp-2) represents vk

(a, akp, bp) represents (other-args-cont arg arg-env ak) iff
      akp > bp and a[akp] = arg
               and a[akp-1] = arg-env
               and (a, akp-2, bp) represents ak              

