123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- ;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.
|