ericson@CSD16.NYU.EDU (Lars Ericson) (01/03/88)
Consider the following calling pattern: ;0 Calling /' with arguments (<f <f 1>> <f <f <f -2<pp Y>>>>) ; 1 Calling // with arguments (<f <f 1>> <f <f <f -2<pp Y>>>>) ; 2 Calling /' with arguments (<f 1> <f <f -2<pp Y>>>) ; 3 Calling // with arguments (<f 1> <f <f -2<pp Y>>>) ; 4 Calling /' with arguments (1 <f -2<pp Y>>) ; 5 Calling // with arguments (<f 1> <f -2<pp Y>>) ; 5 Returned from // with values ((<f 1>) / (<f -2<pp Y>>)) ; 4 Returned from /' with values ((<f 1>) / (<f -2<pp Y>>)) ; 3 Returned from // with values ((<f 1>) / (<f -2<pp Y>>)) ; 2 Returned from /' with values ((<f 1>) / (<f -2<pp Y>>)) ; 1 Returned from // with values ((<f 1>) / (<f -2<pp Y>>)) ;0 Returned from /' with values ((<f 1>) / (<f -2<pp Y>>)) /' is a procedure and // is an operation. Both are compiled, one calls the other. It is apparent that every call is tail-recursive, since the results on the way "back up" are unmodified. Why not use continuations somehow to have a "REWRITE-CALL", similar to a plain old JUMP, which passes arguments to a subprocedure, overwriting the argument space on the stack for the calling procedure, such that when the subprocedure returns, it returns to the caller of the caller? Like DEFINE-INTEGRABLE, REWRITE-CALL would be an optimization that the user applies intentionally when it is clear that the call is tail-recursive. This seems like it would be pretty easy to implement, both for interpreted and compiled code, in terms of continuations. -- Lars Ericson