perm filename CATCH.RPG[3,2] blob sn#553408 filedate 1981-01-03 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00002 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002				New Catch/Throw Functions
C00008 ENDMK
CāŠ—;
			New Catch/Throw Functions
	
The next release of MacLisp at SAIL will use the *catch/*throw
protocol; it is suggested that you convert your functions
as soon as possible. You may want to macro-ize things for now
rather than actually editting the changes in. [rpg;2-jan-81]

    *THROW, *CATCH, CATCHALL, CATCH-BARRIER, and UNWIND-PROTECT.
    For compatibility with the new format of CATCH and THROW in the
    LISP Machine, and in NIL, we are introducing *THROW and *CATCH.
    Please use these, and sometime in the future, CATCH and THROW in
    PDP10 MACLISP may be changed also.  It is recommended that old code be
    converted to *CATCH and *THROW.
      (*CATCH <tag> e1 e2 ... e<n>)
	Forms e1 through e<n> are evaluated, returning the last as the
	value of the CATCH, unless a THROW (or *THROW) occurs whose tag matches
	the value of <tag> during the sub-evaluations; then the value of
	the catch is the value from the THROW.  Note that <tag> is evaluated
	first.
      (*THROW <tag> <val>)
	Both <tag> and <val> are evaluated as in normal SUBR control, 
	and a control-chain break-up is initiated, passing along both 
	values;  at some higher level, the break-up will be "caught".  
	If the "catching" is by CATCH, then the value of <val> is
	passed to CATCH; if by CATCHALL, the both values are passed (q.v.).
      (CATCHALL <fun-2-args> e1 e2 ... e<n>)
	Has same semantics as CATCH, except that if **any** THROW occurs
	during the sub-evaluations, then the value of the CATCH is obtained
	by applying the value of <fun-2-args> to the throw value and throw
	tag.  E.g.
	  (CATCHALL '(LAMBDA (TG VAL)
				;Note that for some tags, the throw is
				;  repeated, so that the CATCHALL acts as
				;  if it in fact ignores that THROW.
			(COND ((MEMQ TG '(TOPLEVEL BREAK)) (THROW VAL TG))
			      ((OR STOPP (EQ TG 'FOO)) (THROW VAL 'FOO))
			      (#T VAL)))
		    (SETUP 25)
		    (RUNLIKE ABAT))
      (CATCH-BARRIER <tag-list> e1 e2 ... e<n>)  
	Has the same syntax as CATCH, and more or less the same semantics, but
	if a thrown tag is not in the tag-list, then the THROW that threw it 
	goes into an unseen-throw-tag error.  The idea is that searching does 
	not proceed back up the stack beyond this point; whereas if a THROW of
	a tag is not caught by a particular CATCH, then tag searching continues
	back up to the stack above the CATCH.

      (UNWIND-PROTECT <e> u1 u2 ... u<n>)
	The form <e> will be evaluated, but if the stack is "unwound" past
        the point of the UNWIND-PROTECT for ANY REASON,
	then the unwinder must cause the evaluation, in order,
	of u1 through u<n> in the environment that obtains by first 
	unwinding to the stack point of the UNWIND-PROTECT; then the 
	unwinding may continue.  If <e> terminates normally, then
	the value will be that obtained from <e>, but the forms u1 
	through u<n> will be evaluated also.  The intent is
	that the operation of <e> will do some things that need to be
	undone after sucessful completion, but which can not be undone 
	merely by lambda-binding (eg, closing an opened file).  Thus any 
	aborting of the evaluation of <e> will not leave undesired states 
	hanging around.  Before the u<n>'s are run, NOINTERRUPT is set to
        T, so that asynchronous conditions cannot cause premature termination
        of the handlers.  It is restored to its previous value upon
        completion of the u<n>'s.  If a THROW is done, the user must reset
        NOINTERRUPT to the value he wishes it to be!  The UNWIND-PROTECT
        frame is removed from the stack BEFORE the u<n>'s are run so that
        they may freely do THROWS (et al.).