;Loop macro blathering.
;
;  This doc is totally wrong.  Complete documentation (nice looking
; hardcopy) is available from GSB, or from ML:LSBDOC;LPDOC (which
; needs to be run through BOLIO). 
;
;This is intended to be a cleaned-up version of PSZ's FOR package
;which is a cleaned-up version of the Interlisp CLisp FOR package.
;Note that unlike those crocks, the order of evaluation is the
;same as the textual order of the code, always.
;
;The form is introduced by the word LOOP followed by a series of clauses,
;each of which is introduced by a keyword which however need not be
;in any particular package.  Certain keywords may be made "major"
;which means they are global and macros themselves, so you could put
;them at the front of the form and omit the initial "LOOP".
;
;Each clause can generate:
;
;	Variables local to the loop.
;
;	Prologue Code.
;
;	Main Code.
;
;	Epilogue Code.
;
;Within each of the three code sections, code is always executed strictly
;in the order that the clauses were written by the user.  For parallel assignments
;and such there are special syntaxes within a clause.  The prologue is executed
;once to set up.  The main code is executed several times as the loop.  The epilogue
;is executed once after the loop terminates.
;
;The term expression means any Lisp form.  The term expression(s) means any number
;of Lisp forms, where only the first may be atomic.  It stops at the first atom
;after the first form.
;
;The following clauses exist:
;
;Prologue:
;	INITIALLY expression(s)
;		This explicitly inserts code into the prologue.  More commonly
;		code comes from variable initializations.
;
;Epilogue:
;	FINALLY expression(s)
;		This is the only way to explicitly insert code into the epilogue.
;
;Side effects:
;	DO expression(s)
;		The expressions are evaluated.  This is how you make a "body".
;		DOING is synonymous with DO.
;
;Return values:
;	RETURN expression(s)
;		The last expression is returned immediately as the value of the form.
;		This is equivalent to DO (RETURN expression) which you will
;		need to use if you want to return multiple values.
;	COLLECT expression(s)
;		The return value of the form will be a list (unless over-ridden
;		with a RETURN).  The list is formed out of the values of the
;		last expression.
;		COLLECTING is synonymous with COLLECT.
;		APPEND (or APPENDING) and NCONC (or NCONCING) can be used
;		in place of COLLECT, forming the list in the appropriate ways.
;	COUNT expression(s)
;		The return value of the form will be the number of times the
;		value of the last expression was non-NIL.
;	SUM expression(s)
;		The return value of the form will be the arithmetic sum of
;		the values of the last expression.
;     The following are a bit wierd syntactically, but Interlisp has them
;     so they must be good.
;	ALWAYS expression(s)
;		The return value will be T if the last expression is true on
;		every iteration, NIL otherwise.
;	NEVER expressions(s)
;		The return value will be T if the last expression is false on
;		every iteration, NIL otherwise.
;	THEREIS expression(s)
;		This is wierd, I'm not sure what it really does.


;		You probably want WHEN (NUMBERP X) RETURN X
;		or maybe WHEN expression RETURN IT
;
;Conditionals:  (these all affect only the main code)
;
;	WHILE expression
;		The loop terminates at this point if expression is false.
;	UNTIL expression
;		The loop terminates at this point if expression is true.
;	WHEN expression clause
;		Clause is performed only if expression is true.
;		This affects only the main-code portion of a clause
;		such as COLLECT.  Use with FOR is a little unclear.
;		IF is synonymous with WHEN.
;	WHEN expression RETURN IT (also COLLECT IT, COUNT IT, SUM IT)
;		This is a special case, the value of expression is returned if non-NIL.
;		This works by generating a temporary variable to hold
;		the value of the expression.
;	UNLESS expression clause
;		Clause is performed only if expression is false.
;
;Variables and iterations: (this is the hairy part)
;
;	WITH variable = expression {AND variable = expression}...
;		The variable is set to the expression in the prologue.
;		If several variables are chained together with AND
;		the setq's happen in parallel.  Note that all variables
;		are bound before any expressions are evaluated (unlike DO).
;
;	FOR variable = expression {AND variable = expression}...
;		At this point in the main code the variable is set to the expression.
;		Equivalent to DO (PSETQ variable expression variable expression...)
;		except that the variables are bound local to the loop.
;
;	FOR variable FROM expression TO expression {BY expression}
;		Numeric iteration.  BY defaults to 1.
;		BY and TO may be in either order.
;		If you say DOWNTO instead of TO, BY defaults to -1 and
;		the end-test is reversed.
;		If you say BELOW instead of TO or ABOVE instead of DOWNTO
;		the iteration stops before the end-value instead of after.
;		The expressions are evaluated in the prologue then the
;		variable takes on its next value at this point in the loop;
;		hair is required to win the first time around if this FOR is
;		not the first thing in the main code.
;	FOR variable IN expression
;		Iteration down members of a list.
;	FOR variable ON expression
;		Iteration down tails of a list.
;	FOR variable IN/ON expression BY expression
;		This is an Interlisp crock which looks useful.
;		FOR var ON list BY expression[var]
;			is the same as FOR var = list THEN expression[var]
;		FOR var IN list BY expression[var]
;			is similar except that var gets tails of the list
;			and, kludgiferously, the internal tail-variable
;			is substituted for var in expression.
;	FOR variable = expression THEN expression	
;		General DO-type iteration.
;	Note that all the different types of FOR clauses can be tied together
;	with AND to achieve parallel assignment.  Is this worthwhile?
;	[It's only implemented for = mode.]
;	AS is synonymous with FOR.
;	
;	FOR variable BEING expression(s) AND ITS pathname
;	FOR variable BEING expression(s) AND ITS a-r
;	FOR variable BEING {EACH} pathname {OF expression(s)} 
;	FOR variable BEING {EACH} a-r {OF expression(s)}
;		Programmable iteration facility.  Each pathname has a
;	function associated with it, on LOOP-PATH-KEYWORD-ALIST;  the
;	alist has entries of the form (pathname function prep-list).
;	prep-list is a list of allowed prepositions;  after either of
;	the above formats is parsed, then pairs of (preposition expression)
;	are collected, while preposition is in prep-list.  The expression
;	may be a progn if there are multiple prepositions before the next
;	keyword.  The function is then called with arguments of:
;	    pathnname variable prep-phrases inclusive? prep-list
;	Prep-phrases is the list of pairs collected, in order.  Inclusive?
;	is T for the first format, NIL otherwise;  it says that the init
;	value of the form takes on expression.  For the first format, the
;	list (OF expression) is pushed onto the fromt of the prep-phrases.
;	In the above examples, a-r is a form to be evaluated to get an
;	attachment-relationship.  In this case, the pathname is taken as
;	being ATTACHMENTS, and a-r is passed in by being treated as if it
;	had been used with the preposition IN.  The function should return
;	a list of the form (bindings init-form step-form end-test);  bindings
;	are stuffed onto loop-variables, init-form is initialization code,
;	step-form is step-code, and end-test tells whether or not to exit.
;
;Declarations?  Not needed by Lisp machine.  For Maclisp these will be done
;by a reserved word in front of the variable name as in PSZ's macro.
;
;The implementation is as a PROG.  No initial values are given for the
;PROG-variables.  PROG1 is used for parallel assignment.
;
;The iterating forms of FOR present a special problem.  The problem is that
;you must do everything in the order that it was written by the user, but the
;FOR-variable gets its value in a different way in the first iteration than
;in the subsequent iterations.  Note that the end-tests created by FOR have
;to be done in the appropriate order, since otherwise the next clause might get
;an error.
;
;The most general way is to introduce a flag, !FIRST-TIME, and compile the
;clause "FOR var = first TO last" as "INITIALLY (SETQ var first)
;WHEN (NOT !FIRST-TIME) DO (SETQ var (1+ var)) WHILE (<= var last)".
;However we try to optimize this by recognizing a special case:
;The special case is recognized where all FOR clauses are at the front of
;the main code; in this case if there is only one its stepping and
;endtest are moved to the end, and a jump to the endtest put at the
;front.  If there are more than one their stepping and endtests are moved
;to the end, with duplicate endtests at the front except for the last
;which doesn't need a duplicate endtest.  If FORs are embedded in the
;main code it can only be implemented by either a first-time flag or
;starting the iteration variable at a special value (initial minus step
;in the numeric iteration case).  This could probably just be regarded as
;an error.  The important thing is that it never does anything out of
;order. 

