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