;;; -*- Mode:Text; Base:10.; Package:User;-*-
STACK GROUPS                               



Stack Group                   26.1 The data type stack-group (usually abbreviated SG) is a type of Lisp
Definitions                    object useful for implementing certain advanced control structures such as
			coroutines and generators. Processes, which are a kind of coroutine, are built
			on top of stack groups (see Section 27, Processes). A stack group represents a
			computation and its internal state, including the Lisp stack.

			At any time, the computation being performed by the Explorer system is
			associated with one stack group, called the current or running stack group. The
			operation of designating a particular stack group to be the current stack group
			is called a resumption or a stack group switch. The previously running stack
			group is said to have resumed the new stack group. The resume operation has
			two parts: first, the state of the running computation is saved away inside the
			current stack group; second, the state saved in the new stack group is restored,
			and the new stack group is made current. Then the computation of the new stack
			group resumes its course.

			The stack group itself holds a great deal of state information. It contains the
			control stack, or regular push down list (PDL). The control stack is what you
			are shown in the debugger. The control stack remembers the function that is
			running, its caller, its caller's caller, and so on, and the point of execution of
			each function (the return addresses of each function). A stack group also
			contains the environment stack, or special PDL. Switching to a stack group
			moves the current bindings from the special PDL to the symbol value cells,
			exchanging them with the global or other shadowed bindings. Switching out of a
			stack group reverses the process. (The name stack group derives from the
			existence of these two stacks.) Finally, the stack group contains various
			internal state information (contents of machine registers and so on).

			When the state of the current stack group is saved, all of its bindings are
			undone, and when the state is restored, the bindings are reinstated. Note that
			although bindings are temporarily undone, unwind-protect handlers are not run
			by a stack group switch (see the function let-globally in Section 2, Symbols).

			Each stack group is a separate environment for purposes of function calling,
			throwing, dynamic variable binding, and condition signaling. All stack groups
			run in the same address space; thus, they share the same Lisp data and the
			same global (not lambda-bound) variables.

			When a new stack group is created, it is empty; it does not contain the state of
			any computation, so it cannot be resumed. Before processing can begin, the stack
			group must be set to an initial state. This is achieved by presetting the stack
			group. To preset a stack group, you supply a function and a set of arguments.
			The stack group is placed in a state such that when it is first resumed, this
			function is called with those arguments. The function is called the initial
			function of the stack group.
------------------------------------------------------------------------------------------------     

Resuming of             26.2 The most noteworthy aspect of stack groups is that they resume each
Stack Groups            other. When one stack group resumes a second stack group, the current state of
			Lisp execution is saved in the first stack group and is restored from the second
			stack group. Resuming is also called switching stack groups.

			At any time, the current computation is associated with one stack group, which
			is called the current stack group. The computations associated with other stack
			groups have their states saved in memory and are not computing. Thus, the only
			stack group that can do anything at all, particularly resuming other stack
			groups, is the current one.

			Suppose computation A is executing and it resumes a stack group B.
			Computation A's state is saved into the current stack group, and computation B
			begins execution. Computation A now lies dormant in the original stack group,
			while computation B resumes computation F, which resumes computation D,
			which resumes computation E, and so on. At some time, some computation
			resumes the original stack group, and computation A is restored from the stack
			group to begin execution once again. The current stack group can resume other
			stack groups in several ways. This section describes all the various kinds of
			resumptions.

			Associated with each stack group is a resumer. The resumer is nil or another
			stack group. Some forms of resuming examine and alter the resumer of some
			stack groups. The process of resuming can also transmit a Lisp object from the
			old stack group to the new stack group. Each stack group specifies a value to
			transmit whenever it resumes another stack group; whenever a stack group is
			resumed, it receives a value.

                  Voluntary     In the following descriptions, the term current stands for the current stack
              Resumption    group, another-sg stands for some other stack group, and object stands for any
			arbitrary Lisp object.
			Stack groups can be used as functions. They accept one argument. If current calls
			another-sg as a function with one argument object, then another-sg is resumed,
			and the object transmitted is object. When current is resumed (usually, but not
			necessarily, by another-sg), the object transmitted by that resumption is
			returned as the value of the call to another-sg. Calling a stack group as a
			function is one of the simple ways to resume the stack group. The value you
			transmit is the argument to the function, and the value you receive is the value
			returned from the function. Furthermore, this form of resuming sets another-sg
			's resumer to be current.

			Another way to resume a stack group is to use stack-group-return. Rather than
			allowing you to specify which stack group to resume, this function always
			resumes the resumer of the current stack group. Using this function is a good
			way to resume whichever stack group resumed your stack group, assuming that
			it was done by function calling. The stack-group-return function takes one
			argument, which is the object to transmit. It returns when another stack group
			resumes the current stack group. The value returned by stack-group-return is
			the object that was transmitted by that resumption. The stack-group-return function
			does not affect the resumer of any stack group.

			The most fundamental way to resume is with stack-group-resume, which takes
			two arguments: the stack group and a value to transmit. It returns when the
			current stack group is resumed, returning the value that was transmitted by
			that resumption, and does not affect any stack group's resumer.

			If the initial function of current attempts to return a value object, then the
			regular kind of Lisp function return cannot take place because the function did
			not have any caller (it was started when the stack group was initialized). Thus,
			instead of normal function returning, a stack group return happens. The
			resumer of current is resumed, and the value transmitted is object.
			Consequently, current is left in a state from which it cannot be resumed again
			(the exhausted state). Any attempt to resume it signals an error. Presetting it
			makes it work again.

             Involuntary      The preceding are the voluntary forms of stack group switch; a resumption
              Resumption    happens because the computation indicated that it should. There are also two 
			involuntary forms in which another stack group is resumed without the explicit
			request of the running program.
			If an error occurs, the current stack group resumes the error handler stack
			group. The value transmitted is partially descriptive of the error. The error
			handler looks inside the saved state of the erring stack group to obtain the rest
			of the information. The error handler recovers from the error by changing the
			saved state of the erring stack group and then resuming it.

			When certain events occur, typically a 1-second clock tick, a sequence break occurs.
			This sequence break forces the current stack group to resume a special stack
			group called the scheduler (see Section 27, Processes). The scheduler
			implements processes by sequentially resuming the stack group of each process
			that is ready to run. 
------------------------------------------------------------------------------------------------     

An Example              26.3 The canonical coroutine example is the so-called same fringe prob-
Using Stack Groups      lem: given two trees, determine whether they contain the same atoms in the
			same order, ignoring parenthesis structure. In other words, given two binary
			trees built from conses, determine whether the sequences of atoms on the
			fringes of the trees are the same, ignoring differences in the arrangement of the
			internal skeletons of the two trees. Following the usual rule for trees, nil in
			the cdr of a cons is to be ignored.

			One way of solving this problem is to use generator coroutines. First, make a
			generator for each tree. Each time the generator is called, it returns the next
			element of the fringe of its tree. After the generator has examined the entire
			tree, it returns a special exhausted flag. The generator is most naturally written
			as a recursive function. The use of coroutines, that is, stack groups, allows the
			two generators to recurse separately on two different control stacks without
			needing to coordinate with each other.

			The program is very simple. To construct it in the usual bottom-up style, first
			write a recursive function that takes a tree and performs stack-group-returns
			for each element of its fringe. The stack-group-return is how the generator
			coroutine delivers its output. You can easily test this function by changing 
			stack-group-return to print and trying it on some examples: 

			(defun fringe (tree)
			  (if (atom tree)
			      (stack-group-return tree)     ; Return this leaf node.
			      (fringe (car tree)); Process leaf nodes on CAR branch.
			      (unless (null (cdr tree))     ; Is the CDR branch empty?
			        (fringe (cdr tree)))))      ; Process leaf nodes on CDR branch.

			Now package this function inside another, which takes care of returning the
			special exhausted flag: 

			(defun fringe1 (tree exhausted)
			 (fringe tree)                             ; root for recursive calls
			 exhausted)                                ; after all recursion is finished

			The samefringe function takes the two trees as arguments and returns t or nil.
			It creates two stack groups to act as the two generator coroutines, presets them
			to run the fringe1 function, and then goes into a loop comparing the two
			fringes. The value is nil if a difference is discovered or t if they are still the
			same when the end is reached: 

			(defun samefringe (tree1 tree2)
			    (let ((sg1 (make-stack-group "samefringe1"))
			          (sg2 (make-stack-group "samefringe2"))
			               (exhausted (list nil)))
			       (stack-group-preset sg1 #'fringe1 tree1 exhausted)
			       (stack-group-preset sg2 #'fringe1 tree2 exhausted)
			       (loop
			          for v1 = (funcall sg1 nil)
			          for v2 = (funcall sg2 nil)
			          do
			            (when (not (eq v1 v2)) (return nil))
			            (when (eq v1 exhausted) (return t))
			        )
			    )
			)

			Now test the samefringe function on two examples: 

			(samefringe '(a b c) '(a (b c))) => t
			(samefringe '(a b c) '(a b c d)) => nil

			A problem arises since a stack group is quite a large object, and you make two of
			them every time you compare two fringes. This process requires considerable
			overhead. It can easily be eliminated with a modest amount of explicit storage
			allocation, using the resource facility (see Section 25, Storage Management).

			You can also avoid making the exhausted flag fresh each time; its only
			important property is that it should not be an atom: 

			(defresource samefringe-coroutine ()
			  :constructor (make-stack-group "for-samefringe"))
			(defvar exhausted-flag (list nil))
			(defun samefringe (tree1 tree2)
			 (using-resource (sg1 samefringe-coroutine)
			   (using-resource (sg2 samefringe-coroutine)
			     (stack-group-preset sg1 #'fringe1 tree1 exhausted-flag)
			     (stack-group-preset sg2 #'fringe1 tree2 exhausted-flag)
			     (loop
			        for v1 = (funcall sg1 nil)
			        for v2 = (funcall sg2 nil)
			        do
			          (when (not (eq v1 v2)) (return nil))
			          (when (eq v1 exhausted) (return t))))))

			Now you can perform as many comparisons as you want with the same amount of
			memory as would have been used for only one comparison.
------------------------------------------------------------------------------------------------     

Stack Group States           26.4 Each stack group has a state, which controls what the stack group does
			when it is resumed. The code number for the state is returned by the function 
			sys:sg-current-state. This number is the value of one of the following
			constants. Only the states actually used by the current system are documented
			here; some other codes are defined but not used. 

               sys:sg-state-active                                                                  Constant
			The stack group is the current one. 

               sys:sg-state-resumable                                                               Constant
			The stack group is waiting to be resumed, at which time it picks up its saved
			machine state and continues doing what it was doing before. 

               sys:sg-state-awaiting-return                                                        Constant
			The stack group called another stack group as a function. When it is resumed,
			it returns from that function call. 

               sys:sg-state-invoke-call-on-return                                                Constant
			When the stack group is resumed, it calls a predetermined function. The
			function and arguments are already set up on the stack. The debugger uses this
			state to force the stack group being debugged to perform various actions. 

               sys:sg-state-awaiting-error-recovery                                             Constant
			When a stack group encounters an error, it goes into this state, which
			prevents anything from happening to it until the error handler has examined it.
			Meanwhile, it cannot be resumed. 

               sys:sg-state-awaiting-initial-call                                                Constant
			The stack group has been preset (see the stack-group-preset function later in
			this section), but it has never been called. When it is resumed, it calls its
			initial function with the preset arguments. 

               sys:sg-state-exhausted                                                           Constant
			The stack group's initial function has returned and cannot be resumed until the
			stack group is once again preset. See stack-group-preset for details.
------------------------------------------------------------------------------------------------     

Stack Group                   26.5 The following functions are associated with stack groups.
Functions                  

               make-stack-group name &key :sg-area :regular-pdl-area :special-pdl-area              Function
			:regular-pdl-size :special-pdl-size :swap-sv-on-call-out 
			:swap-sv-of-sg-that-calls-me :trap-enable :safe
			This function creates and returns a new stack group. The name argument,
			which can be any symbol or string, is used in the stack group's printed
			representation. The options are not very useful because most calls to 
			make-stack-group do not need any options at all.

                          :sg-area - The value of this keyword is an area in which the stack group
			    structure is created. This option defaults to the area identified by the
			    variable default-cons-area.
                          :regular-pdl-area - The value of this keyword is an area in which to create the
			    regular PDL. Note that only certain areas are appropriate for this keyword
			    because regular PDLs are cached in a hardware device called the PDL buffer
			    . The default is sys:pdl-area.
                          :special-pdl-area - The value of this keyword is an area in which to create the
			    special PDL. This option defaults to the area identified by the variable 
			    default-cons-area.
                          :regular-pdl-size - The value of this keyword is an integer that determines the
			    length of the regular PDL to be created. This keyword defaults to 1536.
                          :special-pdl-size - The value of this keyword is an integer that determines the
			    length of the special PDL to be created. This keyword defaults to 1024.
                          :swap-sv-on-call-out, :swap-sv-of-sg-that-calls-me  -  These keywords default
			    to 1. If these are 0, the system does not maintain separate binding
			    environments for each stack group. Do not use this feature.
                          :trap-enable - The value of this keyword determines what to do if a microcode
			    error occurs. If it is 1, the system tries to handle the error; if it is 0, the
			    machine halts. The keyword defaults to 1. It is 0 only in the error handler
			    stack group, a trap in which it would not work anyway.
                          :safe - If this flag is 1 (the default), a strict call-return discipline among stack
			    groups is enforced. If it is 0, no restriction on stack group switching is
			    imposed.

               stack-group-preset stack-group function &rest arguments                                 Function
			This function sets up stack-group so that when it is resumed, function is
			applied to arguments within the stack group. Both stacks, the regular and
			special PDLs, are reset and any previously saved information is lost. The 
			stack-group-preset function is typically used to initialize a stack group
			immediately after it is made, but it can be used on any stack group at any time.
			If you execute this function on a stack group that is not exhausted, its present
			state is destroyed without properly cleaning up by running the clean-up forms
			of unwind-protects. 

               stack-group-resume stack object                                                      Function
			This function resumes stack, transmitting the value object. No stack group's
			resumer is affected. 

               sys:sg-resumable-p stack                                                              Function
			This function returns true if the state of stack permits it to be resumed. 

               sys:wrong-stack-group-state (error)                                                  Condition
			This condition is signaled if, for example, you try to resume a stack group that
			is in the exhausted state. The sys:wrong-stack-group-state condition is based
			on the error flavor. 

               stack-group-return object                                                          Function
			This function resumes the current stack group's resumer, transmitting the
			value object. No stack group's resumer is affected. 

               symeval-in-stack-group symbol sg &optional frame as-if-current-p                     Function
			This function evaluates the symbol in the binding environment of frame in stack
			group sg. A frame is an index in the stack group's regular PDL. If frame is nil,
			the current frame in sg is used. If frame is 0, the environment is global. The frame
			argument defaults to the stack group's current frame.

			This function returns three values:

                          J       The value of symbol.

                          J       A non-nil value (actually a copy of the third value) that indicates that symbol
			    was bound.

                          J       The locative indicating where the value is stored, or nil if there is no
			    location. If the value of as-if-current-p is true, the locative points to where
			    the value would be stored if sg was running. This location can be different
			    from where the value is currently stored. For example, the current binding
			    in stack group sg is stored in the value cell of symbol when sg may be
			    running, but the value of it is stored in the special PDL of sg when sg is
			    not running. If as-if-current-p is nil (the default), the first value is the
			    current value, not what is currently stored in the locative. When sg is the
			    current stack group, as-if-current-p is ignored.

			If symbol is unbound in sg and frame, the first and second values are both nil.
			The third value is still the locative.


			 NOTE:  Do not call this function if sg might be running in another process
			and might be changing its state.                                                                                                            




               current-stack-group-resumer                                                        Variable
			This variable is bound to the resumer of the current stack group. 

               current-stack-group                                                                  Variable
			The value of this variable is the stack group that is currently running. A
			program can use this variable to access its own stack group.

               sys:pdl-overflow (error)                                                           Condition
			This condition is signaled when there is overflow on either the regular PDL or
			the special PDL. The :pdl-name operation on the condition instance returns
			either :special or :regular, which tell handlers where the overflow occurred.

			The :grow-pdl proceed type is provided. It takes no arguments. Proceeding from
			the error automatically makes the affected PDL bigger. The sys:pdl-overflow 
			condition is based on the error flavor. 

               eh:pdl-grow-ratio                                                               Variable
			This variable is the factor by which to increase the size of a PDL after an
			overflow. It is initially 1.5. 
------------------------------------------------------------------------------------------------     

Analyzing                26.6 A stack frame is represented by an index in the regular PDL array of
Stack Frames                  the stack group. The stack frame contains information about the current
			function, the arguments it was called with, and the local variables used within
			the function.

               sys:sg-regular-pdl sg                                                              Function
			This function returns the regular PDL of sg. This function is an array of type 
			art-reg-pdl. Stack frames are represented as indices into this array. 

               sys:sg-regular-pdl-pointer sg                                                          Function
			This function returns the index in the sg argument's regular PDL of the last
			word pushed. 

               sys:sg-special-pdl sg                                                               Function
			This function returns the special PDL of sg. This function is an array of type 
			art-special-pdl, used to hold special bindings made by functions executing in
			that stack group. 

               sys:sg-special-pdl-pointer sg                                                    Function
			This function returns the index in the sg argument's special PDL of the last
			word pushed.
------------------------------------------------------------------------------------------------     

Internal Stack            26.7 The following functions are used to move from one stack frame to
Frame Functions              another when a stack group's regular PDL is examined. 

               eh:sg-innermost-frame sg                                                        Function
			This function returns the regular PDL frame of the innermost frame in sg, the
			one that would be executing if sg were current. If sg is current, the value is
			the frame of the caller of this function. 

               eh:sg-next-frame sg frame                                                            Function
			This function returns the next frame out from frame in sg. The next frame is
			the one that called frame. If frame is the outermost frame, the value is nil. 

               eh:sg-previous-frame sg frame &optional innermost                                   Function
			This function returns the previous frame in from frame in sg. The previous
			frame is the one called by frame. If frame is the currently executing frame (the
			innermost frame), the value returned is nil. If frame is nil, the value returned
			is the outermost or initial frame. If innermost is specified and is a frame in sg,
			it is used as the innermost frame. 

               eh:sg-previous-nth-frame sg frame &optional n innermost                              Function
			This function moves up or down n frames in the stack group sg, starting at 
			frame. If n is positive (it defaults to 1), the function moves inward and returns
			the nth next frame. If n is negative, the function returns the nth previous
			frame. If innermost is specified and is a frame in sg, it is used as the
			innermost frame; all frames inside the innermost are ignored. If the function
			reaches the top or the bottom of the stack, then it returns the innermost or
			outermost frame accordingly. If the specified number of frames is passed, the
			second value is nil. 

			                                                                          



			Running interpreted code involves calls to eval, cond, and so on, which are not
			present in compiled code. The following four functions can be used to skip over
			the stack frames of such functions, showing only the frames for the functions
			the user knows. 

               eh:sg-previous-nth-interesting-frame sg frame &optional n innermost                      Function
			This function is similar to eh:sg-previous-nth-frame, but it skips over
			uninteresting frames. It ignores those frames used by the interpreter and
			special forms such as prog and let. 

               eh:sg-previous-interesting-frame sg frame &optional innermost                         Function
			This function is similar to eh:sg-previous-frame, but it skips over
			uninteresting frames. It ignores those frames used by the interpreter and
			special forms such as prog and let. 

               eh:sg-next-interesting-frame sg frame                                                  Function
			This function is similar to eh:sg-next-frame. It returns the next frame out of
			the stack group sg, but it skips over uninteresting frames. It ignores those
			used by the interpreter and special forms such as prog and let. 

               eh:sg-out-to-interesting-frame sg frame                                             Function
			If frame in the stack group sg is not interesting, this function finds a frame
			outside of it that is interesting. It either returns the value frame or the index
			of a frame outside of frame.



			The following functions are used to analyze the data in a particular stack frame.

               sys:rp-function-word regpdl frame                                                  Function
			This function returns the function executing in frame. The regpdl argument
			should be the sg-regular-pdl of the stack group. 

               eh:sg-number-of-spread-args sg frame                                            Function
			This function returns the number of arguments received by the active frame in
			the stack group sg. The -spread-args part of the function name means that the
			rest argument and arguments received by it are not included. If this function is
			called with keywords, the keyword symbol and the associated value are counted
			as separate arguments. For example: 

			(setq sg (make-stack-group 'sg))    ; Make a stack group.
			(defun test (a b c &key e f) nil)   ; Define a dummy function.
			(stack-group-preset sg 'test 1 2 3 :e 5 :f 6)
			(eh:sg-number-of-spread-args sg (eh:sg-innermost-frame sg)) => 7

			In this example, the innermost frame corresponds to the initial function because
			the stack group is not yet resumed.

               eh:sg-frame-arg-value sg frame n &optional errorp                                   Function
			This function returns the value and the location of argument number n of the frame
			stack frame in the stack group sg. If errorp is true, an error is signaled if n is
			out of range.

			The first value is the value of the specified argument. The second value is the
			location in which the argument is stored when sg is running. The location
			actually may not be in the stack if the argument is special. The location may
			then have other contents when the stack group is not running. If errorp is nil 
			and an error occurred, the function returns a third value-a string describing
			the error. The errorp argument defaults to t.

               eh:sg-rest-arg-value sg frame                                                          Function
			This function returns the value of the rest argument in frame, or nil if there is
			none.

			The second value is true if the function called in frame expects an explicitly
			passed rest argument.

			The third value is true if the rest argument was passed explicitly. If this value
			is nil, the rest argument is a stack list that overlaps the arguments of the frame
			stack frame. (If passed explicitly, it may still be a stack list but not in this
			frame.) 

               eh:sg-number-of-locals sg frame                                                  Function
			This function returns the number of local variables in the frame stack frame. 

               eh:sg-frame-local-value sg frame n &optional errorp                                  Function
			This function returns the value and the location of local variable number n of
			the frame stack frame in the stack group sg. If errorp is true, an error is
			signaled if n is out of range.

			The first value is the value of the specified local variable. The second value is
			the location in which the local variable is stored when sg is running. The
			location actually may not be in the stack; if not, it may have other contents
			when the stack group is not running.

			If errorp is nil and an error has occurred, the function returns a third value-a
			string describing the error. 

               eh:sg-frame-value-value sg frame n &optional errorp                                      Function
			This function returns the value and location of the nth multiple value that frame
			has returned. If errorp is true, an error is signaled if n is out of range.

			If errorp is nil and an error has occurred, the function returns a third value-a
			string describing the error. 

               eh:sg-frame-value-list sg frame                                                        Function
			This function returns two values that describe whether the frame's caller wants
			multiple values as well as any values that frame is returning. The first value
			returned is a list containing the values being returned by frame. The second
			value can be one of the following three values:

                          J       nil - Indicates that this frame was not invoked to return multiple values.

                          J       A number - The number of values returned.

                          J       A locative - Indicates that this frame was called with multiple-value-list.

			The third of the preceding values is included for historical reasons; the value
			returned is always the beginning of the list being returned after all the values
			have been calculated.

               eh:sg-frame-special-pdl-range sg frame                                             Function
			This function returns two values delimiting the range of sg's special PDL that
			belongs to the specified stack frame. The first value is the index of the first
			special PDL word that belongs to the frame, and the second value is the index of
			the next word that does not belong to it.

			If the specified frame has no special bindings, both values are nil. Otherwise,
			the indicated special PDL words describe bindings made on entry to or during
			execution in this frame. The words come in pairs.

			The first word of each pair contains the saved value; the second points to the
			location that was bound. When the stack group is not current, the saved value
			is the value for the binding made in this frame. When the stack group is
			current, the saved value is the shadowed value, and the value for this binding
			is either in the cell that was bound or is the saved value of another binding, at
			a higher index, of the same cell.

			The sys:%%specpdl-closure-binding bit is nonzero in the first word of the pair
			if the binding was made before entry to the function itself; this includes
			bindings made by closures and by instances (including self). Otherwise, the
			binding was made by the function itself (including the arguments that are
			declared special).

			The symeval-in-stack-group function can be used to find the value of a special
			variable at a certain stack frame.
------------------------------------------------------------------------------------------------     

Input/Output in             26.8 Because each stack group has its own set of dynamic bindings, a stack
Stack Groups            group does not inherit its creator's value of *terminal-io* nor its caller's
			unless you make special provision. (For information about the variable 
			*terminal-io*, see the section entitled Streams in the Explorer Input/Output
			Reference manual.) The *terminal-io* that a stack group receives by default is a
			background stream that does not normally expect to be used. If it is used, it
			turns into a background window that requests the user's attention (usually
			resulting from an error printout that tries to print on the stream). For related
			information, see the Explorer Window System Reference manual.

			If you write a program that uses multiple stack groups and you want them all to
			perform input and output to the terminal, pass the value of *terminal-io* to the
			top-level function of each stack group as part of the stack-group-preset. That
			function should bind the *terminal-io* variable.

			Another technique to achieve these same results is to use a closure as the
			top-level function of a stack group. This closure can bind *terminal-io* and
			any other variables that should be shared between the stack group and its
			creator.
