Interlisp_Reference_Manual_1974 Interlisp Reference Manual 1974
Interlisp_Reference_Manual_1974 manual pdf -FilePursuit
Interlisp_Reference_Manual_1974 Interlisp_Reference_Manual_1974
User Manual: Interlisp_Reference_Manual_1974
Open the PDF directly: View PDF .
Page Count: 715
Download | |
Open PDF In Browser | View PDF |
...... INTERLISP REFERENCE MANUAL BY WARREN TEITELMAN contributions by: A.K.HARTLEY J. W. GOODWIN BOLT BERANEK & NEWMAN D. G. BOBROW P. C. JACKSON L. M. MASINTER XEROX PALO ALTO RESEARCH CENTER XEROX PALO ALTO RESEARCH CENTER 3180 PORTER DRIVE/PALO ALTO/CALIFORNIA 94304 BOLT BERANEK & NEWMAN Copyr;1:ht /') 1974 XEROX CORPORATION Acknowledgements and .Background INTERLISP (formerly BBN LISP) has evolved from a succession of LISP systems that began with a LISP designed and implemented for the DEC PDP-1 by D. G. Bobrow and D. L. Murphyt at Bolt, Beranek and Newman in 1966, and documented by D. G. Bobrow. An upwards compatible version of this LISP was implemented for the SDS 940 in 1967, by Bobrow and Murphy. This system contained the seeds for many of the capabilities and features of the current system: a compatible compiler and interpreter, 2 uniform error handling, an on-line LISP oriented ed1tor,3 sophisticated debugging facilities,4 etc. 940 LISP was also the first LISP system to demonstrate the feasibility of using software paging techniques and a large virtual memory in conjunction with a list-processing system [Bob2]. DWIH, the Do-What-I-r1ean error correction facility. was introduced into the system in 1968 by W. Teitelman [Tei2]. who was also responsible for documentation for the 940 LISP system. 1~~--~~~---~~---~----------~------------------------------~------------------~- D. G. Bobrow is currently at Xerox Palo Alto Research Center (PARe), D. L. Murphy is with Digital Equipment Corp. 2 The preliminary version of the compiler was written by L. P. Deutsch. now at Xerox PARCo This was considerably modified and extended by D. L. Murphy before producing the final working version. 3 The original idea of a LISP oriented structure editor belongs to L. P. Deutsch. The editor in its current form was written by W. Teitelman, now of Xerox PARC., 4 Designed and implemented by W.· Teitelman. i In 1970. an upwards compatible version of 940 LISP called BBN LISp6 was designed for the PDP-tO by D. G. Bobrow, D. L. Murphy, A. K. Hartley, and W. Teitelman, and implemented by Hartley with assistance from Murphy. A. K. Hartley was also responsible for modifying the 940 LISP compiler to generate code for the PDP-tO. system for hardware PDP-l0 designed and implemented by D. the Burchfiel, D. BBN-LISP ran under TENEX, a sophisticated time sharing L. Murphy, T. _ R. Strollo, and R. S. G. Bobrow, D. Tomlinson.[Bob1] With paging and Z56K of virtual memory provided by TENEX, practical J. it became to provide extensive and sophisticated interactive user support facilities, such as the progranuner's assistant [Tei4], CLISP [Tei5], and a more sophisticated DWIM. all of whic:h were designed and· developed by W. Teitelman. In 1971, th~ block compiler was designed and implemented by D. G. Bobrow. The BBN-LISP Manual [Te,3] was written by.W. Teitelman, with contributions from A. K.. Hartley and from J. W. Goctdwin, who also wrote TRANSOR and the special arithmetic functions, as well a!) a number of other utility functions. of the system was changed from BBN-LISP to maintenance and develop~ent of the sys~em INTERLISP in 1973, The name when the evolved into a joint effort between Bolt Beranek and Newman, and Xerox Palo Alto Research Center. The INTERLISP reference manual was written by W. Teitelman, with contrlbutions from A. K. Hartley, J. W. Goodwin, and D. G. Bobrow. The cover was designed by Alice R. Fikes. INTERLISP is currently the LISP' system used at Bolt Beranek and Newman, Xerox Palo Alto Research Center, Stanford Research Instit.ute Artificial Intelligence Center. Information Sciences Ir.sti tute, and the Dendral Project at Stanford University. in addition to being available at Computer Corporation of America i--------------------------------------------------~-------------~------------- The design, construction and documentation for BBN LISP was sponsored by the Information Proces~ing Techniques Section of the Advanced Research Project Agency, as was all of the subsequent work on the system that was performed at BSN. Since March 1972, the contributions made to the development of the system by W. Teitelman, including the preparation of this manual, were sponsored by Xerox Palo Alto Research Center. ii and Case Institute of Technology. The total user conununity now comprises approximately one hundred users. INTERLISP is a continuously evolving system, both in response to complaints, suggestions, network, and requests of the many users scattered throughout the ARPA as well as the long range goals of the individuals primarily responsible for the system, which are currently: Person Te itcTman Xerox Palo Alto Research Center 3180 Porter Dr. Palo Alto, Calif. 94304 Responsible for User facilities: i.e~, prettyprint, editor, break and trace, adVising. printstructure, DWU1, CLISP, programmer's assistant. A. K. Hartley Bolt Beranek & Newman 50 Moulton St. Cambridge, Mass. 02138 Basic System: i.e., interpreter, input-output, garbage collector; plus all SUBRS, i.e. hand-coded machine language functions such as PRINT, CONS, PROO, GO, etc.; plus compiler. J. W. Goodwin Bolt Beranek & Newman 50 Moulton St. Cambridge, Mass. 02138 Special Arithmotic Functions: e.g. LOG, SIN, SQRT, etc.; plus functions for accessing TENEX capabilities such as SUBSYS, FILDIR, et al.; plus TRANSOR as well as various utility functions such as LOADFNS, SORT, etc. (as indicated in the text of this manual). w. * The preparation of this manual has involved the efforts of several persons at Xerox PARC, whom I specifically want to mention. and to express my appreciation for their support through this arduous, and at times seemingly endless task. Thank you Suzan (Jerome), Janet (Farness), Peter (Deutsch), Larry (Tesler). I couldn't have done it without Bob (Walker), and you~ Warren Teitelman Palo Alto December, 1973. ii1 TABLE OF CONTENTS SECTION 1: Introduction SECTION 2: Using INTERLISP Using the INTERLISP Manual •••.•.• ~ •••••.••• ~...... Using the INTERLISP System on Tenex •.•••..•••••••• 1 4 SECTION 3: Data types, Storage Allocation, and Garbage Collection Data Ty·p,es ••••••••••••••••••••••••••••••••• ~ ••••.•• Literal Atoms ...•••...••..•..••..••••••••..•• Pnames ..•.•. , ••.•••••••••••••••• '••••••••••••• Numerical Atoms ...•......•.....•...•••••••..• Li s. t s ..... ~ .............•.................... Arrays ',.. " ....... ~ ..' ......................... . St.r·ings .••.•••••••••••••••••.•••••••••••••••• Storage Allocation and Garbage Collection ••••.•.•. Shared INTERLISP .................................. . 1 2 4 4 7 8 9 11 14 SECTION 4: Function Types and Impltcit PROGN Exprs ..........~ ....•.••..• *' ••••••••••••••••••••••• 1 Compiled Functions ••••..•.••.••.••••..•••••••••••• Function Type ...•..••, •.••••••••••.•••••••••••.•. "c' •.••••• 2 PROGN •••••••••••••••• •". ~ •••••••••••••••••••••••••• 3 4 Implicit PROGN 4 SECTION 5: Primi~ive .. ................................ . ~ Functions and Predicates Primitive Functions ..•.••.•••••••••.•••••••••••••• RESETVAR and RESETFORM .•..••..•••••••••••••••••••. Predicates and Logical Connectives .••.•••••••••••• 1 9 11 SECTION 6: 'List Manipulation and Concatenation SECTION 7: Property Lists and Hash Links Property Lists ..•.......••••••••••.••.•••.••••••••• 1 Hash Links ....... ~ .. ~ ..............~... •.. .. . . . . •. • 4 llash Overfiow' • • . • . . • • • • . • • • • • • • • • • • • • • • • • • • • • 7 i TABLE OF CONTENTS (cont.) SECTION 8: Function Definition and Evaluation SECTION 9: The INTERLISP Editor Introduction ............•.•••••••••.•••••••••••••• Commands for the New User .•....•..•.••...•.••••\ •.• Attention Changing Commands •••••..•••••••••••••••• Local Attention Changing Commands •••••••••••• Commands Tha t Search ....•....•.••••.••••••••• Search Algorithm .........•••......•.•.•. Search Commands' ......••.•.•••••••••••••• Location Specification •...•.•••••••••••• Commands That Save and Restoro the Edit Chain ••••••• 111 •••••••••••••••••••••••• Commands That ~lodify Structure •.......•...•••••••. Implementation of Structure Modification Commands ••••••••••••••••••• III. • • • • • • • • • • • • • • The A, B, : Commands ...••.....•..•.••.••••••• Form Oriented Editing and tho Role of UP ••••••• Extract and Embed •......••••..••••••.•••••••• 1 10 15 15 21 23 25 28 34 36 37 39 43 45 Commands That "Move Parentheses" •...••••••••• 48 51 TO and THRU •••••••••••••••••••••••••••••••••• 54 l'he MOVE Command •••••••••••••••••••••• " •••••• The Commands Conunands Commands R Command ..........••• -• •••••••••••••••••• That Print ......•••.•.••••••••••••••••••• That Evaluate •.•••.•••••••••••••••••••••• Tha t Tes t ..•.•.••••.••..•••.•••..•.•••••• 60 62 64 ...••••.••..•••••••••••••••.•••••••••••••••• 67 Niscellaneous Commands •.•••....••••.••••.••.•••••• 70 ~Iacros UNDO •••••••••••••••••••••••••••••••••••••••••••••• EDITDEFAUL T ••••••••••••••••••••••••••••••••••••••• Editor functions 57 78' 80 83 SECTION 10: Atom, String, Array, and Storage Manipulation Pnames and Atom Manipulation ..••...••.•.••••••••.• String functions ..........••.•....••••.••••..•.••• Searching Strings ........•...••.......••••.•• String Storage ...•..•.••••.•.•••••••••.•.•••• Array Functions ......••....••.••••••••••••••.••••• Storage Functions ....•••...•....••.•••••..•.•••••• 1 5 8 11 12 14 SECTION 11: Functions with Functional Arguments SECTION 12: Variable Bindings and Pushdown List Functions The Pushdown List and the Interpreter •.•.•••••.••• The Pushdown List and Compiled Functions •••••••••• Pushdown List functions ..•..•.....••••••••••••••.• The Pushdown List and Funarg •••••••••••••••••••••• i1 3 5 6 11 TABLE OF CONTENTS (corit~) SECTION 13: Arithmetic:Ftinctions General Comments Integer Arithmetic Floating Point Arithmetic ••••••••••••••••••••••••• Mixed Arithmetic Special Functions Reusing Boxed Numbers - SETN .•••••••••.••••••••••• Box and Unbox, •• ................................. o' • • • • • • • • • • • • • • • • • • • • • • • • • • • • ' • • • • • • 1 2 6 7 8 10 12 SECTION 14: Input/Output Functions .................................. . Files ....... . . Addressable Files .••••••••••••••••••••••••••• JFN Functions Input Functions Output Functions Printlevel Input/Output Control Functions .~ .••••.•••••.•••••. Line-buffering and CONTROL ••••••••••••••••••• Special Functions Symbolic File Input ••••...•••.•••••••••••••••••••• Symbolic File Output PRETTYPRINT Comment Feature PRETTYDEF Special PRETTYPRINT Controls ••••••••••••••••• File Package " ............................. ......... .................... . ...................................... ... ................................. . ' ' 1 5 8 10 18 19 21 23 26 27 29 29 30 31 38 44 SECTION 15: Debugging - The Break Package Debugging Facilities BREAK 1 ........•..•.. Break Commands Brkcoms ..... . Brkfile Breakmacros Break Functions BREAKIN 1 '4 ...................................... ..... ............. ............. . ................................... '.' ' 7 14 15 15 16 19 SECTION 16: Error Handling Unbound Atoms and Undefined Functions ••••••••••••• Teletype Initiated Breaks .••.•....••, •••••••••••••• Control U •.•••. Control B ..... . . Control E Other Types of Errors ....•...•.••.••••..•••••••••• Breakcheck - When to Break' ••.••••••••••••••••••••• Error Types Error Handling by Error Type ••••••••••••••••• Error Functions .......................... . iii 1 2 Z 3 3 4 4 7 10 12 TABLE OF CONTENTS (cont.) SECTION 17: Automatic Error Corr 9ction - Tho DWIM Facility l Introduction Interaction wi th DWIM ......•....•...•.•..•..••.•.• Spellirig Correction Protocol .•...•••..••••••• Parentheses Errors Protocol •.••••...•.••••.••• Spelling Correction .... ~ .......••.••••.•..•••••••• Spelling Lists Error Correction Unbound Atoms Undefined Car of Form .....•..••••.••..••••.•• Undefined Function in Apply ...•••..•••••••••• DW I ~IUSERFN Spelling Corrector Algorithm .••.••.••••••.•••••• ~. .............................. • • • • • • • • • • • • • • • • • • • • • I."• • • • • DWI~1 Functions ........................... ., ......~ .. 1 5 5 7 10 11 14 16 17 18 19 20 23 SECTION 18: The Compiler and Assembler The Compiler ..... . Compiler Questions Nlambdas ......... . .............................. . 1 3 5 Globalvars ....................................... . 6 Compiler Functions RECONPILE Open Functions Compiler Macros FUNCTION and F~nctlonal Arguments ..•.•..••••..•••• Block Compiling Specvars Localfreevars Retfns Blkapplyfns Blklibrary Linked Function Calls Relinking The Block Compiler BLOCKCONPILE Block D~clarations ..•..•.••••.•••••.•..•... 7 10 13 14 16 ............................. BtO~lPL ..................................... . I1RECOMPILE Compiler Structure ASSEMBLE ...... . l.AP Us ing ASSE~IBLE Miscellaneous .............•.•.•. Compiler Printout and Error Messages ••.••••••••••• o •• o • • • • • • • • • • • • • • 17 18 18 20 20 21 21 25 26 27 28 30 31 34 35 40 46 41 48 SECTION 19: Advising Implementation of Advising ••.••••••••••••••••••••• Advise Functions ..•..•.• 0 ••••••••••••• iv 0 ••••••••••• 2 5 TABLE OF CONTENTS (~ont.) SECTION 20: Printstructure and Interscope Printstructure ...•....••.•.•.••••...••...•.....•.• 1 Intcrscope ............................................ 10 SECTION 21: Miscellaneous Measuring Functions •..•.. ~........................ 1 BR EAK rlQWN. • •••••••••••••••••• ,..................... EDI TA ••••••• ;'. • ~" • • • • • • • • • •~. • • • • • • • • • • .'. • • • • • • • • • • • 5 8 Input Protocol ...•..........•....•..•..••••.• F.DITA commands and variables ................• Interfork Communication .•.........•.•.•••••.•.•••• 10 12 17 Subsys .................•"............•....•..••.•,.. 18 Miscellaneous TENEX Functions ......••... ~......... Printing Reentrant and Circular List Structures 21 24 SECTION 22: The Programmer's Assistant and LISPX Introduction .......•...•.•.•...•••.•••.•••....•••. 1 Overview ........ ,", ...... ., ....'...................... 6 Event Specification ...........•••.....•. ~......... History, Commands ................•...•..••••••.•.•• Implementation of REDO, USE, and FIX .•......• History Commands Applied to History Commands. HistorY Commands That Fail................... ~lore History Commands •.........•....••.•...•• Miscellaneous Features and Commands .....••..•.•••. 11 14 17 19 20 21 28 Undoi.ng ...... :...............................•..... ,..... 38 Testmode .........•...•••..•....••••••••••.•.•• 41 Undoing out of order ...........•.....•...•.•• SAVESET .................. '. • . . . . . . • . .• . . . . . . . . Format and Use of the History List .•....•.•••.•... LISPX and READLINE •........••..•..•.•..•.•.•..••.. Functions ................•..•.••••...••.•••••.•.•• Tho Editor and the Assistant ..•••.•••••...•.•..•.• 42 43 44 47 48 Statistics ........... ....... Greeting and Use~ e·....................... Initialization ..••.••••.•••.•••• v ~1 63 64 TABLE Of CONTENTS (cont.) SECTION 23: CLISp·- Conversational LISP Introduction CLISP Syntax ...•.............•..•.........••...••• Infix Operators ...........•.•.......•..•..•..••••• Prefix Operators ..•........•..•......••••...•..••. Constructing l.ists - the <.> Operators ..••..•••••• IF, TIIEN. ELSE Iterative Statements ..........•..•••.....••.•••••. Errors in Iterative Statements .•.•.....•.••.• Defining New Iterative Statement Operators CLISP Translations .....•••••..••.•..••.•.••••••••.• Declarations .............••••••••.••.•••.•.•••.•.• Local Declarations ..•...•••.•..•....•.••...• The Pnttern Match Compiler ..•••••..•••••••••••.••• Element Patterns ..•..•...•••.•••.....•••••.... Segment Patterns ••..•••..•....••.•.•••••.•.•• 1 9 10 13 16 17 18 27 28 30 33 35 36 39 41 Assignments ..•.•.•.•••..••••••.••.••••.••.••• 43 Place-markers ...••.•••..•••••••••••••••••.••• I~cplacements .•...•••.•..•.••...••.••.•.•••••• Reconstruction ....•••••.••••••..••••••.•••••• Record Package ........•.•.••...•..••••..•••••••••. Record Declarations ...•........••••....••...• CREATE Implementation ....• ~ .•..•.••..•...••...•••... CLISPIFY DWHtIFY Compiling CLISP Operation CLISP Interaction with User .•••..• ~ .•.•..••••••••• CLISP Internal Conventions ....•••..•.••.••.••.•••• CLISP Functions and Variables .•••.•.•.••.••••••••• 44 44 46 48 ................................... •••••••••••• tI •••••••••••••• It • • • • • • •: • • • • • • • • 51 55 57 58 61 63 64 67 68 71 APPENDIX 1: TRANSOR Introduction Using TRANSOR The Translation Notes TRANSORSET Controlling the sweep 1 3 4 8 14 APPENDIX 2: INTERLISP Interpreter APPENDIX 3: Control Characters MASTER INDEX vi SECTION 1 INTRODUCTION This document is a reference manual for INTERLISP, a LISP system currently implemen,ted on the DEC POP-tO under the BBN TENEX time sharing system.[Bob1] INTERLISpl is designed to provi~ethe user access to the large virtual memory allowed by TENEX, with a relatively small penalty in speed (using special paging techniques described in [BobZ]). Additional data types have been added,' including strings, arrays, and hash association tables (hash links) (Sections 7 and 10). interpreter. The system includes a compatible compiler (Section 18) and Machine code can be intermixed with INTERLISP expressions via the assemble directive of the compiler. The compiler also contains a facility for "block compilation" which allows a group of functions to be compiled as a unit, suppressing internal names. Each successive level of computation, from interpreted through compiled, to block-compiled provides. greater speed at a .cost of debugging ease . INTERLISP ~as been designed to be a good on-line interactive system. Some of the features provided include elaborate debugging facilities with tracing and conditional breakpoints (Section 15), and a sophisticated LISP oriented editorwi thin the system (Section 9). Utilization of a uniform error processing through user accessible routines (Section 16) has allowed the implementation of DWIM, a !!o-~at-! -~ean facility, which automatically corrects many types of. errors without losing the context of computation (Section 17). 1.1 The CLISP facility (Section 23) extends the LISP syntax by enabling ALGOL-like infix operators such as +, -, -, /, =, ., AND, OR, etc., as well as IF-THEN-ELSE statements and FOR-WHILE-DO stiltements. CLISP expressions are automatically converted to equivalent LISP for'ms when they are first encountered,. CLISP also includes list construction operutors, as well as a LISP oriented pattern match compiler. A novel and useful facility lof the INTERLISP system is the programmer's assistant (Section 22), which monitors and records all user inputs. The user can instruct the progranuner I s ,assistant to repeat a particular operation or sequence of operations, with specified operations. modifications, or to UNDO the effects of po~.sible The goal of the programmer's assistant, OWIH, CLISP. etc. is to provide a programming environment which will "cooperate" with the user in the development of his programs, and free him to concentrate more fully on the conceptual difficulties and creative aspects of the problem he is trying to solve. To aid in converting to INTERL ISP programs written in other LISP dialects, e.g., LISP 1.5, Stanford LISP, accepts transformations (or I~e, have implemented TRANSOR, a subsystem which can operate from previously defined transformations), and applies these transformations to source programs written in another LISP dialect, producing object programs which will run on INTERLISP (Appendix 1). In addition, TRANSOR alerts the programmer to problem areas that (may) need further attention. TRANSOR was used extensively in converting from 940 LISP to BBN-LISP on the PDP-l0. A set of transformations is available for converting from Stanford LISP and LISP 1.5 to INTERLISP. A complete format directed list processing system FLIP [Teil], is available for use within INTERLISP. Although we have tried to be as clear and complete as possible, this document 1.2 is not designed to be an introduction to LISP~ Therefore, some parts may only be clear to people who have had some experience with other LISP systems. good introduction to LISP has been written by Clark Weissman [Weil]. A Although not completely accurate with respect to INTERLISP. the differences are small enough to be mastered by use of this manual and on-line interaction. Another useful introduction is given by Berkeley [Bert] in the collection of Berkeley and Bobrow [Ber2]. Changes to this manual will be issued by replacing sections or pages, and reissuing the index and table of contents at periodic intervals. In addition, the manual will be maintained on-line, and up to date versions of any or all chapters will be available in the form of TENEX files from W. Teitelman at Xerox PARC. 1.3 Bibliography [Bert] Berkeley. E.C .• "LISP, A Simple Introduction" in Berkeley. E.C. and Bobrow, D.G. [Ber2]. [Ber2] Berkeley, E.C., and Bobrow, D.G. (editors), The Programming Language LISP, its Operatiol!! and Applications, MIT Press, 1966e [Bobl] Bobrow, D. G., Burchfiel, J. D., Murphy, D. L., and Tomlinson, R. 8. nTENEX, a Paged Time Sharing System for the PDP-I0", Communications of :the ACM, March, 1972. [Bob2] Bobrow, D.G., and Murphy, D.L. "The Structure of a LISP System Using Two Level Storage", Communications of the ACM, VIS 3, March 1967. [ Bob3] Bobrow, D.G., and Wegbreit, B. "A Model and Stack Implementation for Mul tiple EnvironmEmts" (to be published), Third International Joint Conference ~!! Artificial Intelligence, August 1973. [Meel] McCarthy, J. et ale [Murl] Murphy, .D.L. "Stora"e Organization and Management in TENEX", Proceedings of Fal~ Joint Computer Conference, December 1972. [8mi1] 8mi th, D. "MLISP" Art;ificial University, October 1970. [Teit] Teitelman, W. FLIP, A format Directed List Processor in LISP, BBN Report, 196-:;-:- - [Tei2] Teitelman, W. "Toward a Programming Laboratory" in Walker, D. (ed.) International Joint Conference on Artificial Intelligence, May 1969. --- [ Tei3] Teitelman, W., Bobrow, D.G., Hartley. A.K. Murphy, D.L. BBN-LISP TENEX Reference Manual, Bolt Beranek and Newman, July 1971, first revision, Febru8r~1972, second revision August 19,72. [Tei4 ] Teitelman, W. "Automatl!d Programmering - The Programmer's Assistant", Proceedings of the Fall Joint Computer Conference, December 1972. [Tei5 ] Teitelman, W. "CLISP - Conversational LISP"~ Third International Joint Conference ~l Artificial Intelligence, August 1973. [Weil] Weissman, C. LISP 1.5 LI;SP 1.5 Programmer's Manual, MIT Press, 1966. ~rimer, Intelligence Memo No. Dickenson Press (1967). 1.4 135 Stanford SECTION 2 USING INTERLISP 2.1' Using the INTERLISP'Manual ..; ~:Format, Notation, and Conventions The INTERLISP sections. manual Each is divided' into separa'te more section· ig paginated ,independently, updates 'of sections. or to less independent facilitate issuing Each sec'tion "cont'ains an index to ' keywords, functions, and variables contained in that section. In addition, there is a composite index for the entire manual, plus several appendices and a table of contents. Throughout the manual~ terminology'and conventions will be offset from the text and typed in italics, ·frequently at the beginning of a section. one such notational ~onvention For example, is: The' names of functions and ,,«riables are written in lOUler case and underlined when theu appear in the text. Examples: Meta-LISP notation is used Jor describing Jonms. member[x;y] is equivalent t'o (MEMBER X Y), 'member[car[x];FOO] is equivalent to (MEMBER (CAR X) (QUOTE FOO». Note that. in meta-LISP notation lower case variables are evaluated, upper case quoted. . notation is used to, distinguish between £!!!!:! and lli.!.: e.g., if !=(A B C). is (FOO A B C). Similarly, l (FOO x) is (FOO (A B C», whereas(FOO • x) In other words, ! is cadr of (FOO x) but cdr of (FOO • x). is caddr of, (FOO x'Y)','but cddr of (FOO x • y). 2.1 Note that this convention is i.e., (FOO . (A B C» in fact followed by the read program, and (FOO A B C) read in as equal structures. Other important conventions art: TRUE in INTERLISP means not NIL. The purpose of this is to allo,~ a single function to be used both for the computation of some quantity, and as a test for a condition. For example, the value of member[x;y] is either NIL. or the tail of 1.. beginning with !. Similarly, the value of !!.!: is the' value of its first TRUE, i.e.,. non-NIL, expression, and the. value of !Jrld is either NIL, or the value of its last expression. Although most lists terminate in NIL. the occasional list that ends in an atom, e.g •• (A B . C) or worse, a nUlmer or string, could cause bizarre effects. Accordingly. we have made the fol.lowing implementation decision: All junction.s that iterate throl!lgh a li.st. e.g •• member. length. mapc etc. terminate bll an nli.s.tp checlc.. 1'ather than the conventional nuLl-checlt, a.s a .sajetll precaution again.st encouTiltering dat.a tupes which might cause infinite cd r Loop.s. e. g .• s tri ngs. number~;. arraus. t Thus, member[x;(A B . C)]=member[x;(A B)] reverse[(A B . C)]=reverse[(A B)] append[(A B • C);y]=append[(A B);y] For users with an application requiring extreme efficiency,1 we have provided fast versions of memb, last, n1;h, !!!!!£. and length which compile open and i---~-~-I~--;;;;;-~;~-~~--;;;~;;;d'-~~-~~;~--;~;-~~;;;~~;~~~:-~~--;;;;;;-;;~~~;;; about 12, although both gener'ate only one word of code. 2.2 terminate on NIL checks. and therefore may'cause infinite cdr loops if given poorly formed arguments. However. to help detect these situations, fmemb, flast ~ fnth, fassoC, and 'flength 'all generate errors when interpreted if their argument ends 1n a non-list other'than NIL, e.g. BAD ARGUMENT - FLAST. Most Junctions that set sustem parameters. e.g .• printleueZ. linelenath, radix, etc .• return as their ualue the old setting. 1/ giuen NIL as an argument. theu return the current ualue without changing it. All SUBRS, i. e., hand coded junctions. such as read, print, eu'al, ~, etc., have 'argument names' (U V W) as described under arglist, Section 8. Howeuer, Jor tutorial purposes ,more suggestille names are used in the descriptions 01 these Junctions, in the text. Most Junctions whose names end in ! are predicates. e.g. numberp, tailp. exprp, most JUri,cttons whose names' end in !l. are nZambda's. t.e., do not require quoting their arguments, e.g., setg, define,. nlsetg . •• ~ is equal to 1/." means equal(x,IIJ is true. as opposed to"! t's !!l. to 1/." meaning eq(x,uJ is true. i.e .• !. and II. are the same identical tiSP pointer. When neru literal atoms are created (bu the read program. pack. or mitatom). theu are provided with a junction dejinition cell initialized to NI£ (Section 8), a ualue cell initialized to the atom NOBIND (Section 16), and a propertll list initialized to NIL (Section 7). The junction dejinition cell is accessed bll the functions getd and putd described" in Section 8. The ualue cell oj an atom is car oj the atom. and its propertu list is cdr 0/ the atom. In particular, £l!!. oj NI£ and cdr oj NI£ are alwalls NIL. and thesustem will resist attempts to change them. The term lis t rejersto anu structure created bU one or more con.se.s • i.e. it doe.s not hcive to end in NIL. For example, (A . B) is a list. The Junction listp, Section 6. is used to test lor li.sts. Note that not being a list does not nece.ssarily impZu an atom. e.g .• strings' and aTraus are not lists. nor are theyatom.s. See Section 10. Many .sy.stem Junctions haue extra optional arguments jor internal use that are not de.scribed in the writeups. For example, readline is' described as a Junction oJ no arguments. but arglist(READLINE} returns (LINE LISPXFLG). In such cases, the user should just ignore the extra arguments. . INTERLISP departs from LISP 1.5 and, other LISP dialects in that car oj a Jorm is neuer evaluated~ In other words, if £!!. of a form is not an atom with a function definition, and not a function object, i.'e. a list LAMBDA, NLAMBDA, or FUNARG, an error is generated. must be used if the name of a function is to be functional arguments are applied. 2.3 ~ ~ of which is or !ru!.!I* (section 8) computed as for example, when 2.2 Using the INTERLISP System on TENEX - An Overview Call INTERLISP by typing LISP followed by a carriage return. INTERLISP will type an identifying message, the date, and a greeting, followed by a '~'. prompt top character indicates INTERLISP executive, that the user called !!'y'algt, line, it is evaluated; the second. eval and Rtalking toR the (for historical reasons), indicates the user is talking to TENEX. inputs in ei ther eval or is This level just as I@' evalgt 'calls lispx which accepts !..I!.l!.!I format: if just one expression is typed on a if two 4~xpressions are typed. the first is .!.I!.P1I-ed to !..I!.l!.!I art. described in section 8. value is typed, followed by ~ In both cases. the indicating INTERLISP is ready for another input. INTERLISP is normally exited via the fUnction LOGOUT. i.e.. the user types LOGOUT( ). However. typing contr"ol-C at any point in the computation returns control immediately to TENEX. The user can then continue his program with no ill effects with the TENEX CONTINUE comand, even if he interrupted it during a Or he can reenter his program at evalqt with the TENEX garbage collection. REENTER command. The latter is DEFINITELY not advisable !l the Control-C typed during !! garbage computation will collec1~ion. return control ~ Typing control-D at any point during a to evalgt. If typed during a garbage collection, the garbage collection will first be completed, and then control will be returned to INTERLIiSP' s top level, otherwise, control returns immediately. When typing to the INTERLISP read program, typing a control-Q will cause INTERLISP to print 'II' and clear the input buffer, i.a., erase the entire line up to the last carriage return. Typing control-A erases the last character typed in, echoing a \ and the erased character. beyond the last carriage return. Control-A will not back up ControI-O can be used to tmmedtatelu clear 2.4 the output buffer, and rubout to immediatel,l clear the input buffer. 2 In addi tion, typing, control-U (in most cases) will cause the INTERLISP editor (Section 9) to be called on the, expression being read, when the read 1s completed. Appendix 3 contains a list of all control characters, and a reference to that part of the manual where they are described. Since the INTERLISP read program is normally line-buffered to make possible the action of control-Q,a the user must type • carriage return b.fore any characters are delivered to the function requesting input, e.g., .. E T.> T 4 However, the read program automatic.llll supplies (and prints) this carriage return when a matching right parenthesis is typed, .aking it unnecessary for the user to do so, e.g., "CONS(A B) (A • B) The INTERLISP read program treats square brackets as 'super-parentheses' ': a right square bracket automatically supplies enough right parentheses to match back to the last left square bracket (in the expression being read), or if none has appeared, to match the first left parentheses, e. g. , (A (B (C]= (A (B (C»), (A [B (C (0] E)·(A (8 (C (0») E). 2--~-~-----------~---------------~--~-~--------------------------~------------~ The action of control-Q takes place when it is read. If the user has 'typed ahead' several inputs, control-Q will only affect at most the last line of input. Rubout however will clear the entire input buffer as soon as it is typed, i.e., even during a garbage collection. 8 Except following control[T], see Section 14. " '.,' is used throughout the manual to denote carriage-return. 2.5 Thus to input an atom containing % is the universal escape character for read. ABX (C or a syntactic delimiter, precede it by X, e.g. xx. See Section 14 for more details. Most of the "basics" of on-lillie use of INTERLISP, e.g. defining functions, error handling, editing, saving your work, following brief console session. 1. are illustrated in the Underlined characters were typed by the user. The user callslNTERLISP from TENEX, greeting. etc., The prompt character ~ INTERLISP prints a date, and a indicates the user is at the top level of INTERLISP •. 2. The user deC·ines a functi')n, INTERLISP, functions fact, for computing factorial of n. are defined via DEFINE or DEFINEQ, In (Section 8). Functions may independently evaluate arguments, or not evaluate them, and spread their arguments, or not spread them (Section 4). The function fact shown here is an example of an everyday run-of .. the-mill function of one argument, which is evaluated. 3. The user "looks" at the lFunction definition. Function definitions in INTERLISP are stored in a special cell called the function definition cell, which is associated with the name of the function (Section 8). is accessible via the two functions, getd and putd, putd). Note that expression, i.e. form for eval. 4. the an input consisting and defineq use of a single (GETD (QUOTE FACT», which was therefore interpreted as a The user could also have typed GETD(FACT). The user runs his function. by typed u~)er ('def~ne This cell DWI" (Section 17). Two errors occur and corrections are offered In each case, the user indicates his approval, DWI" makes the correction, i.e. actually changes. the definition of fact, and then continues the computation. 2.6 @LISP,> INTERLISP-I0 11-17-73 ••• GOOD EVENING. (LAMBOOA (N) (COHO «EO N 0) NIL) Z (T (ITIMES H (FACTT (SUBI H] (fACT) ~(GETO (QUOTE FACT» 3 (LAMBOOA (H) (CONO «EQ H 0) NIL) (T (ITIHES N (FACTT (SU81 N»»» ~FACT(3) . . 4 LAMBOOA [IN FACT] -> LAMBDA? !ESl FACTT [IN FACT] -> FACT? !ESl ~OEFINEQ«FACT NON-NUMERIC ARG NIL IN ITIHES 5 , (BROKEN) :BT,> ITIMES CONO FACT CONO FACT CONO FACT **TOP** :N,> 1 :EOITF(FACT) EDIT *(R NIL 1) *OK,> FACT :RETURN 1.> 'BREAK' = 1 8 1- 6 ~PP 9 10 11 FACT,> 12 (FACT [LAMBDA (N) (CONO « EQ NO) 1) FACT (T (ITIMES N (FACT (SUBI N]) ~PRETTYOEF«FACT) FACT. ,I 13 14 FACT) 2.7 5. An error occurs that OWl" cannot handle. and the system goes into a break. At this point. the user can type in expressions to be eval-ed or apply-ad exactly as at the top level. The prompt character ':' indicates that the user is in a break. i.e. that the conte~t of hi$ c~mputation is available. In other words. the system is actually "within" or "below" the call to itimes in which the error occurred. 6. The user types in the break command, BT, which calls (or a backtrace to be printed. In INTERLISP, interpreted and compil~d code (see Section 18 for discussion of the compiler) are completely compatible, and in both cases, the name of the function that was called, as well as the names and values of its arguments are stored on the stack. The stack can be searched and/or modified in various ways (see Section 12). Break commands are discusse:d in Section 15, which also explains how the user can "break" a particular function, i.e. specify that the system go into a "break H whenever a 'certain function or functions are called. that point the user can c!xamine the state of the computation. At This facility is very useful for debugging. 7. The user asks for the value of the variable or binding. rr. i.e. the most recent value, The interpretEtr will search the stack for the most recent binding, and failing to find one, will obtain the top level value from the atom's value cell, which is £![ of the atom (Section 3). If there are no bindings, and the value cell contains the atom NOBINO, an unbound atom error is generated (Section 16). 8. The user realizes his error. and calls the editor to fix it. the system is ~till (Note that in the break.) The editor is described at length and in detail in Section 9. It is an extremely useful facility of· INTERLISP. Section 9 begins with a simple introduction designed for the new user. 2.8 9. The user instructs the editor to replace all NIL's (in this case there is only one) by 1. The editor physically changes the expression it is operating on so when the user exits from the editor, his function, as it is now being interpreted. has been changed. 10. The user exits from the editor and returns to the break. 11. The user specifies the value to be used by itimes in place of NIL by using the break command RETURN. This causes the computation to continue, and 6 is ultimately returned as the value of'the original input, fact(3). 12. The user prettyprints (Section 14) fact, i.e. asks it be printed with appropriate indentations to indicate structure. a comment facility. Prettyprint also provides Note that both tbe changes made to fact by the editor and those made by DWIM are in evidence. 13. The user writes his function on a file by using prettydef (Section 14), creating a TENEX file, FACT.;l, which when loaded into INTERLISP at a later date via the function load (Section 14), will cause fact to be defined as it currently is. restoring an There is also a facility in INTERLISP for saving and entire core image via the functions Sysout and sysin (Section 14). 14. The user logs out, returning control to TENEX. However, he can still continue his session by re-entering INTERLIBP via the TENEX REENTER or CONTINUE command. 2.9 Index for Section 2 Page Numbers APPLY[FN;ARGS] SUBR apply format APPLY*[FN;ARG1; .•. ;ARGn] SUBR* ARGlIST[X] back trace ....................•••••.••••••••••• ................................... . BAD ARGUMENT FASSOC (error message) BAD ARGUMENT FLAST (error message) BAD ARGUMENT FLENGTH (error message) BAD ARGUMENT FMEHB (error message) BAD ARGUMENT FNTH (error Illessage) BT (break command) CONTINUE (tenex command) CONTROL[U] SUBR control characters control-A control-C control-D control-O control-Q control-U debugging OEFINE[X] OEFINEQ[X] NL* dot notation DWIM EQ[X;Y] SUBR · ..................................... . ·..................................... . ·..................................... . eQ 2.1 2.6 2.3 .................................... . EQUAL[X;Y] · equal escape character EVAL[X] SUBR eval format EVALQT FASSOC[X;Y] files FLAST[X] FLENGTH[X] FMEMB[X;Y] FNTH[X:N] function definition cell functional arguments garbage collection GETD[X] SUBR line-buffering LINELENGTH[N] SUBR LISTP[X] SUBR lists lOAO[FILE;LDFLG;PRINTFLG] lOGOUT[] SUBR NlISTP[X] NOBINO null-check predicates PRETTYDEF PRETTYPRINT PRINTlEVEl[N] SUBR • • • • • '• • • • • • • • I •••••••••••••••••••••• .......... .......................... . ........................................... ' ........................................ ·..................................... . .......... ................... . .................................... ' ....................... ·..................................... . ·............................... ...... . ·.................................... . ·.................................... . ·..................................... . ..................................... .............................. ••••••• II ••••••••••••••••••••••••••• ' INI)EX.2.1 2.3-4 2.4 2.3 2.3 2.8 2.3 2.3 2.3 2.3 2.3 2.8 ·2.4,9 2.5 2.4-5 2.4 2.4 2.4 2.4 2.4 2.5 2.8 2.6 2.6 2.3 2.3 2.3 2.6 2.4,6 2.4 2.4 2.3 2.9 2.3 2.3 2.3 2.3 2.3,6 2.3 2.4 2.3,6 2.5 2.3 2.3 2.3 2.9 2.4 2.2 2.3,8 2.2 2.3 2.9 2.9 2.3 Page Numbers prompt character property list pushdown list PUTD[X;Y] SUBR RADIX[N] SUBR REENTER (tenex command) RETURN (break command) rubout square brackets SYSIN[FILE] SUBR SYSOUT[FILE] EXPR TENEX true (U V W) (value of ARGlIST) U.B.A. (error message) value cell variable bindings ~ (carriage-return) I I (typed by system) X (escape characterl notation (typed by system) \ (typed by system) ................................... ......................... ................................. ................................ ......... ................................. . " •••• ill ...................... ............................... ••••••••••••••••••••••••••••••••• •••••••• 0 ••••• _ ••••••••••••• .............................. ••••••••• 0 ••••••••••••••••••• ] ~ (typed by system) INDEX.2.2 2.4.6,8 2.3 2.8 2.3,6 2.3 2.4,9 2.9 2.5 2.5 2.9 2.9 2.4,6,9 2.2 2.3 2.8 2.3 2.8 2.5 2.4 2.6 2.1 2.8 2.4 2.5 2.4,6 SECTION 3 DATA TYPES, STORAGE ALLOCATION, AND GARBAGE COLLECTION1 INTERLISP operates ;in an 18-bitaddress spaci. This address space is divided into 512 word pages with a limit of 512 pages, or 262,144 words, but only that portion of address space. currlntly in use actually exists on a·ny storage medium. INTERLISP itself· and>. all data storage are containld within this address space. . A pointe... to a data Ile.entsuch as a nullber, atOll,·etc., is simply thl addrlss of the data'll,.ent in this 18-bit'address spaci • . 3.1 Data Types The data types of INTERLISP are lists, atoms, pnames, arrays, large and small integers, floating point numbers, string . ~haracters .and string pointers. Compiled code and hash arrays are currently included with arrays. In the descriptions of the various data types given below, for each data type, first the input syntax and output format are described, that is, what. input sequence will cause the INTERLISP read program to construct an Illment of that type, and how the INTERLISP print program will print such an Ilemlnt. those functions that construct aliments of that data type are given. Next, Note that some data types cannot be input, thlY can only be constructed, e.g. arrays. Finally, the format in which an Il ••lnt of that data type i·5 stor.d in •••ory is described. i---------------------------------------------------~-------------------------This section was written by A. K. Hartley. 3.1 3.1.1 Literal Atoms A literal atom is input as any string of non-delimiting characters that cannot be interpreted as a number. The syntatic characters that delimit atoms are space, end-of-line,2 line-feed, ,~ ( ) • ] and [. However, these characters may be included in atoms by precedin" them with the escape character X. Literal atoms are printed by print and prinZ as a sequence of characters ,with xes inserted before all delimitilllg characters (so that the atom will read back in properly). Literal atoms are printed by print asa sequence of characters wi thout extra X' s. these For example, the atom consisting of the five characters A, B, C, (, and 0 will be printed as ABCX(D by print and ABC(D by prinl. The extra Xt 5 are an art1lfact of the print program; they are not stored in the atom's pname. Li teral atoms can be constructed by pack, mkatom, and gensym (which uses. mkatom) • Literal atoms are unique. In other words, if two literal atoms have the same pname, i.e. print the same, they will allDalls be the same identical atom, that" is, they will always have the same address in memory. or equivalently, they will always be corresponding to !!l.a ~ Thus if ~lck or mkatom is given a list of characters literal atom that already exists, they return a pointer to that atom, and do not make a new atom. Similarly, if the read program is given as input of a sequence of char'acters for which an atom already exists. it returns a pointer to that atom. j--------------_________________ end-of-line character carriage-return. An 8 O ___________________ is transmitted by ~ _________________________ TENEX when it sees _ a Note that this is not true for strings, large integers, floating point numbers, and lists, i.e. the~, all can print the same without being g. 3.2 A literal atom is a 3 word (36 bits) datum containing: PROPERTY LIS T (CDR) WORD I: 0 WORD 2: TOP LEVEL BINDING (CAR) 17 18 35 FUNCTION CALLING I NSTRUCTIO N 0 WORD 3: PNAME 0 I 35 RESERVED FOR FUNCTIONS ON FILES 17 18 35 I FIGURE 3-1 Car of a literal atom, i.e. the right half of word 1, contains its top level binding, initially the atom NOBIND. Cdr of the atom is a poi'nter to, its property list, initially NIL. Word Z. the function definition cell. is a full 36 bit word, containing an instruction to be executed for calling the function associated with that atom, if any. The left half differs for different function types (i.e., EXPR, SUBR, or compiled code); the right half is a pointer to the function definition. 4 The pname cell, the left half of the third word, contains a pointer to the pname of the atom. The remaining half word is reserved for an extension of INTERLISP to permit storing function definitions on tiles. a-------------------------------------------------------~---------------------This use of a full word saves some time in function calls trom compiled code in that we do not need to look up the type of the function definition at call time. 3.3 3.1.2 Pnames The pnames of atoms, 6 pointed to in the third word of the atom, comprise another data type with storage assigned as it is needed. occurs as a component of an atom or 'a string. This data type only It does not appear, for example, as an element of a list. Pnames have no input syntax or, output format as they cannot be directly referenced by user programs. A pname is a sequence of 7 bit characters packed 5 to a word, beginning at a word boundary. The first chara«:ter of a pname contains its length; thus the maximum length of a pname is 126 characters. 3.1.3 Numerical Atoms Numerical atoms. or simply numbBrs, do not have property lists, value cells, functions definition cells. or e'xplicit pnames. There are currently two types of numbers in INTERLISP: integer:s, and floating pOint numbers_ Integers The input syntax for an integel'" is an optional sign (+ or -) followed by a 6-~-----~-----------~--------------------------------- ------------------------- All INTERLISP pointers have pnames, since we define a pname Simply to be how that pointer is printed. However, only literal atoms and strings have their pnames explicitly st()red. Thus, the use of the term pname in a discussion of data types 01" storage, allocation means pnames of atoms or strings, and refers to a sequence of characters stored in a certain part of INTERLISP's memory_ 3.4 sequence of digits, followed by an optional Q.8 If the Q is present, the digits are interpreted in octal, otherwise in decimal, e.g. 77Q and 63 both correspond to the same integers, and in fact are indistinguishable internally since no record is kept of how integers were created. The setting of radix (Section 14), determines how integers are printed: signed or unsigned, octal or decimal. Integers are created by pack and mkatom when given a sequence of characters observing the above syntax, e.g. (PACK (LIST 1 2 (QUOTE Q») • 10. Integers are also created as a result of arithmetic operations, as described in Section 13. An integer is stored in one 36 bit word: thus its magnitude must be less than 2t35. 7 To avoid h~ving to store (and hence garbage collect) the values of small integers. a few pages of address space, overlapping the INTERLISP machine language code, are reserved for their representation. ttself, minus a constant, is the value of the number. 'small' integers is -1536 thru +1535. The small number pointe .. Currently the range of The predicate smallp is used to test whether an integer is IsmaIl'. While small integers have a unique representation, large integers do not. In other words, two large integers may have the same value. but not the same' address in memory. and therefore not be!!. For this reason the function ~ (or equal) should be used to test equality of large integers. 6---~-------~~----------------------------------------------------------------- and terminated by a delimiting character. self-delimiting, e.g. lists. 7 Note that 50..8 data types ar. If the sequence of digits used to create the integer is too large, the high order portion is discarded. (The handling of overflow as a result of arithmetic operations is discussed in Section 13.) 3.5 Floating Point Numbers A floating point number is input as a signed integer, followed by a decimal point, followed by another sequence of digits called the fraction, followed by an exponent (represented by E followed by a signed integer). B Both signs are optional, and either the fraction following the decimal point, or the integer preceding the decimal point may be omitted. One or the other of the decimal point or exponent may also be om:l.tted, but at least one of them must be present to distinguish a floating poin1; number from an integer. For example, the following will be recognized as floating point numbers: 5. 5.00 5.01. .3 5E-3 -5.2E+6 5.1E2 5E2 Floating point numbers are pril1lted using the facilities provided by TENEX. INTERLISP calls the floating point number to string conversion routines 9 using the format control specified by the function fltfmt (Section 14); initialized to T. or free fOMllat. For example, fltfmt· is the above floating point numbers would be printed free format as: 5.0 5.0 5.01 .3 .0051 -5.2E6 500.0 510.0 Floating point numbers are also c:reated by pack and mkatom, and as a result of arithmetic operations as described in section 13. A floating point number is storedl in one 36 bit word in standard POP-tO format. The range is ±2.94E-39 thru ±1.69E38 (or 2t-128 thru 2tI27). 8---~------------------------------------------------- ------------------------- and 9 terminate~ by a delimiter. Addi tional information concerning these conversions may be obtained from the TENEX JSYS Manual. 3.6 3.1.4 Lists The input syntax for a list is • sequenceperty listsobserue this conue~tion by cl/cling down the property lists two cdrs at a time. Nost of these Junctions also generate an error. ARG NOT ATOM, i! given an argument which is not a literal atom, i.e., thell cannot be used directly on lists. The term 'property name' or ' property' is used for the propertll indicators appearing in the odd positions, and the term 'property ualue' or 'ualue oj a property' or simply 'ualue' lor the ualues appearing in the euen positions. Sometimes the phrase 'to store on the property --' is used, meaning to place the indicated tnformation on the property list under the property name --. Properties are usuallY atoms. although no checks are made to eliminate use oj non-atoms in an odd position. However, the property list searching functions all use g. Property List Functions put[atm;prop;val] puts on the property list of atm, the property ~ with value val. value for the property val replaces any previous ~ on this property list. Generates an error, ARG NOT ATOM, if atm is not a literal atom. addprop[atm,prop;new;flg] ~ Value is val. the value n!! to the list which is the value of property ~ on property list of atm. If fIg is T. !!!!! is consed onto the front of value of 7.1 ~, otherwise it is ~ed on the end (nconct). If atm does not have a property 2rQ2. the effect is the same as put[atm;prop;list[new]], for exaunple, if addprop[FOO;PROP;FIE] is followed by addprop[FOO;PROP;FUM], be (FIE FUM). getp[FOO;PROP] will The value of add prop is the (new) property value. If atm is not a literal atom, generates an error, ARG NOT ATOM. remprop[atm;prop] removes all occurrences of the property 2r22 (and its value) from the property list of atm. is ~ is not Value if any were found, oth,erwise NIL. If !!!!! a literal atom, generates an error, ARG NOT ATOM. changeprop[x;propl;prop2] Changes name of property ~ to ~ on property list or !, (but does not arrect the value or the property). Value is !. unless ~ is not round, in which case, the vaiue is NIL. If ! is not a literal atom, generates an error, Gets th. item arter the atom l on list!. If l is ARG NOT ATOM. get[x;y] not on the list !, value is NIL. For example, get[A B C D):B].C. Note, since i!! terminates on a non-list, get[atom,anuthing] is NIL. Thererore, to search a property 1is t, Il!!I!. shou ld be used, or get applied to cdr(atom]. 7.2 getp[atm;prop] gets the property value for list of!!m. ~ from the property The value of S!12 is NIL if atm is not a literal atom, or irQ2 if not found. Note, the ualue of 2!!! mau al80 be NIL, iJ there i8 an the corre8ponding propertu ualue i8 NIL. Note: Since time, ~ ~ccurrence oj ~ but searches a list two items at a the same object can be used as both a property name and a property value, e.g., if the property list of atm is (PROP1 A PROP2 B A C), then getp[atmjA] • C. Note that however get[cdr[atm];A] • PROP2. getlis[x;props] searches the property list of !. and returns the property list as of the first property on props that it finds e.g., if the property list of ! is (PROP1 A PROP3 B A C), getlis[xj(PROPZ PROP3)]=(PROP3 B A C) Value is NIL if no element on ~ is found. ! can also be a list itself, in which case it is searched as above. deflist[l;prop] is used to put values under the same property name on the property lists of several atoms. list of two-element lists. ! is a The first element of each is a literal atom, and the second element is the property value for the property ~. The value of deflist is NIL. Note, Manu atom8 in the8U8tem fllreadu haue propertu li8t8, with properties used bU the compiler. the brealtpacltalle. DWIH, etc. Be careful not to clobber such sU8tem propertie8. The ualue oj 8U8'prop8 gilles the complete li8t of the propertu names used bU the 8ustem. 7.3 7.2 Hash Links The description of the hash link facility in INTERLISP is included in the chapter on property lists because of the similarities in the ways the two features are used. A property list provides a way of associating information with a particular atom. pointe~ A hash link is an association between any INTERLISP (atoms, numbers, arrays II strings, lists, et al) called the hash-item, and any other INTERLISP pointer called the hash-value. stored in cdr of the atom. called the hash-address, Property lists are Hash links are implemented by computing an address, in a specified array. called the hash-array, and storing the hash-value and the hash-item into the cell with that address. The contents of that cell, i.e. the hash-value and hash-item, is then called the hash-link. 1 Since the hash-array is obviously much smaller than the total number of . possible hash-items,2 the hash-address computed from item may already contain a hash-link. If this link is fro[[l item, 3 the new hash-value simply replaces the old' hash-value. be computed, Otherwise, ano1;her hash-address (in the same hash-array) must etc. until an empty cell is found, 4 or a cell containing a hash-link from item. When a hash link for item is being retrieved, the hash-address is computed i--~-~--~~~--~--~-~-~-----------'------·----~--------- ----------------------~-~- The term hash link (unhyphenated) refers to the process of associating information this way. or thEI 'association' as an abstract concept. 2 3 4 which 1s the total number of INTERLISP pointers, i.e., 256K. ~ is used for comparing itE~ with the hash-item in the cell. After a certain number of iterations (the exact algorithm is complicated), the hash-array is considered to be full, and the array is either enlarged, or an error is generated, as described below in the discussion of overflow. 7.4 using the same algorithm as that employed for making the hash link. corresponding cell is empty, there is no hash link for item. hash-link from item, the hash-value is hash-address must be computed, and so forth. 6 returned. If the If it contains a Otherwise, another Note that more than one hash link can be associated with a given hash-item by using more than one hash-array. Hash Link Functions In the description of the functions below, the argument array has one of three forms: (1) NIL, in which case the hash-array provided by the system, syshasharray. is used;6 (2) a hash-array created by the function harray, or created 'from an ordinary array using clrhash as described below; or (3) a list ~ of which is a hash-array. The latter form is used for specifying what is to be done on overflow, as described below. harray[n] creates a hash-array of size n,. equivalent to clrhash[array[n]]. clrhash[array] sets all elements of array to 0 and sets left half of first word of header to -1. puthash[item;val;array] Value is array. puts into array a hash-link from item to val. 6--~--------------------------------------------------------------------------- For reasonable operation, the hash array should be ten to twenty percent larger than the maximum number of hash links to be made to it. 6 syshasharray is not used by the system, it is provided solely for the user's benefit. It is initially 512 words large, and is automatically enlarged by 50" whenever it is 'full'. See page 7.7. 7.5 Replaces previous link from same item, if any. val=NIL any old link is removed, hash-value or NIL is not allowed). gethash[item;array] If (hence Value is a ~. finds hash-link from item in array. and returns the hash-value. Value is NIL if no link exists. gethash compiles open. rehash[oldar:newar] hashes all items and. values in oldar into newar. The two arrays do not. have to be (and usually aren't) the same size. maphash[array:maphfn] Value is ~. maphfn is a function of two arguments. For each hash-link in array, maphfn will be applied to the has,h-value and hash-item, e.g. maphash[a;(LAHBDA(X Y) (AND(LISTP Y) (PRINT X»)] will print the hash-value for 1is,ts. dmphash[arrayname] al~ hash-links from The value of maphash is array. Nla~da-nospread that prints on the primary output file a loadable form which will restore what is in thEI (E hash-array specified (DHPHASH SYSHASHARRAY» by arrayname, e. g. as a prettydef command will dump the system hash-array. Note, all g identitie~ except G/tom~ and ~mall integer~ are Lost bU dumping and l oading becau~e read wi II create new ~tructure for each item. Thus if two li~t~ contaiRan !!l. substructure, when theu are dumped and Loa~ed baclc. in. the corre~pondinQ' ~ub~tructure~ while equal are no Longer g. 7~-~---------------------------·'-----------------------------------~----------circlprint and circlmaker (Section 21) provide a way of dumping and reloading structures contaill'ling !!l substructures so that these identities are preserved. 7.6 Hash Overflow By using an array argument of a special form. the user can provide for automatic enlargement of a hash-array when it overflows, i.e., is full and an attempt is made to store a hash link into it. the form (hash-array. n), rr f a In the first case. a new hash-array is II a PQsitive integer; floating point number; or (hash-array) created with The array argument is either of 0 or (hash-array. f), more cells than the current hash-array. In the second case, the new hash array will be f times the size of the current hash-array. case, (hash-array), is equivalent to (hash-array. 1.5). The third In each case, the old hash-array is rplacaed into the dotted pair, and the computation continues. If . a hash-array overflows, and the array argument used was not one of these three forms, the error HASH TABLE FULL is generated, which will either cause a break or unwind to the last errorset. as per treatment of errors described in Section 16. The system hash array. syshasharray, is automatically enlarged by 1.5 when it is full. 7.7 Index for Section 7 Page Numbers ....................... AOOPROP[ATH;PROP;NEW;FlG] ARG NOT ATOM (error message) CHANGEPROP[X;PROP1;PROP2] CIRClMAKER[L] CIRCLPRINT[L;PRINTFLG;RLKNT] CLRHASH[ARRAY] SUBR OEFtIST[L;PROP] OMPHASH[L] NLtfr ERRORSET[U;V] SUBR GET[X;Y] GETHASH[ITEM;ARRAY] SUBR GETLIS[X;PROPS] GETP[ATM;PROP] HARRAY[lEN] hash link functions hash links · hash overflow HASH TABLE FULL (error message) hash-address hash-array · hash-item hash-link hash-value MAPHASH[ARRAY;HAPHFN] property property list • •••••••••••••• '* ••••••••••••••••• property name 'property value PUT[ATH;PROP;VAL] PUTHASH[ITEH;VAL;ARRAY] SUBR REHASIf[OLOAR;NEWAR] SUBR REMPROP[ATH;PROP] SYSHASHARRAY (system variable/parameter) SYSPROPS (system variable/parameter) value of a property ·................... ............ . .................................... . ..................................... .................................... ....................................... ·.................................... . ·............................... . ............................... ............ ......... .................. . ~ INDEX.7.1 7.1 7.1-2 7.2 7.6 7.6 7.5 7.3 7.6 7.7 7.2 7.6 7.3 7.3 7.5 7.5-6 7.4-6 7.7 7.7 7.4 7.4-5,7 7.4-6 7.4-6 7.4-6 7.6 7.1 7.1-3 7.1,3 7.1,3 7.1-2 7.5 7.6 7.2 7.5,7 7.3 7.1 SECTION 8 FUNCTION DEFINITION AND EVALUATION General Comments A function defini tion in INTERLISP is stored in a special cell called the function definition cell, which is associated with each literal atom. This cell is directly accessible via the two functions putd, which puts a gefinition in the cell, and getd which gets the the funct;i.on ~ from the cell. In addition, returns the function type, i.e., EXPR, EXPR* FSUBR* as described in Section 4. an expr, compiled ~.finition and subrp, are true if the function is ~,ccodep, function, or subr respectively; argtype returns 0, 1, 2, or 3, depending on whether the function is a spread or nospread (i.e., its fntyp ends in *), or evaluate or no-evaluate (i.e., its ~ begins with F or CF); arglist returns the list of arguments; and nargs returns the number of arguments. ~,exprp, ccodep, subrp. argtype, arglist, and nargs can be given either a literal atom, in which case they obtain the function definition from the atom's definition cell, or a function definition itself. Subrs Because subrs,l are called in a special way, their definitions are stored i-----------------------------------------------------------------------------Basic functions, handcoded in machine language, e.g. cons, car, cond. The terms subr includes spread/nospread, Ival/noeval functions,-r7e.~e four (ntype s SUBR, FSUBR, SUBR·, and FSUBR •• 8.1 differently than those of compiled or interpreted functions. In the right half of the definition cell is the address of the first instruction of the subr. and in the left half its argtype: 0, I, 2, or 3. pair of argtype and addr~ss. the definition cell. but a new getd of a subr returns a dotted Note that this is not the same word as appears in ~ffi!; i.e •• each getd of a subr performs a £Qn!. Similarly. putd of a definition 'of the form (number. address). where number = 0, 1, 2, or 3, and address is in the appropriate range, stores the definition as a subr, i. e., takes the £.2!l!. apart and stores £!!: in the left half of the defini tion cell and cdr in the rJLght half. Validity of Definitions Al though the function definition c'ell is intended for function definitions, putd and getd do not make thorough checks on the validity of definitions that "look like" exprs, compiled code, or subrs. Thus if putd is given an array pointer, it treats it as compiled code, and Simply stores,the array pOinter in the definition cell. getd will then return the array pointer. Similarly. a call to that function will simply transfer to what would normally be the entry \ point for the function, and plroduce random results if the array were not compiled function. Similarly. if putd is given a dCltted pair of the form (number 0 address) where number is O. 1, 2, or 3, and address falls in the subr range. putd assumes it is a subr and stores it away as described earlier. getd would then return £2.!l! of the left and right half, i.e 0, a dotted pair equal (but not!.9.) to the expression originally given put!!. Similarly, a call to this function would transfer to the corresponding address. Finally, if putd is given any other list, it simply stores it away. this A call to function would then go through the interpreter as described in the appendix. 8.2 Note that putd does not actually check to see if the s-expression is valid defin it ion. i. e., begins with LAMBDA or NlAMBDA. Simi larly. m.r.J! is true if a definition is a list and not of the form (number. address), number = 0, 1, 2, or 3 and address a subr address; subrp is true if it is of this form. arglist and nargs work correspondingly. Only fntyp and argtype check function definitions further than that described above: both argtype and ~ return NIL when ~ is true but £!!: of the definition is not LAMBDA or NLAMBDA.2 In other words, if the user uses putd to put (A Be) in a function definition cell. getd will return this value, the editor and prettyprint will both treat it as a definition, exprp will return T. ccodep and subrp NIL, arglist B, and nargs 1. getd[x] gets the function gefinition of~. Value 1s the definition. 3 Value is NIL if ~ is not a literal atom, or 'has no definition. fgetd[x] fast version of getd car[vag[addl[loc[x]]]]. that compiles open as Interpreted. generates an error, BAD ARGUMENT - FGETD, if .! is not a literal atom. 4 2---~~;;;-;~~~~~~~;-~;~;-d~~~;;;~~-~;i~;-~~-~;~;~;;-;~d-~~~~~O;;-;~d-~;~~;-~~;; check. The compiler and interpreter also take different actions for LAMBDAs and NlAMBDAs, and therefore generate errors if the definition is neither. 8 Note that getd of a subr performs a footnote on fgetd below. 4 Fgetd is intended primarily to check whether a function ha~ a definition, rather than to obtain the definition. Therefore, for subrs, fgetd returns just the address of the function definition, not the dotted pair returned by get~, page 8.2, thereby saving the cons. 8.3 £Q!!!, as described on page 8.2. See putd[x;y] put:s the !!efinition Value into !'S function cell. Generates an error, ILLEGAL ARG - is~. PUTD, if ! ~ is not a literal atom, or 'J. is a string. number. or literal atom other than NIL. putdq[x;y] nlalmbda version of considered quoted. movd[from.to;copyflg] Moves the redefines putd; If arguments are Value is !. definition to. both of from copyflg=T, definition of from is used. meaningful forexprs, to a !2, £22'i. i.e., of the copyflg=T is only although movd works compiled functions and subrs as well. for The value of .movd is to. Note, subrp. ccodep. exprp. aratupe. nargs. and argltst all can be gtuen etther the name 0/ a function. or a deftnttton. ~. fntyp[fn] Value is NIL if fn is not a function definition or the name of a defined function. Otherwise fnt'J.P returns one of the following as defined 1n the section on function types: EXPR CEXPR SUBR FEXPR CFEXPR .FSUBR EXPR* CEXPR* SUBR* FEXPR* CFEXPR* FSUBR* The prefix r indicates unevaluated arguments, the prefix £ indicates compiled code; and the suffix • indicates an indefinite number of arguments. 8.4 ~ returns FUNARG if fn is a funarg expression. See Section 11. subrp[fn] is true if an~ only if fntyp[fn] is either SUBR, FSUBR, ·SUBR". ,or FSUBR-, i. e.. the third column of fntyp's. ccodep[fn] is true if and only if fntyp[fn] is either CEXPR, CFEXPR, CEXPRft,or CFEXPR*, i.e., second column of fntyp's. exprp[fn] is true if fntyp[fn] is either EXPR, FEXPR, EXPR*, or FEXPR*, i.e. , first column of fntyp' s. However, exprp[ fn] is also true if fn is (has) a list definition that is not a SUBR, but does not begin with either LAMBDA or NLAMBDA. In other words" exprp is not quite as selective as fntyp. argtype[fn] fn is the name of a function or its definition. The value of argtype is the argtype of fn, i.e., 0, 1 p 2, or 3, or NIL if fn is not a function. The interpretation of the argtype is:, o eval/spread function (EXPR, CEXPR, SUBR) 1 no-eval/spread functions (FEXPR, CFEXPR, FSUBR) 2 eval/nospread functions (EXPR*, CEXPR*, SUBR*) 3 no-eval/nospread functions (FEXPR*, CFEXPR*, FSUBR*) i.e., argtyp~ 8.5 corresponds to the roUls of fntyps. value is the number of arguments of fn, or NIL if fn is not a function. 6 nargs uses exprp, not nargs[fn] fnty~, so that nargs[(A (B C) 0)]-2. Note that if fn 1s a SUBR or FSUBR, nargs • 3, regardless of the number of arguments logically needed/used by If the routine. nars,s arglist[fn] fn is a nospread = 1. ,value is the 'argument list' for fn. the function, 'argument functions. list' is an atom for Note that nospread Since NIL is a possible value, for arglist, generated", ARG:S NOT AVAILABLE, if fn is not a function. 6 If fn is a FSUBR-, SUBR· or FSUBR, the value is U. an error the value of arglist is is (U V W), if a SUBR- or This is merely a •feature , of arglist, subrs do not actually store the names U, V, or W on the stack. However. if the user breaks or traces a SUBR (Section 15), these will be the argumen't names used when an equivalent EXPR definition is constructed. define[x] The argument of define is a list. Each element of the list is itself a list either of the form (name' definition) or (name arguments ••• ). In the second case, following 'arguments' Is the body of the definition. As an example, consider the 6-------------~------------------------------------------------------~--------1.e., if ~, ccodep, and subrp are all NIL. 6 If fn is a compiled function, the argument list is constructed, 1.e. each call to arglist requires making a new list. for interpreted functions, the argument list is simply cadr of getd. 8.6 following two' equivalent expressions for defining the function null. 1) (NULL (LAMBDA (X) (EQ X NIL») 2) (NULL (X) (EQ X NIL» define will generate an error on encountering an atom where a defining list is expected. If dfnflg=NIL. an attempt to redefine a function fn will cause define to print the message (fn REDEFINED) and to save the old definition of fn using savedef before redefining it. redefined. If dfnflg=T. If dfnflg=PROP or ALLPROP, the the function is Simply definition is stored on the n~w property list under the property EXPR. (ALLPROP affects the operation of rpaqq and ~. section 5). dfnflg is initially NIL. dfnflg is reset by load to enable various ways of handling the defining of functions and setting of variables when loading a file. For most applications, the user will not reset dfnflg directly himself. Note, define will operate correctlu if the Junction is alreadu deJined and broken. aduised. or broken-in. nlambda nospread version of define. i.e., takes an indefinite number of arguments evaluated. Each Xi must be a list, of the form described in define. which are not defineg calls define, so dfnfig affects its operation the same as define. savedef[fn] Saves the definition of tn on its property list under property EXPR, CODE, or SUBR depending on its!n!l2. Value is the property name used. If getd[fn] is non-NIL, but fntyp[fn] is NIL, saves on property name LIST. This situation can arise 8,.7 when a function is redefined which was originally' defined with LAMBDA misspelled or omitted. If l:n- is a list, savedef operates on each function in the list, and its value is a list of the individual values. unsavedef[fn;prop] Res1~ores lis1~ the definition of fn from' its property under Value is ~ property ~. (see savedef above). If nothing saved under J!.!:.Qj!. and fn jls defined, returns (prop NOT FOUND r, otherwise genorates an error, NOT A FUNCTION. If ,~ is not given, i.e. NIL, unsavedef looks undor EXPR, CODE, and SUBR, in that order. value of unsavedef is the property name, The or if nothing is found and fn is a function, the value is (NOTHING FOUND); otherwise generates an error, NOT A FUNCTION. If ,dfnflg=NIL, the current definition of fn. any., is saved using savedef. if Thus one can use I unsilvedef to switch back and forth between two defj,ni tions of the same function, keeping one on its property list and the other in the function deftnition cell. If fn is a list, unsavedef operates on each func:tion of the list, and its value is a list of the individual values. 8.8 eval[x]7 eval evaluates the expression ~ and returns this va lue i . e. eva 1 provides a way of call ing the interpreter. type Note that eval is itself a lambda function, its so argument is the first evaluated, e.g., (ADD1 3» (ADD1 3) ... (EVAL FOO) ~SET(FOO 4 "'EVAL(FOO) (ADD1 3) e[x] nlambda or (EVAL (QUOTE FOO» nospread version of Thus eval. it eliminates the extra pair of parentheses for the list apply[fn;args] of arguments for eval. i.e., eval[x]. Note however equivalent to INTERLISP, the user can type just ! evaluated. (See Section 3.) e x is that in to get ! ~ applies the function fn to the arguments aras. The individual elements of args are not evaluated by fn is simply called with args as its argument list. 8 Thus for the purposes of ~, ~, nlambda's and lambda's are same. However like eval, ~ treated is a the lambda function so its arguments are evaluated before it is called e.g., 7-----------------------------------------------------------------------------eval is a 5ubr 50 that the 'name' ! does not actually appear on the stack. 8 Note that fn itself, as in (APPLY (QUOTE (APPLY (QUOTE (ADD1 3). . may still explicitly evaluate one or more of its arguments the case of setq. Thus SETQ) (QUOTE (FOO (ADD1 3»» will set FOO to 4, whereas SET) (QUOTE (FOO (ADD1 3»» will set FOO to the expression 8.9 ..SET(FOOI 3) 3 ..SET(FOOl 4) 4 .. (APPLY (QUOTE IPLUS) (LIST FOOl FOOl] 7 Here, fool and fo02 were evaluated when the second ~ argument to was evaluated. Compare with: ..SET(FOOl (ADDl Z» (ADDl 2) ..SET(FOOl (SUB1 5» (SUBl 5) .. (APPLY (QUOTE IPLUS) (LIST FOOl FOOZ] NON-NUMERIC ARG (AD01 Z) equi.valent to example, if apply[fnjlist[arg ; ••• ;arg n ]] For 1 fn is the name of a functional argument to be applied to ! and (APPLY* FN X Y), which (APPLY FN (LIST X Y». is Note X. one can write equivalent that to (FN X Y) spe(:ifies a call to the function FN itself. and will cause an error if FN is not defined. Sec1~ion evala[x;a] (See FN will not be evaluated. 16.) Simulates a-list evaluation as in LISP 1.5. ~ is a forl1la, ! is a list of dotted pairs of variable name ! is 'spread' on the stack, and then and value. ~ is evaluated, i.e. t any variables appearing free in ~~, will ~hat be also appears as given the value E![ in of an element of .! the cdr of that elelllent. rpt[rptnjrptf] Evaluates the expression rptf rptntimes. At any POillt. rptn is the number of evaluations yet to 8.10 take place. evaluation. Returns If rptn ~ the value of the last 0, rptf is not evaluated, and the value of rpt is NIL. Note, !21 is a lambda function. so both its arguments are eualuated be/ore ~ is called. For most applications. the user will probablu lDant to use !P.!:.!I. • rptq[rptn;rptf] nlambda version of rpt:' rptn is evaluated, rptf is not, e.g. (RPTQ 10 (READ» to read. arg[var;m] ~ will perform ten calls compiles open. Used to access the individual arguments lambda nospread function. arg function used like .!!! is the name of' the atomic argument list y!.!: to a function, and is not evaluated; and example, following the is an nlambda lambda-nospread mis the desired argument, consider is of a the number of evaluated. definition For of iplus in terms of plus. [LAMBDA X (PROG «M 0) LP (N 0» (COND «EQ N X) (RETURN H») (SETQ N (ADOl N» [SETQ M (PLUS M (ARG X N») (GO LP] The value of arg is undefined for mless than or equal to 0 or greater than the ualue of y!!:. 9 Lower numbered arguments appear earlier in the form, e.g. for (IPLUS A B C), 8.11 arg[X;l]=the value of A, arg[Xi2]cthe value of B, and arg[X;3]=the value of C. Note that the lambda variable should never be reset. However, individual arguments can be reset using setarg described below. setarg[var;m;x] set~ to ~ the mth argument for the lambda nospread fun'ction whose argument considered quoted, mand! list is Y.ill:. Y1!.!: is are evaluated; e.g. in the previous example, (SETARG X (ADD1 N)(HINUS H» would be an example of the set,arg. 8.12 correct form for Index for Section 8 Page Numbers ........................ a-list ADVISED (property name) ALLpROP APPLY[FN;ARGS] SUBR APPLY-[FN;ARG1; ... ;ARGn] SUBRARG[VAR;M] fSUBR ARGLIST[X] · ARGS NOT AVAILABLE (error message) ARGTYPE[FN] SUBR argument list · BAD ARGUMENT - FGETD (error message) BROKEN (property name) · BROKEN-IN (property name) CCODEP[FN] SUBR · CEXPR (function type) CEXPR* (function type) CFEXPR (function type) CFEXPR- (function type) CODE (property name) · ......................................... ............................... . ................................ ................................. . • II •••••••••••••••••••••••••••••• ............ ........................ . ........................ ............................... ··......................... .. ........................ ·........................ . .......................... ........................... DE FIN E[ X] •••••••• '••••••••••••••••••••••••••••••• DEFINEQ[X] NL* OFNFLG (system variable/parameter) .............. E[XEEEE] NL* ·................................ . • ••••• II ••••••••••••••••••••••••••• ................................ . EVAL[X] SUBR · EVALA[X;A] SUBR EXPR (property name) EXPR (function type) EXPR* (function type) · EXPRP[FN] SUBR FEXPR (function type) FEXPR- (function type) FGETD[X] FNTYP[ X] FSUBR (function type) FSUBR- (function type) · FUNARG (function type) function definition and .evaluation function definition cell functional argument · GETD[X] SUBR ILLEGAL ARG - PUTD (~rror message) INCORRECT DEFINING FORM (error message) interpreter LAMBDA LIST (property name) MOVD[FROM;TO;COPYFLG] NARGS[X] NLAMBDA nospread NOT A FUNCTION (error message) (NOT FOUNO) (NOTHING FOUND) PROP[X;Y] PUTD[X;Y] SUBR PUTDQ[X;Y] NL · REDEFINED (typed by system) ··.......................... . ..................... .... . ......................... . ·................................ . " ........................................ ·......................... . ........................ . ............. " ............................. . ·........................... . ..................................... ...................................... ........................................ • ................... 0 ••••••••• ................... ··............................... ...................... ........ . ·................................. . ·................................ . ................................. . ..................... INDEX.8.1 " 8.10 8.7 8.7 8.9 8.10 8.11 8.1,3-4,6 8.6 8.1-5 8.1 8.3 8.7 8.7 8.1,3-5 8.4-5 8.4-5 8.4-5 8.4-5 8.7-8 8.6-7 8.7 8.7-8 8.9 8.9 8.10 8.7-8 8.4-6 8.4-5 8.1,3-6 8.4-5 8.4-5 8.3 8.1,3-7 8.4-6 8.4-6 8.5 8.1-12 8.1-2 8.10 8.1-3,7 8.4 8.7 8.9 8.3,5,8 8.7 8.4 8.1,3-4,6 8.3,5 8.1 8.8 8.8 8.8 8.7 8.1-4 8.4 8.7 Page Numbers RPT[RPTN;RPTF] RPTQ[RPTN;RPTF] NL SAVEDEF[X] " SETARG[VAR;H~X] fSUBR spread SURR (function type) SUBR (property name) SUBR* (function type) 5UBRP[FN] SUBR subrs U (value of ARGLIST) (U V W) (value of ARGLIST) UNSAVEOEF[X;TYP] ... ......... ............. . .... ...................... . ~ ' •• " • • • • • • • 4t • • • • • • • • • • • • • • • UIDEX.8.Z 8.10-11 8.11 8.7-8 8.12 8.1 8.4-6 8.7-8 8.4-6 8.1,3-5 8.1 8.6 8.6 8.8 SECTION 9 THE INTERLISP EDITOR t The INTERLISP editor allows rapid, convenient modification of list structures. "ost often it is used to edit function definitions, (often while the function itself is running) via the function editf, e.g., EDITF(FOO). However, the editor can also be used to edit the value of a variable, via !!!!!y, to edit a property list, via editp, or to edit an arbitrary expression, via~. It is an important feature which allows good on-line interaction in the INTERLISP system. This chapter begins with a lengthy introduction intended for the new user. The reference portion begins on page 9.15. 9~1 Introduction Let us introduce some of the basic,editor commands, and give a flavor for the edi tor's language structure by guiding the reader through a hypothetical editing session. Suppose we are editing the following incorrect definition of append: i-----~---------·------------------------·------------ -----------.-.-----.-.---- The editor was written by and is the responsibility of W. Teitelman. 0.1 (LAMBDA (X) Y (COND «NUL X) Z) (T (CONS (CAR]I (APPEND (CDR X Y] We call the editor via the funct;ion edi tf: "EDITF(APPEND) EDIT * The editor responds by typing EOIT followed bY., which is the editor's prompt character, i.e., it signifies that the editor is ready to accept commands. 2 At any given moment, the editor's attention is centered on some substructure of the expression being edited. This substructure is called the current expre$$ion, and it is what the user sees when he gives the editor the command P, for print. Initially, the c:urrent expression ·is the top level one, i.e., the entire expression being edi t,ed. Thus: .p (LAMBDA (X) Y (COND & &» * Note that the editor prints tho current expression as though pr1ntlevel were set to 2, i.e., sublists of Slliblists are printed as &. The command ? will print the current expression as though printlevel were 1000. *7 (LAMBDA (X) Y (COND «NUL X) Z) (T (CONS (CAR) (APPEND (COR X V»~»~»~ * and the command PP will prettyprint the current expression. 2-------------------~-------------~----------------------------------------~~-- In other words. all lines beginning with • were typed by the user, the rest the editor. by 9.2 A positive integer is interpre,ted by the editor as a cODlDand to descend into the correspondingly numbered element of the current expression. Thus: *2 *p (X) * A negative integer has a similar effect, but counting begins from the end of the current expression and proceeds backward, i.e •• -1 refers to the last element in the current expression, -2 the next to the last, etc. For either positive integer or negative integer, if there 1s no such element, an error occurs,3 the editor types the faulty cODlDand followed by a 1, and then another * The current expre&&ion i& neller changed when a co.and cau&e.s fin error. Thus: *p (X) *2 2 1 *1 *p X • A phrase of the form 'the current expression is changed' or 'the current expression becomes' refers to a shift in the editor's attention, not to a modification of the structure being edited. When the user changes the current expression by descending into 'it, the old current expression is not lost. Instead, the editor actually operates by a~~-----~----------------------------~---------------- ------------------------- 'Editor errors' are not of the flavor described in Section 16. i.e., they never cause breaks or even go through the error machinery but are direct calls to error! indicating that a coaunand is in some way faulty. What happens next depends on the context in which the command was being executed. For example, there are conditional commands which branch on errors. In most situations, though, an error will cause the editor to type the faul ty command followed by a 1 and wait for more input. Note that typing control-E while a cOllUDand is being executed aborts the cOlIIDand exactly as though it had caused an error. 9.3 maintaining a chain of expressions leading to the current one. expression is simply the last link in the chain. The current Descending adds the indicated subexpression onto the end of the chain, thereby making it be the current expression. The command 0 is used to ascend the chain; it removes the last link of the chain. thereby making the preutou8 link be the current expression. Thus: -p X -0 P (X) -0 -1 P (CONO (& Z) (T &») - Note the use of several conunand~» on a single line in the previous output. editor operates in a line buffered mode, the same as evalqt. The Thus no command is actually seen by the editor', or executed, until the line is terminated, either by a carriage return, or a matching right parenthesis. The user can thus use control-A and control-'l! for line-editing edit comands. the same as he does for inputs to evalqt. In our edi ting session, we will make the following corrections to append: delete Y from where it appears, add Y to the end of the argument list,4 change NUL to NUll, change Z to Y, add Z after CAR, and insert a right parenthesis following CDR X. first we will delete Y. By now we have forgotten where we are in the function defini"tion, but we want to be at the ·top· so we use the cormnand· t, which ascends through the entire chain of expressions to the top level expression, 4---T~;~;-~~~-~;;;;~~~~~-~~~id-~;-~~~~~h-~f-;;-~~;-~;;;;~~~~:-~:;::-HOV~-Y-f;~~ its current position to a ne'w position, and 1n fact there is a MOVE command in the edi tor. However, f(Jr the purposes of this introduction, we will confine ourselves to the simpler edit commands. 9.4 which then becomes the current expression, i.8., t re.ov•• all links except the first one. P (LAMBDA (X) Y (COHO 6 6» *t * Note that if we are already at the toP. t has no .ffect, i ••.• it is • NOP • . However, 0 would generate an error. In other words. t •••ns -go to the top,- while 0 means wascend one link.- The basic structure modification commands in the editor are: n (n) ~ 1 deletes the corresponding element from the current expression. (n 8 1 ••• n ,m em) ~ 1 replaces the nth ele.ant in the current expression with (~n 8 1 ••• 8 m) n ,m 1 insertse 1 ••• e. before the nth element in the current expression. ~ Thus: *p (LAMBDA (X) Y (COHO 6 6» *(3) *(2 (X *p V»~ (LAMBDA (X Y) (COHO 6 6» * All structure modification done bU the editor i, de,tructiue. t.e .• the editor uses rplaca and rplacd to phustcaLLu chaR,e the ,tructure it .a, ,tuen. Nota that all three of the above co..ands perfoMD their operation with respect 9.5 to the nth element from the front of the current expressioni the sign of ! is used to specify whether the operation is replacement or insertion. Thus. there is no way to specify deletion or' replacement of the nth element from the end of the current expression, or insertion before the nth element from the end without counting .out that elelmant's position from the front of the list. Similarly. because we cannot specify insertion after a particular element, we cannot attach something at the end of the current expression using the above commands. Instead, we use thEI command N (for !!£2!!£). Thus we could have performed the above changes instead by: *p (LAMBDA (X) Y (COND 6 6» lIr(3) lIrZ (N Y) *p (X Y) lIrt P lIr (LAMBDA (X Y) (CCJND & &» * Now we are ready to change NUL to NULL. Rather than specify the sequence of descent commands necessary to re!ach NUL, and then replace it with NUll, e.g., 3 Z 1 (1 NULL), we will use F. the! find cODlDand, to find NUL: *p (LAMBDA (X Y) (COHD 6 6» *F NUL *p (NUL X) *(1 NULL) *0 p « NULL X) Z) * Note that F is special in that it corresponds to two inputs. In other words, F says to the edt tor, "treat your' next conunand as an expression to be searched for." The search is carried out in printout order in the current expression. If the target expression is not found there, F automatically ascends and searches those portions of the higher expressions that would appear after (in a printout) the current expression. If the search is successful, the new current 9.6 expression will be the structure where the expressi,on was found, 6 and the chain will be the same as one resulting from the appropriate sequence of ascent and descent commands. If the search is not successful, an error occurs, neither the current expression nor the chain is changed: B "P «NULL and X) Z) "F COND P COND ? "P .."«NULL X) Here Z) the search failed to find a £!!!!!! following the current expression, al though of course a cond does appear earlier in the structure. This last example illustrates another facet of the error recovery mechanism: to avoid further confusion when an error occurs, all commands on the line beuond the one which caused the ,error (and all comands that may have been typed ahead while the editor was computing) are forgotten.? We could also have used the R command (for replace) to change NUL to NULL. A command of the form (R e 1 e 2 ) will replace all occurr~nces of e 1 in the current expression by e 2 • There must be at'least one such occurrence or the R command w111 generate an error. Let us use the R command to change all Z'. (even though there is only one) 1n append to Y: 6~----~~~-~~--~-------·------------------------------------~---------.--------- If the search is for an atom, e.g., F NUL, the current expression will be the structure containing the atom. 6 F is never a NOP, i . e., if successful, the current expression after the search will never be the same as the current expression before the search. Thus F expr repeated without intervening commands that change the edit chain can be used to find successive instances of expr. ? i. e. the input burfer is cleared (and saved) (see clearbuf, Section 14). I t can be res tored, and the type-ahead recovered via the co_and SBUFS (alt-mode BUFS). described in Section 22. 9.7 *t (R Z Y) *F Z Z? *PP [LAMBDA (X Y) (COND «NULL X) Y) (T (CONS (CAR) (APPEND (CDR X Y] * The next task is to (CAR) change to (CAR X). We could do this by (R (CAR) (CAR X», or by: *F CAR *(N X) *p (CAR X) * The expression we now want to change is the next expression after the current expression, i.e., we are currently looking at (CAR X) in (CONS (CAR X) (APPEND (COR X -1, We could get to the append expression by typing 0 and then 3 or V»~). or we can use the connand N)I:, which does both operations: *p (CAR X) *NX P (APPEND (CDR X V») * Finally, to change (APPEND (COR X (2 (COR X) V), or (2 (COR X» to (APPEND (COR X) V), we could perform V»~ and (N Y). or 2 and (3), deleting the V, and then o (N V). However, if Y were a complex expression, we would not want to have to retype it. removes Instead, we could IJse a command which effectively -inserts and/or left and right parentheses. There are six of these comMands: BI,BO,LI,LO,RI, and RO, for !!oth in, I!oth 2,ut, left in, left 2,ut, right in, and r.ight .Q.ut. Of course, we will ,always have the same number of left .parentheses as right parentheses, because 1~he parentheses are just a notational guide to 9.8 structure that is provided by our print program. 8 Thus, left in, left out, right in, and right out actually do not insert or remove just one parenthesis, but this is very suggestive of what actually happens. In this case, we would like a right parenthesis to appear following X in (CDR X Y) • Therefore, we use the co_and (RI Z Z), which means insert a' right parentheses after the second element in the second element (of the current expression): *p (APPEND (CDR X V»~ *(RI 2 2) *p (APPEND (CDR X) Y) * We have now finished our editing,and can exit from the editor, to test append, or we could test it while still inside of the editor, by using the E command: *E APPEND«A B) (C 0 E» (A BCD E) * The E command causes, the next input to be given to evalgt. If there is another input following it, as in the above example, the first will be applied (apply) to the second. Otherwise, the input is evaluated (eval). We prettyprint append, and leave the editor. 8-----------------~--~-------------------------------- ------------------------- Herein lies one of the principal advantages of a LISP oriented editor over a text editor: unbalanced parentheses errors are not possible. 9.9 *PP [LAMBDA (X Y) (CONO «NULL X) Y) (C#~R (T (CONS *OK APPEND 9.2 X) (APPEND (CDR X) Y] Commands for the New User As mentioned earlier, the INTERL.ISP manual is intended primarily 8S manual, and and accordingly. the remainder of this chapter is organized a reference presented While the commands. introduced in the previous scenario constitute a complete set, i.e., the user could perform any and all editing operations using just those commands, therel are many situations in which knowing the right command(s) can save the user considerable effort. the We include here as part of introduction a list of those commands which are not only frequently applicable but also easy to us.e. They are not presented in any particular order, and are all discussed in detail in the reference portion of the chapter. UNDO undoes the last modification to the structure being edited, e.g., if the user deletes the wrong element, UNDO will restore it. of should UNDO give the The availability user confidence to experiment with any and all editing coaunands, no matter how complex, because he can always reverse the effect of the command. BK like NX, except makes the expression immediately be/ore the current expression become current. BF ~ackwards find. Like F, except backwards, i.e., 1n inverse print order. 9.10 searches \ Restores the current expression to the expression before the last ·big jump·, e.g., a find command, an t, or another \. For example, if the user types F CONO, and then F CAR, \ would take him back to the CONO. Another \ would take him back to the CAR. \P like \ except it restores the edit chain to its state as of the last print, either by P, 1, or PP. If the edit chain has not been changed since the last print, \P restores it to its state as of the printing before that one, i.e., two chains are always saved. Thus if the user types P followed by 3 2 1 P, \P will take him back to the first P, i.e., would be equivalent to 0 0 O. Another \P would then take him back to the second P. Thus the user can use \P to flip back and forth between two current expressions. The search expression given to the F or BF command need not be a literal S-expression. can be a pattern. Instead, it The symbol Be can be used anywhere within this pattern to ma.tch with any single element of a list, and -- can be used to match with any .segment. of a list. incorr~ct F (NUL Be) definition of append Thus, in the used cou Id have been used to find earlier, (NUL X), and F (CDR _a) or F (CDR Be A), but not F (CDR 6), to find (CDR X V). Note that at and -- can be nested arbitrarily 9.11 ~eeply in the pattern. For example. if there are many plac:es where the variable X is set, F SETQ may not find the desired expression, nor may F (SETQ X &). It may be necessary to use F (SETQ X (LIST --». However, the usual technique in such a case is to pick out a unique atom which occurs F commands. I~rior to the desired expression, and perform two This -homing in- l)rOCeSS seems to be more convenient than ultra- precise specification of the pattern. 5 (alt-mode) $ 1s equivalent to -- at the character level, e.g. VERS will match with VERYLONGATOH t as will SATOM, SLC)NGS. (but not SLONG) and SVSNSMS. $ F ~[SETQ VERS (CONS a of inside ne~'ted can be patt~rn, e.g., --». If the search is successful, the editor will print = :followed by the atom which matched with the $- atom, e.g., -F (SETQ VERS &) =VERYLONGATOH - Frequently the user will want to replace the entire current expression. or insert something before it. In order to do this using a command of the form (n e1 em) or (-n e 1 .•. em)' the user must be above the current expression. In other words, he would have to perform a 0 followed by a conunand with the appropriate number. However, if he has reached the current expression via an F command, he may not know what that number is. In this case, the user would like a command whose effect w()uld be to modify the edit chain so that the current expression became tht! first expression. element in a new, higher current Then he could perform the desired operation via (1 e 1 ••• em) or (-1 e 1 •.• em). UP is provided for this purpose. 9.12 UP after UP operates, the old current expression is the first element of the new current expression. Note that if the current expression happens to be the first element in the next higher expression, then UP is exactly the same as O. Otherwise, UP modifies the edit chain so that the new current expression is a tail9 of the next higher. expression: *F APPEND P (APPEND (CDR X) Y) *Up p .•. (APPEND & V»~ ·0 P (CONS (CAR X) (APPEND & V»~ • The ••• is used by the editor to indicate that the current expression is a tat 1 of the next h1gher expression as opposed to being an element (1 •••• a member) of the next higher expression. Not.: if the current expression is alreadu a tail. UP has no effect. (8 e 1 ••• em) inserts e 1 ••• em before the current expression. i.e., does an UP and then a-I. (A e 1 .•• em) inserts e 1 ••• em after the current expression, i.e., does an UP and then either a (-2 8 1 ••• e.) or an (N e 1 ••• em)' if the current expression is the last one 1n the next higher expression. 9~-----~--------·-------------------------------------------------------------Throughout this chapter 'tail' means 'proper tail' (see Section 5). 9.13 (: 8 reJl,laces current expression by e 1 ••• 8m, i.8., does an UP and then a (1 e 1 ••• em). 1 ••• em) deletes current expression: equivalent to (:). DELETE Earlier. we introduced the RI co_and in the append example. The rest of the conunands in this family: BI, BO" lI, lO, and RO, perform similar functions and are useful in certain situations.. In addition, the commands HBO and XTR can be used to combine the effects of several commands of the BI-BO family. used to embed the current expression in a larger expression. HBO is For example, if the current expression is (PRINT bigexpression), and the user wants to replace it by (CONO (FlG (PRINT bigexpression»), he could accomplish this by (LI 1), (-1 FLG). (LI 1), and (-1 CONO) •. or by a single HBO command, page 9.47. XTR is used to extract an expres,sion from the current expression. For example, extracting the PRINT expression from the above CONO could be accomplished by ( 1), (LO 1), (1). and (LO 1) (.r by a single XTR command. The new user is encouraged to include XTR and MBO in his repertoire as soon as he is familiar with the more basic commands. This ends the introductory material. 9.14 9.3 Attention Changing Commands Commands to the edi tor fall into t~ree classes: commands that change the current expression (i.e., change the edit chain) thereby ·shifting the editor's attention,· commands that modify the structure being edited, and miscellaneous commands, e.g., exiting from the editor. printing. evaluating expressions. etc. Within the context of commands that shift the editor's attention, we can distinguish among (1) those comands whose operation depends only on the structure of the edit chain, e.g., 0, UP, NX; (2) those which depend on the contents of the structure, i.e., commands that search: and (3) those commands which simply restore the edit chain to some previous state, e.g., \, \P. (1) and (Z) can also be thought of a$ local, small steps versus open ended, big jumps. Commands of type (1) are discussed on page 9.15-21. type (2) on page 9.21-34, 9.3.1 UP and type (3) on page 9.34-36. Local Attention-Changing Commands (1) If a P command would cause the editor to type before typing the current expression, i.e. the current expression is a tail of the next higher expression, UP has no effect: otherwise (2) UP modifies the edit chain so that the old current expression (l.e., the one at the time UP was called) is the first element in the new current expression. 10 io------------------~--~----·----------------------·--------------------------If the current expression is the first element in the next higher expression UP simply does a the edit chain. o. Otherwise UP adds the corresponding tail to 9.15 Examples: The current expression in each case is (CONO «NUll X) (RETURN 1. V»~). *1 P CONO ·UP P (CONO (Be Be» z. *-1 P «NUll X) (RETURN V»~ ·UP P «NUll X) (RETURN *up P ... «NUll X) (RETURN 3. V»~ V»~) *F NULL P (NULL X) ·UP P «NULL X) (RETURN *UP P V»~ ... «NULL X) (RETURN V»~) The execution of UP is' straightforward, except in those cases where the current expression appears more than onl:e in the next higher expression. For example, if the current expression is j(A NIL B NIL C NIL) and the user performs 4 followed by UP. the current eXlpression should then be ••• NIL C NIL). UP can determine which tail is the corlrect one because the commands that descend save the last ta i I on an internal editor variable t command is executed, las tail. Thus after the 4 lastail 1s (NIL C NIL). When UP is called, it first determines if the current expression is a tail of the next higher expression. If it is, UP is finished. Otherwise, UP computes memb[current-expression;next-higher-expression] to obtain a tail beginning with the current expression .11 If 1there are no other instances of the current expression in the next higher expression t this tail is the correct one. ii------------------------------------------------------------------------~---- The current expression should alwall$ be either a t'ail or an element of the next higher expression. If it is neither, for example the user has directly (and incorrectly) manipulated the edit chain, UP generates an error. 9.16 Otherwise UP uses lastailto select the correct tail. t2 ~ 1) n (n adds the ~th element of the current expression to the front of the edit chain, thereby making it be the new current expression. by UP. Generates an Sets lastail for use error if the current expression is not a list that contains at least ~ elements. -n (n ~ 1) adds the ~th ele.ment from the end of the current expression to the front of the edit chain, thereby making it be the new current expression. lastail for use by UP. Sets Generates an error if the current expression is not a list that contains at . least o ~ elements. Sets edit chain to cdr of edit chain, thereby making the next higher expression be the new current expression. Generates an error if there is no higher expression, i.e. cdr of edit chain is NIL. Note that 0 usually corresponds to going back to the next higher left 12----------------------------------------------------------------------------Occasionally the user can get the edit chain into a state where lastail cannot resolve the ambiguity, for example if there were two non-atomic structures in the same expression that were g, and the user descended more than one level into one of them and then tri.d to come back out using UP. In this case, UP prints LOCATION UNCERTAIN and generates an error. Of course, we could have solved this problem completely 1n our implementation by saving at each descent both elements and tails. However, this would be a costly solution to a situation that arises infrequently, and when it does. has no detrimental effects. The lastail solution is cheap and resolves 99X of the ambiguities. 9.17 parenthesis, but not always. (A BCD E F B), and the user for example, if the current expression 15 p~trforms: *3 UP P ... C D E F G) *3 UP P ••• E F G) *0 P .•• C 0 E F G) If the intention is to go back to the next higher left parenthesis, regardless of any intervening tails, the c(IDlDand 10 can be used .13 10 dOEIS repeated 0' s until it reaches a point where the current expression is not a tail of the next hl"her expression, i.e .• always goes back to the next higher left parenthesis. t sets edit chain to last of edit chain, thereby malting the top level expression be the current expression. NX Never generates an error. effectively does an UP followed by a 2,14 thereby mak.lng the current eXlllression. expression be the next Generates an error if the current eXlllression is the last one in a list. (However, tNX described below will handle this case.) Bt( makes the current expression be the previou~ i3~~--------------------------------------------------------------------------~ !O is pronounced bang-zero. 14 Both NX and BK operate by performing a ! 0 followed by an appropriate number, i.e. there won't be an extra tail above the new current expression, as there would be if NX operated by performing an UP followed by a 2. 9.18 expression ,in the next higher expression. Generates an error if the current expression 1s the first expression in a list. For example, if the current expression is (CONO «NULL X) (RETURN V»~): *F RETURN P (RETURN Y) *BK P (NULL X) (NX n) n ~ 1 equivalent to !!. NX commands, except if an error occurs, the edit chain is not changed. (BK n) n 2 1 equivalent to !!. Bk commands. except if an error occurs, the edit chain is not changed. Note: !NX (NX -n) is equivalent to (Bk n), and vice versa. makes current expression be the next expression at a higher level, i.e., goes through any number of right' parentheses to get to the next expression. 9.19 for example: frPP (PROG «L L) (UF L» lP (CONO «NULL (SETO L (CDR L») (ERROR!» ([NUll (COR (FHEHB (CAR L) (CADR l] (GO LP») (EOITCOM (QUOTE NX» (SETQ UNFIND UF) (RETURN L» *F COR P (COR L) *NX NX ? *!NX P (ERROR!) *!NX P «NULL &) (GO LP» *!NX P (EDITCOH (QUOTE NX» * !NX operates by doing O's until it reaches a stage where the current expression is not the last expression in the next higher expression, and then does a NX. Thus ! NX always goes through at least one unmatched right parenthesis, and the new current expression is alwaYli on a different level, i.e. , fNX and NX always produce different results. For example using the previous current expression: *F CAR P (CAR L) *!NX P (GO LP) *\P p (CAR L) frNX P (CAOR l) * (NTH n) n I- 0 equivalent to ! followed by UP, i~e.t causes the list starting with the !th element of the current eX~tress ion ( or !!.th from the end 1f 9.20 n < 0) to become the current expression .16 Causes an error if current expression does not have at least !!. elements. A generalized form of NTH using location specifications is described on page 9.3Z. 9.3.2 Commands That Search All of the editor conunands that search uS,e the same pattern matching routine. 16 We will therefore begin our discussion of searching by describing the pattern match mechanism. A pattern pat matches with! if: 1. pat is !! to !. Z. pat is 3. pat is a number and !.9..2 to !. 4. pat is a string and strequal[pat;x] is true. 5. If car[pat] is the atom *ANY*, cdr[pat] is a list of patterns and &. pat matches ! if and only if one of the patterns on cdr[pat] matches x. 6a. If pat is a literal atom or string containing one or more altmodes, each $ can match an indeCini te number (including 0) of contiguous characters in a literal atom or string, e.g. VERS matches both VERYlONGATOH and "VERYLONGSTRING· as do SLONGS (but not SLONG), and SVSLSTS. i6-~--~----~------------------------------------------------------------------~ (NTH 1) is a NOP t as is (NTH -n) where n is the length of the current expression. 16 This routine is available to the user directly, and is described on page 9.88. 9.21 6b. If pat is a liter'al atom or string ending in troo alt-modes, pat matches with the first atom or string that is ·close· to pat. in the sen se used by the spe 11 ing correc tor ( Sec t ion 17). E •g • CONSSSS matches with CONS, CNONCSS with NCONC or NCONC1. The pattern matching routine always types a message of the form =x to inform the user of the object matched by a pattern of type 6a or 6b, 17 e. g. I=VERVLONGATOH. 7. If carr pat] is th4' atom --. pat matches! if a. cdr[pat]=NIL" i.e. pat=(--), e.g. (A _e) matches (A) (A 8 C) and (A . 8) In other words, -- can match any tail of a b. lis~. cdr[pat] matches with some tail of !, e.g. (A (&» will match with (A B C (D», but not (A 8 C D). or (A 8 C (D) E). However, note that (A -- (&) _e) will match with (A B C (D) E). In other words, -- can match any interior segment of a list. 8. If car[pat] is thu atom •• , pat matches! if and only if cdr[pat] is !9. to !.18 9. Otherwise if ! is a list, pat matches! if car[pat] matches car[x]. and cdr[pat] matches cdr[x]. When the edi tor is searching. t;he pattern matching routine is called to match with element.s in the structure,. unless the pattern begins with •••• in which case cdr of the pattern is matched against proper tails in the structure. Thus if the current expression is (A B C (8 C». 17-----------------------------··----------------------------------------------unless editquietflg=T. 18· Pattern 8 is for use by plr"ograms that call the editor as a subroutine, since any non-atomic expres~iion in 8 command tllped in by the user obviously cannot be !!.!l to already eXi!.ting structure. 9.22 *F (8 --) *p (8 C) *0 F ( ••• 8 --) *p , ••• 8 C (8 C» Matching is also attempted with atomic ta1ls (except for NIL). Thus *p (A (8 • C» *F C *p C) Although the current expression is the atom C after the (inal command, it is printed as ... • C) to alert the user to ,the fact that C is a tat I, not an element. Note that the pattern C will match with either instance of C in (A C (8 . C». whereas ( •••• C) will match only the second C. The pattern NIL will only match with NIL as an element, i.e. it will not match in (A I), evan though .cddr of (A B) is NIL. However, ( •••• NIL) (or equivalently ( ••• » may be used to specify a NIL totl, e.g. ( •••• NIL) will match with £sl!: of the third subexpression of «A. B)(C • D) (E». Search Algorithm Searching begins with the current expression and proceeds in print order. Searching usually means find the next instance of this pattern, and consequently a match is not attempted that would leave the edit chain unchanged. 19 At each step, the pattern is matched against the next element in the expression currently being searched, unless the pattern begins with in which case it is matched against the next tail of the expression. 19----------~--------------~----------------------------~---------~-----~------ However, there is a version of the find command which can succeed and leave the current expression unchanged (see page 9.26). 9.23 If the match is not successful, the search operation is recursive first in the car direction and then in the cdr direction, i.e. , if the element under examination is a list, the search descends into that list before attempting to match with other elements (or tlllils) at the same level. 20 However. at no point is the totiill recursive depth of the search (sum of number of cars and cdrs descended int(.) allowed to exceed the value of the variable maxlevel. At that point. the search of that element or tail is abandoned, exactly as though the element or tail had been completely searched without finding a match. and the search continues with the element or tail for which the recursive depth is below maxlevel. This feature is designed to enable the user to search circular list structures (by setting maxlevel small). as well as protecting him from accidentally encountering a circular list structure 1n the course of normal editing. maxlevel is initially set to 300. 21 If . a successful match is not found in the current expression, the search automatically ascends to the ne,ct higher expression,22 and continues searching there on the next expression after the expression it just finished searching. If there is none, it ascends again, etc. This process continues until the entire edit chain has been sear'ched, at which point the search fails, and an error is generated. If the search fails (or, what is equivalent, is aborted by control-E), the edit chain is not changed (nor are any conses performed). If the search is successful, i. e., an expression is found that the pattern 20----------------------------------------------------------------------------There is also a version of the find convnand (see page 9 .27) which only attempts matches at the top level of the current expression, i.e., does not descend into elements, or ascend to higher expressions. 21 maxlevel can also be set to 22 See footnote on page g. 24. I~Il, which is equivalent to infinity. 9.24 matches, the edit chain is set to the value it would have had had the user reached that expression via a sequence of integer commands. If the expression that matched was a list, it will be the final link in the edit chain, i.e., the new current expression. If the expression that matched is not a list, e.g., is an atolD, the current expression will be the tail beginning with that atom,23 i.e., that atom will be the first element in the new current expression. In other words, the search effectively does an Up.24 Search Commands All of the commands below set lastail for use by UP, set un find for use by \ (page 9.35), and do not change the edit chain or perform any conses if they are unsuccessful or aborted. F pattern i.e., two commands: the F informs the editor that the next command pattern. is to be interpreted as a This is the most common and useful fonm of the find command. If successful, the edit chain always changes, i.e., F pattern means find the next instance of pattern. If lDemb[pattern;current-expression] is true, does not proceed with a full recursive search. F If the value of the memb is NIL. F invokes the search algorithm described earlier. 23~--------~---~-~-------------~---~-~-------- ______ M- - - - - - - - - - - - - - - - - - - - - - - - - c~se. the current Unless the atom is a tail, e.g. B in (A • B). In this expression will be B, but will print as •••• B). 24, Un less upfindflg=NIl (initially set to T) • 9.43-44. 9.25 For discussion, see page Thus if the current expression 1s (PROG NIL lP (COND (-- (GO lPl»)) ... LPI ... ), F lPl will find the prog label, not the lPl inside of the GO expression, even though the latter appears first (in print order) in the current expression. Note .that 1 (making the atom PROG be the current expression), followed by F lPl would find the first lPl. (F pattern sante as F pat tern, i. e., finds the !!ext instance N) of pattern, except the memb check of F pattern is not; performed. (F Similar to F pattern, except may succeed without pattern T) chalnging edit chain, and does not perform the memb che'ck. Thus if the current expression is (COND •• ). F COND will look for the next CONO, but (F CONO T) will 'stay here'. (F pattern n) n ~ 1 Finds the Equivalent !!th to (F pattern N) place (F that pattern repeated n-l pattern T) matches. followed times. Each by time pattern successfully matches, !! is decremented by 1. and the search continues, until!!. reaches o. Note that the pattern does not have to match with !!. i.dentical expressions; it just has to match !!. times. Thus if the current expression is (FOOl FOOZ FOO3), (F FOOS 3) will find FOOl. If the pattern does not match successfully ~ times, an error is generated and the edit chain is unchanged (even if the pattern matched n-l times). 9.26 (F pattern) or only matches with elements at the (F pattern NIL) top level of the current expression, search will not descend into i. e. , the the current expression, nor will it go outside of the current expression. "ay succeed without changing edt t chain. For example, if the current expression is (PROG NIL (SETQ X (CONO & &» the SETQ, whereas (F (CONO (CONO 6) ••• ), F CONO will find the COHO inside --» will find the top level CONo, i.8., the second one. (FS pattern 1 ••• pattern n ) equivalent to F pattern t followed by F pattern 2 followed by F pattern n , so that if F patternm fails, edit chain is left at place patternm_1 matched. (F- expression x) equivalent to (F (_. expressioQ) x), i.e., searches for a structure !.!I to expression, see page 9.22. (ORF pattern 1 ••• pattern n ) equivalent to (F (-ANY· pattern 1 ••• pattern n ) H), i.e., searches for an expression that is matched by either pattern 1, pattern 2 , ••• or pattern n • See page 9.21. BF pattern ~ackwards find. Searches in reverse print order, beginning with expression immediately before the current expression (unless the current expression is the top level expression, in which case BF searches the entire expression, in reverse order). 9.27 SF uses the same pattern match routine as F, and maxlevel and upfindflg have the same effect, but the searching begins at the end of each list, and des'cends into each element before attempting to match that element. If unsuccessful, the search continues with the next previous element, etc., until the front of the list is reached, at which point BF ascends and backs up, etc. For example, if the current expression is (PROG NIL (SETQ .X (SETQ Y (LIST Z») (CONO «SETQ W --) --» --), F LIST followed by SF SETQ will leave the current expression as (SETQ Y (LIST Z)), as will F CONO followed by BF SETQ. sealrch always includes current expression, i. e. , (BF pattern T) starts at the end of current expression and works bac:kward, then ascends and backs up, etc. Thus in the previous example, where F CONO followeBF SETQ found (SETQ Y (LIST Z», F CONO follellwed by (BF SETQ T) would find the . (SETQ W --) expression. (BF pattern) (BF pattern NIL) sarne as BF pattern. Location Specification Many of the more sophisticated commands described later in this chapter use a more general method of specifying position called a location specification. A location specification is a Ijtst of edit commands that are executed in the normal fashion with two excepti.ons. First, all commands not recognized by the 9.28 editor are interpreted as though they had been preceded by F.26 For example, the location specification (CONO Z 3) specifies the 3rd element in the first clause of the next COND. 28 Secondly, if an error occurs while evaluating one of the co_ands in the location specification, and the edit chain had been changed. i.e., was not the same as it specification. was at the beginni~g of that execution the location operation· will continue. of the location In other words, the location operation keeps going unless it reaches a state where it detects that it is I looping', at which point it gives up. Thus, if (CONO Z 3) is being located, and the first clause of the next CONO contained only two elements, the execution of the command 3 would cause an error. The search would then continue by looking for the next CONO. However, if a point were reached where there were no further COHOs, then the first command, COHO, would cause the error; the edit chain would not have been changed, and so the entire location operation would fail, and cause an error. The IF conunand in conjunction with the II function provide a way of using arbitrary predicates applied to elements in the current expression. will be described 1n detail later in the chapter, along with IF and II examples illustrating their use in location speCifications. Throughout this chapter, specification. the meta-symbol , is used to denote a location Thus' is a list of commands interpreted as described above. , can also be atomic, in which case it is interpreted as list[@]. 26----------------------------------------------------------------------------Normally such commands would cause errors. 26 Note that the user could always write F COHO followed by 2 and 3 for (COHO Z 3) if he were not sure whether or not COHO was the name of an atomic command. 9.29 (lC • (f) pr y, e.g. CADR->CAAR. Note that the S feature can be used to delete or add characters, as well as replace them. For example, (R $1 $) will delete the terminating l's from,all Similarly, if an alt-mode in ! does not have a mate literal atoms and strings. in the characters matched by the S are effectively deleted. For example, (R $1$ $) will change AND/OR to ANO. 66 l can also be a list containing ~, alt-modes, e.g. (R 11 (CAR I>:~ will change FOOl to (CAR FOO), FIE1 to (CAR FIE). If ! does not contain alt-modes, , 83 - - i; -;-;; ;~~~; -;-~~~i~~: not- matter appearing in I -; - whether refers to the entire ;h;; -i; -~;;; ~ ~j.-li-~~- -r-;p-l-a~-e-d- -b-;-; -;;;;;; ~ - -;;;;; ! or l themselves are strings, and (R "SOS" "SAS·) equivalent. Note also thillt x will never match with a number, (R S1 SZ) will not change 11 to-12. (R SOS SAS), (R "SOS" SAS), (R SDS "SAS"), i.e. are i.e. 64 Note that CAOOR was not changed to CAAAR, i.e. (R SDS SAS) does not mean replace every D with A, but replace the first 0 in every atom or string by A. If the user wanted to replace every 0 by A, he could perform (LP (R SOS SAS». 66 However, there is no similar operation for changing ANDIOR to OR, since the first $ in l always corresponds to the first I in !, the second I in ~ to the second 1n !, etc. 9.58 expression matched by!. e.g. (R LONGATOH 'S) changes LONGATOH to 'lONGATOM, (R (SETQ X &) (PRINT S» changes every (SETQ X &) to (PRINT (SETQ X &».88 Since (R $x! $y$) is a frequently used operation for replacing ~haracters, the following command is provided: CRC x equivalent to y) Rand RC change all instances of ! to l. (R $xI $y$) The commands Rl and Ret are available for changing just one, (i.e. the first) instance of ! to l. (Rt x y) find the first instance of ! and replace it by (Rei x y) (Rl IxI Iy$). ~. In addition. while Rand RC only operate within the current expression, Rt and RCt will continue searching, a la the F command, until they find an instance of !, even if the search carries them beyond the current expression. switches the nth and mth elements of the current (SW n m) expression. for example, if the current expression is (LIST (CONS (CAR X) (CAR V»~ (CONS (CDR X) (CDR V»~), (CONS (CAR X) (CAR V»~). (SW 2 3) will modify it to be (LIST (CONS (COR X) (COR and m is V»~ The relative order of !!. not important, i.e., (SW 3 2) and (SW Z 3) are equivalent. 66---~--------------------------------------------------~---------------------If x is a pattern containing an alt-mode pattern somewhere within it, the characters matched by the alt-modes are not available. and for the purposes of replacement, the effect is the same as though x did not contain any altmodes. For example, if the user types (R (CAR FS) (PRINT S», the second I will refer to the entire expression matched by (CAR FS). 9.59 SW' ~th uses the generalized NTH conunand to find the and mth elements, a la the DI-DO commands. Thus in the previous example, (SW CAR CDR) would produce the same result. Commands That Print 9.5 PP prettyprints the current expression. P prints the current expression as though printlevel were set to 2. (P m) prints mth element of current expression as though ~lntlevel (P 0) (P SalDe m n) were set to 2. as P pr:lnts mth element of current expression as though ID[lntlevel were set to ft. prints current expression as though pr1ntlevel (P 0 n) we."e set to !!. ? Both sBllle (P m) and (P m n) use as (P 0 100) the generalized NTH command to obtain the corresponding element, so that !! does not have to be a number, e.g. (P COHD 3) will work. PP causes all comllu!nts to be printed as 9.60 --COMMENT-- (see Section P and ?print as .-COMMENT-. only those comments that are (top level) elements of the current expression. 81 14) . PP* prettyprints current expression, including comments. PP* is equivalent to PP except that it first reset~ .*comment*·flg to NIL (see Section 14). In fact, it is defined as (KESETVAR *-COMMENT**FLG NIL PP), see page 9.77. PPV prettyprints current expression as a variable, i.e. no special treatment for LAMBDA, CONO, SETQ, etc., or for CLISP. PPT prettyprints current expression, printing eLISP translations, if any. a~----------------------------------------------------------------------------Lower expressions are not really seen by the editor; the printing command simply sets printlevel .n~ calls print. 9.61 9.6 Commands That Evaluate E o1;,ill "he" tllped in,68 causes the editor to call li.spx giving it the next input as argument. B9 Example: *E BREAK(FIE FUM) (FIE FUM) *E (FOO) (FIE BROKEN) (E x) evaluates !. i.e.. performs eval[x]. and prints the result on the teletype. (E x T) The (E x) s~me as (E .x) but does not print. and (E x T) commands are mainly intended for use by macros and subroutine calls to the editor'; the user would probably type in a form for evaluation using the more convenient format of the (atomic) E cODlDand .• Example: (I 3 (GETD (QUOTE Foo») will replace the 3rd element of the current expression with the definition or roo. 70 (I N Foo (CAR FIE» will attach the 69 1 ispx is used by evalqt Bind break for processing teletype inputs. If nothing else is typed on the same line, lispx evaluates its argument. Otherwise, lispx applies it to the next input. In both cases, lispx prints the result. See above example, and Sections 2 and 22. 70 The I command sets an internal flag to indicate to the structure modi fica tion cODlDands not tell copy expression( s) when inserting, replacing, or attaching. 9.62 value of foo and £!r of the value of fie to' the end of the current expression. (I F= FOO T) will search for an expression ~ to the value of foo. If £ is not an atom, £ is evalu~ted also. FOO), if !.!a is NIL, Example: ,(I (CONO «NULL FLG) (QUOTE -1» (T-1» the value of foo before the first of .the current expression, otherwise el~ment ~nserts replaces the first element by the value of foo. is an NLAHBDA. NOSPREAD function (not a command). Its value is what the current expression would be after executing the edit commands com! ••• comn starti~g from the present edit chain. Generates an error if any of com 1 thru comn cause errors. The current edit chain is never changed.?1 Ex~mple: (I R(QUOTE X) (II (CONS •• Z») expression by the first The I ~ replaces all XiS in the current containing a Z. command is not very convenient for computing an entire edit command for execution. since it computes the comand name and its arguments separately. Also, the I command cannot be used to compute an atomic commande, The following two commands provide more general ways of computing commands. (COMS Xl ••• "n) Each Xi is evaluated and its value is executed as a cODlDand. 7i----------~~-----~---~---------------------------·-- ---------~--------------- Recall that A, 0, :, INSERT, REPLACE, and CHANGE mate special checks for I I forms in the expressions used for inserting or replacing, and use a copy of II form instead (see page 9.43). Thus, (INSERT (II 3 2) AFTER 1) is equivalent to (I INSERT (COPY (II 3 2» (QUOTE AFTER) 1). 9.63 For example, (COMS (CONO (X (LIST 1 X»» will replace the first element of the current expression with the value of ! if non-NIL, otherwise do nothing.?2 executes com •••• comn " is mainly useful in conjunction with the COMS command. COHSQ For example, suppose the user wishes to comlllUte an entire list of comands for evaluation, as opposed to computing each c,olIIDand one at 8 time as does' the COPIS cOlIIDand. He would then write (COMS (CONS (QUOTE COMSQ) x» commands" 9.7 e.g •• (COMS (CONS (QUI)TE COMSQ) (GETP FOO (QUOTE COMMANDS»».'" Conunands That Test generates an error unless the value of eval[x] is (IF x) true, i.e., if eval[x] eval[x]=NIl, IF will For where x computed the list of some editor' commands, ~ause causes an error or an error. the occurrence of an error has a well defined mean ing, i. e ., they use errors example, an error condition in 1;0 8 branch on, as cond uses NIL and non-NIL. For location specification may simply mean -not this one, try the next.- Thus the location specification (IPlUS (E (OR (NUHBERP (II 3» second argument is a number. provides (ERRORI» T» specifies the first IPlUS whose The IF comand, by equating NIL to error ~ a more natural way of accomplishing the same result. equivalent location specification is (IPLUS (IF (NUMBERP (II 3»». 9.64 Thus, an The IF command can also be used to select between two alternate lists of commands for execution. (IF x coms 1 coms Z) If eval[x] is true, execute coms 1 ; if eval[x] causes an error or is equal to' NIL, execute coms ·73 z for example, the command (IF (READP T) NIL (P» will print the current expression provided the input buffer is empty. IF can also be written as: (IF x coms t ) if eval[xl' is true, execute coms t ; otherwise generate an error. (LP • coms) repeatedly executes ~, a list of commands, until an error occurs. For example, (lP F PRINT (N T» expression. will attach a T at the end of every print (lP F PRINT (IF (II 3) NIL «N T»» will attach a T at the end of each print expression which does not already have a second argument. 14 When an error occurs. lP prints n OCCURRENCES. 73----~-~--~--~-------------------------------------~---------------~---------- Thus IF is equivalent to (COMS (CONS (QUOTE COHSQ) (COND ( (CAR (NlSETQ (EVAl X») COMS!) (T COMSZ»». 74 i. e . the form (II 3) wi 11 cause an error if the edit conunand 3 causes an error, thereby selecting «N T» as the list of ,commands to be executed. The IF could also be written as (IF (CDDR (II» NIL «N T»). 9.65 whElre n is the number successfully executed. of times The edit chain is left of the last complete successful execution of (lPQ . coms) SaDie as LP but was ~ does not print the a~ ~. message n C-CCURRENCES. In order to prevent non-terminating loops, both lP and lPQ terminate when the number of iterations reaches m1Clxloop , initially set to 30. 76 , Since the .ed;1t chain 15 left as of the last successful completion of the loop, the user can simply continue the LP cODlDand ",ith REDO (Section ZZ). (SHOW • x) ! 1,5 a list of patterns. all instances of the SHOW does a LPQ printing indicated e.Ql. (SHOW FOO (SETQ FIE 6» andl all (SETQ FIE 6)' s. expression(s), will print all FOO's Generates an error if there aren't any instances of the expression(s). (EXAM • x) lik.e SHOW except calls the editor recursively (via the TTY: cODlDand described on page 9.70) on each instance of the indicated espressfon( s) so that the user can examine and/or change them. (ORR coms l .•• comsnl begins by executing coms l , a list of, commands. If no error occurs, ORR is finished. Otherwise, ORR ORR restores the edit chain to its original value, and continues by executing coms Z ' etc. If none of the cODlDand lists execute without errors, i.e., 9.66 the ORR -drops off the end-, ORR generates an error. Otherwise, the edit chain is left as of the completion. of the first cOPlDand list which executes without an error. 76 For example, (ORR (NX) (!NX) NIL) will perform a NX, if possible, otherwise a !NX, if possible, otherwise do nothing. (ORR (UP (1» 9.8 (BK UP (2» Si.ilarly, DELETE could be written as (UP (: NIL»). Macros Many of the more sophisticated branching commands in the editor, such as ORR, IF, etc., are most often used in tonjunction with edit macros. The macro feature permits the user to define new commands and thereby expand the editor's repertoire. 77 Macros are defined by using the'" command., (M c • coms) For £ an atom, M defines £ as an atomic command. 78 Executing £ is then the same as executing the list of commands £2m!. For example, (M BP BK UP P) will define BP as an atomic command which does three things. a BK, and UP. and a P. "acros can use commands defined by macros 76 - - ~ i~ --;; --~ --~;;.;;~~- -;;;;- -i-; --p-e-r-f~~-t-I-y- --l~~~-{,-- ~~d- -~~i i--;i~;;; -- ;;;~~~; successfully. Thus, making the last 'argument' to ORR be NIL will insure that the ORR never causes an error. Any other atoll is treated as (atom) t i.e., the above example could be written as (OR NX !NX NIL). 77 However built in commands always take precedence over macros, i.e. t editor's repertoire can be expanded. but not redefined. 78 If a macro is redefined, its new definition replaces its old. g.67 the as well as built in conunands in their definitions. For example, suppose Z is defined by (M l -1 (IF (READP 'f) NIL (P»), does a -1, and then if nothing has been typed, P. a i.e. l Now we zz define can by (M II -1 l), and ZZZ by (M III -1 -1 Z) or (" Zll -1 ll). Macros can also define list commands, i.e., commands that take arguments. (M (c) (arg t ••• argn ) • coms) ~ an atom. "defines ~ as a list command. EXEtcuting (c e 1 ••• en) is then performed by substituting thr'oughout For example, we could define e1 £Q!!!!, for arg l , ... en for argn and then executing £Q!!!!. more general BP by (M (BP) (N) (BK N) UP P). ill Thus. (BP 3) would perform (BK 31), followed by an UP, followed by a P. A list command can be defined via a macro so as to take a fixed or indefinite number of 'arguments', as with spread vs. nospread functions. The form given above specified a macro with a fixed number of arguments, as indicated by its argument list. If the 'argunlant list' is atomic, the command takes an indefinite number of argumants.?~ (M (c) arg . coms) ~, arg both atoms, defines (c e 1 substituting (e 1 Executing command. for executing For example, the command 2ND, arg ~ as a list cOlIIDand. en) is en) , i.e. , throughout performed by of the cdr £Q!!!, and then ~. page 9.30. ( " ( 2ND) X (ORR « lC • X) (LC • X»». 9.68 can be defined as a macro by Note that for all editor commands, 'built in' conunands as well as commands defined by macros, independent. atomic definitions and list definitions are completelu In other words, the existence of an atomic definition for £ in no way affects the treatment of £ when it appears as £!r of a list command, and the existence of a list definition for £ in no way affects the treatment of £ when it appears as an atom. In particular, £ can be used as the name of either an atomic command, or a list command, or both. In the latter case, two entirely different definitions can be used. Note also that once £ is defined as an atomic command via a macro definition, it will not be searched for when used in a location specification,. unless it is preceded by an F. Thus (INSERT -- BEFORE BP) would not search for BP, but ins tead perform a BK. and UP, and a P, and then do the insertion. The corresponding also holds true for list commands. Occasionally. the user will want to employ the S command in a some temporary result. (H (SW) mac~o to save For example, the SW command could be defined as: (S (I 1 FOO) (N H) (NTH N) FOO 1) HARK 0 (NTH M) ~ (I 1 FIE» (S FIE 1) 80 Since this version of SW sets foo and fie, using SW may have undesirable side effects, especially when the editor was called from deep in a computation, we would have to be careful to make up unique names for dummy variables used in edi t macros, which is bothersome. Furthermore, it would be impossible to define a command that called itself recursively while setting free variables. The BIND command solves both problems. 80----------------------------------------------------------------------------A more elegant definition would be: (SW) (N H) (NTH N) HARK 0 (NTH H) (S FIE 1) (I 1 (II .. 1» ..... < I 1 FIE», but this would still use one free variable. (H 9.69 (BIND . coms) b1.nds three dummy variables 11, 12, 13, (1ni tialized to NIL), and then executes the edit cOlIIDands £Q.!!!!. Note that these bindings are only in effect while the commands are being executed, and that BIND can be used recursively; it will rebind '1, 12, and '3 each time it is invoked. 81 Thus we could now write SW safely as: (M (SW (N M) (BIND (NTH N) (5 '1 1) HARK 0 (NTH H) (5 12 1) (I 1 11) ~ (I 1 12»». User macros are stored on a lisit usermacros. The prettydef command USERHACROS (Section 14), is available for dumping all or selected user macros. 9.9 NIL Miscellaneous Commands unless preceded by F or 8F, is always a NOP. Thus extra right parentheses or square brackets at the ends of commands are ignored. TTY: calls the editor recursively. The user can then tYJ,e in commands, and have them executed. The TT": comand is completed when the user exits from thet lower editor. The TTY: conunand is extremely u~.eful. (see OK and STOP below). It enables. the user to set up a complex operation, and perform interactive attention-changing commands part way through 8i-~~------------------------------------------------- ------------------------- BIND is implemented by (PltOG (II 12 13) (EOITCOMS (COR COM») where com corresponds to the BIND command, and editcoms 15 an internal editor function which executes a list of comands. 9.70 For example the command (MOVE 3 TO AFTER CONO 3 P TTY:) allows the user to it. interact, in effect, within the MOVE command. Thus he can verify for himself that the correct location has been found, or complete the specification ·by hand. It In effect, TTY: says • I 'Ii tell you what you should do when you get there.· The TTY: command operates by printing TTY: and then calling the editor. The initial edit chain in the lower editor is the one that existed in the higher editor at the time the TTY: command was entered. Until the user exits from the lower editor, any attention changing commands he executes only affect the lower editor's edit chain. 82 When the TTY: command finishes, the lower editor's edit chain becomes the edit chain of the higher editor. OK exits from the editor STOP exits from the editor with an error. Mainly for use in conjunction with TTY: co_ands that the user wants to abort. Since all of the commands in the editor are errorset protected, the user must exit from the editor via a command. 83 STOP provides a way of distinguishing between a successful and unsuccessful (from the user's standpoint) ed'iting session. For example, if the user, is executing (MOVE 3 TO AFTER COHD TTY:), and he exits from the lower editor with an OK, the HOVE cOlIIDand will then 82-~--~-------------·--------~------------------------ ------------------------- Of course, if the user performs any structure modification commands while under a TTY: conunand, these will modify the structure in both editors, since it is the same structure. 83 Or by typing a control-D. STOP is preferred even if the user is editing at the evalgt level, as it will perform the necessary 'wrapup' to insure that the changes made while editing will be undoable (see Section 22). 9.71 complete its operation. If the user wants to abort the MOVE command, he must make the TTY: command generat'B an error. lower editor with a STOP command. He does this by exiting from the In this case, the higher editor's edit chain will not be changed by the TTY: command. SAVE exits from the editor and saves the 'state of the edi t I on the property list of the function or variable being edited under property the EDIT-SAVE. If the editor is called again on the same structure, ·continued,· i.e., the editing is the edit chain, effectively mark list, value of un find and undolst are restored. For example: *p (NUll X) *F COND P (COND (& &) (T *SAVE FOO &» . "'EOITF(FOO) EDIT *p (COND (& &) (T &:~) *\ p (NUll X) * SAVE is necessary only if the user is editing many different expressions; an exit from the editor via OK alwlsys saves the state of the edit of that call to the editor. 84 Whenever the editctr is entered, it checks to see if it is editing the same expression as the last one edited. In this case, it restores the mark 84-------~----------~------------·--------------------------------------------~ on the property list of the atom EDIT, under the property name lASTVALUE. also remprops EDIT-SAVE frOID the property list of the function or variable being edited. OK 9.72 list, the undolst, and sets un find to bl the edit chain as of the previous exit from the editor. For example: "EDITF(FOO) EDIT *p (LAMBDA (X) (PROG6 6 lP • • • 6» ~P (COND 6 Be) *OK FOO any nu.olr of lispx inputs except for calls to the editor . "EOITF(FOO) EDIT *p (LAMBDA (X) (PROG Be • lP 6 •• 6» *\ p (COND '" * &) Furthermore, as a result of the history f.ature (section 22), if the editor 1s called on the same express~on within a certain nuaber of lispx inputs,86 the stata of the edit of that expression is restored, regardless of how •• ny other expressions .ay have been edited in the •• anti.,. 86-~---~~--~-~------------------------------~-----·~-------------------~------- Namely, the size of the history list. initially 30, but it can be increased the user. by 9.73 for example: "EDITF(FOO) EDIT • •p (COND (3& 3&) (6 3&) ( 3& ) (T 6» ·OK FOO . less than 30 lispx input,. including editing . "EDITF(FOO) EDIT .\ P (COND (Be Be) (3& Be) (Be) (1 Be» • Thus the user can always contJlnue editing,' including undoing changes from a previous editing session, if (1) No other expressions have been edited since that seS5ion;86 or (2) That session was (3) It was ended with a SAVE cOllllland. ~sufficientIY' • RAISE recent; or • • is an edit macro (I 1 (U-CASE (II derine~ as UP followed by 1»), i. e • it raises to upper- case the current expression, or if a tail, the first element of the current expression. LOWER Similar to RAISE, except uses I-case. 86------------------------------·----------------------------------------------Since saving takes place at ext t time, intervening calls that were abo ....'ted via control-D or eXited via . STOP will not afrect the editor' s memory of this last session. 9.74 First does a RAISE. and then lowers all but the CAP first character. i.e. the first character 1s left capitalized. Note: RAISE, LOWEll. and CAP .re all NOPs if the corresponding atom or string t& alreadu in that state. (RAISE equivalent x) to (I R (L-CASE x) x), i.e. changes every lower-case x to upper-case in the current expression. (LOWER similar to RAISE, x) CASE except performs (I R x (L- x». Note in both (RAISE x) and (LOWER x), ! is typed in in upper case. REPACK Permits the 'editing' of an atom or string. For example: *p -THIS IS A LOGN STRING-) REPACK *EOIT P (T HIS X I S X A X LOG N % S T R 1 N G) Jr(SW G N) *OK 87 -THIS IS A LONG STRINGl1li REPACK operates by calling the editor recursively on unpack of the current i~------------------~---------------------------------------------------------Note that this could also have been accomplished by (R SGNS SNGS) or s1mply (RC GN HG). 9.75 expression, or if it is a list, on unpack of its first element. If the lower editor is exited successfully, i.e. via OK as opposed to STOP, the list of atoms is made into a single atom or string, which replaces the atom or string being 'repacked.' The new atom or string is always printed. (REPACK @) (LC does ') followed by e.g. REPACK, (REPACK THISS). (; • x) ! is the text of a comment. ; ascends the edit chl!in looking for a •safe' place to insert the cOIJwent, e. g. • in a cond clause. after a I!.!:2.S stlstement, etc., and inserts (* • po:Lnt, if possible, eX«UDple, if (FACT (SUB1 N)) the otherwise current alter that x) before. For expression is in [COND ( (ZEROP N) 1) (T (ITIHES N (FACT (SUBI N] (; CALL FACT RECURSIVELY) would insert (* CALL FACT RECURSIVELY) be/ore the itimes eX~lression. 88 ; does not change the edit chain, but unfind is set to where the comment was actually inserted. JOINe is used to join two neighboring COND's together, e.g. (CONO clause l clause Z) followed by 88----------------------------------------------------------------------------If inserted after the i tirr!!.!,. the comment would then be (incorrectly) retu.rned as t. he value of the cond. However. if the cond was itself a 2!:QD. statement, and hence its value was not being used, the comment coula-bi (and would be) inserted after the itimes expression. 9.76 (CONO clause 3 clause 4 ) becomes (CONO clause l clauseZ clause 3 clause 4 ). JOINC does an (F CONO T) first so that you don't have to be at the first COND. spli ts one CONO into two. ! specifies the last clause in the first COND, e.g. (SPLITC 3) splits (CONO clause l clause Z clause l clause 4 ) into (CONO clause l clause Z) (CONO clause l clause4 ). Uses generalized NTH command, so that ! does not have ,to be (SPLITC a number, RETU~N). e.g.,the user can say, meaning split after the clause containing RETURN. SPLITC also does an (F COHO T) first. CL Clispifies current expression. See Section 23. ow Owimifies current expression. See Section 17 and 23. (RESETVAR var for. • coms) executes ~ while Y!r is reset to the value of form, and then restores !!!., i •e • effect 1ve ly calls the function resetvar (Section 5). 9.77 9.10 UNDO Each conunand that causes struc1~ure modification automatically adds an entry to the front of undolst that contains the information required to restore all pointers that were changed by that command. UNDO undoes the modification last, i.e. cODlDand most that recent, has not structure yet been undone,89 and prints the name of that command, e.!~., "SO UNDONE. The edit chain is then exactlll Whist it was before the·' undone' coaunand had been pelr-formed. 90 If there are no cODlDands to undo, UNI)O types NOTHING SAVED. I UNDO undoes all modifications performed during this edjLting session, i.e. this call to the editor. As each command is undone, its name is printed a la UNDO. If there is nothing to be undone, IUNDO pr:l.nts NOTHING SAVED. 89----------------------------------------------------------------------------Since UNDO and 'UNDO cause structure modification, they also add an entry to undolst. However, UNDO ~nd !UNDO entries are skipped by UNDO, e.g., if the user performs an INSERT, and then an MBD, the first UNDO will undo the MBD, and the second will undo the INSERT. However, the user can also specify precisely which cflmmands he wants undone by identifying the. corresponding entry on the history list as described in Section 22. In this case, he can undo an UNDO command, e.g. by typing UNDO UNDO, or undo a !UNDO command, or undo a command other than that most recently performed. 90 Undoing an event containing an I. E. or S command will also undo the side effects of the evaluation(s), e.g. undoing (I 3 (/NCONC FOa FIE» will not only restore the 3rd element but also restore FOO. Similarly, undoing an B command will undo the set. See discussion of UNDO in Section 22. (Note that if the I command was typed directly to the editor, INCONC would automatically be substituted for NCONC as described in Bection 22.) 9.78 Whenever the user conttnue$ an editing session 8S described on page 9.12-14, the undo information of the previous session is protected by inserting a special blip, called an undo-block, on the front of undolst. This undo-block will terminate the operation of a IUNDO, thereby confining its effect to the current session, will si.ilarly prevent an UNDO command from operating on ~nd cOmMands executed in the ,revious session. Thus, if executes the user enters the editor continuing a session, and immediately an UNDO or IUNDO, the editor will type BLOCKED instead of NOTHING SAVED. Si.ilarly, if the user executes several cormnands and then undoes them all, another UNDO or IUNDO will also cause BLOCKED to be typed. UNBLOCK re.oves an undo-block. blocked state, i.e. If executed at if UNDO or IUNDO a non- could operate, types NOT BLOCKED. TEST adds an undo-block at the front of undolst. Note that TEST together with fUNDO provide a 'tentative' mode for editing, i.e. the user can perfor. a number of changes, and then undo all of thelll with a Single !UNDO command. 9.79 Editdefault 9.11 Whenever a command is not recol}nized, i.e.; is not "built' in' or defined as a macro, the editor calls an in1;ernal function, editdefault,,"t'o'-determine what action to take. 91 If a location specification is being \ executed, an 'internal flag informs edi tderault to treat the command as though it bad 'bean'prec'eded by an F. If the command is a list, an attempt is made to perform spelling correction on car of the command 92 using editcomsl,: a list of' all !ist edit corntnand~. 93 If spelling correction is successful,94 the correct coimnand name is' 'rplacaed into the command. and the editor In other words, if the user types continues (lP F ~RINT by executing the command. (HBBD AND (NUll FlG»)), only one spelling correction will be necessary to change HBBD to MBD. If spelling correction is not successful, an error is generated. If the command is atomic, the pl~ocedure followed is a little more elaborate. 9j------------------------------·----------------------------------------------Since ed i tdefau 1 t is part of the edit block. the user cannot advise or redefine it as a means of alJlgmenting or extending the editor. However, the user can accomplish this via edituserfn. If the value of the variable edituserfn is T, editdefault calls the function edituserfn giving it the command as an argument. If edituserfn returns a non-NIL value, its value 1s interpreted as a singlEt command and executed. Otherwise, the error correction procedure described below is performed. 92 unless dwimflg:NIl. See Sect.1on 17 for discussion of spelling correction. 93 When a macro is defined vi.. the H conunand, the command name is added to edi tcomsa or editcomsl. depending on whether it is an atomic or list command. The prettydef cO~land USERHACROS (Section 14), is aware of this, and provides for restoring !ditcomsa and editcomsl. . 94 Throughout this discussion. if the command was not typed in directly, the user will be asked to approve the spelling correction. See Section 17. 9.80 1) If the command is one of the list commands, i.e., a member of editcomsl, and there is additional input on the same teletype line. treat the entire line as a single list command. 96 Thus, the user may omit parentheses for any list command typed in at the top level (provided the command 1s not also an atomic command, e.g. NX, BK). For example, *p (COND (& &) (T &» *XTR 3 Z] ·HOVE TO AFTER lP * If the command is on the list editcomsl but no additional input 1s on the teletype line, an erro~ is generated, e.g • •p (COND (& &) (T &» *MOVE MOVE? • If the command is on editcomsl, and not typed in directly, e.g. it appears as one of the commands in a lP command, the procedure is similar. with the rest of the command stream at that level, being treated as "the teletype line", e.g. (lP F (COND (T &» Z) XTR 2 2).98 If the command was typed in and the first character in the command is an 8, 96----------------------------------------------------------------------------The line is read using readline (Section 14). Thus the line can be terminated by a square bracket, or by a carriage return not preceded by a space. 96 Note that if the command is being executed in location context, editdefault does not get this far, e.g. (HOVE TO AFTER COND XTR 3) will search for XTR, not execute tt. However, (HOVE TO AFTER COND (XTR 3» wll1 work. 9.81 treat the 8 as a mistyped left parenthesis, and and the rest of the line as the arguments to the command, e.g., -p (COND (& Be) (T 8:» -8-2 (Y (RETURN Z») =(-2 -p (COND (Y Be) (Be Be) (T Be» 3) I f the command was typed il1l, is the name of a function. arid is followed by NIL or a list £!r of which is not an edit command, assume the user forgot to type E and means to apply the function to its arguments, type -E and the function name, and perform the indicated computation, e.g. -BREAk(FOO) =E BREAK (FOO) • 4) If the last character in the cODlDand is P, and the first n-l characters comprise a number, assume that the user intended two cODlDands, e.g., -p (COND (& 8r) (T 8r Jt ) -OP =0 P (5ETO X (COND Be &» 5) Attempt spelling correction using editcomsa, and if successful,97 execute the corrected command. 6) Otherwise, if there is additional input on the same line, or cODlDand stream, spelling correct using editcomsl, e.g., ~~--;;;-;;;;;;;;-;;-;;;;-;:;;:------------------------------------------------- 9.82 *HBBO SETQ X =HBD .. 7) Otherwise, generate an error. 9.12 Editor Functions edite[expr;coms;atm] edits an expression. Its value is element of editl[list[expr]:coms;atm]. the last Generates an error if expris not a list. editl[l;coms;atm:mess] edIt1 98 i$ the edItor. Its first argum~nt is the edit chain, and its value is an edit chatn, namely gg the value of ! at the time editl is exited. ~ is an optional list of commands. for interactive editing, coms is NIL. In this case, editl types EDIT and then waits for input from teletype. tOO Exit occurs only via an OK, STOP, or SAVE cOlIIDand. If £em! is not NIL, no message is typed, and each 98----------------------------------------------------------------------------edit-e", not edit-one. 99 ! is a specvar, and so can be examined or set by edit conunands. for example, t is equivalent to (E (5ETO l (LAST L» T). However, the user should only manipulate or examine I directly as a last resort, and then with caution. - NIL, editl types it instead of EDIT. For example, the TTY: command is essentially (SETQ l (EDITl l NIL NIL (QUOTE TTY:»). 100 If mess is not 9.83 mmnber of £!!!!!!. e"ecuted. is treated as a command and If an error occurs in the execution of one of the commands, no error message is printed, the rest of the commands are ignored, and e'ditl e)tits with an error, i.e. the effect is the same a!; though a STOP command had been executed. If all comands execute successfully, editl returns' the current value of at,!! is optional. !. On calls from edi tf, it is the ' name of the function being edited; on calls from editv, the name of the var'iable, and calls from ed!!2, the atom whose edited. property list is being The property list of atm is used by the SAVE command for saving the state of the edt t. Thus SAVE 'will not save anything if !!!!!=NIL, 1.e. wh'sn editing arbitrary expressions via edi te or editl directly. editIO[l,coms;messieditlflg].fO.f like editl except does not rebind or initialize the editor's various state variables, such as lastail, unfind, undolst, marklst, etc. editf[x] nli~bda. car[x] nospread function for editing a function. is the name of the opt;ional list of cODUDands. function,cdr[x] For the' rest of 'the dislcussion, fn is car[x], and £!!!!.! is cdr[x]. The value of editf is fn. 9.84 an (1) In the most common case, fn is an expr, and !.!!!!!. simply ,performs putd[fn;edite[getd[fn];coms.fn]]. (2) If fn is not an expr, but has an EXPR property, edi tf prints PROP, and performs edite[getp[fn;EXPR];coms:fn]. If edite returns (i.e. if the editing is not terminated by a STOP), and some changes were made, editf performs unsavedef[fn], prints UNSAVED, and then does putd[fn;value-ofedite]. (3) If fn is neither an expr nor has an EXPR property, but its top level value is a list, editf assumes the user meant to call editv, prints =EDITV, calls edi tv and returns. Similarly, if fn has a non-NIL property list, editf prints =EDITP, calls editp and returns. (4) If fn is neither a, function, nor has an EXPR property, nor a top level value that is a list, nor a non-NIL property list, editf attempts spelling correction using the spelling list userwords, 102 and if successful, goes back to (1). Otherwise, editf generates an fn NOT EDITABLE error. If editf ultimately succeeds in finding a function to edit, i.e. does not exit by calling editv or editp, editf calls the function addspell after editing has been completed. lOa Addspell 'notices' fn, i.e. sets lastword to fn, and adds fn 102---------------------------------------------------------------------------Unless dwimflg=NIL. Spelling correction is performed using the function misspelled? If fn=NIL, misspelled? returns the last 'word' referenced, e.g. by defineq, editf, prettyprint etc. Thus if the user defines foo and then types editf[], the editor will assume he meant foo, type -FOO, and then type EDIT. See Section 17. 108 Unless dwimflg=NIl. addspell is described in Section 17. 9.85 to the appropriate spelling lists. newfile? If any changes were made, editf also calls which performs the updating for the file package as described in Section 14. ed1tv[editvx] nlambda, nospread function, similar to editf, for editing yalues. car[editvx] specifies the value, cdr[editvx] is an optional list of co_ands. If car[editvx] is a list, it JLS evaluated and its value given to edite, e.g. EOITV«COR (ASSOC (QUOTE FOO) D'ICTIONARY»». In this case, the value of editv 1s T. However. for most applications, car[editvx] is a variable name, i.e. atomic, as in EOITV(FOO). If the value of this variable is NOBIND, editv checks to see if it 1s the name of a function, and if so, assumes the user meant to call editf, prints =EOITF, calls edi tf and returns. Otherwise, editv attempts spelling correction using the list ~ords.l04 Then editv will call edite on the value of car[editvx] (or the corrected spelling thereof). Thus, if the value of foo is NIL, and the user performs I(EOITV FOO), no spelling correction will occur, since foo is the name of a variable in the user's system, i.e. it has a value. However,. edite will generate alll error, since foo's value is not a list, and hence not editable. If the use." performs (EOITV FOOO), where the value of fooo is NOBINO, and foo is on the user's spelling list, the spelling corrector will correct FOOO to FOO. Then edi tEt will be called on the value or foo. Note that this may still result in an errctr if the value of faa is not a list. When (if) edite returns, editv sets the variable to the value returned, and calls addspeIl and newrile? 104------------------·--------------------------------------------------------Unless dwimflg=NIL. Misspelled? is also called if carr edi tvx] is NIL, so that EOITV() will edit lastword. 9.86 The value of editv is the name of the variable whose value was edited. editp[x] _ nlambda, nospread function, similar to editf for editing I!roperty lists. If the property list of car[x] is NIL, editp attempts spelling correction using userwords. property list Then editp calls edite on the of spelling thereof). car[x], When (if) (or ~ the corrected returns, editp rplacd's car[x] with the value returned, and calls addspell. The value of editp is the atom whose property list was edited. editfns[x] nlambda, nospread function, used to perform the same editing operations· on several functions. car[x] is evaluated to obtain a list of functions. cdr[x] is a list of edit commands. editfns maps down the list of functions, prints the name of each function, and calls the editor (via editf) on that function. 106 For example, EDITFNS(FOOFNS (R FIE FUM» will change every FIE to FUM in each of the functions on foofns. The call to the editor is errorset protected, so i06-~:;:-~h;-~;ri~i~i~~-~r-;~i~f~;-~i;h~-b;~----------------------------------- [MAPe (EVAL (CAR X» (FUNCTION (LAMBDA (Y) (APPLY (QUOTE EDITF) (CONS (PRINT Y T) (CDR Xl 9.87 that if the editing of one function causes an error, editfns function. 108 will proceed to the next Thus in the above example, if (me of the functions did not contain a FIE, the R command would cause an errOlr, but editing would continue with the next function. The value of editfns is NIL. edit4e[pat;x;changeflg] i!. the pattern match routine. ~!-matches!. Its value is T if See page 9.21-23 for definition of 'nlatch I .107 Note: before each search operation in the editor begins, the entire pattern is scanned for atoms or strings containing alt-modes. patterns of the These are replaced by form' (CONS (QUOTE $) (UNPACK atom/string» for 6a, and (CONS (QUOTE SS) (CONS (NCHARS atom/string) (UNPACK atom/string»), for 6b. 108 Thus from the standpoint of !!lit4e, pattern type 6a is indicated by car[pat] being the atom $ ($ is alt-mode) and pattern type 6b by car[pat] being the atom $S (double alt-mode). 106---------------------------------------------------------------------------In particular. if an error occurred while editing a function via its EXPR property. the function would not be unsaved. In other words, in the above example, only those functions which contained a FIE. i.e. only those actually changed. would be unsaved. 107 changeflg is for internal use by the editor. 108 In latter case, atom/string corresponds to the atom or string up to but not including the final two-alt-modes. possible. In both cases, dunpack is used wherever 9.88 Therefore, if the user wishes to call edit4e directly. he must first convert any patterns which contain atoms or strings ending in alt-modes to the form recognized by edit4e. This is done with the function editfpat. editfpat[pat;flg] makes a copy of pat with all patterns of type 6 converted to the form expected by edit4e. 109 editfindp[x:pat;flg] allows a program to use the edit find command as a pure predicate from outside the editor. expression, pat a pattern. ~ is an The value of editfindp is T if the command F pat would succeed, otherwise. NIL editfindp calls editfpat to convert pat to the form expected by edit4e. unless flg=T. Thus, if the program is applying editfindp to several pattern, different it will expressions be more using efficient the same to call editfpat once, and then call editfindp with the converted pattern and esubst[x:y;z;errorflg;charflg] the !!saT. equivalent to performing (R y x)110 with ~ as current expression, i. e. the arguments is the same as for subst. and/or ! can employ alt-modes. esubst is the modified!. tID Note that The of the type that never causes a break. 9.89 value of ~ of ~enerates an error ttt unless charflg=T. in which case it is equivalent to (RC y x). 9.59. 111 order See page if I not found in!. If errorflg-T. also prfnts an error message of thefonl y 1. eSlubst is always undoable. changename[fn;from;to] rel)laces all occurrences of from by to, in the de1finition of fn. If fn is an expr, changename performs nlsetq[ esubst[ to; from;getdt tn]]]. is compiled, (and If fn changename searches the literals of all of its compiler generated subfunctions). replacing each occurrence of from with to. 112 The' value of changename is fn if at least one instance of from was found, otherwise NIL. changename is used by break and advise for changing calls to fnl to calls to fnt-IN-rnZ. editracefn[com] is available to help the user debug complex edit maClros, or subroutine calls to the editor. If editracefn is set to T, the function editracefn is called whenever a command that was not typed in by the user is about to be executed, giving it that comrlland as its argument. BRE~'" options described However. the TRACE and below are probably sufficient for most applications. ii2---------------------------------------------------------------------------Will succeed even if from i~; called from fn via a linked call. In this case, the call will also be relinked to calr-to instead. 9.90 If edi tracefn is set to TRACE, the name of the cOlIIDand and the current expression are printed. If editracefn=BREAK, the same information printed, and the editor goes into a break. user can then examine the state of the editor. editracefn is initially NIL. 9.91 is The Index for Section 0 Page Numbers (A el ... em) (edit conunand) ......••..••..•••••• AOOSP£LL[X;SPlS'T;N] ..•... _~ ••..••••••••••••••••• AFTER (in INSERT command) (in editor) ••••••.•••• AFTER (in MOVE command) (1n editor) ............ . (B 01 ... em) (edit command) .•..•••••••••••••••• BEFORE (in INSERT command) (in editor) •••••••••• BEFORE (in MOVE command) (in editor) .•.•••.••••• (BELOW com x) (edit command) ................... . (BELOW com) (edit command) .••.•••••••••••••••••• BF (edit conunand) ....•.••••••••••••••••••••.•••• (BF pattern T) (edit command) .•.•••••••••••••••• (BI n m) (edit command) ..•••..•••••••••••••••••• (BI n) (edit command) .•...••.••••••••••••••••••• (BIND. corns) (edit command) ••••.••••••••.•••••• BK (edit command) ............•.•••••••••.••..••• (BK n) (n a number, edit command) •••.••...•.•••• BLOCKED (typed by editor) •....••••••.•••••.•.••• (BO n) (edit command) ...........••••...••••••••• BY (in REPLACE command) (in editor) ••••••••••••• CAN'T - AT TOP (typed by editor) .••••.•••.•••••• CAP (edi t command) ........•.•.•••••••••••••••.•• (CHANGE @ TO ... ) (edit command) ••••..•.•.••.••. CUANGENAHE[ FN; FROM; TO] •....••••••••••••••••••••• CL (e d i t comma nd ) . . . . . . . . . . . . • • • • . . . . . • • • • • • • • . • commands that move parenthe:ses (in editor) ••••.• (COMS xl ... xn) (edit command) •.•••••••.•.••••• (COMSQ . corns) (edit command) ••••••••••••••••••• continuing an edit session •..••••••••••••••••••• control-D control-E ...................................... . ...................................... . current expression (in editor) •••••••••••••••••• DELETE (edit command) .....•..•••.••••••••••••••• ( DE LE TE . @) (ed i t command) ...•.•••••••••.•••••• DESTINATION IS INSIDE EXPRESSION BEING HOVED (typed by editor) .......•••.•••.••••••••••• OW (edit command) ................................ . DWIHFLG (system variable/parameter) ••••••••••••• E (edi t command) .................................. . (E x T) (edi t command) ..•...•••••••••••••••••••• (E x) (edit command) ...••.•.••••••••.••••••••••• EOIT (typed by editor) .••.•.•••••••••••••••••••• edi t chain ............... t •••••••••••••••••••••• edit commands that search .......•••••.••.•••••.• ed it commands that test .....••.•.•.••.•••••••••• edit macros ...................................... . EDIT-SAVE (property name) ~ ...•••.•••••••••••.•.• EOIT4E[PAT:X;CHANGEFLG] .....••....•.••••••••••••• EOITCOMSA (editor variable/parameter) .••••••..•• EOITCOMSL (edi tor variable/I)arameter) ••••••••.•• EOITOEFAULT (in editor) ......•..•...•....•..••.•. EOITE[EXPR;COHS;ATH] ...•. ~ ••••••••••..••.••••••• EOITF[X] NL* .............., .••••••••.•.••••..••••• EOITFINDP[X;PAT;FlG] ....• ~ ••••••.••••••••••••••• EOITFNS[X] NL •........•.•.••••••.••••••••••••••• EOITFPAT[PAT;FLG] .•...•.• ~ editing compiled functions ••••••••••••••••••.••• u •••••••••••• IN[)EX.9.1 ••••••••• 9.13,39-40 9.85-87 9.41 9.48 9.13,30"40 9.41 9.48 9.31 9:31 9.10.28 9.28 9.8,52 9.52 9.70 9.10,18-19 9.19 9.79 9.8,52 9.42 9.5,17 9.75 9.4'2 9.90 9.77 9.51-54 9.63 9.64 9.72-74 9.71 9.3 9.2,4,8.11-15,23 9.14,37,40,42 9.42 9.49 9.77 9.80,85"86 9.9,62 9.62 9.62 9.83 9.4,7.11~13,15,23 9.21-33 9.64 9.67-70 9.72 9.88 9.80,82 9.80-82 9.80-83 9.1,83,86-87 9.1,84-86 9.89 9.87-88 9.69 9.90 Page Numbers EOITL[L;COMS;ATM;MESS] .........•.•...••......... EOITLO[L;COMS;MESS;EDITLFLG] ..........•..•.•.•.. EOITP[X] Nt* ...••.•......•.•••••••••.••••••••••• EOITQUIETFLG (e~itor variable/parameter) •••.••.• EDITRACEFN ...................................... . EOITUSERFN •...••.•..• 0 •••••••••••••••••••••••••• EOITV[EOITVX] Nt- ...•.•.•••••••••••••••••••••••• (EMBED @ IN ... ) (edit command) •.••••••••••••••• errors (in editor) ..••.•.•••••••••••.••••••••••• ESUBST[X;Y;Z;ERRORFLG;CHARFLG] ..••....••••.•.••• ( EXAM . x) (ed i t command) ••••.•••••••••••••••••• EXPR (property name) ........•....•.•••••.••••••• (EXTRACT @1 from. @2) (edit cODlDand) •••••.••••• F (edit command) .........••..•••.•••.••••••••••• F pattern (edit command) ....••••••••••••••••..•• (F pattern N) (edit command) .•...•.•••••••.•••.• (F pattern n) (n a number. edit command) ••.••••• (F pattern T) (edit command) .•.•••.•••.••••••••• (F pattern) (edit command) •••••••••••••••••••••• (F= ... ) (edit command) ..•.......•••••.••••.•••• FOR (in INSERT command) (in editor) •••..••.•.••• FROM (in EXTRACT command) (in editor) ••••••••••• (FS ... ) (edit command) ..•..•••••••••••••••••••• generalized NTH command (in editor) ••••••••••••• HERE (in edit command) ..... ~ ...•••••..••••••••.• history list ................................... . (I c xl ... xn) (edit command) .•.••..•.•.•..•.•. (If x coms1 coms2) (edit command) •••.•••••..•.•• (IF x coms1) (edit command) .•.....•••.••.•..•..• (If x) (edit command) .......•....••••••••••..•.•. implementation of structure modification commands IN (in edito.r) ...........••...•.•••••.••.•.••. (in EHBED command) (in editor) ••••••••••••••• (INSERT ... AFTER. @) (edit command) ••••••..••• (INSERT ... BEFORE . @) (edit command) ..••.••••• (INSERT ... FOR. @) (edit command) •••••••.•.••• JOINC (edit command) ....•...•••••••••••••••••••• L-CASE[X;FLG] .....................•••.........•. LASTAIL (editor variable/parameter) ••••••••••••• LASTVALUE (property name) .........••.••.••.•.... LASTWORO (system variable/parameter) •••••••••••• (LC . @) (edit command) .....•....••...••••••..•• (LCL . @) (edit command) •.•..•••.•••.•••••••••.• (LI n) (edit command) .....•..•••.••••.••••.••••• lISPX .......................................... . (LO n) (edit command) .....•...•...•..••••••.••.• location specification (in editor) ••••••••..•••. LOCATION UNCERTAIN (typed by editor) •••••.••.••• LOWER (edit command) ....•..••••••••••••••••••••• (LOWER x) (edit command) ...•.•••..••..•••.•••••. (LP . corns) (edi t command) •.......•......•.•••.• (LPQ . coms) (edit command) .••••.••••.•••..••••• (H (c) (argl .•. argn) • corns) (edit command) (M (c) arg .. corns) ..0' •.•••••••••••••••••••••••••• (H c . corns) (edit command) ••••••••••••••••••••• macros (in editor) •..••••••••••••••••••••••••••• HARK (edt t conunand) ••.••••••••••.••••••••••••••• 9.83-84 9.84 9.1,85,87 9.22 9.90-91 9.80 9.1,85-86 9.48 9.3 9.89 9.66 9.85,88 9.46 9.6,25-26 9.25 9.26 9.26 9.26 9.27 9.27 9.41 9.46 9.27 9.32,52,60 9.42 9.73,78 9.62 9.65 9.65 9.64 9.37-39 9.48 9.41 9.41 9.41 9.76 9.74 9.16-17,25,84 9.72 9.85-86 9.30 9.30 9.8.53 9.62,73 9.8,53 9.28-29,64 9.17 9.74 9.75 9.65-66 9.66 9.68 9.68 9.67 9.67-70 9.34 Page Numbers (HARK a tom) (edi t conunand) •••••••••••••••••••••• HARKLST (editor variable/parameter) ••••••••••••• HAXLEVEl (editor variable/parameter) •••••••••••• HAXLOOP (editor variable/parameter) ••••••••••••• HAXLOOP EXCEEDED (typed by editor) •••••••••••••• (HBD 01 ... em) (edit conunilnd) •••••••••••••••••• (MOVE @1 TO com • @2) (edi 1~ command) ••••••••••• 0 n (n a number, edit command) •••••••••••••••••••• (N el •.. em) (edit command) •••••••••••••••••••• (n e 1 ... em) (n a number, edt t command) ••• (n) (n a number ted! t commclnd) ••••••••••••••• 0 •••• 0 •• NEWFILE?[NAME;VARSFLG] ....•••••.•••••••••••••••• NEX (edit command) ..••••.••••• (NEX x) (edit command) ••.••••••• ~ ••••••••••••••• NIL (edit command) .•••••.••••••••••••••••••••••• 0 NOBIN[) •••••••••••••• 0 •• .....•.......•.•.. '.•.••••••••••••••••.•••• NOT BLOCKED (typed by editor) ••••••••••••••••••• NOT CHANGED, 50 NOT UNSAVEO (typed by editor) NOT EDITABLE (error message) •••••••••••••••••••• NOTHING SAVED (typed by editor) ••••••••••••••••• (NTH n) (n a number, edit c:ommand) •••••••••••••• (NTH x) (edit command) ••.) ••••••••••••••••••••••• NX (edt t command) •...•••., ••••••••••••••••••••••• (NX n) (n a number, edi t command) ••••••••• OCCURRENCES (typed by editor) •••••••••••••• ~ •••• 0 0'< ••••• (edit cornrnand) ....................... (edit command) ........................ . (edi t command) ........................ . P (edt t command) •••••••• (P m n) (edi t command) •• (P m) (edit conunand) •••• (pattern .• @) (edit command) ••••••••••••••••••• pattern match (in editor) ••••••••••••••••••••••• PP (edi t command) •••••••..••••••••••••••••••••••• ppliII: (edi t command) ••••••..••••••••••••••••••••••• PPT (edit command) .••••••.••••••••••••••••••••••• PPV (edit command) ••••••..••••••••••••••••••••••• prom p t c h a rae t e r •••.•••••.••••••••••••••••••••••• PROP (typed by cd! tor) •••.•••••••••••••••••••••• (R x y) (edi t command) ........................... . (Rt x y) (edit command) • RAISE (edit command) ••••.••••••••••••••••••••••• (RAISE X) (edit command) .•••••••• (RC x y) (edit command) •.••••••••••••••••••••••• (Ret x y) (edit command) •••••••••••••••••••••••• 0 •••••••• (ORF ... ) (ORR ... ) t• • • • • • • • • • • • • • • • • • • • • • • • II ••••••••••••••••••••••• t• • • • • • • • • • • • • • • • • • • • • • • • 0 t· •••••••••••••••••••••• 0 0 •••••••••••••• REAOL INE[ LINE; LISPXFLG] .....•.••••••••••••••••.• REPACK (edit command) ••••••••••••••••••••••••••• (REPACK @) (edit conunand) ••••••••••••••••••••••• (REPLACE @ WITH ... ) (edit command) ••••••••••••• RESETVAR[RESETX;RE5ETY;RESETZ] NL •.•.•••••.••••• (RESE TVAR var form . corns) (ed! t cOlilDand) ••••••• (RI n m) (edi t command) ••••••••••••••••••••••••• (RO n) (edit command) ••••••••••••••••••••••••••• (5 var . @) (edit command) ••• SAVE (edi t command) ••••••••••••••••••••••••••••• 0 •••••••••••••••••• search algorithm (in editor) •••••••••••••••••••• (SHOW. x) (edit command) ••••••••••••••••••••••• INDEX.9.l 9.34 9.34,84 9.24,28 9.66 9.66 9.47 9.48 9.3.17 9.36 9.5,36 9.5,36 9.86 9.32 9.32 9.64,70 9.86 9.79 9.85 9.83,85 9.78 9.20 9 ..32-33 9.8,18-t9 9.19 9.65 9.71,76,83 9.27 9.66 9.2,60 9.60 9.60 9.33 9.21-23,88-89 9.2,60 9.61 9.61 9.61 9.2 9.85 9.7,57 9.59 9.74 9.75 9.59 9.59 9.81 9.75 9.76 9.42 9.77 9.77 9.8,53 9.8.53 9.36 9.72,74,83-84 9.23-25 9.66 Page Numbers spelling correction ....•..••••••••••.•••••••..•• (SPLITC x) (edit command) ..•.•...••••.•••••••.•• STOP (edit command) ....•...•.••.••...•.••••.•••• structur~ modification commands (in editor) (SURROUND @ IN •.. ) (edit command) •..••••..•.••• (SW n m) (edit command) .••••••••••••••••••.••••• teletype ........... ............................. . TEST (edit command) .••••••••••••.••••••••••••••• THRU (edi t command) •.••.••.•..•••••••.•••.•••••• TO (edit command) .•••••••••••••••••••••••••••••• TTY: (edit command) ...••...••••..••••••.•••••••• TTY: (typed by editor) •.•••••••••••••••••••••••• U-CASE[ X] .............••.••••••••••••••••••••••• UNBLOCK (edit command) .•••.••.•••••••••••••••••• UNDO (edit command) ....•..••••••••••.••••.•••.•• undoing (in editor) ....••.••.••.•••••••••••••••• UNOOLST (editor variable/parameter) ••••••••••••• UNDONE (typed by editor) .•.•.••••••••••••••••••• UNFIND (editor variable/parameter) •••••••••••••• UNSAVEO (typed by editor) .•••••••••••••••••••••• UP (cdi t command) .......•.•.•.•••••••••••••••••• UPFINDFLG (editor variable/parameter) ••••••••••• USERMACROS (editor variable/parameter) ••.•..•••. USERMACROS (.pret tydef command) .....•.•.•••.•.••• USERWOROS (system variable/parameter) ••.••.••.•• WITH (in REPLACE command) (in editor) •.•••••• WITH (in SURROUND command) (in editor) .•••..•••. (XTR . @) (edit command) .•.•••••••••.••••••••••• o (edit conunand) .........•.•.•.•••••.•.•••••..•• ! 0 (edi t comm nchars[x] or < minus[nchars[x]] or ! corresponds to a character in ! to the If ! righ~ is of the character indicated by not a string, equivalent m. to subs,tring[mkstring[x];n ;m], except substring does not have to actually make the string if .! is a litelrel atom. 6 For example, substring[CA B C);4;6]-WB C·. gnc[x] Bet !ext £haracter of string!. Returns the next char'acter of the string, Cas an atom), and removes the character from the string. is the null string. is made. Returns NIL if .! If! isn't a string, a string Used for sequential access to characters of a. string. Note that if ! is a substring of I. gnc[x] does not remove the character from I. i.e. pnc doesn't physically change the string of characters. just the pointer end the byte count. B 6---------------------------------~-------------------------------------------See string storage section that follows. 6 See string storage section that follows. 10.6 glc[x] sets last !;,haracter of string!. Above remarks about pnc also supply to glc. lambda nospread function. Concatenates (copies of) any number of strings. The arguments are transformed to strings if they aren' t strings. Value is the new string, e.g. concat[ -ABC- ;OEF; -GHI-] = -ABCOEFGHI-. The value of concat[l is the null string, -- rplstring[x;n;y] Re!!ace characters character negative. n with ! string string l. ! n may beginning at be positive or and l are converted to strings if they aren't already. (converted)!. of Characters are smashed into Returns new!. Error if there is not enough room in ! for l' i.e. the new string would be longer than the original.' Note that if ! is a substring of !. ! will also be modified by the action of rplstring. mkatom[x] Creates an atom whose pname is the same as that of the string ! or ,if ! isn't a string. the same as that of mkstring[xl, e.g. atom X(AX ax ex). If mkatom[(A B C)l is the atom would have ) 99 characters, causes an error, ATOM TOO LONG. 7-----------------------------------------------------------------------------If l was not a string, ! will already have been partially modified since rplstring does not know whether l will 'fit' without actually attempting the transfer. 10.7 Searching Strings strpos is a function for searching one string looking for another. Roughly it corresponds to member, except that it returns a character position number instead of a tail. This number can then be given to substring or utilized in other calls to strpos. strpos[x;y;start;skip;~nchor;tail] ! and I are both strings converted automatically). (or else they are Searches I beginning at cha."acter number start, (or else 1 if sta~rt is NIL) and looks for a sequence of characters equal to!. If a match is round, the corresponding chal"acter position is returned, otherwise NIL, e.g., , strpos[-ABC-,-XYZABCDEF-]=4 strpos[-ABC·,·XYZABCDEF-;5]=NIl strpos[·ABC·,·XYZABCDEFABC-;5]=10 ski)! can be used to specify a character in ~ that with the matches any character in I, e.g. strpos[·A&C'-;-XYZABCDEF·;Nll;&]=4 If anchor chal~acters is T, strpos compares ! beginning at position start, or 1. If that comparison fails, strpos returns NIL without seal~ching any further down I. Thus it can be used to compare one string with some portion of another string, e.g. strpos[-ABC·;·XYZABCDEF·;NIl;NIl;T]=NIl strpos[·ABC·;·XYZABCDEF·;4;NIL;Tl=4 10.8 Finally, if tail is T. the value returned by strpos if successful is not the starting position of the sequence of characters corresponding to !, but the position of the first. charac ter after that, i.e. starting point plus nchars[x] e.g. strpos[-ABC-i-XYZABCOEFABC-;NIl;NIliNIliT]-7. Note that strpos[-A-;-A-;NIL;NIL;NIL;T]-2, even though -A- has only one character. Example Problem Given the strings !, l' and !, write a function corresponding to that portion of ! ~ that will make a string e.g. and between Solution: (FOO [LAMBDA (X Y Z) (AND (SETQ Y (STRPOS Y X NIL NIL NIL T» (SETQ Z (STRPOS Z X V»~ (SUBSTRING X Y (SUB1 Z]) strposl[a;str;start;neg] str is a string (or else automatically to a string), characters or character codes. 8 it ! is is converted a list of strposl searches str beginning at character number start (or else 1 if .!1!.!::!=NIl) for one of the characters in~. If one is found, strposl returns as its value the 8---------~------------------------------------------- ------------------------- If any element of a is a number, it is assumed to be a character code. Otherwise, it is converted to a character code via chconl. Therefore, it is more efficient to call strposl with! a list of character codes. 10.9 cor'responding character position, otherwise NIL. E.gl., strposl[(A B C);-XYZBCO·]=4. If neg=T, str'posl searches for a character not on !, e.g., strposl[(A B C); ·ABCOEF·:NIL;T]=4. If ! is an array, it is treated as a bit table. Thel bits of (EL TAl) correspond to character codes 0 to 43Q, of (ELT A 2) to codes 44Q to 107Q, etc:. Thus an array whose 'first element was 17Q wOUild be equivalent to a list (400 410 420 430) or (1_. If ~ I I- I). is not a bit table (array), strposl first converts it to a bit table using makebittable described below. If strposl is to be called frequently with the same list of characters, a cons,iderable savings can be achieved by converting the list to a bit table once, and then passing the bit table to strpos~ as its first argument. makebittable[l:neg;a] makes a bit table suitable for use by strposl. andl neg are as for strposl. ! If! is not an array with at least 4 elements, makebittable will create an array and return that as its value. Otherwise it uses (and changes) !. Note: if neg=T. strposl must call makebittable whether ! is a list or an array. To obtain bit table a/fficiency with neg=T, makebi ttable should be called with neg=1, to construct the -inverted- table, and the resulting table (array) should be given to strpc,sI with neg-NIL. 10.10 String Storage A string is stored in 2 parts; the characters of the string, and a pOinter to the characters. The pointer, or 'string pointer', indicates the b,te at which the string beg,ins and the length of the string. storage. a It occupies one word of The characters of the string are stored five characters to a word in portion of the INTERLISP address space devoted exclusively to storing characters. Since the internal pname of literal atoms also consists of a pOinter to the beginning of a string of characters and a byte count, conversion between literal atoms and strings does not require any additional storage for the characters of the pname, although one cell is required for the string pointer. 9 When the conversion is done internally, e.g. as in substring, strpos, or strposl, no additional storage is required for using literal atoms instead of strings. The use of storage by the basic string functions is given below: mkstring[x] substring[x;n:m] x string no space x literal atom new pOinter other new characters and pointer ! string new pointer x literal atom new pOinter other new characters and pointer 9-~---~--~---------------~---------------------------- ------------------------- Except when the string is to be smashed by rplstring. In this case, its characters must be copied to avoid smashing the pname of the atom. rplstring automatically performs this operation. 10.11 gnc[x] and glc[x] x string no space, pointer is modified other like mkstrina. but doesn '·t make much sense args, any type new characters for whole new string, one new pointer rplstring[x:n:y] no new space unless characters are in x string (as space pname mkstring[ atom]) in of result which case 1f is quietly copied to string space 10.3 x other new pointer and characters y any type type of y doesn't matter Array Functions Space for arrays and compiled code are both allocated out of a common array space. . Arrays of pointers and unboxed numbers may be manipulated by the following functions: array[n:p:v] This function allocates a block of n+Z words, of which the first two are header information. The nex1; pin are cells which will contain unboxed numbers, and are initialized to unboxed last n-p 2 0 ini1~ialized avajLlable storing contain y. an poilllters) • will contain pointers with y, i.e., both £!!: and cdr are for ini1~ially (i.EI., cells o. . The array information, If ~ is NIL, containing all and each 0 is used INTERLISP The value of array is the array, also 10.12 called an array pOinter. If sufficient space is not available for the array, a garbage collection of array space, GC: 1, is initiated. If this is unsuccessful in obtaining sufficient space, an error is generated, ARRAYS FULL. Array-pointers print as In, _here n is the octal representation 0/ the pointer. Note that In _tll be read a$ a lit~ral atom. and not an array pointer. arraysize[a] Returns the size of array I. Generates an error, ARG NOT ARRAY, if I is not an array_ arrayp[x] Value is ! if ! is an array pointer otherwise NIL. No check is made to ensure that ! actually addresses the beginning of an array. elt[a.n] Value is nth element of the array 1 10 elt generates an error, ARG NOT ARRAY, if ! is not the beginning of an array.l1 If n corresponds to the unboxed region of !, the value of elt is the full 36 bit word, as a boxed integer. If n corresponds to the potnter region of !, the value of elt is the seta[a;n:v] ~ half of the corresponding element. sets the nth element of the array I_ Generates an io------------~---------------~---~------------------- ------------------------- elt[a;l] is the first element of the array (actually corresponds to the 3rd cell because of the 2 word header). 11 arrayp is true for pointers into the middle of arrays, but elt and seta must be given a pointer to the beginning of an array, i.e.,~ value of array. 10.13 error, ARG NOT ARRAY, of an array. If ~ i f ! is not the beginning corresponds to the unboxed regjion of !, y must be a number, and is unboxed and stored as a full 36 bit word into the nth elenlent of!. If!! corresponds to the pointer region of !, y replaces the £!! half of the nth The value of seta is y. elenlent. Note that seta and el t are a llDall.!; i""erse operations. eltd[a;n] samel as 81 t for unboxed region of a, but returns cdr half of nth element, if.!! corresponds to the pointer regionlOf !. setd[a;n;v] samel as seta for unboxed region of a, but sets cdr half' of nth element, if n corresponds to tiii poinlter region of!. The value of ~ is .!. In ,other words, eltd and setd are! always inverse operations. 10.4 Storage Functions reclaim[n] Initiates a garbage collection of type n. Value of r~eclaim is number of words available "(for that typi) after the ~ollection. Garbage collections. IDhether inuoled directlll bll the user or indirectlll bll need Jor storage. do not confine their actil/itll solelll to the data tllpe lor which thell were called. but automaticallll collect some or all 0/ the other tllpes (see Section 8). ntyp[x] Value is type number. for the data type of INTERLISP pointer !, e.g. ntyp[(A • B)] is 8, the type number for lists.. Thus GC: 8 indicates a garbage collection of list words. 10.14 type number arrays, compiled code stack positionsi list words· atoms . floating point numbers large integers small integers string pointers pname storage string storage 1 2 8 12 16 18 20 24 28 30 typep[x;n] eq[ntyp[x];n] gcgag[message] message is a string or atom to be printed (using print) wherever a garbage collection is begun. If message=T, its 'standard setting, GC: is printed, followed by the type number. When the garbage. collection is c!:omplete. two numbers are printed the number of words collected for that type, and the total number or words available for that type, i.e. allocated :but not necessarily currently in use (see --, minfs ~elow). Example: "'RECLAIM( 18) GC: 18 511, 3071 FREE WORDS 3071 "'RECLAIM(12) GC: 12. 1020, 1020 FREE WORDS 1020 If message=NIL, no garbage collection message is printed, either on entering or leaving the garbage collector. Value of i£H!i is old setting. 10.18 minfs[njtyp] 8ets the minimum amount of free storage which will be maintained by the garbage collector for data types of type number!IR. If,p after any garbage collection tor that type, fewer than II free words are pre$ent. sufficient storage will be added (in 512 word chunks) to rai~e the level to If !IR=NIl, 8 is used, i.e. th~ n. minfs.refers to lis·t words. If l~.NIl, minfs returns the current !!!!!!f! setting for the corresponding type. A minfs setting can also be changed dynamically, even during a garbage collection, by typing control-8 followed by a number, followed by a perio,d. 12 If the control-S was typed durirng a garbage collection, the number is the new minfs setting for the type beinlg collected, otherwise for type 8, i.e. list words. Note, A garbage collection oJ a 'related' tupe mall also cause more storage to be assigned to that tllpe. See discussion oJ garbage collector algorithm. Section 8. storage[flg] Prints amount ot storage (by type number) used by and assigned to the user, e.g. 12----------------------------------------------------------------------------When the control-S is typed, INTERLISP immediately clears and saves the input buffer, rings the bell, and waits for input, which is terminated by any non-number. The input buffer is then restored, and the program continues. If the input was terminated by other than a period, it is ignored. 10.16 "STORAGE() TYPE USED ASSIGNED 1 8 12 80072 7970 7032 87552 16 0 18 24 28 30 1124 118 4226 573 4608 1024 SUM 101115 113664 9216 7680 512 2560 512 If f1g=T. includes storage used by and assigned to the system. gctrp[n] Value is NIL. sarbage£ollection tra~. Causes a (simulated) control-H interrupt when the number of free list words (type 8) remaining equals !!, garbage collection would occur in The message GCTRP interrupt (Section occurs. Note is 16) that by i.e. when a n more conses. the function printed, is called. and a advising (Section break 19) interrupt the user can program the handling of a 1lillI!. instead of going into a break. 18 Value of 1lillI!. is its last setting. gctrp[ -1] will I disable' a previous Qctrp since there are never -1 free list words. qctrp is initialized this way. ii----------------------------------------------------------------------------For Ilf!!:..2 interrupts, interrupt is called with intype (its third argument) equal to 3. If the user does not want to go into a break, the advice should still allow interrupt to be entered, but first set intype to -1. This will cause interrupt to -quietly· go away by calling the function that was interrupted. The advice should not exit interrupt via return, as in this case the function that was about to be called when the interrupt occurred would not be called. 10.17 gct,rp[] returns number of list words left, i.e. nun~er of conses until next type 8 garbage collection, see Section 21. conscount[n] conscount[ ] returns INT'ERLISP started up. number of conses since If !! is not NIL, resets conscount to !!. closer[a.x] Stores ! into memory location ! . Both ~ and !! must be numbers. openr[a] Value is the number in memory location .!, boxed. 10.18 i. e. Index for Section 10 Page Numbers ·................................ . ·............................. . ·............................... . AOOOn (gensym) ARG NOT ARRAY (error message) ARRAY[N;P;V] SUBR array functions array header ARRAYP[X] SUBR ARRAYS FULL (error message) ARRAYSIZE[A] ATOM TOO LONG (error message) bell (typed by system) CHARACTER[N] SUBR character atoms character codes · CHCON[X;FLG] SUBR CHCON1[X] SUBR ClOSER[A;X] SUBR compiled code CONCAT[Xl;X2: .•• ;Xn] SUBRCONSCOUNT[N] SUBR control-H control-S DCHCON[X;SCRATCHlIST;FlG] DUNPACK[X;SCRATCHLIST;FLG] ElT[A;N] SUBR ELTO[A;N] SUBR FCHARACTER[N] SUBR garbage collection GC:, (typed by system) ••••••••••••••••••••••••••• GC: ,1 (typed by system) GC: 8 (typed by system) GCGAG[MESSAGE] SUBR GCTRP[N] SUBR GENNUM (system variable/parameter) GENSYM[CHAR] GlC[X] SUBR GNC[X] SUBR input buffer · INTERRUPT[INTFN.INTARGS;INTYPE] literal atoms MAKEBITTABLE[L;NEG;A] MAPATOMS[FN] SUBR MINFS[N;TYP] StlBR MKATOM[X] SUBR MKSTRING[X] SUBR NCHARS[X] SUBR NTHCHAR[X;N] SUBR NTYP[X] SUBR null string OPENR[A] SUBR PACK[X] SUBR PACKC[X] SUBR pnames prin2-pnames print name RAOIX[N] SUBR RECLAIM[N] SUBR ·.................................. . ..................... ·.................................. . ........................... · ............................. ·............................... . ............................... . ·............................. .. ·................................ ................................ ·............................... . ·............................. . ....................................... ....................................... ·................................ . .............................. .............................. ......................... ·................................. . ·.................................. . ..................................... ..................................... .................................. . ................. ·................................. . ·............................. . ·............................. . ·................................ . ................................ ·..................... ............ . ·........... .................. .. ·.................................. ·................................. . ··.................................. . ................................. . .......................................... ·................................... . ...................................... ·................................. . ·............................... . ' ' INDEX.10.1 10.5 10.13-14 10.12 10.12-14 10.12 10.13 10.13 10.13 10.2,7 10.16 10.4 10.2 10.4 10.4 10.4 10.18 10.12· 10.7,12 10.18 10.17 10.16 10.4 10.3 10.13 10.14 10.4 10.13-18 10.15 10.13 10.14 10.15 10.17 10.5 10.4-5 10.7,12 10.6,12 10.16 10.17 10.11 10.10 10.5 10.16 10.7 10.5,11 10.3 10.3 10.14 10.6-7 10.18 10.2 10.4 10.1-4,11 10.1,3-4 10.1 10.1 10.14 Page Numbers RPlSTRING[X;N;Y] SUBR RSTRING[] SUBR searching strings SETA[A;N;V] SETO[A;N;V] STORAGE[FlG] STREQUAl[X;Y] string characters string functions string pointers string storage STRINGP[X] SUBR STRPOS[X;V;START;SKIP;ANCHOR;TAIL] STRPOSl[A;STR;START;NEG] SUBSTRING[X:N;H] SUBR type numbers TVPEP[X;N] unboxed numbers (in arrays) UNPACK[X;FLG] SUBR I (followed by a number) ... ................................. . .................................... , ..................... IND:EX.I0 .2 10.7,12 10.5 10.8-10 10.13 10.14 10.16 10.5 10.11 10.5-10 10.6,11 10.11-12 10.5 10.8-9 10.9-10 10.6,11 10.14 10.15 10.12 10.2-3 10.13 SECTION 11 FUNCTIONS WITH FUNCTIONAL ARGUMENTS As in' all LISP 1.5 Systems, arguments can be passed which can then be used as functions. However, since £!! of a form is neuer evaluated, !22!l or· apply· must be used to call the function specified by the value of the functional argument •. Functions which use functional arguments should use variables with obscure names to avoid possible conflict with variables that are used by the functional argument. for example, all system functions standardly use variable names consisti,ng of the function name concatenated with! or fn, e.g. mapx. Note that by specifying the free variables used in a functional argument as the second argument to function, thereby using the INTERLISP FUNARG feature, the user can be sure of no clash. function[x;y] If l=NIL, the value of is an nlambda function. function is identical to quote, for example, (HAPC LST (FUNCTION PRINT» will cause mapc to be called with two arguments the value of 1st and PRINT. Similarly, (HAPCAR LST (FUNCTION(LAHBDA(Z) (LIST (CAR Z»») will cause mapcar to be called with the value of 1st and (LAMBDA (Z) (LIST (CAR Z»). compiled, function will cause code to be for !; guote will not. 11.1 Thus When ~omplled (MAPCAR LST (QUOTE (LAMBDA to be called with therefore will cause mapcar the value of 1st expression (LAMBDA --). will --») and The functional still be the argument interpreted. The corresponding expression using function will cause a dummy function to be created with definition (LAMBDA --)_ and then compiled. mapcar would then be Icalled with the value of 1st and the name of the dummy function. See Section 18. If l is not NIL_ it is a list of variables that are (presumably) used freely by!. In this case, the value of function is an expression of the form (FUMARG x array), where variable for Funa~ map[mapx;mapfnl;mapfriZ] If bindings array those contains variables on ~. is described on page 11.5-7. ~lapfnZ is NIL, map applies the function mapfnt to :.uccessive tails of the list mapx. first the it computes mapfnl[mapx], That is, then mapf'nl[cdr[mapx]]. etc., until mapx is exhausted. 1 If mapfnZ is provided, mapfnZ[mapx] and is used instead of cdr[mapx] for the next call for mapfnt_ e.g., if mapfnZ were cddr, alternate elements of the list would be skipped. The value of map is NIL. map compiles open. i--------~--------------------·-------·-·------------- ------------~~-------~--~ i.e." becomes a non-list. 11.2 mapc[mapx;mapfnl;mapfn2] Identical to map. except that mapfnl[car[mapx]] is computed each at instead iteration of mapfnl[mapx]. i.e., mapc works on elements, map on tails. The value of mapc is NIL. mapc compiles open. maplist[mapx;mapfnl ;mapfn2] successively computes the same values that map would compute; and returns a list consisting of those values. maplist compiles open. computes the same values that mapc would compute, mapcar[mapx;mapfnl:mapfn2] and returns a list consisting of those values, e.g. mapcar[x;FNTYP] is a list of fntyps for each element on!. mapcar compiles open. Computes the same values as map and maplist but mapcon[mapx;mapfnl :mapfn2] nconcs these values to form a list which it returns. mapcon compiles open. mapconc[mapx;mapfnl:mapfn2] Computes the same values as mapc and mapcar, but nconcsthe values to form a list which it returns. mapconc compiles open. Note that mapcar creates a new list which is a mapping of the old list in that each element of the new list is the result of applying a function to the corresponding element on the original list. mapconc is used when there are a variable number of elements (including none) to be inserted at each iteration, e.g. mapconc[X:(LAMBDA (Y) (AND Y (LIST V»~)] will make a list consisting of ! with all NILs removed, mapconc[X;(LAHBDA (Y) (AND (LISTP Y) linear list consisting of all the 11.3 lists on !, e.g. V»~] if will make a applied to «A B) C (0 E F) (G) H I) will yield (A B 0 E F G)~2 subset[mapxjmapfnl ;mapfn2J applies mapfnl to elements of mapx and returns a list of those elements for which this application is non-NIL, e.g., subset[(A B 3 C 4);NUMBERP] = (3 4). map'fn2 plays the same role as' wi th map, mapc, et ale map2c[mapx;mapy;mapfnl,mapfnZ] subset compiles open. Identical to mapc except mapfnl is a function of two arguments, and mapfn1[car[mapx]:car[mapy]l is computed at each interation. 3 Terminates when etther mapx or map2car[mapx;mapy;mapfnl;mapfn2] ~ Identical func:tion to of are exhausted. mapcar two except mapfn1 is a and arguments mapfnl[car[mapx];car[mapy]] is used to assemble the new list. Terminates when either mapx or m!2l is ttxhausted. Note: CLISP (Section 23) provides a more general and complete facility for expressing iterative statements, e.g. (NUMBERP (CAR X» (FOR X IN Y COLLECT (CAOR X) WHEN UNTIL (NULL X»). 2--------------------------------'---------------------------------------------Note that since !!l.i!pconc uses !!.£Q.!!£ to string the corresponding lists together, in this example, 'the original list will be clobbered, i.e. it would now be «A B 0 E f G) C (0 E F G) (G) H I). If this is an undesirable side effect, the functional argument to mapconc should return instead 8 top level copy, e.g. in this case, use (AND (lISTP Y) (APPEND V»~. a mapfn2 is still a function clfone argument, and is applied twice on each iteration; mapfn2[mapx] gives the new mapx, mapfnZ[mapy] the new~. cdr is used if mapfn2 is not supplied, i.e., 1s NIL. 11.4 maprint[lst:file;left:right;sepiPfn:lispxprintflg] is a ge·nerel printing function. It cycles through 1st applying pfn (or print if pfn not given) to each element of 1st. Between each application, maprint performs prinl of sep, or • • if sep=NIL. If left is given, it is printed (using print) initially; if right is given it is printed (using prinl) at the end. , For example, maprint[x;NIL;X(;X)] is equivalent to prin1 for lists. To print a list with commas between each element and a final '.' one could use maprint[x;T;NIL;X.;%,]. If lispxprintflg • T, lispxprinl is used for prinl (see Section 22). Mapdl,searchpdl See Section 12. mapatoms See Section 5. every, some, notevery, notany See Section 5. Funarg function is a function of two arguments, 2f' a function. and I variables used freely by!. a list of If I is not NIL, the ualue of function is an expression of the form (FUNARG x array), where array contains the bindings of the variables on l at the time the call to function was evaluated. not a function itself. Like LAPlBDA and NLAHBDA. funarg is it has meaning and is specially recognized by INTERLISP only in the context of applying a function to arguments. In other words, the expression (FUNARG x array) 15 used exactly 11.5 like a function. 4 When a funarg is applied, the stack is modified so that th~ bindings contained in the arra3' will be in rorce when !, the runction. 1s called. 6 For example, suppose a program wished to compute (FOO X (FUNCTION FIE», and fie used land! as free variabJles. If foorebound land z, fie would obtain the rebound values when it was applied from inside of foo. (FOO X (FUNCTION FIE (Y Z»), instead foo· would By evaluating with called be (FUNARG FIE array) as its second/argument, where arral contained the bindings of ~. and! (at the time foo was c:alled). Thus when fie was applied from inside of foo, it would 'see' the original values of land !. However, funarg variables. computation, ~Iust is more than a way of circumventing the clashing of For examp.le, a funarQ expression can be returned as the value of a and then used 'hlgher up', e.g., when the variables contained in array: werli! no longer on the stack. function array, bindings of the Furthermore, if the in a funarg expression .sets any of the variables contained in the the array itself (and only the array) w1ll be changed. . For example, suppose foo is defined as (LAMBDA (LST FN) (PROG (Y Z) (SElQ Y 8c) (SETQ Z 8c) ••• (HAPC LIST FN) ••• » and (FOO X (FUNCTION FIE (Y Z» )is evaluated. the mapc in foo) changes ~ If one application of fie (by and !, then the next application of fie will obtain the changed va lues of land ! retsu 1ting from the previous appl ica tion of fie, since both applications of fie come from the exact same funarg object, and hence use the exact same array. The bindings of land! bound inside of foo, and the bindings of 1.. and ! abofJe foo would not be affected. In other. words, 4-----------------------------------------------------------------------------LAMBDA, NLAMBDA, and FUNARG expressions are sometimes called • function objects' to distinguish them from functions, i.e., literal atoms which have f~nction definitions. 6 The implementation of funarg is described in Section 12. 11.6 the variable bindings contained in array are a part of the function object, i.e., the funarg carries its environment with it. Thus by creating. a funarg expression with function, a program can create a function object which has updateable binding( s) associated with the object which last between calls to it, but are only accessible through that instance of the maintain function. two For example, different using the funarg device, a program could instances of the same random number generator in different states, and run them independently. Example If foo is defined as (LAMBDA (X) (CONO «ZEROP A) X) (T (MINUS X») and fie as (LAMBDA NIL (PROG (A) (SETQ A 2) (RETURN (FUNCTION FOO»». then if we perform (SETQ A 0), (SETQ FUM (FIE», the value of f!!!!! is FOO, and the value of (APPLY* FUM 3) is 3, because the value of A at the time faa is called is O. However if fie were defined instead as (LAMBDA NIL (PROG (A) (SETQ A Z) (RETURN (FUNC.TION FOO (A»»), the value of fum would be (FUNARG FOO array) and so the value of (APPLY* FUM 3) would be -3, because the value of A seen by foo is the value A had when the funarg was created inside of fie, i.e. 2. 11.7 Index for Section 11 Page Numbers APPLY[FN;ARGS] SUBR .......•••••.••••••.••••.••.• APPLY*[FN;ARG1; ... ;ARGn] SUBR* ••••••••••••••.••• CLISP ........................................... . FUNARG .......................................... . FUNCTION[EXP;VLIST] NL •....••.•••••••••••••.•••• objects ..•.•..•.. , ••.••••••••••••••••• fune tiona 1 argumen ts ....•.•••••••••••••••••••••• func~tion 0 •• MAP[ MAPX; MAPFN 1 ; MAPFN2 ] .. 0' • • • • • • • • • • • • • • • • • • • • • • MAP2C[MAPX;MAPV;MAPFN1;MAPFNZ] .••••••••••••••••• MAP2CAR[MAPX;MAPY;MAPFNl;MAPFN2] •. ~ •••••.•.•.••• MAPC[MAPX;MAPFN1;MAPFN2] MAPCAR[MAPX;MAPFN1;MAPFN2] .•.••.•••••••••....••• MAPCON[MAPX;MAPFN1;MAPFN2] ...•.••.•.•..•.•...••• MAPCONC[MAPX;MAPFN1;MAPFN2] •..•••••.•••••.•••••• MAPLIST[MAPX;MAPFN1;MAPFN2] ~ .••.•.••..••.•.•...• MAPRINT[LST;FILE;LEFT;RIGHT;SEP;PFN;LSPXPRNTFLG] •• SUBSET[MAPX;MAPFNl;MAPFNZ] ••.••••••.•••••••••.•• variable bindings .•••••••.•••••••••••••••••••••• .Q •••••••••••••••••••••• INDIEX .11.1 11.1 11 • 1 11.4 11.1-2,5-7 11.1-2,5,7 11.6 11. 1 11.2 11.4 11.4 11.3 11.3 11.3 11.3 11.3 11.5 11.4 11.5-7 SECTION 12 VARIABLE BINDINGS AND PUSH DOWN LIST FUNCTIONS A number of schemes have been used in different implementations of LISP tor storing the values of variables. These include: 1. Storing values on an association list paired with the variable names. 2. Storing values on the property list of the atom which is the name or the.variable. 3. Storing values in a special value cell associated with the atom name, putting old values on a pushdown list, and restoring these values when exiting from a function. 4. Storing values on a pushdown list. The first three schemes all have the property that values ar. scattered throughout list structure space, and, in general, in a paging environment would require references to many pages to determine the value of a variable. would be very undesirable in our system. This In order to avoid this scattering, and possibly excessive druM references, we utilize a variation on the fourth standard scheme, usually only used for transmitting values of arguments to compiled functions; that is, we place these values on the pushdown list. 1 But 12.1 since we use an interpreter as WEill as a compiler, the variable names must also be kept. The pushdown list thus contains pairs, each consisting of a variable name and its value. Each pair occupies one word or •slot • on the pushdown 1 ist, with the name in the left; half, 1.e. cdr, and the value 1n the right half, i.e. car. The interpreter gets the value of a variable by searching back up the pushdown list looking for a· 'slot' for which cdr 1s the name of the variable. car is then its value. One advantage of this scheme is that the current top of the pushdown stack is usually in core, and thus drum references are rarely required to find the value of a variable. Free variables work automatically in a way similar to the association list scheme. An additional advantage of this s.cheme is that it is completely compatible with compiled functions which pick up their arguments on the pushdown list from known positions, instead of doing a search. - To keep complete compatibility. , our compiled functions put the rliames of their arguments on the pushdown list, although they do not use them to reference variables. Thus, free variables can be used between compiled and interpreted functions with no special declarations necessary. fo~ The names on the pushdown list are also very useful in debugging, they make possible a comple'te symbolic back trace in case of error. Thus this technique, for a small extra overhead, minimizes drum references, provides symbolic debugging information, and allows completely free mixing of compiled and interpreted routines. There are three pushdown lists used in INTERLISP: the first is called the parameter pushdown list. and contains pairs of variable names and values t and temporary storage of pointers; tille second is called the control pushdown list, and contains function returns and other control information; and the third is called the number stack and is used for storing temporary partial results of numeric operations. 12.2 However, it is more convenient for the use~ to consider the push-down list as a single "list" containing the names of functions that have been entered but. not yet eXited. and the names and values of the corresponding variables. The multiplicity of pushdown lists in the actual implementation is for efficiency of operation only. The Push-Down List and the Interpreter In addition to the names and values of arguments for functions. information regarding partially-evaluated expressions is kept on the push-down list. For example, consider the following definition of the function, fact (intentionally faulty) : (FACT [LAMBDA (N) (CONO «ZEROP N) L) (T (ITIMES N (FACT (SUBI N]) In evaluating the form (FACT 1), as soon as fact is entered, the interpreter begins evaluating the implicit ~ following the LAMBDA (see Section 4). first function entered in this process is cond. list of clauses. cond begins to process its After calling zerop and getting a NIL value, cond proceeds to the next clause and evaluates T. Since T is true, impliCit This ~ The the evaluation of the that is the consequent of the T clause is begun (see Section 4). requires calling the function itimes. called, its arguments must be evaluated. searching the stack for th~ However before itimes can be The first argument is evaluated by last binding of N; the second involves a recursive call to fact, and another implicit ~, etc. Note that at each stage of this process, some portion of an expression has been evaluated, and another is awaiting evaluation. 12.3 The output below illustrates this by showing the state of the push-down list at the point in the computation of (FACT 1) when the unbound atoDIi L is reached • .. FACT(I) U.S.A. (L BROKEN) :BTV! -FORM* (BREAKI L T L NIL 134047) 10 (L) 10 «(ZEROP N) L) (T (ITIHES N (FACT (SUBI N»») 1 CONO *FORM* (CONO «ZEROP N) L) (T (ITIHES N (FACT (SUBl N»») 10 «CONO «ZEROP N) L) (T (ll'IHES N (FACT (SUBl N»»» 2 N 0 FACT *FORM* (FACT (SUBI N» #2 ITIHES 10 «FACT (SUBI N») 3 #0 1 4 *FORM* (ITIHES N (FACT (SUBI N») 10 « ITIHES N (FACT (SUB1 N»» 5 10 «(ZEROP N) L) (T (ITIHES N (FACT (SUBl N»») 6 *FORM* (CONO «ZEROP N) L) (T (ITIHES N (FACT (SUBI N»») 10 (CONO «ZEROP N) L) (T (ITIHES N (FACT (SUBl N»»» 7 CONO N1 FACT Internal calls to eval, e.g., from cond and the interpreter, are marked on the push-down list by a special mark called an oval-blip. by the appearance of (VAG 64) position, for that slot. in the left-half, eval-blips are indicated i.e. the variable name They are printed by the backtrace as *FORM*. The genealogy of *FORM*'s is thus a history of the computation. Other temporary information is frequently recorded on the push-down list in slots for which the 'variable name I is (VAG 0), which prints as 10. In this example, this information consists of (1) the tail of a list of cond clauses, (2) the tail of an implicit J!!:QIl!!. i.e., the de,'inition ot fact, (3) the tail of an argument 12.4 list, (4) the value of a previously Qvaluated argument, (5) the tail of a cond clause whose predicate evaluated to true, and (6) and (7) same as (1) and (2). Note that a function is not actually entered and does not appear on the stack, until its arguments have been evaluated. 2 Also note that the 10 'bindings' comprise the actual working storage. In other words, in the above example, if a (lower) function changed the value of the binding at (1) (not recommended) the cond would continue interpreting the new binding as a list of ~ clauses. Similarly, if (4) were changed, the new value would be given to itimes as its first argument after its second argument had been evaluated. and itimes was actually called. The Pushdown List and Compiled Functions Calls to compiled functions, and the bindings of their arguments. i. e. names and values, are handled in the same way as ,for interpreted functions (hence the compatibility between interpreted and compiled functions). However, compiled functions treat free variables in a special way that interpreted functions do not. Interpreted functions "look up" free variables when the variable is encountered, and may look up the same variable many times. However, compiled functions look up each free variable only once. 3 Whenever a compiled function is entered, the pushdown list is scanned and the most recent binding for each free variable used in the function is found (or if there is no binding, the value cell is obtained) and stored in the right half of a slot on the stack (an unboxed 0 is stored in the left half to distingUish this 'binding' from 2~----------------~----------------------------------------------------~~------ except for functions which do not have their arguments evaluated (although they themselves may call eval, e.g. cond). 8 A list of all free variables is generated at compile time, and is in fact obtainable from the compiled definition. See Section 18. 12.5 ordinary bindings). Thus, following the bindings of their arguments, compiled functions store on the pushdown list pointers to the bindings for each (ree variable used in the function. In addi tion to the pointers tOI free variable bindings, compiled functions differ from variables t interpreted i. e. J!!:.Q.Il! functions in and open la.mbdas. the way they treat locally bound Whereas in interpreted functions progs and open lambdas are called in the ordinary way as functions, in compilation, progs and open lambdas disappear, although the variables bound by them are stored on the stack in the conventional manner so that functions called from inside them can reference the variables. argum~nts following the pointers (if any). These variables appear on the stack to the compiled function (if any) and the (ree variable The only way to determine dynamically what variables are bound locally by a compiled function is to search the stack from the first slot the la.st argument to the 1:unction (which can be found with stknargs and beyond stkarg described below), to the slot corresponding to the Itr.st argument of the next function. Any slots encoun1~ered that contain literal atoms in their left half are local bindings. Pushdown List Functions NOTE: Unless otherwise stated, for all pushdown list functions, position on the control stack. (STKPOS pos 1) is used. pos is a If pos is a literal atom other than NIL, In this case, if pos is not found, i.e., stkpos returns NIL, an ILLEGAL STACK ARG error is generated. stkpos[fn;n;pos] Searlches the control stack starting at pos for the ~th occurrence of fn. 12.6 Returns control stack position of that fn if found,4 els.NIL. If ~ is po.itive, searches backward (normal usage). is negative, searches forward, control stack. i.e., If n down the For eXUlple, stkpos[FOO;-2;FIE] finds second call to FOO after (below) the last call to FIE. If !!. is NIL, 1 is used. 'If pos is NIL, the search starts at the current position. stkpos[] gives the current position. stknth[n,pos] Value is the stack position (control stack) of the !!th function call relative to position pos. If > 0, and the current position is assumed for n < 0, pos is NIL, the top of stack is assumed for n i.e., stknth[-l] is the call before stknth, stknth[1] is the call to evalgt at the top level. Value of stknth is NIL if there is no such call e.g., stknth[10000] or stknth[-10;stknth[5]]. fstknth[n;pos] version of stknth that compiles open. stkname[pos] Value is the name of the function at control stack posi tion pos. In this case, pos must be a real stack position, not an atom. In summary, stkpos converts. function names to stack positions, stknth converts numbers to stack positions, and stkname converts positions to function names. 4--------~-----~·------------------------------------------------------~-----~- A staek position is·a pointer to the ~orresponding slot on the control or parameter stack, i.e., the address of that cell. It prints as an unboxed number, 8.g.,.132002, and its type is 2 (Section 10). 12.7 Information about the variables bound at a· particular function call can be obtained using the following func:tions.: stknargs[pos] Value is the number of ar:-guments bound by the func:tion at position pOSe stkarg[n;pos] Value is a pOinter to the !!.th argument (named or not)I 6 of the function at position pos, i.e., the value is a parameter stack position. ~ of this pointer gives the value of the binding, cdr the namE~. !l=1 corresponds to the first argument at pos . !! can be 0 or negative, i.e., stkarg[OjFOO] is pointer to the slot immediately before the IS fir!.t argument to FOO, 5tkarg[ -1 .FOO] the one before that, etc. fstkarg[n;pos] ver$ion of stkars that compiles open. Note that the user can change (set) the value of a particular binding by performing an rplaca on the value of stkarA. Similarly, rplacd changes (sets) the name. The value of stkarg is a posit:lon (slot) on the parameter stack. currently no analogue to stknth for the parameter stack. There is However, the parameter stack is a contiguous block of memory, so to obtain the slot previous to a given slot, perform vag[subi[loc[slot]]]; to obtain the next slot perform vag[addl[loc[slot]]]. i.e. 6--~------------~--~-~----------~---------------------------~------------------ Subrs do not store the names of their arguments. 12.8 . stkarg[2;pos] • vag[.dd1[loc[stk.rg[1;pos]]]].~ As an example of the use of stknargs and stkarg: variables[pos] returns list of variables bound at pOSe can be defined by: (VARIABLES [LAMBDA (POS) (PROG (N l) (SETQ N (STkNARGS POS» LP (COND «ZEROP N) (RETURN L») (SETQ L (CONS (CDR (STKARG N POS» l» (SETQ N (SUBt N» (GO lP]) The counterpart of variables is also available. stkargs[pos] Returns list of values of variables bound at pOSe The next three functions, sttscan, evalv, and stkeval all involve searching the parameter pushdown stack. For all three functions, pos may be a position on the control stack, i.e., a value of stkpos or stknth. 7 In this case, the ,search starts at stkarg[stknargs[pos]jPos] i.e., it will include the arguments to the function at pos but not any locally bound, variables. pos may also be a posi tion on the parameter stack, in which case the search starts with, and includes that position. Finally, pos can be NIL, in which case the search starts with the current position on the parameter stack. 6----------~--------------------------------------------------~-----------~---See Section 13 for discussion of vag and loco 7 or a function name, which is equivalent earlier. t~ stkpos[pos;l] , as described stkscan[var;pos] Sear-ches backward on the parameter stack from' pos for a binding of yare binding if found, position, otherwise Value is the slot for that i.e., y!!: a parameter stack itself (so that in the casu of literal atoms, £!!: of stkscan is always the value of !!!). evalv[var,pos] car[ stkscan[var; pos]], i. e. , returns the value of the atom!!!: as of position pOSe stkeval[pos;form] is a more general evalv. evaJl[form] at position pas, It is equivalent to i.e., all uartabLe& evaJluated in form, will be evaluated as of pos. B Finally, we have two functions which clear the stacks: retfrom[pos;value] clears the stack back to the function at position pos I' and effects a return from that function with vall!! as its value. reteval[pos;form] clears the stack back to the function at position pos.. value t.hen to evaluates form and returns with the next higher functio~. In its other words, reteval[pos,form] is equivalent to ret1:rom[pos ;stkeval[ pas; form]]. 9 8---~~~;~;;:-;~;-;~~~~;~~;-;~-;~;:;-;~;~-;;;~;;;~;i,i;-;;;;;;~~;-;~;-;;;~;:-::;:: stkpos, stknth, retfrom, etc., 'see' the stack as it currently is. page 12.11-13 for descri~ti n of how stkeval is implemented.) 9 Provided form does footnote 8-.- not in'folve any stack functions, 12.10 as (8ee explained in We also have: mapdl[mapdlfn:mapdlpos] starts at position mapdlpos (current if NIL), and applies mapdlfn to the function !!!!!!! at each pushdown position, i.e., to stkname[mapdlpos] until the top of stack is reached. Value is NIL. mapdlpos is updated at each iteration. For example. mapdl[(LAHBOA (X) (ANO' (EXPRP X) (PRINT X»)] will print all exprs on the push-down list. mapdl[(LAHBOA (X) (CONO «GREATERP (STKNARG HAPOLPOS) 2) (PRINT X] will print all functions of more than two arguments. searchpd1[srchfn:srchpos] searches the pushdown list starting at position srchpos (current if NIL) until it finds a position for which srchfn applied to the n!m! of the function called at that position is not NIL. Value is (NAME • position) if such a position is found, otherwise NIL. srchpos is updated at each iteration. The Pushdown List and Funaro The linear interrupted scan up ,the parameter stack for a variable bind,ing by can be a special mark called a skip-blip appearing on the stack in a name position (See Figure 12-1). In the value position is a pointer to the posi tion on the stack where the search is to be continued. used to ,make stkeval. page 12.10 work. This is what is It is also used by the funarg device (Section 11). When a funarg is applied, INTERLISP puts a skip-blip on the parameter stack 12.11 wi th a pointer to the funarg array, and another skip-blip at the top of the funarg array pointing back to tho stack. like it has a patch. The effect is to make the stack look The names sind values stored in the funarg, array, will, thus be seen before those higher on title stack. Similarly, setting a variable whose binding ,is contained in the fUflarg array will change only the array. Note however that as a consequence 01: this implementation, the &ame instance 0/ lunar, object cannoet be u&ed, rectJ'r.sil1el,l. 12.12 fI USE OF 'SKIPBLIPS' PARAMETER STACK PARAMETER STACK • • • • • NM NM NM NM SKIP NM NM VAL VAL • .- • • • VAL r+ VAL • VAL VAL NM NM SKIP NM VA NM. VAL f.4-- • • ARGUMENTS TO STKEVAL • BEGIN EVALUATION OF FORM • • • STKEVAL FUNARG FIGURE 12-1 12.13 FUNARG ARRAY Index for Section 12 Page Numbers association list back trace ................ t •••••••••••••••••••••• control pushdown list debugging eval-blip EVALV[VAR;POS] free variables ...••...•.•....•••••••••••••••••••• free variables and compiled functions ••••••••••• FSTKARG[N;POS] BUBR FSTKNTH[N;POS] BUBR FUNARG ,* •••.•••• •••••• ILLEGAL STACK ARG (error m~ssage)' ~ •••••••••••••• locally bound variables MAPOL[MAPOLFN;MAPOLPOS] number stack .........•••• ~.~ •••• i • • • • • • • • • • • • • • • parameter pushdown list •• ••••••••••••••••••• pushdown 1 is t ~ ot •••••••• 0 • • • • • • • •' • • • • • • • • • • • • • • ............ ,.••...••.....•.......•. pushdown list functions .. RETEVAL[POS;FORM] BUBR RETFROM[POS;VALUE] BUBR searching the pushdown list SEARCHeOL[SRCHFN;SRCHPOS] skip .. blip slot (on pushdown list) •• " • '. '0' • • • • • • • • • • • • • • • • • • stack position STKARG[ N; POS] SUBR STKARGS[POS] ., STKEVAL[POS;FORM] SUBR • ,. • 'I •••••••••••••••••••••• STKNAME[POS] SUBR STKNARGS[POS] SUBR STKNTH[N;POS] BUBR STKPOS[FN;N;POS] STKSCAN[VAR;POS] SUBR •••••••••••••••• 0 •••••••••••••••••••••• t1 ••••• ' ••••••••••••••••• .............. ......... ........... . •••' • • • • It • • • • • • • • • • • • • • • • • • • • • • ' value cell ............... variable bindings VARIABlES[POS] f· •••••••••••••••••••••• ....•••• ~ •••••••••••••••••••••• 10 -FORM- • • • • • • • • • • • • • • • • • • • • • • • • • • e. • • • • • • • • • • • • • • • INDEX.12.1 12.1-2 12.2,4 12.2 12.2 12.4 12.10 12.2,5 12.5 12.8 12.7 12.11-12 12.6 12.6 12.11 12.2 12.2,8-9,11 12.1-13 12.6-11 12.10 12.10 12.6,9 ·12.11 12.11 12.2,6,8,10 12.6-7,9-10 12.8-9 12.9 12'.10-11 12.7 12.8 12.7-9 12.6-7,9 12.10 12.1 12.1-6 12.9 12.4-5 12.4 SECTION 13 NUftBERS AND ARITHftETIC FUNCTIONS 13.0 General Comments There are three different types of numbers in INTERLISP: small integers, large integers, and floating point numbers. 1 Since a large integer or floating point number can be (in value)' any 36 bit quantity (and vico versa), it 1s necessary to distinguish between those 36 bit quantities that represent large integers or floating point numbers, and other INTERLISP pointers. We do this by -boxing- the number, which is sort of like a special ·cons·: when a large integer or floating pOint number is created (via an arithmetic operation or by read), INTERLISP gets a new word from -number storage· and puts the large integer or floating point number into that word. INTERLISP then passes around the pointer to that word, i.e., the -boxed number-, rather than the actual 36 bit quantity i tse If. Then when a numeric function needs the actual numeric quantity, 1t performs the extra level of addressing to obtain the -value- of the number. This latter process is called ·unboxing-. Note that unboxing does not use any storage, but that each boxing operation uses one new word of number storage. Thus, if a computation creates many large integers or floating point numbers, i.e., does lots of boxes, it may cause a garbage collection of large integer space, GC: 18, or of floating point number space, GC: 16. 1----------~---~-~----------~--------~------~-----------------------------~---- Floating point numbers are created by the read program when a • or an E appears in a number, e. g. 1000 is an integer, 1000. a floating point number, as are lE3 and I.E3. Note that 10000, 1000F, and IE30 are perfectly legal literal atoms. 13.1 13.1 I~teger Arithmetic Small Integers Small integers are those integers for which smallp is true, currently integers whose absolute value is less thalll 1536. Small integers are boxed by offsetting them by a constant so that they overlay an area of INTERLISP's address space that does not correspond to any [NTERLISP data typo. 'Thus boxing small numbers does not use any storage, and furthermore, each small number has a unique representation, so that not be used for ~ may be used to check equality. large eq[2000;addl[1999]] is NIL! in'tegers ~ or floating Note that point ~ numbers, should e. g. , or equal must bo used instead. Integer Functions All of the functions described below work on integers. Unless specified otherwise, i f given a floating I.oint number, they first convert the number to an integer by truncating the fractional bit~, e.g., iplus[2.3;3.8]=5; if given a non-numeric argument, they generate an error, NON-NUMERIC ARG. It is important to use the integer arithmetic functions, whenever pOSSible, in place of the more general arithmetic functions which allow mixed floating point and integer arithmetic, e.g., ~lus integer functions compile o'pen, vs plUS, igreaterp vs greaterp, because the and therefore run faster than the general ari thmetic functions. and because the compiler is ·smart· about eliminating unnecessary boxing and unboxlng. Thus, the expression (IPLUS (IQUOTIENT (ITIHES N 100) H) (ITIMES X Y» will compile to perform only one box, the outer one, and the expression (IGREATERP (IPLUS X Y) (IDIFFEREHCE A B» 13.2 will compile to do no boxing at all. Note that the POP-1Q 1$ a 36 bit machine. so that all integers are between -2t35 and 2t35-1. 2 Adding two integers which produce a result outside this range causes overflow, e.g., 2t34 + 2t34. The procedure on overflow is to return the largest possible integer, i ••• 2t35 - 1. 3 Xi + Xz + ••• + iminus[x] - x idifference[XjY] x - Y add1[x] x+ sub1[x] x .;. 1 "n 1 the product of !l'!Z' ••• !" iquotient[x;y] x/y truncated, e.g., iquotient[3:Z]-1, iquotient[-3,Z]--1 iremainder[x;y] the remainder when ! is divided by l' e.g., iremainder [3:2]-1 igreaterp[x;y] T if x > y: NIL otherwise 2-----------------------------------------------------------------------------Approximately 34 billion 3 If the overflow occurs by trying to create a negative number of too large a magnitude, -2t35 is used inst.ad of 2t35-1. 13.3 < y; NIL otherwise ilessp[x;y] T is x zerop[x] defined as eq[x;O]. Note that zerop should not be u.sed for floating point numbers because 'it uses ~. Use eqp(x,O] instead. minusp[x] T jLf ! is ne,gative; Does not NIL otherwise. con'vert ! to an integer, but simply checks sign bit. eqp[n;m] T jLf !! and othf3rwise. m are (!!9. !,g. or equal numbers, may be used if !!. and to Ibe small integers.) ~ NIL m are known does not convert !!. and m to integers, e.g., eqp[ZOOO;ZOOO.3]=NIL, but it can be used to compare an integer and a floating \ point number, e.g., eqp[ZOOO;ZOOO.O]=T. not generate an error if !! or smallp[n] mare !!9.2 does not numbers. T if !! 15 a small integer, else NIL. smallp does not generate an error if !! is not a number. fixp[x] ! if ! is an integer, else NIL. Does not generate an ttrror i r ! is not a number. fix[x] Converts ! to an integer by truncating fractional bits, e.g., flx[Z.3] = Z, fix[-1.7] = -1. If ~ is alrElady an integer, fix[x]=x and doesn't use any stor'age .4 4------------------------------------------------------------------------------Since FIX is also a lispx leommand (Section ZZ), typing FIX directly to 1 ispx wi 11 not cause the func:tion fix to be called. 13.4 lambda no-spread, value is logical and of all its arguments, as an integer, e.g., 10gand[7;5;6]-4. lambda no-spread, value is the logical its arguments, as an ~ of all integer, e.g., logor[ 1;3 ;9]-11. lambda no-spread, value is the logical exclusive ~ of its arguments, as an integer, e.g., 10gxor[II;5] • 14, 10gxor[11;5;9] • 10gxor[14;9] • 7. lsh[n;m] (arithmetic) left shift, value is n*Ztm,i.e., shifted left !!! places. negative. ~ is !1 can be positive or I f ! is negative, ~ is shifted ri,ht -m places. rsh[n;m] (arithmetic) right shift, value is n*Zt-m, i.e., is shifted right negative. llsh[n:m] mplaces. !1 can be positive or If!!! is negative, !1 is logical left !hift. ~ On PDP-10, le/t -! places. !!!h is equivalent to Ish. lrsh[n:m] !ogica~ right !hift. The difference between a logical and arithmetic right shift lies in the treatment of the sign bit for negative numbers. For arithmetic right shifting of negative numbers, the sign bit is propagated, i.e., the value is a negative number. For logical right shift, zeroes are propagated. Note that shifting (arithmetic) a negative number 'all the way' to the right yields -1, not O. 13.5 13.2 Floating Point Arithmetic All of the functions described below work on floating point numbers. Unless specified otherwise, if given an integer, they first convert the number to a floating point number, e.g., fIJlus[I;2.3] = fplus[I.0;2.3] • 3.3; it' given a non-numeric argument, they generate an error, NON-NUMERIC ARG. The largest floating point number is 1.7014118£38, the smallest positive (nonzero) floating point number is 1.4693679E-39. same as for integer arithmetic. For underflow, i.e. trying to create a number o. of too small a magnitude. the value will be fminus[x] The procedure on overflow is the - x X1 * xZ . ••• • xn fquotient[x;y] x/y fremainder[x;y] the remainder when ! is divided by l. e.g., fremainder[I.0:3.0]= 3.72529£-9. minusp[x] T if ! is negative; NIL otherwise. Wdrks for both integers and floating point numbers. eqp[x;y] T i1F ! and l are g, or equal numbers. discussion page 13.4. fgtp[x:y] T if x ) y, NIL otherwise. 13.6 8ee is ! floatp[x] if ! otherwise. is a floating point NIL number; Does lIot give an error if ! is not a number~ Note that il numberp(x} is true. thell either /txp(x} or Iloatp(x] is true. float[x] Converts ! to a floating point number, e.g., flo.t[O] • 0.0. 13.3 The Mixed Arithmetic functions in this section are 'contagious floating point ,arithmetic' functions, i.e., if any of the arguments are ,floating point numbers, they act exactly like floating point functions, and float all arguments, and return a floating point number as their value. Otherwise, they act like the integer functions. argument, If given a non-numeric they generate an error, NON-NUMERIC ARG. minus[x] - x difference[x;y] x - y quotient[x;y] if ! and I are both integers, \ value is iquotient[xiY], otherwise fquotient[x;y]. remainder[x;y] if ! and I are both integers, value iremainder[x;y], otherwise fremainder[xiY]. 13.7 is greaterp[x:y] T if x > y, NIL otherwise. lessp[ x ;.Y] T if x < Y. NIL otherwise. abs[x] ! if x minl~, 13.4 > O. otherwise -x. !!!! uses greaterp and (not igreaterp and iminus). Special Functions These functions are all "borrowI9d" from the FORTRAN library and handcoded in INTERLISP via ASSEMBLE by J. W. Goodwin. They utilize a power series expansion e.g., 5in[30]-.5 and their values are (supposed to be) 27 bits accurate, exactly. expt[m:n] If!!! is an integer and !!. is a value is mtn. positive integer. value "is an integer, e.G, exp1~[3;4].81, otherwise the value is a floating point number. If!!! is negative and !!. fractional, an error is generated. sqrt[n] value is a square root of !! as a floating point number. !! may be fixed or floating Generates an error if !! is negative. point. sqrt[n] is about twice as fast as expt[n;.5] log[x] valllie is natural logari thm of ! pOint number. antilog[x] as a floating ! can be integer or floating pOint. value is floating point number whose logarithm 1s !. ! can be integer or floa.ting point, antilog[l] - e • 2.71828 ••• 13.8 8.g., sin[x;radiansflg] ! in degrees unless radlansflg=T. Value 1s s1ne of ! as a floating point number. cos[x;radiansflg] Similar to sln. tan[x:radiansflg] Similar to sin. arcsin[x:radiansflg] ! is a number between -1 and 1 (or an error is generated). point The value of arcsin is a floating is and number, radiansflg=T. In in degrees other arcsin[x;radiansflg]-! then unless words, if sin[z;radiansflg]=!. The range of the value of arcsin is -90 to +90 for degrees, -n/2 to n/2 for radians. arccos[x,radiansflg] Similar to arcsin. Range is 0 to 180, 0 to arctan[x;radiansflg] Similar to arcsin. Range is 0 to 180, 0 to n. rand[lower:upper] Valu~ ft. is a pseudo-random number between lower and upper inclusive, i.e. rand can be used to generate a sequence of random numbers. integers, the value of If both limits are rand is an integer, otherwise it is a floating point number. The algorithm is completely deterministic, i.e. given the same initial state, rand produces the same sequence of values. The internal state of rand is ini tialized using the function randset described below, and randstate. 13.9 is stored on the free variable Val1IJe is internal state of rand after randset has randset[x] finished operating, int'Bgers. ~=T, If ~=NIL, as a dotted pair of two value is current state. If rands tate is initialized using the clocks. Othl9rwise. ! is interpreted as a previous internal sta·teti.e. a value of randset, and 1s used to reslBt randstate. 13.5 For example, 1. (SETO OLDSTATE (RANOSET» 2. Use rand to generate some random numbers. 3. (RAHDSET OLDSTATE) 4. rand will generate same sequence as in Z. Reusing Boxed Numbers - SETH rplaca and rplacd provide a way of cannibalizing list structure for reuse in order to avoid making new structure and causing garbage collections. 6 This section describes an analogous function for large integers and numbers, setn. floa~ing point setn is used like setq, i.e., its first argument is considered as quoted, its second is evaluated. set is a large integer or If the current value of the variable being point number, the new value is deposited into that word in number storage., i.e., no new storage is used. 8 If the current floa1~ing value is not a large integer or' floating point number, e.g., it can be NIL, setn operates exactly like setg, i.e., the large integer or floating point number is boxed, and the variable is set. This eliminates initialization of the variable. 6-------------------------------··---~---------------- -------------------------- This technique is frowned upon except in well-defined, localized situations where efficiency is paramount. 6 The second argument to setn must always be a number or a NON-NUMERIC ARG error is generated. 13.10 setn will work interpretively, i.e., reuse a word in number storage, but will not yield any savings of storage because the boxing of the second argument will still take place, when it is evaluated. The elimination of a box is achieved only when the call to setn is compiled, since !!!n compiles open, and does not perform the box if the old value of the variable can be reused. Caveats concerning use of SETH There are three situations to watch· out for when using!!!n- The first occurs when the same variable is being used for floating point numbers and large integers. If the current value of the variable is a floating point number, and it is reset to a large integer, via !!!rr. the large integer is Simply deposited into a word in floating point number storage, and hence will be interpreted as a floating point number. Thus. "(SETQ FOO 2.3) 2.3 ,,(SETH FOO 10000) 2. 189529E-43 Similarly. if the current value is a large integer, and the new value is a floating point number. equally strange results occur. The second situation occurs when a !!!! variable is reset from a large integer to a small integer. large integer In this case, the small integer is simply deposited into storage. It will then print correctly, and function arithmetically correctly, but it is not a small integer. and hence will not be ~ to another integer of the sam. value, I.g., 13.11 .. (5ETQ FOO 10000) 10000 .. ( SETN F4)() 1) 1 .. (IPlUS FOO 5) 6 "(EQ Foo 1) NIL "(5MALLP FOO) NIL In particular, note that zerop WJl1l return NIL even if the variable is equal to O. Thus a program which begins with FOO set to a large integer and counts it down by (SETH FOO (SUBI FOO» mu~.t terminate with (fQP FOO 0), not (ZEROP FOO). Finally, the third situation to IIlatch out for occurs when you want to save the current value of a setn variable for later use. For example, if FOO is being used its by setn, and the user wants to save current value on FIE, (SETQ FOO FIE) is not surficent, since the next setn on Foo will also change FIE, because its changes the wQlrd in number storage pointed to by FOO, and hence pointed to by FIE. The number must be copied, e.g. , (SETQ FIE (IPlUS FOO», which sets FIE to a new word in number storage. setn[var;x] nlarrtbda function like setq. y.!.!: is quoted, ! is evaluated, and its value must be a number. will be set to this number. of Y!r is a large number, that cannibalized. word If the current value integer or floating in y!.!: number storage point is The value of setn is the (new) value of !!!.. 13.6 Box and Unbox Some applications may require that a user program explicitly perform the boxing and unboxing operations that ar"e usually implicit (and invisible) to most 13.12 programs. The respectively. functions that perfona these operations are loc and vag For exam'ple, if • user program executes a TENEX J8YB using the ASSEMBLE directive. the value of the ASSEMBLE expression will have to be boxed --») .. to be used arithmetically, e.g., (IPlUS X (lOC (ASSEMBLE It must be emphasized that Arbi trarll unboxed numbers should not be passed around flS because they can cau.se trouble lor the garbage collector. ordtnflrll l1.lue.t For example, suppose the value of 2S were 150000, and you created (VAG X), and this just happened to be an address on the free storage list] The next garbage collection could be disastrous. For this reason t the function vag must be ~sed with extreme caution when its argument's range is not known. One place where vag is safe to use is for performing computations on stack positions, which are simply addre.s.ses of the corresponding positions (cells) on the stack. them. To treat these addresses as -"umbers, the program must first box Conversely, to convert numbers to corresponding stack positions, the program must unbox them. Thus, suppose ! were the value of stkarg, i.e. II corresponds to a position on the parameter stack. To obtain the next position on the stack, the program must compute (VAG (ADD1 (lOC X»). Thus if 132002,7 (lOC X) would be ~ 3Z00ZQ,8 (ADD1 (LOC X» would be ~ were 32003Q, and (VAG (ADD1 (lOC X») would be 13Z003. Note that rather than starting with a number, and unboxing it to obtain its numeric quantity, here we started with an address, i.e., a 36 bit quantity, and 7---~----------------------------··---·-------------------------.-----------~-An INTERLISP pointer (address) which does not correspond to the address of a list structure, or an atom, or a number, or a string, is printed· as In, g given in octal. B Q following a number means the numeric quantity is expressed in octal. 13.13 wishing to treat it as a number" boxed it. For example, loc of an atom, e.g., (LOC (QUOTE FOO», treats the atom as a 36 bit quantity. and makes a number out of it. If the address of the a1tom FOO were 125000, (LaC (QUOTE fOO» 125000, i.e. the location of f~). would be It is for this reason that the box operation is called loc, which is short for location. 9 Note that FOO does not print as 1364110 (125000 in octal) because the print routine recognizes that it is nn atom, and therefore prints it in a special way, i.e. by printing the individual characters that comprise it. Thus (VAG 125000) would print as fOO, and Ulould be in fact fOO. loc[x] Plaktas a number out of !, i. e. , returns the location of !. vag[x] The inverse of loco of The compiler eliminates (IPLUS X (LOC (ASSEMBLE --») ~~ ! must be a number; the value is the unbox of !. Iltxtra vag's and loc's for example will not box the value of the ASSEMBLE, and then unbox it for the addition. 9------~-~--------~------------------------~-------------------------------~~-~ vag is an abbreviation of Y,!lue set. 13.14 Index for Section 13 Page Numbers ABS[X] AOOl[X] ANTILOG[X] ARCCOS[X;RADIANSFLG] ARCCOS: ARG NOT IN RANGE (error message) ARCSIN[X;RADIANSFLG] ARCSIN: ARG NOT IN RANGE (error message) ARCTAN[X.RADIANSFLG] arithmetic functions ASSEMBLE box boxed numbers boxing COS[X;RAOIANSFLG] OIFFERENCE[X;Y] EQP[X;Y] SUBR EQUAL[X;Y] EXPT[M;N] FGTP[X;Y] SUBR FIX[X] FIXP[X] FlOAT[X] floating point arithmetic floating point numbers FlOATP[X] SUBR ........ ......................................... ........................................... .. .............................. .. · ................................. .................................... . .................................. ............... ......................... . ' ~ FHINUS[X] •••• s • • • • • • • • • • •, • • • • • • • • • • • • • • • • • • • FPlUS[Xl;X2; ... ;Xn] SUBR* FQUOTIENT[X;Y] SUBR FREHAINOER[X;Y] SUBR FTIHES[Xl;X2; ... ;Xn] SUBR* GC: 16 (typed by system) GC: 18 (typed by system) GREATERP[X;Y] SUBR IOIFFERENCE[X;Y] IGREATERP[X;Y] SUBR IlESSP[X;Y] ILLEGAL EXPONENTIATION: (error message) ........................ ......................... IMINUS[X] •••••••••••••••••••••••••••••••••••• ,,'. .............................. integer arithmetic IPlUS[Xl;X2; ... ;Xn] SUBR* IQUOTIENT[X;Y] SUBR IREMAINOER[X;Y] SUBR ITIHES[Xl;X2; ..• ;Xn] SUBR* large integers lESSP[X;Y] LLSH[N;H] SUBR lOC[X] SUBR LOG[X] lOGANO[Xl;X2; .•. ;Xn] SUBR* LOGOR[Xl,X2; .•• ;Xn] SUBR* lOGXOR[Xl;X2; ..• ;Xn] SUBR* LRSH[N;H] LSH[N,H] SUBR " HINUS[X] SUBR HINUSP[X] SUBR mixed arithmetic ....................... .................................. ............................. ........ . ' ....................... ........ ........................ .. ··................................. ................................ INDEX .'13.1 13.8 13.3 13.8 13.9 13.9 13.9 13.9 13.9 13.Z-10 13.13 13.14 13.1 13.1-Z,10-12 13.9 13.7 13.Z,4,6 13.2 13.8 13.6 13.4 13.4 13.7 13.6-7 13.1-2,4,10 13.7 13.6 13.6 13.6 13.6 13.6 13.1 13.1 13.8 13.3 13.3 13.4 13.8 13.3 13.Z-5 13.3 13.3 13.3 13.3 13.1-2,10 13.8 13.5 13.13-14 13.8 13.5 13.5 13.5 13.5 13.5 13.7 13.4,6 13.7-8 Page Numbers NON-NUMERIC ARG (error message) numbers octal overflow PlUS[Xl;X2; ... ;Xn] SUBR* Q (following a numb~r) QUOTIENT[X;Y] SUBR RAND[lOWER;UPPER] random numbers RANDSET[X] RANDS TATE REMAINDER[X;Yl SUBR RSU[N;M] SETN[VAR;X] NL SIN[X;RADIANSFlG] small integers SMAllP[N] SQRT[N] SQRT OF NEGATIVE VALUE (error message) SUBl[X] TAN[X;RADIANSFlG] TENEX TIMES[Xl;XZ; ... ;Xn] SUBR* unboxed numbers unboxing VAG[X] SUBR ZEROP[X] I (followed by a number) • < ••••••• ................................ ...................................... INOEX.13.Z 13.2,6-7 13.1-14 13.13 13.3,6 13.7 13.13 13.7 13.9 13.9 13.10 13.9-10 13.7 13.5 13.10-12 13.9 13.1-2 13.2,4 13.8 13.8 13.3 13.9 13.13 13.7 13.13 13.1-2,12 13.13-14 13.4 13.13 SECTION 14 INPUT/OUTPUT FUNCTIONS Files 14.'1 All input/output functions in INTERLISP can specify their' source/destination file with an optional extra argument which is the name of the file. must be opened as specified below. This file If the extra argument is not given (has value NIL) •. the file specified as ·primary· for input (output) Normally these are both T. for teletype input and output. is used. However, the primary input/output file may be changed by input[file]l Sets fIle as the primary input file. Its value is the name of the old primary input file. input[] returns current primary input file, which is not changed. output[file] Same as input except operates on primary output file. Anll file which i& made primarll mu&t haue been preuiou&l,l input/output, except lor the file T, .hich i& al.all& open. opened lor 1---~-------------------------------------------------------------~-----------The argument name file is used for tutorial purposes only. The arguments to all subrs are U.~and Was described in arg1ist, Section 8. 14.1 Opens file for input, and sets it as the primary infile[ r'ile] input file. 2 The value of infile is the previous prililary input ·file. as input[file]. If file is already open, same Generates a FILE WON'T OPEN error if file won't open, e.g., file is already open for outl,ut. Opens file for output, and sets it as the primary outfile[file] output f11~.3 The value of outfile is the previous priulary output file. If file is already open, samEI as output[file]. Generates a FILE WON'T OPEN errcJr if file won't open, e.g., if file is already open for input. For all input/output functions, names, i.e. file can be file follows the TENEX conventions for file prefixed by a directory name enclosed in angle brackets, can contain alt-modes or control-F's, and can include suffixes and/or version numbers. Consistent with TENEX, when a file is opened for input and no version number is given, the highest version number is used. Similarly. when a file is opened for output and no version number is given, a new file is created with a version number one highelr than the highest one currently in use with that file name. Regardless of the file name given to the INTERLISP function that opened the 2-----~-----------------------------------------------------------~-----------To open fi Ie without changing the primary input file, perform input[infile[file]]. 8 To open file without output[outfile[f1le]]. ch,snging the 14.2 primary output file, perform file, INTERLISP maintains only full -TENEX file names4 in its internal table of open files and any function whose value is a file name always returns a full file name, e.g. openp[FOO]=FOO.;3. Whenever a file argument is given to an ilo function, INTERLISP first checks to see if the file is in its internal table. If not, INTERLISP executes the appropriate TENEX JSYS to -recognize- the file. If TENEX does not successfully recognize the file, a FILE NOT FOUND error is generated. 6 If TENEX does recognize the file, it returns to INTERLISP the full file name. Then, INTERLISP can continue with the indicated operation. If the file is being opened, INTERLISP opens the file and stores its (full) name in the file table. If it is being closed, or written to or read from, INTERLISP checks its internal table to make sure the file is open, and then executes the corresponding operation. Note that each time a tull file name is not used, INTERLISP must call TENEX to recognize the name. Thus if repeated operations are to be performed, it is considerably more efficient to obtain the full file name once, e.g. via infilep or outfllep. Also. note that recognition by TENEX is performed on the user's entire directory. Thus, even if only one file is open, say FOO.;I, FS (F altmode) will not be recognized if the user's directory also contains the file FIE.: 1. Similarly, it is possible for a file name that was previously recognized to become ambiguous. for example, a program performs infile[FOO], opening FOO.: 1, and reads several expressions from FOO. Then the user types control-C, creates a FOO.:2 and reenters his program. Now a call to read giving it Foo as its file argument will generate a FILE NOT OPEN error, because TENEX will recognize FOO. as FOO.:Z. 6 except for infilep, outfilep and openp, which in this case return NIL. 14.3 infilep[file] Ret;urns full file name of file if recognized by TE~JEX. NIL otherwise. The full file name will cOl1ltain a directory field only if the directory differs from the currently attached directory. Recognition is in ver'sion number input context, is given, the i.e. highest if no version nuaber is returned. in/tlep and outlilep do not open anu lile&. or change the primaru Itle&, theu are pure predicate&. outfilep[file] Similar to infilep, output context, given, i.e. a version except is in if no version number is number recognition one higher than the highest version number is returned. closef[flle] Closes file. Generates an error, FILE NOT OPEN, if file not open. close the teletype. pr~mary If file is NIL, it attempts to primary input file if other than Failing that, it attempts to close the output file if other than teletype. Failing both, it returns NIL. If it closes any file, it returns the name of that file. If it closes either of the primary files, it resets tha~ prilDary file to teletype. closeall[ ] Closes all open files (except T). Value is a list of the.files closed. openp[file;type] If ~~=NIL, value is file (full name) if open either for reading or for writing. value is NIL. 14.4 ~ is Otherwise If !lI!.! is INPUT or OUTPUT, value is file if open for corresponding type, otherwise NIL. If !l2! is BOTH, value is file if open for both input and output, (See iot11e, page 14.6) otherwise NIL. Note: the value of .2J!!!!.I! is NIL if file 1s not recognized, 1.8 • .2J!!!!.I! does not generate an error. openp[] returns a list of all files open for input or output, excluding T. Addressable files For most applications, files are read starting at their beginning and proceeding sequentially, i.e. the next character read is the one immediately following the last character read. Similarly; files are written sequentially. A program need not be aware of the fact that there is a file pointer associated , with each file that points to the location where the next character is to be read from or written to, and that this file after each input or output operation. Th~s ~ointer is automatically advanced section describes a function which can be used to reposttton the file pointer, thereby allowing a program to treat a file as a large block of auxiliary storage which can be access randomly.B For example, one application might involve writing an expression at the be,tnntn, of the file, and then reading an expression from a specified point in its 6-·-----~--------------------------------------------------------~-------------Random access means that any location is as quickly accessible as any other. For example, an array is randomly accessible, but a list is not, since in order to get to the n!h element you have to sequence through the first n-1 elements. 14.6 mtddle.? A file used in this fashion is. much like an array in that it has a certain number of addressable locations that characters can be put into or taken from. However, unlike arrays, files can be enlarged. For example, if the file pointer is positioned at the end of a file and anything is written, the file "grows." It is also possible tIC) position the file pointer beuond the end of file and then to write. 8 In this case, the file is enlarged, and a "hole" is created, which can later be wr'itten into. Note that this enlargement only takes place at the end of a file: it is not possible to make more room in the middle of a file. In other words, if expression A begins at positon 1000, and expression B at 1100, and the program attempts to overwrite A with expression C, which is 200 characters long, part of B will be clobbered. 1ofile[file] Opens file for both input and output. fil!. Does not change either primary input or primary output. default Value is is same If no version number is given, as for infile, i.e. highest version number. sfptr[file;address] ~ets file ~oin!e! for file to address. 9 Value is 7---~h~;--;;;;;;~;;;-~~~~i~--;;;~1;;;--;h~-f1i~--b;-~~~~--~~;--;;;h-~~~~~--;~d output. This can be achie'ved via the function iorile described below. However, random file input lor output can be performed on files that have been opened in the usual way by infile or outfile. 8 If the program attempts to read beyond the end of file, an END OF FILE error occurs. 9 TENEX uses byte addressing; the address of a character (byte) is the number of characters (bytes) that precede it in the file, i.e., 0 is the address of the beginning of the file. However, the user should be careful about computing the space needed for an expression, since end-of-line is represented as two characters in a file, but nchars only counts it as one. 14.6 old setting. file. 10 address--1 corresponds to the end of If address-NIL, sfptr returns the current value of file pointer without changing it. fi1epos[x;file:start;end;skip;tail]11 10). Searches f!!! for! a lastrpos (Sec'tion Search begins at start (or if start=NIL, the current position of file pointer), and goes to end (or if !.rul=NIl, to the and of file). address Value is of start of match, or NIL if not found. skip can be used to specify a character which matches any character in the file. If tail is T, and the search is successful, the value is the address of the first character alter the sequence of characters corresponding to !, instead of the starting address of the sequence. In either case, the file is left so that the next i/o operation begins _at the address returned as the value of filepos. 1j------~----------------~~---------------------------------------------------Note: if a file is opened for output only, either by outfile, or openf[ file; 100000q] (see page 14.8), TENEX assumes that one intends to write a new or different file, even if a version number was specified and the corresponding file already exists. Thus, sfptr[file;-1] will set the fi Ie pointer to O. If a file is opened for both reading and writing, either by iofile or openf[file:300000q]. TENEX assumes that there might be material on the file that the user intends to read. Thus, the initial file pointer is the beginning of the file, but srptr[file;-l] will set it to the end of the file. Note that one can also open a file for appending by openf[file;20000q]. In this case, the file pointer right after opening is set to the end of the existing file. Thus, a write will automatically add material at the end of the file, and an sfptr 1s unnecessary. ' t1 filepos was written by J.W. Goodwin. 14.7 Openf opens file. openf[file;x] aCCIBSS ! is a number whose bits specify the and mode for file, i . e. ! corresponds to the second argument to the TENEX JSYS OPENF (see JSY.s Manual). Value is full name of file. openf permits opening a file fc.r read, write, execute, or append, etc. and allows specification of byte size, i.e. a byte size of 36 enables reading and writing of full words. openf does not affect the primary input or output file set tings, and does not check wh4!ther the file is already open - i. e. the same file can be opened more than once, possibly for different purposes. 12 openp will work for files opened with !!)penf. The first argument to openf can also be a number, which is then interpreted as JfN. This results in a more eff'1cient call to openf. and can be signficant if the user is making frequent call:s to openf, e.g. switching byte sizes. JfN functions" 3 JFN stands for Job file !lumber. It is an integral part of the TENEX file system and is described in [Plur't], and in somewhat more detail in the TENEX JSYS manual. The following function can be used to obtain the JfN for an already opened file. opnJfn[ file] returns the JFN for fi Ie. If file not open, generates a FILE NOT OPEN error. i2---------------------~--------··-----------------------------~-----~---------The -thawed- bit in'! permits opening a file that is already open. 13 The JFN functions were writt4!n by J.W. Goodwin. 14.8 Example:, to write a byte on a file [DEFINEQ (BOUT (LAMBDA (FILE BYTE) (LOC (ASSEMBLE NIL (CQ (VAG BYTE» (PUSH NP • 1) (CQ (VAG (OPNJFN FILE») (POP NP • 2) (JSYS 51Q) (HOVE 1 • 2)] or to read a byte from a f1le [DEFINEQ (BIN (LAMBDA (FILE) (LOC (ASSEMBLE NIL (CQ (VAG (OPNJFN FILE») (JSVS 50Q) , (HOVE 1 • 2] Making BIN and BOUT substitution laacros can save boxing and unboxing in compiled code. The following functions are available for direct manipulation of JFN's: gtjfn[file;ext;v;flags] sets up a 'long' call to GTJFN (see JSYS manual). file is a file name possibly containing control-F and/or alt-mode. ext is the default extension, y the default version (overriden if f1le specifies extension/version, e.g. FOO.COM;2). flags 1s as described on page 17, section 2 of JSYS manual. f!!! and ext may be strings or atoms; y and flags must be numbers. ' Value is JFN, or NIL on errors. rljfn[ jfn] releases jfn. rljfn[-l] releases all JFN's which do not specify open files. jfns[jfnjac3] Value of rljfn is T. converts jfn (a slDall number) to a fl1e name. 14.9 ac3 is either NIL, ,meanlngformat the file name as would openp or other INTERLISP file funct1.ons, or else is a number, meaning formata<;cordingto,JSYS manual. The value of jfnsis atomic e~c,ept where enough options are specified by ac3 to exceed atom size (2 100·~hara~ters). In this case, the value is returned as a string. 14.2 Input Functions Most of the /unctions described below have an (optional) (!rgument l.1!!!.. which s peciJi es the name 0/ the Ji leon which the operat ton' is talc.6; pl ace. If that argument is NILi theprtmarll input/ile will beus'ed. to Note, in all INTERLISP sumbolic files, end-of-line is indicated by the characters carriage-return and line-feed in that order. Accordinglu, on input from Jiles, INT¥JfI$Pwill s~,tp all ltne-feedswhich immediate"lll /ollow' carriage-returns'. On input /rom teletllpe, INTERLISP will echo a line-feed whenever a carriage-return ts input. For all input functions except ~adc and peelc, when reading /rom the teletype, control-A erases the last character tllped in, echoing a \ and the erased character. Control-A will not baclc.up bellong the last carriage return. ,. Typing control-Q causes INTERLISP print II and clear the input buller. i.e. erase the entire line bacl to the last carriage-return. When reading from a Itle. and an end oj file is encounte'red. all input functions close the lile and generate an,error, END OF FILE. to read[file;flg] Re~ds one S-expression from file. Atoms are deltmited by parentheses, brackets, double quotes, spaces, and carriage~returns. To input an atom whic:h contains one of these syntactic delimiters, prec:eded the delimiter by the escape character X, e.g. AB,(C, is the atom AB(C, XX is the atom X. i~-------------------------------------------------------------~--------------~ Actually. INTERLISP skips the next character after a carriage-return without looking at it at all. : 'J ">r 14.10 Strings are delimited by double quotes. To input a string containing a double qUote or a I, precede it by X. e.g. "ABX"C" is the string AB"C. Note that I can always be typed even if next character is not 'special', e.g, "AlBIC is read as ABC. If an atom is interpretable as a number, read will create a number, e.g. lE3 reads as a floating point number. 103 as a literal atom, 1.0 as a number. 1,0 as a literal atom, etc. 'Note that an integer can be input in octal by terminating it with a 0, e.g. 170 and 15 read in as the same integer. The setting of radix. page 14.22, deteMmines how integers are printed. i.e. with or without 0'5. When reading f[tfm the teletllpe, all input is line-buffered to enable the action of control-Q. Thus no characters are actuallll .seen bll the program until a carriage-return i.s typed. However. for reading bll read or uread. when a matching right parenthe.si.s i.s encountered. 'he effect i.s the .same-GS though a carriage return were tllped. i.e. the characters are tran.smitted. To indicate thts, INTERLlSP alsoprtnt.s a carriage-return Line-feed on the teletllpe. flg=T suppresses the typed by following read parenthesis. carriage-return a normally matching right (However. the characters are still given, to read - 1.e. the user does not have to type the carriage return himself.) ratom[f1Ie] Reads 1n one atom from file. Separation of atoms 16-~-----~-------------------------------------------- ------------------------- Unless control[T] has been performed (page 14.24). 14.11 is defined by described below. action of setsepr and setbrk X is also an escape character for ratom, and the remarks concerning control-A, control-Q, and line-buffering also apply. If the characters comprising the atom WOUld' nonnally be interpreted as a number by read, that number is also returned by ~. Note however tha't ratom takes no speCial action for • whether or not it is a break character, 1.e. ratom never makllts a string. The purpose oj ratom. rstring. setbrk. and setsepr is to allow the user to wri te his own read program wi t~lout hailing to resort to reading character bll character and then calling pac!!:. to male atoms. The function uread (page 14.16) is auailable if the user wants to handle input as read does, i.e. same action on parentheses, double quotes. square brackets :---etot. spaces, and carriage-return. but in addition, to spLit atoms that contain certain characters, as specified bU setbJ~l and setsepr. rstring[file] Reads in one string from file, terminated by next break or separator character. Control-A, control· Q. nnd I have the same effect as with ratom. Note that the brealt. or separatol' character that terminates a call to ratom or rstrtng is not read bll that call" but remains in the buffer to become the first character seen bll the next readilt, function that is called. ratoms[a;file] Calls ratom repeatedly until the atom ! is read. Returns a list of atoms read. not including !. setsepr[lst;flg] Set separator characters. setbrk[lst;flg] Set brea! characters. 14.12 Value is NIL. Value is NIL. For both setsepr and setbrk", 1st is a list of character codes, fIg determines the action of setsepr/setbrk as follows: NIL clear out old tables and reset. o clear out only those character"s in 1st i.e. this provides an unsetsepr and unsetbrk. 1 add characters i.~ 1st to corresponding 'table. Characters specified by setbrk will delimit atoms, and be returned as separate atoms themselves by ratom. 18 Characters specified by setsepr will be ignored and serve only to separate atoms. For example, if $ was a break character and ] a separator character, the input stream ABC]]DEFSGH]SS would be read by 6 calls to ratom returning respectively ABC, DEF, $, GH, S, S. Note that the action of X is not affected by setsepr or setbrk. To defeat the action of X use escaper]. as described below. The elements of 1st may also be characters e.g. setbrk[ (X( X» 1 has the same effect as setbrk[(40 41)]. Note however that the 'characters' 1,2 ••• 9,0 will be interpreted as character code$ because they are numbers. Initially, the break characters are"[ ] ( ) and • and the separator characters are space, tab, carriage-return, line-feed, end-of-line, and form-feed. (Note that • is not a break or separator character.) setbrk[ T] sets the break characters to their initial ~ett1ngs, and setsepr[T] does the same for the separator characters. getsepr[] Value 1s a list of separator character codes. i6--~-~--~----------~----------·---------------------- ------------------------- but have no effect whatsoever on the action of read. 14.13 getbrk[] Value is a list of break character codes. escape[flg] If flg=NIl, chalracter. makes X act like every other Normal setting is escaper T]. The value of escape is the previous setting. ratest[x] If ! . T, ratest returns T if a separator was enc4)untered immediately prior to the last atom read by ratom, NIL otherwise. If ! • NIL, ratest returns T if last atom read by or rat~ read was a break character, NIL othurwise. If ! . 1, ratest returns T if last atom read (by read or ratom) contained a X (as an escape cha."acter, e. g., X[ or XAXBXC), NIL otherwise. readc[file] Reads the next character, including ", Value is the character. Action of ", etc. readc is subJect to line-buffering, i. e. readc will not return a value until the line has been terminated even if a character has been typed. control-A and contro1-Q will have Thus, their usual effElct. If control[ T] has been executed (page 14 • ~~4) , defeating 1ine-buffering, readc wi 11 return a value as soon as a character is typed. In addition, if control-A or control-Q are typed, reac~ will return them as values. 14.14 peekc[filejflg] Value is the next character, but does not actually read it, i.e. remove it from the buffer. If ' !!a-NIL, peekc is not subject to line-buffering, i.e. it returns a value as soon as a character has been typed. If!!H-T, peeke waits until the line has been terminated before returning its value. This means that control-A and control-Q will be able.to perform their usual editing functions. lastc[file] Value is l!!! uread[filejflg] (for !!ser read).. ~haracter read from file. Same as read except it uses separator and break characters set by setsepr and setbrk. This function is useful for reading in list structure in the normal way, while splitting atoms containing special characters. Thus with space a separator character, and break characters of ( ) • and • the input stream (IT'S EASY.) is read by ~ as the list (IT • S EASY X.) Note that ( ) [ ] and • must be included in the break characters if uread is to take action on them, i.e. assemble special lists and make strings. flg=T suppresses carriage-return normally typed following a matching right parentheses. 14.11. 14.15 See page Notel read. ratom. ratoms. peelt.(~. reade, and uread all wait lor input if there is none. The onlll wall to te&t whether or not there i& input ioS to use readp. readp[file] Value is T if there is anything in the input buffer of file, NIL otherwise (not particularly meaningful for. file other than T). Note that because of line-buffering, readp may return T, indicating there is input in the buffer, but read may still have to wait. readline[]17 rea~s list. a line from the teletype, returning it as a If readp[T]. is NIL, Othlsrwise it reads readline·retU~n~ expressions, using NIL~ read, 1.8 until it encounters either: (1) a carriage-return (typed by the user) that is not preceded by any spaces, e.g. ABC,) and readline returns (2) (A B C) a list terminating in a 1]1, in which case the list is included in the value ·of re4dline, e.g. A B (C D] and readline returns (A B (C D». 17----------------------------------------------------------------------------Readline actually has two ar"guments for use by the system, but the user should consider it as a function of no arguments. 1.8 Actually, readline performs (APPLY. LISPXREADFN T), as described in Section 22. lispxreadfn is initially READ. 14.16 (3) an unmatched right parentheses or right square bracket, which is not included 'in the value'of readline, e.g. ABC] and readline returns (A B C). In the case that one or more spaces precede a carriage-return, or a list is terminated with a ')', readline will type • and continue reading on the t next line. 19 e.g. ABC .~ ••• (O-E F) ••• (X Y Z] and readline returns (A B C (D E F) (X Y Z». skread[ file :rereadstringtO is a ,!!ip .!:!!!! function. It moves the file pointer for !!!! ahead as if one call to read had been performed, without paying the storage and compute cost to really read in the structure. rereadstring is for the case where the user has already performed some ~'s and ratom's before deciding to skip this expression. In this case, rereadstring should be the material already read (as a 5 tr1ng) , and skread operates as though it 19-~--~------------------------------------------·---- ------------------------- If the user then types another carriage return, the line will terminate e.g. ... ~ and readline returns (A B C) 20 skread was written by J.W. Goodwin. 14.17 had seen ,that material first, paren-count, ThEI double-quote thus getting its count, value of" skread is X) etc. set up if the #irst thing enc:ountered was a closing paren: Xl if the read ter'mina,ted on an unbalanced 'Xl,' also would ,have ,closed. ,any i;.e'~ extant 'one) 'which open, left par'ens; otherwise the, value of skread is NIL. 14.3 Output Functions Most of the lunctton$ de$crtbed below haue an (opttonal) argument,lile' 'which specifies the name oj the Ii le on which the operation is to tale place. 11 that argument is NIL, the primaru output lile will be used. Note: in all INTERLIS," svmbojti,c, Jile$, end-ol-line t~ indicated bli the characters carriage-return andline-/eed in that order. Unle$s otherwise stated carriage-return oppeartng ill the description oJ an output Junction means carriage-return and line-feed. t prin1[x;file] prilnts ! on file. prin2[x;file] prilllts ! on file with X' sand •• s inserted where reqillired for it to read back in properly by read. Both print and prin2 print lists as well as atoms and strings; prin1 is usually used only for (PRINt (QUOTE X[» explicitly formatting printing characters, e.g. might, ,be used to print a left square bra'cket (the X would ~ not be printed by print). prin~~ , . is used for printing S-expressions which can !,~. then be read back into INTERLISI) with read i.e. regular INTERLISP formatting characters in atoms will be preceded by X's, e.g. the atom '(}Iis printed as X(X) by prinZ. If radix=8, prin~ prints a (but both print the integer in octal). 14.18 g after integers but print does not Prints! with X's and ·'5 inserted where required prin3[x;file] for it to read back in properly by uread, i.e. uses slparator and break characters specified by setbrk and setsepr to determine when to insert X's. print[x:file] Prints the S-expression ! using prinZ: followed by a carriage~return For all printing Junctions. pointers numbers, are printed as IN, where N is oj the pointer (regardless oJ rad(x). correctlu. i.e .• it will read in as the line-feed. Its value is ~. other than lists. strings, atoms, or the octal representation 0/ the address Note that this UI1,ll not read back in atom 'IN'. nspaces; its value is NIL. spaces[njfile] Prints terpri[file] Prints a carriage-return; its value is NIL. Printlevel The print functions print, print, prin2, and prin3 are all affected by a level parameter set by printlevel[n] Sets print level to !l, value is .old setting. Initial value is tOOO. printlevel[] gives current setting. The variable !l controls the number of unpaired left parentheses which will be printed •. Below that· level. all lists will be printed as 6. Suppose! = (A (B C (0 (E F) G) H) K). (A (B C & H) K). and if !l e Then if !l :I 2, print[x] would print 3. (A (B C (D 6 G) H) K), and if !l • 0, just &. 14.19 If printlevel is negattue. the action is similar except that a carriage-return is inserted between all occurrences of right parenthesis immediately followed by a left p~rent~esis. The printlevel setting can be changed dynamica,lly, even while INTERLISP is printing, by typing control-P f'ollowed by a number, i.e. a string of digits, followed by a period or exclamat:iop pOint. 21 Theprintlevel will immediately be set to this number. 22 If. the print r ou t1:ne, is currently deeper than the new level, Thus, all unfinished lists above that level will be terminated by ---)-. if a circular or long list of atoms, control-PO. is, being printed out,' typing will cause, the list,' to: be terminated. If a period is used to terminate the printlevel setting, the printlevel will be returned to its previous settinu after this printout. If an exclamation point is used, the change 15 permanent and the printlevel is not restored (until it is changed again)~ . Note, prtntleuel onlll alleets t~tletllpe output. as though leuel is tn/intte. Output to all other liles, ercts 2i-----~------------~--------------------------------- ------------------------- As soon as control-P is typed, INTERLISP clears and saves the input buffer, clears the output burfer, rings the bell indicating it has seen the control-P, and then waits f(]lr input which is terminated by any non-number. The input buffer is then restored and the program c,ontinues. If the input was terminated by other than a period or an exclamation point. 1 t 15 ignored and printing will continue, except ,that cha~acters cleared from the output buffer will have been lost. . 22 Another way of -turning Oflf- output is to type control-O, which simply clears the output buffer, thereby effectively skipping the next (up to) 64 , character~. 14.20 14.4 Input/Output Contrel Functions clearbuf[file;flg] Clears the input buffer for file. If file is T and fig is T, contents of INTERLISP's line buffer and the system buffer are saved (and can be obtained via linbuf and sysout described below). When either control-P, control-D, or control-S control-E, is typed, control-H, INTERLISP automatically does a clearbuf[T;T]. (For control-P and control-S, INTERLISP restores the buffer after the interaction. linbuf[flg] See Appendix 3.) if fI9=T, value is INTERLISP' 5 line buffer (as a string) that was saved at last clearbuf[T;T]. If flg=NIl, clears this internal buffer. sysbuf[flg] same as linbuf for system buffer. If both the system buffer and INTERLISP' s line buffer are empty, the internal buffers associated with linbuf and sysbuf are not changed by a clearbuf[T;T]. bklinbuf[x] ! is a string. buffer to!. bklinbuf sets INTERLISP' s line If greater than 160 characters, first 160 taken. bksysbuf[x] ! is a string. bksysbuf sets system buffer to !. The effect is the same as though the user typed !. bklinbuf, bksysbuf. linbuf, and sysbuf provide a way of 'undoing' a clearbuf. Thus if the user wants to ·peek· at various characters in the buffer, he could perform clearbuf[T;T], examine the buffers via linbuf and sysbuf, and then put them back. 14.21 radix[n] Resets output radi~3to I n I w!.th sign in~lc.tor the' sign of n. For example, shown wi ttl, the following -9 will print as radic~s':~ radix printing 10 -9 , 68719476727 -10 i.e. (2t36-9) -llQ 8 777777777767Q -8 Value of radix is its last setting. radix[] gives current it. setting without changing Initial setting is 10. fltfmt[n] Sets floating format control to rr (See TENEX JSYB for manual interpretation of fltfmt[T] !l) • spel:ifies free format (see Section 3). fl tlrmt is last setting. set1~ing Value of fltfmt[ l returns current without changing it. Ini tia1setting is T. line1ength[n] Sets the lengt~ of the print line for all files. Value is the former setting of the line length. Whenever printing an atom would go beuond length of autclmatically the, line, inserted returns current setting. a the carriage~return first. 1s llnelength[ ] Initial setting is 72. 23----------------------------------------------------------------------------Currently, there is no input radix. 14.22 position[file] Gives the column number the next character will be read from or carriage-return, printed to, e.g. position-O. after a that Note position[file] is not the same as sfptr[file] which gives the position in the" lile, not on the line. Line-buffering and CONTROL In INTERLISP's normal state, characters typed on the teletype (this section does not apply in any way to input from a tile) are transferred to a line buffer. Characters are transmitted from the line buffer to whatever input function initiated the request (i.e., ~f ~, ~, rstring, or readc)24 onlll when a carriage-return is typed. 26 Until this time, the user can delete characters one at a time from the input buffer by typing control-A. characters are echoed preceded by a \. The Or, the user can delete the entire line buffer back to the last carriage-return by typing control-Q, in which case INTERLISP echoes 11. 26 (If no characters are in the buffer and either control-A or control-Q is typed, INTERLISP echoes II.) Note that this line editing is not performed by read or ratom, but by INTERLISP, i.e. it does not matter (nor is it necessarily known) which function 24----------------------------~----------------------- ------------------------- peekc is an exception; it returns the character immediately. 26 As mentioned earlier, for calls from read or uread, the characters are also transmitted whenever the parentheses count reaches o. In this case, if the second argument to read or uread is NIL, "INTERLISP also outputs a carriagereturn line-feed. -- 26 Typing rubout clears the entire input buffer at the time it is tllped, whereas the action of control-A and control-Q occurs at the time they are read. Rubout can thus be used to clear type-ahead. 14.23 will ultimately proce$,s the characters. INTERLISP input buffer., if the user exec,u,tes to they are still in, the function that is currentlu whether parentheses counting is observed, e.g. (.P~OGN (RATOM)' ',t".,·., ,', is~the Note also that it t~a,~.,:~~t.ermines .requesting input only that (READ» '" and, types in A (8 C D) he will have ' type in the carriage-return t:ollowing ,the right parenthesis before any action is taken, whereas if he types (PROGN (READ) (READ» he would not. However, once a carriage-return has been typed, the entire line is 'available' even if not all of it is processed by the function initiating the request for input, i.e. if immediately any on characters the (PROGN (RATOf1) (READC» next are 'left over', request for they ~illb~ input. - followed byA B carriage-return example, For will returned perform both operations. Turning-off Line-buffering The function control[T~, control is .vailable to defeat this ,11ne-buffering. After characters are returned to ,the, calling function without line- buffering as below. de~cribed The function that initiates the request for input determines how the line is treated: 1. read/urea,d if the expre,ssion being typed:ls a lis.t, the effect 15 the same as though control NIL, were parentheses. i.e. line-buffering until carriage-return If the expression being typed is not a list, it is returned as soon as a break or separator chclracter is encountered,,27 27--" - - - - _._ • -'c~ or, matching ,. - -:.~ -."., - ,g. g • ,1 _ .. - -.'- - . - : - - - - . , - - - - . - - - - - - - , - ~ ... - - . - - - - - - .. - -:- . . . (READ) followed -1;"""-'-." -,~- - - ~ - .... - - _... An exception to the above occurs when the break or separator chara'cter is a (,If, or [,'since returning Cit this 'point would leave the line buffer in a "funny" state. Thus if control is T and (READ) is followed by 'A8C(', the A8C will not be read until a carriage-return or matching parentheses 1s encountered. In this ..case, the user could,con~trol-Q the entire:" line, since all of t'lle 'c'haracters are still ,in the buffer., 14.24 by ABC space will immediately return ABC. Control-A and control-Q editing are available on those characters still in the buffer. Thus, if a program is performing several reads under control[T], and-the user types NOW IS THE TIME followed by control-Q, he will delete only TIME since the rest of the line has already been transm!~ed to read and processed. 2. ratom characters are encountered. returned as soon as a br~ak' or separator character is Before then, control-A and control-Qmay be used as with read, e.g. (RATOH) followed by ABCeontrol-Aspace will return AB. (RATOH) followed by (control-A will return ( and type II indicating that control-A was attempted wi th nothing in tJle buffer, since the ( is a break character and would therefore already have been read. 3. reade/peeke the character is returned immediately; no line editing is possible. particu lar. In (READC) followed by control-A will read the control-A, (READe) followed by X will read the X. control[u] eliminates !!=T INTERLISP's normal line- buffering. u=NIl restores line-buffering (normal). u=O eliminates echo of being character deleted by control-A. restores echo (normal). u=1 The value of control when !!=T or NIL previous line-buffering setting, i.e. is its T or NIL. When !:!,=O or 1, its value is 1 ts previous echo setting, 1.e. 0 or 1. 14.25 14.5 Special Functions sysout[file] Sa,'es the user' s private memory on file. Also' sa,'es the .stacks, so that if a program performs a sys;out.. the subsequent sysin will continue from thalt point. e. g. (PR,OGN (SYSOUT (QUOTE FOO» will . cause HELLO (SY'SIN (QUOTE FOO» ( full name). ,to (PRINT (QUOTE HELLO») ,be' printed after The value of sysout is file A value of NIL indicates the sysout was unsuccessf,ul, i.e., either· disk' or computer error, or user's directory was full. SlIsout does not saue the state 0/ anu open Jtles. Whenever the INTERLISP sustem are not compatible. sysin[file] iJ; reassembled and/or reloaded, old svsout Jiles restores the state' of fille. INTERLISP from a Value is list[file]. Sysout If sysin returns NIL, thelre was a problem in reading the file. If the file. was not found or is incompatible (see note abo've), generates an error, FILE NOT COMPATIBLE. Stncesystn conttnues tmmedtatelll where susout Le/t all, the onlu wall for a program to determine whether it is just cominll back. Jrom a svsin or from a svsout is to test the ualue 0/ ~lsout. For example, (CONO «lISTP (SYS()UT (QUOTE FOO») (PRINT (QUOTE HELLO»» will cause HEllO to be printed follclwing the sysin, but not when the sysout was performed. 14.26 14.6 Symbolic File Input load[file;ldflg:printflg] Reads successive S-expressions from evaluates each as it is read, file and until it reads either NIL. or the single atom STOP. Value is file (full name). If printflgaT. load prints "the value of each 8expression: otherwise it does not. the operation of define, defineg, ldflg affects ~. and rpaqq. While load is operating, dfnflg (Section 8) is reset to Idflg. 28 Thus, if ldflg=NIl, and a function is redefined, a message is printed and the old definition saved. If ldflg=T, definition is simply overwritten. the function property lists definitions under are the the old If Idflg=PROP, stored property on EXPR. the If ldflg=AllPROP, not only function definitions but also variables set by proper~y lists. 29 10adfns[fns;file:ldf19]30 ~ and ~ are stored on permits selective loading of function definitions. fns is a list of function names, a single function name, or T, meaning all functions (but no 28---~~----------~------------------------------------ ------------------------- Using resetvar (Section 5). dfnflg cannot simply be rebound because it 1s a GLOBAL variable. See Section 18. 29 except when the variable has value NOBIND, in which case it is set to the indicated value regardless of dfnrls. 80 loadfns was written by J.W. Goodwin. 14.27 var'iabl9s, property values, etc.) .' file can be either a compiled or symbolic file, i.e., any file thillt can be loaded by load. file is "opene"d and sCt:lnned ill the manner of load, and every function definition found for a function on fns is I081ded .31 . The interpretation of ldflg is the same as for load. loadfns uses skread (page 14.17) and lcskip (a subfunction of recompile) to skip over undesired moterial on the file, and so it is very efficient. The value of loadfns is a list of those functions loaded plus a list of those functions not found (if any) headed by the atom NOTFOUND:. e.g., from using (FOO FIE (NOTFOUND: FUM». readfile[file] Reads successive 8-expressions r!!~ file until the single atom STOP is read, or an end of file encountered. Value is a list of these 8- exp.ressions. ~i---------------------------·--"-------------------~--~~----~----------------If a compiled definition is loaded, so are all compiler generated subfunctions. Note however if fns specifies entries to a block (see Section 18) the user must al~.o specify the block itself. , 14.28 14.7 Symbolic File Output writefile[x;file:dateflg] Writes successive S-expressions from ! on file. If ! is atomic, its value is used. open, it is opened. If file is not If the first expression on ! is the type produced by printdate, or if date fig is T, • new date expression is written. If file is a list, car[file] is used and the file is left opened. Otherwise, when ! is finished, a STOP is printed on file and it is closed. Value is file. nlambda, nospread function that performs output[T] pp[x] and then calls prettyprint: PP FOO is equivalent to PRETTVPRINT«FOO»; PP(FOO FIE) o~ (PP FOO FIE) is equivalent to PRETTVPRINT«FOO FIE». Primary output file is restored after printing. prettyprint[lst]32 33 1st is a list of functions (if atomic, its value is used). The definitions of the functions are printed in a pretty format on the primary output file. For example, (FACTORIAL [LAMBDA (N) (COND «ZEROP N) 1) (T (ITIMES N (FACTORIAL (SUB1 N]) 82----------------------------------------------------------------------------The prettyprint package was written by W. Teitelman. 83 prettyprint has a second argument that is T when called from prettydef. In this case, whenever prettyprint starts a new function, it prints (on the teletype) the name of that function if more than 30 seconds, (real time) have elapsed since the last time it printed the name ot a functione 14.29 Note: prettyprint will operate correctly on fugctions broken-i~, that are broken, advised, or have been compiled with their definitions saved on their property lists - it prints the: original, pristine' detini tion, but does not change the current state of the function. If prettyprint is given an atom which is not the name ofa function, but has a value, it will prettyprint the value. 34 Otherwise,prettyprint~. will perform spelling correction. If all A facility for annotating INTERLISP, functions is provided in prettyprint. Any fails, prettyprint returns (atom NOT PRINTABLE). Comment Feature S-expression beginning with right margin. (FACTORIAL [LAMBDA (N) (COND «ZEROP a is interpreted as a comment and printed in the Example: (a COMPUTES NI) (a 0!-1) N) 1) (. RECURSIVE DEFINITION: Nt.NaN-11) (T (ITIHES N (FACTORIAL (SUB1 N]) These comments act~ally form a peart of the function definition. Accordingly,. is defined as an NlAHBDA NOSPREAD function that returns its argument, i.e. is equivalent to quote. it When running an interpreted function, a is entered the same as any other INTERLISP function. Therefore, cO,mments should only be placed where they will not harm the computation, i.e. where a quoted expression could be placed. For example, wr"i ting (ITIHES N (FACTORIAL (SUB1 N» (~ RECURSIVE DEFINITION» in the above function would cause an error when ITIMES attempted to multiply N, N-lt, and RECURSIVE. 34 - - - - - - - - - - - -.~ ,... - - - - - - - ~ ~ - •.• - - - .' - - - - _.. - - - - - -.- - - ... - - - - - - - -." - - - - - - - - - - - - - - ... -- - - - - except when prettyprint is c~llled from prettydef. 14.30 For compilation purposes, " is defined as a macro which compiles into no instructions. Thus, if you compile a function with comments, and load the compiled definition into another system, the extra atom and list structures storage required by the comments will be eliminated. comment feature is intended to be used. This is the way the For more options, see end of this section. Comments are designed mainly for documenting Thus listings. when prettypr1nt1ng to the teletype, comments are suppressed and printed as the string **COMMENT-*.36 Prettydef prettydef[prettyfns;prettyfile;prettycoms]36 that are Used to make suitable for loading symbolic which files contain function definitions, variable settings, property lists, et aI, in a prettyprint format. The arguments are interpreted as follows: prettyfns Is a list of function names. The functions on the list are prettyprinted surrounded by a (DEFINEQ ••• ) so that they can be 36----------------------------------------------------------------------------The value of **comment**flg determines the action. If IIrlircomment**flg is the comment is printed. Otherwise, the value of IIrlircomment**flg is printed. **comment-.flg is initially set to " **COMMENT** ". The function ~ is provided to prettyprint functions, including their comments, to the teletype. ~ operates exactly like .I!I!. except it firs,t sets "*comment**flg to NIL. NIL, 36 prettydef actually has two additional arguments for use by the system. 14.31 loaded with' load. If pre'ttYfns is atomic' (the preferred usage h i tstop level value is used as the list of function names, and an'.!J!.!9.!l 87 will alsl!) be written which will' set that atom to the lis't of functions when the file is' loaded. ~~t written expression will also be A which inft!)rms the user of the named atom or list of funlctions when the file is subsequently loaded. . prettyfile is 'the name of the file on which the out'put is to be ,,,ritten. The following options exist: prettyfile=NIL The primary output file is used. prettyfile atomic The file is opened if not already open, and becomes primary output file. is closed at end of prettydef File and primary output file is restored. prettyfile a list Car of the list is assumed to be the file name, and is opened if not already open. The file is left open at end of prettydef. 37----------------------------------------------------------------------------rpaqq and !:J!!.q are like se1~ and setq, except they set the top level value. See Section 5. 14.32 prettycoms Is a list of commands interpreted as described below. If prettycoms is atomic (the preferred usage), its top level value is used and an rpaqq is written which will set that atom to the list of commands when the file is subsequently loaded, exactly as with prettyfns. These commands are used to save on the output file top level bindings of variables, property lists of atoms, miscellaneous I~TERLISP evaluated upon loading. arrays, and advised functions. forms to be It also provides for evaluation of forms at ouput time. The interpretation of each command in the command list is as follows: 1. if atomic, an this atom when Z. I ~ th~ is written which will restore the top level value of file is loaded. (PROP propname atom 1 ••• atomn ) an appropriate deflist will be written which will restore the value of propname for each atom! when the file is loaded. If propname=All, the values of all user properties (on the property list of each atom i ) are saved. a8 If propname is a li'st, deflist's will be written for each property on that list. 3. (ARRAY atom 1 ••• atomn ), each atom following ARRAY should have an array as its value. An appropriate expression Will be written which will set the atom to an array of exactly the same size, type, and contents upon loading. 38----------------------------------------------------------------------------sysprops is a list of properties used by system functions. Only properties not on that list are dumped when the ALL option is used. 14.33 4. (P .•• ), each S-expression following P will be printed on the output file, and consequently evaluated when the file is loaded. 5. (E .,.. ), each form following E will be evaluated at output time, i.8., when prettydef reaches this command. 6. (FNS fn 1 ... fn m), a defineq is written with the definitions of fn l ••• fn m exactly as though (fn 1 ••• fn m) where the first argument to pr~ttydef. For example, suppose the user ,,,anted to set some variables or perform some computations in a file be/ore defining functions, he would then write the definitions using the FNS command instead of the first argument to prettydef. 7. (VARS var 1 .. '. var n ), for eilch var i , an expression will be written which wi 11 set its top level valUEt when the file is loaded. If Y!!:.i is atomic, Y!!.i will be set to the prettydefed. i.e. non-atomic, tO~I-level value it had at the time the file was (RPAQQ vari top-level-value) is written. it (FOO (APPEND FIE FUM» is or int,erpreted (F~)() as (var If Y!!:i is form). e.g. (QUOTE (FOOl FOOZ FOO3»). In this case the expression (RPAQ var form) is written. 8. fn l .•• fn m), for each fn n • an appropriate expression will be' wri tten which will reinstate the function to· its advised state when the (ADVISE file is loaded. 9. (ADVICE fn 1 ... fn m,), for E!ach fn i , will write a deflist which will put the advice back on the property list of the function. use readvise to reactivate the advice. The user can then See Section 19. 10. (BLOCKS block 1 ... block n ) for each block i , a declare expression will be wri tten which the block comp:lle functions interpret as block declarations. See Section 18. 14.34 com 1 ... comn ) , each of the interpreted as a prettydef command. 11. (COMS commands com t ~ •• comn will be 12. (AOOVARS (var t • lstt) ... (var n • lst n » For each var i , the effect is the same as (RPAQ var i (UNION lst i var i », i.e. each element of lst i not a member of var i (at load time) is added to it. Y!!!i can initially be NOBINO, in which case it is first set to NIL. 13. (USERMACROS atom t ... atomn ), each atom i is the name of a user edit macro. USERMACROS writes expressions for adding the definitions to usermacros and the names to the appropriate spelling lists. (USERHACROS) will save all user edit macros. 14. (IFPROP propname atom t ••• atomn ) same as PROP command, except that only non-NIL property values are saved. For example, if FOOl has property PROPt and PROPl, FOOl has PROP3, and FOO3" has property PROP1 and PROP3, (IFPROP (PROPIPROPl PROP3) FOOl FOOl FOO3) will save only those 5 property values. 15. (COHPROP propname atom, •.. atomn) same as PROP command, except that the corresponding deflist expression will also be evaluated when the file is compiled. 16. (COHPROP* Useful fot outputting MACROs. propname atom, ..• atomn) , same as COMPROP except that the corresponding deflist expressions are not copied to the compiled file by tcompl, bcompl. recompile, or brecompile. 17. (PO ... ), like P except that the corresponding S-expressions are also printed as DECLARE expressions, and thus will be evaluated when the file is compiled. In other words, (PO (OEFLIST (QUOTE --) (QUOTE propname» essentially equivalent to (COHPROP propname --). 14.35 1s In each of the commands described above, if the atom * follows the command type, the form following the *, i.e., ~ of the command, is evaluated and its value used in executing the command, e.g., (FNS * (APPEND FNSI fNS2».89 * Note that (COMS form) provide,s a way of computing what should be done by prettydef. New prettydef conunands can be defined via prettymacros (see page 14.40). If prettydef Qn is pret tymacros, spelling list. given it a command not attempts one of the above, spelling correction40 using and not defined prettycomsplst as a If successful, the corrected version of prettycoms is written (again) on the output file. 41 If unsuccessful, prettydef generates an error, BAD PRETTYCOH. 39-------------------------------'---------------------------------------------Except for the PROP, IFPROP, COMPROP, and COMPROP* commands, in which case the * must follow the property name, e.g., (PROP MACRO * FOOHACROS). 40 unless dwimflg=NIl. See Section 17. 41 since at this point, the uncorrected prettycoms would already have been printed on the output file. When the file is loaded, this will result in prettycoms being reset, and a message printed, e.g. (FOOVARS RESET). The value of FOOVARS would then be the corrected version. 14.36 Example: (FOOl FOOZ F003» (PROP MACRO FOOt FOO2) (P (MOVD (QUOTE FOOl) (QUOTE FIE1] ~PRETTYOEF(FOOFNS Foo FOOVARS) ~SET(FOOFNS ~SET(FOOVARS(FIE would create a file FOO containing 1. A message which prints the time and date the file was made (done automatically) 2. OEFINEQ followed by the definitions of FOOl, FOO2. and FOOl 3. (PRINT (QUOTE FOOFNS) T) 4. (RPAQQ FOOFNS (FOOt Foo3 FOOl» 5. (PRINT (QUOTE FooVARS) T) 6. (RPAQQ FOOVARS (FIE ... ) 7. (RPAQQ FIE value of fie) 8. (OEFLIST (QUOTE «FOOl propvalue) (FOO2 propvalue») '(QUOTE MACRO» 9. (MOVO (QUOTE FOOl) (QUOTE FIE1» 10. STOP printfns[x] ~ is a list of functions. and prettyprints the printfns prints defineq functions. Used by prettydef, i.e. command (FNS • FOO) is equivalent to command (E (PRINTFNS FOO». printdate[ffle;changes] prints the expression at beginning of prettydefed files that upon loading types the time and date the file was made, and stores this time and date on the property list' of file under the property FILEDATE. tab[pos;minspaces;file] changes is for use by the file package. performs appropriate number of spaces to move to 14.l7 position pos. minspaces I indicates the minimum number of spaces to be printed by tab, i.e., it is intended to be small number (if NIL, 1 is used). Thus, if position + minspaces is greater than pos, tab does a terpri and then spaces[pos]. endfile[file] Prints STOP on file and closes it. printdef[expr;left;def] prints the expression expr on the primary output fil '9 in a pretty format. margin margin). (linelength left is the left hand determines the right hand 2 is used if left=NIL. defllT means expr is a function definition, or a piece of one, i.e. prettyprint printdef[getd[fn];NIL;T]. is essentially If def=NIL, no special action will be taken for LAMBDA's, PROG's, CONO's, cOlDlllents, CLISP, etc. der is NIL when prettydef calls prettyprint to print variables and property lis1;S, and when printdef is called from the editor via the command PPV. Special Prettyprint Controls All variables described below, i.e., Irpars. firstcol, et aI, are globalvars. see Section 18. Therefore, if they are to be changed, they must be reset, not rebound. Irpars controls the number of right parentheses necessary for square bracketing to occur. brackets are used. 14.38 If Irpars-NIL, no Irpars is initialized to 4. linelength[n] determines the position of the right margin for prettyprint. firstcol is the starting column for comments. setting is 48. line length. , • I Initial Comments run between firstcol and If a word in a comment ends with a and is not on the list abbrevlst, and the position is greater than halfway between firstcol and linelength, begins on encoun~ered the next word a new line. in Also, the comment if a list is in a comment, and the position is greater than halfway. the list begins on a new line. prettylcom If a. comment pretty~com is bigger in size, (using count) than it is printed starting at column 10, instead of firstcol. prettylcom is initialized to 14 (arrived at empirically). widepaper[flg] widepaper[ T] sets linelength to 120, firstcol to 80 and prettylcom to 28. This is a useful setting for prettyprinting files to be listed on wide paper. w1depaper[] restores these parameters to their 1ni tial values. The value of widepaper is its previous setting. commentflg If £!! of an expression is ~ to commentflg, the expression is treated as a comment. commentflg is initialized to ,. prettyflg If pre·ttyflg is NIL, printdef uses prin2 instead 14.39 of prettyprinting. This is useful for producing a fast symbolic dump (e.g. when TENEX is very slow.) Note that the file loads the same as if it were prettyprinted. clispifyprettyflg prettyflg is initially set to T. if T, causes prettyprint to clispify each function definition before printing. See Section 23. clispifyprettyflg is initially NIL. prettymacros Is an assoc-type list for defining substitution macros for prettydef. If (FOO (X Y) • coms) app1aars on prettymacros, then (FOO A B) appearing in the third argument to prettydef will cause A to be substituted for X and B for Y throughout £2!!!!. ( i.11t ., cddr of the, macro) • and then £2!!!! treated as 41 list of commands for prettydef. A comment of this form causes (* E x) pre1~typrint com~ent time, e.g., ~ to be evaluated at (- E (RADIX 8» as a in a function. containing octal numbers can be used to change the readable printout. radix to produce more The comment is also printed. Converting Conunents to Lower CasEI This section is for users operating on terminals without lower case who nevertheless would like their cOlnments to be converted to lower case ror more readable line-printer listings. Users with lower-case terminals can skip to the File Package sections (as they can type comments directly in lower case). 14.40 If the second atom in a comment 15 XX, the text of the comment is converted to lower case so that it looks like English instead of LISP (see next page) • The output on the next page illustrates the, result of a lower casing operation. Before this function 'was prettydefed, all comments consisted of upper case atoms, e.g., the first comment was (* XX INTERPRETS A SINGLE COMMAND). Note that comments are converted onlu when they are actually writte.n to a file by prettydef. The algorithm for conversion to lower case is the following: If the first character in an atom is t, do not change the atom (but remove the t). first character is Xt convert the atom to lower' case. 42 INTERLISP word,44 do not change it. If the If the atom43 is an Otherwise, convert the atom to lower case. Conversion only affects the upper case alphabet, i.e., atoms already converted to lower case are not changed if the comment is converted again. converting., the first character in the comment and the following each period are left capitalized. first When character After conversion, the comment is physically modified to be the lower case text .minus the XX flag, so that conversion is thus only performed once (unless the user edits the comment inserting additional upper case text and another XX flag). 42--U;;;-;~;~-~;;;-ii-;;-i-i;-~h;-;;~;;;-~h;;;~;;;:-----------------.----------48 minus any trailing punctuation marks. 44 i.e., is a bound or free variable for the function containing the comment, or has a top level value, or is a defined function, or has a non-NIL property list. 14.41 (BREAKCOM [LAMBDA (BRKCOH BRKFLG} (PROG (BRKZ) TOP (SELECTQ BRKCOH [t (RETEVAL (QUOTE BREAK1) ( QUOTE It ERROR] ] (GO (~ Interprets a single command.) (~ Evaluate BRKEXP unless already evaluated, print value, and exit.) (BREAKCOHI BRKE)(P BRKCOM NIL BRKVALUE) (BREAKEXIT» (OK c. Evaluate BRKEXP, unless already evaluated, do NOT print value, and exit.) CBREAKCOH 1 BRKE)(P BRKCOM BRKVALUE BRKVALUE) (BREAKEXIT T» (tWGO (* Same as GO except never saves evaluation on his tory. ) .( BREAKCOM t. BRKE)tP BRKCOM T BRKVALUE) (B~EAKEXIT» . (RETURN (~ User will type in expression to be evaluated and returned as value of BREAK. Otherwise same as GO.) (BREAKC0t11 [SETQBRKZ (COND (BRKCOHS (CAR BRKCOHS» (T (LISPXREAD T] (QUOTE RETURN) NIL NIL (LIST (QUOTE RETURN) BRKZ» (BREAKEXIT» (EVAL (* Evaluate BRKEXP but do not exit from BREAK.) (BREAKCOHI BRKEXP BRKCOM) (COND (BRKFLG (BREAKZ) (PRINt BRKFN T) (PRINt (QUOTE • EVALUATED T») (SETO 'VALUE (CAR BRKVALUE» ) 14.42 (. For user's benefit.) lease 1st Words on lcaselst will always be converted to lower case. lcaselst is initialized to contain words which are INTERLISP functions but also appear frequently in comments as English words. e.g. AND, EVERY, GET, GO, LAST, LENGTH, LIST, etc. Thus, in the example on the previous page, not was written as tHOT, and GO as tGO in order that they might be left in upper case. ucaselst words on ucaselst (that do not appear on lcaselst) will be left . in upper case. ucaselst is initialized to NIL. abbrevlst abbrevlst is used to abbreviations and words distinguish that end in between periods. Normally, words that end in periods and occur more than halfway to the right margin cause carriage returns. Furthermore, during conversion to lowercase, words ending in periods, except for those on abbrevlst, cause the first character in the next word to be capitalized. abbrevlst is initialized· to the upper and lower case forms of ETC. I.E. and E.G. l-case[x;flg] value is lower case version of!. the first letter is capitalized, l-case[FOO;T] = Foo, l-case[FOO] If fIg is T, e~g. = foo. string, the value of I-case is also a If! is a ~tring, l-case[-FILE NOT FOUND-:T] • -File not found-. u-case[x] Similar to I-case 14.43 e.g. 14.8 File Package46 This section describes a set of functions and conventions for facilitating the bookkeeping involved with working in a large system consisting of many symbolic files and their compiled counter'parts. The file package keeps track of which files have been in somo way modified and need to be dumped, which files havo been dumped, but still need to be listed and/or recompiled. The functions described below comprise a coherent package for eliminating this burden from the user. They require that for each file, the first argument to prettydet, (if any), be an atom of the forllll fileFNS.and the third argument, (if any). be fileVARS where file is the name of the . file, e.g. prettydef[FOOFNS;FOO;FOOVARS].46 The functions load, editf, edit~!, tcompl, recompile, bcompl, brecompile, and DWIM interact with the function:s and global variables in the file package as follows. Whenever load is callEld, its argument is added to the list filelst, and the property FILE, value {fileFNS fileVARS). is added to the property list of the file name. 47 This property value is used to determine whether or not the file has been modified since thEt last time it was loaded or dumped. Whenever the user calls editf and change.s a function,. filelst is searched to find the 45------------------------------··------------------------~--------------------The file package was written by W. Teitelman. It can be disabled by setting filepkgflg to NIL. 46 47 file can contain a suffix and/or version number, e.g. PRETTYOEF(FOOFNS FOO.TEH;3 F(~VARS) is acceptable. The essential point is that the FNS and VARS be computable from the name of the file. The name added to filelst has the version number and directory field removed, if any. fileFNS and fileVARS are constructed using only the name field, i.e., if the user porforms load[ FNSIVARS. filefnslst[file] returns a list of the functions in file, specified by fileFNS and fileVARS. i. e. fllefnslst knows about prettymacros. newfile2[name;coms;type] £Q!!!! is a list of prettydef commands, ~ is usually FNS or VARS but may be BLOCKS, ARRAYS, etc. or the name of any other prettydef command. If n!!!=NIL, newfile2 elements of type!l2!. returns a list of all (filefnslst and bcompl and brecompile use this option.) If !!.!!!!!=T, newfile2 returns T if there are anll elements- of type!l2!. (makefile uses this option to determine whether the file contains any FNS, and therefore should be compiled, whether it contains whether to call any BLOCKS, and to if so, determine bcompl/brecompile or tcompl/recompile.) Otherwise, newfile2 returns -contained- in~. (whereis uses newfl1e2 in this way.) 14.49 T if n!m! is • If the user often employs • • their expansion by the various parts of prett~macros, the system that need to interr'ogate files can result in a large number of conses and garbage collections. If the user could inform the file package as to what his various prettymacros: actually produce, this expansion would not be necessary. For example, the user may have a macro called GRAMMARS which dumps various property list but no functions. Thus, the file package could ignore this conunand when seeking information about FNS. The user can supply this information by putting on the pr'operty list of the prettymacro, e.g. GRAMMARS, under the property PRETTYTYPE, 4)6 a function (or LAMBDA expression) arguments, com and VARS, etc. BLOCKS. ~, where ~ is a prettydef command, and function is FNS, The resul t of applying the function to these arguments should be a list of those elements of type 1l2! contained in £2m. the ~ of two corresponding to GRAMMARS For example, might be ( LAMBDA( COM TYPE)( AND (EQ (CAR C()M) TYPE)( EQ TYPE (QUOTE GRAMMARS» (CO'R COM». 67 Currently, the file package knows about two "types": functions and variables. As described in footnote on pa.ge 14.45, whenver a function or variable is changed, it is added to changedfnslst or changedvarslst respectively. Updatefiles operates by mapping down filelst and using newfile2 to determine if the corresponding file contain:s any of the functions on changedfnslst or changedvarslst. The user can tell the file package about other types by adding appropriate entries to prettytypelst. Each element of prettytypelst is a list of the form (name-of-changedlist, type string), where string is optional. For 56------------------------------··---------------------------------------------If noth ing appears on property PRETTYTYPE, the command is expanded as before. 67 Note that since the function is given the entire command as an argument, the same function could be used for several different types. 14.50 example, prettytypelst (CHANGEOVARSlST VARS».68 is If initially the user «CHANGEDFNSlST FNS -functions-) adds (CHANGEDGRAMlST GRAMMARS) to prettytypelst, then updatefiles will know to move elements on changedgramlst to the FILE property'for the files that contain them. 69 68----------------------------------------------------------------------------If string is supplied, files? will inform the user if any elements remain on the changed list after updatefiles has completed. Similarly, makefiles will warn the user that some elements of this type are not going to be dumped in the event that it could not find the file to which they belonged. 69 It is the user I s responsibility to see that elements are added to the changed list in the first place. 14.51 Index for Section 14 Page Numbers ABBREVlST (prettydef variable/parameter) ••...... address~ab 1e files ..........•.••..•.•.•••..••••.• ADDVARS (prettydef command) ......••••••••••••.•• ADVICE (prettydef command) ••.•...•.•.••.••.••••• ADVISE (prettydef command) .........•.•••.•••••.• ALL (use in prettydef PROP command) ••••••••••••• AllPROP (as argument to load) •..•...••••••••••.• ARRAY (prettydef command) ...•.•......•••.•.••••• BAD PRETTYCOH (prettydef error message) ••••••••• BCOHPl[FIlES;CFIlE;NOBlOCKSFLG] ••..••.••••.•.••. bell (typed by system) •.•.••.•••.•••••••••.•••.• BKlINBUf[X] SUBR ........••.••.••••.••.•••.•.•••. BKSYSBUF[X] SUBR ............•••.•.••..••••.•.••• block declarations ......•.•.•••.•.••.••.....•••• BLOCKS (prettydef command) .•....•.•..•.•..•.•••• break characters .......•.••..••.......•••••.•••• BRECOMPILE[FILES;CFILE;FNS;COREFLG;NOBLOCKSFLG] C (makefi 1e option) ......••.....••••.••..••••..• carriage-return .......•..•.•......••.•.•...•.••• CHANGEOFNSLST (file package variable/parameter) • CHANGEOVARSlST (file package variable/parameter) .. CLEANUP[FIlES] NL- ........•......••••••.••..••.• CLEARBUF[FILE;FLG] SUBR ••••••••••••••••••••••••• CLISP .111 ••••••••••••••••••••••••••••••••••••••••• ClISPIFY[X;l] ..............•.•..•••••••.••..•••• ClISPIFY (makefile option) •..•.•..•••••••••••.•• ClISPIFYPRETTYFLG (prettydef variable/parameter) .• CLOSEAll[] SUBR ...........•.•.•••••••••.••..•.•• CLOSEF[FILE] SUBR .............•.•••.••.•••.••••• COMHENTFLG (prettydef variable/parameter) •.••••. comments (in listings) ...••.•.•..•.•.••••••••••. COMPllEFIlES[FIlES] NL- ••••••••••••••••••••••••• COMPROP (prettydef command) •....•••••••.•••••••• COHPROP* (prettydef command) ••••.••••.••••..••.• COMS (prettydef command) •.....••.•••••.•.•.•••.• CONTROl[U] SUBR ......•..•...•••••••••.•.••..••.• control-A ...................................... . control-D ...................................... . control-E .......... s • • • • • • • • control-F ........................................ . control-H ....................................... . control-O ........................................ . control-P ....................................... . control-Q ....................................... . control-S .................. DECLARE " ......................................... . I1 . . . . . . . . . . . . . . . . . . . . III .................... . DEFLIST[l;PROP] ...........•...•.••• ~ •••••.••.... DFNFLG (system variable/parameter) ••..••.•.••.•• OW 1M •...• It DWIMIFY[X;L] •••••••••••••••••••••••••••••••••••••• ........•....••••••••••••••••••• II ••• E (prettydef command) .......•••••••••••..••.••.• E (in a floating point number) •...••..•••.••.•.. E (u s e inc omme n t s ) . . • . . . • • • • • • • • . • • • • . • • • • . . . • • EDITF[X] NL* ......................... : ...•......• EDITV[EOITVX] NL- ••••••••••••••••••••••••••••••• END OF FILE (error message) .••••••••.••••••••.•• INDEX.14.1 14.39,43 14.5 14.~5 14.34 14.34 14.33 14.27 14.33 14.36 14.44,46 14.20 14.21 14.21.47 14.34 14.34 14 . 12 -15 , 19, 24 14.44.46-48 14.46 14.10-11,13,15-19,23 14.45,50 14.45,50 14.45,48 14.21 14.46 14.40,46 14.46 14.40,46 14.4 14.4 14.39 14.30-31,40 14.48 14.35 14.35 14.35 14.11,14,23 14.10,12,14-15,23,25 14.21 14.21 14.2 14.21 14.20 14.20-21 14.10-12,14-15,23,25 14.21 14.34-35 14.33 14.27 14.44 ,14.46 14.34 14.11 14.40 14.44 14.44 14.6,10 Page Numbers end-of -1 ina .................................... . ENOFILE[Y] •...•.. "' •••••••••••••••••.•••••••••••• ESCAPE[FLG] SUBR ..•....•.••...•..•••••••..••. ~ •. escape character .•.•.•• ~ •••••••••••••••••••••••• EXPR (property name) •••••••••••••••••••••••••••• FAST (makefile option) •••••••••••••••••••••••••• fast symbolic dump .•....•••••••••••••••••••••••• FILE (property name) .•.••••••••••••••••••••••••• f1 Ie names FILE FILE FILE file ..............................•....... NOT COMPATIBLE (error message) ••••••••••••• NOT FOUND (error message) •••.•••••.•••••••• NOT OPEN (error message) ••••••••••••••••••• package .•..•...••.•••.••••••••••••••••••••• file pointer ..... III •••••••••••••••••••••••••••••• FILE WON'T OPEN (error message) FIlECREATED .............. 41 eo • • .••••••• o.~ ............ . FILEOATE (property name) fileFNS .•••••••••••••••• ....• ,. ....••..••• ,. ••••••••••••••• •••••••••••••••••••••••••• FILEFNSLST[FILE] .........••..••..•••..•••••••.•• FILEGROUP (property name) .•........••.•••••••••• FILELST (file package variable/parameter) ••.•••• FILEPKGFLG (file package variable/parameter) FILEPOS[X;FILE;START;END;SKIP;TAIL] ••••••••••••• files .......... "............................... . FIlES?[ ] ....................................... . FILETYPE (property name) fileVARS •••.••••.•••.••••••••••• ....................................... . FIRSTCOL (prettydef variable/parameter) ••••••••• floating point numbers •••••••••••••..••.•••••••• FLTFMT[N] SUBR ... ~ .•..••••• ~ •••••••.•••••.•.•••• FNS (prettydef command) .•••••••••••••••••••••••• form - r e e d . . . . •. •••. •. . •. •••••••••••••e • • • • • • • • e • GETBRK[] SUBR .• ~ ........••..•.•..••••••..••..••• GETSEPR[] SUBR .......•..••.••••••...••.••••••••• GLOBALVARS (system variable/parameter) •••••••••• GTJFN[FILE;EXT;V;FLAGS] ..•..••.•••••.•••.•••...• IF PROP (prettydef command) •••••••••••••••••••••• INFILE[FILE] SUBR ...•.•.••••••••.••.•••••••••••• INFILEP[FILE] BUBR ..•...••..•••••••••••.••••..•• INPUT[FILE] SUBR ...•.•..••..••.••.•.••••••.••••. input buffer ................. input functions input/output 0 •••••••••••••••••• ...••...••.•••••••••••••••••••••• ................................... . input/output control functions ••.••••••••••••••• IOFILE[FILE] SUBR ....•.•••.••.••.••..••.••••.•.• IS A COMPILED FILE AND CANNOT BE DUMPED. (error message) ••.••••.••••••••••••••••••.• JF N .•.•••••••••••••••••••••••••••••••••••••••••• JFNS[ JFN ;AC3] .•.•••.••••••••••• EX .14.3 14.22,39 14.16 14.47 14.45,47 14.11 ,14.27,44 14.27-28 14.43 14.40-43 14.45-48 14.45,47-48,~1 14.38 14.6 14.49-50 14.27 14.46 14.30 14.45-46,48 14.45-48 14.11-12 14.11,18 14.8 14.1 14.3-5,8 14.8 14.2,6-7 14.3-4 14.1 14.20 14.18-20 ' 14.34 14.11,23-24 14.35 14.15.25 14.23 14.29 14.31 14.38 14.36 14.31-38,40,44,46 14.33-37 14.39-40,46 14.39 14.36,40,49-50 14.29 14.46 14.50 14.45,50 14.1-2,4,10 14.1,4,18 14.18-19 14.18-19 14.19 14.19 14.29,37,44,46 14.38-39 Page Numbers PRINTFNS[X] .•.........•••.••.••••••••.••••••••.. pr in t leve 1 ........................... . ,......... . PRINTLEVEL[N] SUBR .•...•.•••.••.••• PROP (prettydef command) •••••••••••••••••••••••• Q (following a number) •••••••••••••••••••••••••• QUIT (tenex command) •.•••••••••••••••••••••••••• RADIX[N] SUBR .••.••..••..••.••••••••.••••..•••.• RATEST[X] SUBR •.•.••.•..•••••.••••.••.••.•••.••• RATOM[FILE] SUBR ..•.•.•..•.•••••••....•••.•....• 0 RATOMS[A;FN] •••••••••••• •••••••••••••••••••••••••••••••••••• RC (makefile option) .•••••••••••••••••••• ~ •••••• READ[FILE;FLG) SUBR ••••••••••••••••••••••••••••• READC[FILE] SUBR .•...•..•.•••••••••.••...•.•••.. READFILE[FILE] ..........•••••••.•••••••••••••••• READLINE[LINE;LISPXFLG] .•..••.•.••••.••••.•••• ~. READP[FILE] SUBR ...•....•..••••.••••..••.••••••• READVISE[X] NL* ...........•..•..•••.•....•...••• RECOMPILE[PFILE;CFILE;FNS;COREFLG] .•••••••.••••• (REDEFINED) (typed by system) ••••••••••••••••••• RLJFN[ JFN] ........•••••..••.•••••••.• • ~ .•...•.... RPAQ[RPAQX;RPAQY] NL •.•.•.••.••••••••••.•...•••. RPAQQ[X;Y] NL ......•••..•.•.•••.•••..•.••.•••... RSTRING[] SUBR ....•••••••••••••••••••••..•.••••• rubout .......................... 0 ••••••••••••••• searching files ...•....••••••••••••••.••••.•.••• separator characters ..•••••• ~ ••••••••••••••••••• SETBRK[LST;FLG] SUBR ..•.••••• SETSEPR[LST;FLG] SUBR ..•••••..••••••.•••••.•.•.. SFPTR[FILE;ADORESS] SUBR .•••.•••.•••..••.•••.... SKREAD[FILE;REREADSTRING] .•..•....•....•.•..•.•• 0 space •••••••••••••••••• ...........•..•••...•••••.•••••..•••••••••• SPACES[N;FILE] SUBR ......•..••.....••.•••••••.•• square brackets (inserted by prettyprint) ••••••• STOP (at the end of a file) ••••••••••••••••••••• strings ................................... $ ••••• STRPOS[X;Y;START;SKIP;ANCHOR;TAIL] ••.•.••...•••. SUBSYS[FILE/FORK;INCOHFILE:OUTCOHFILE; ENTRYPOINTFLG] ••...•••.•••••••••••••••.•.• symbol ic fi Ie input •.•.•.•••••.••••••••••••••..• symbolic file output .••.••.••••••••••••••••••••• SYSBUF[FLG] SUBR .......••••.•••.••••.•••••••..•• SYSFILES (system variable/parameter) .••••••••••• SYSIN[FILE] SUBR ........•.•.•...•.•••••••••••••• S YSOUT[ FILE] EXPR •.•.•.....•.•...•...••.•••••••. SYSPROPS (prettydef variable/parameter) .•••••••• tab ............... ,. ............................ . TAB[POS;MINSPACES;fILE] •••••••.••••••••••••.••.• TCOMPL[FILES] .•...•.••...•.•..•••••..•••••••••.• teletype ....................................... . ••••••••••••••••••••••••••••••••••• e •••••• TENEX ...•••••.•••••••••••••••••••••••••••••••••• TERPRI[FILE] SUBR U - CASE[ X] .......•....•.......•....•..... ..•••..•...••••.••••••••••••••••••••••• UCASELST (prettydef variable/parameter) ••••••••• UPDATEFILES[] •.••. ~ .••••...•••••.••••••••••••••• UREAD[FILE;FLG] SUBR .....•••.••••.•.•••••••••••• USERMACROS (editor variable/parameter) •••••••••• INDEX. 14 .4 14.37 14.19-20 14.19 14.33,36 14.11,18,22 14.48 14.11,18,22 14.14 14.11-13,25 14.12 14.46 14.10-11,24 14.14,25 14.28 14.16-17 14.16 14.34 14.44,46,48 14.27 14.9 14.27,32 14.27,32-33 14.12 14.23 14.7 14.12-15,19,24 14.12-13,15,19 14.12-13,15,19 14.6-7.23 14.17-18,28 14.13 14.19 14.38 14.27-29,38 \14.11 14.7 14.48 14.27-28 14.29-38 14.21 14.49 14~26 14.21,26 14.33 14.13 14.37 14.44,46 14.1,4,10-11,16,20,23, 31 14.2-4,6-8,40 14.19 14.43 14.43 14.45,50-51 14.11-12,15,24 14.35 Page Numbers USERMACROS (prettydef cOllumlnd) •••••••••••••••••• VARS (prettydef command) ....•.••.••.•.••••.••••. version numbers ......••••••••••••••••••••••••••• 14.35 14.34 14.2 14.48 WHEREI-S[X] •••••••••••••••••••••••••••••••••••••• WIDEPAPER[FLG] .........••...•.•.••••..•..•••...• 14.39 WRITEFIlE[X;FILE;OATEFLG] ......•..••............ 14.29 II 14.11-14,19 (followed by a number) .•••••••••••••.••••••••• 14.19 1# (typed by system) ..•..••••••••••••••••••••••• 14.10,23,25 IRPARS (prettydef variable/parameter) •••••••••.• 14.38 S (alt-mode) ................... 14.2 " (escape character) ...•.••••••••••••••••••••••• 14.10-14,18-19,25 " (use 1n comments) ...•...•.•••••••••••.•••.••••• 14.41 "" (use 1n commen ts) .•...•••.•••••••••.••••••••• 14.41 & (typed by system) .......••.••.•••.••.•...••••• 14.19 ( 14.13 ) 14.13 lIr (u 5 e .inc omme n t 5 ) •••••..••••••••••••••••••••••• 14.30,39 lIr (use in prettydef command) .•.....•••..•.•••••• 14.36 lIrllrCOMMENT-* (typed by system) •.•••.••••.••.•.•.• 14.31 lIr*COMMENT**FlG (prettydef variable/parameter) 14.31 -- (typed by system) .........•••••••.•••.••••••• 14.20 14.13 ... (typed by system) 14.17 [ 14.13 [,] (inserted by prettypr1nt) •••••••.••.•.•••••• 14.38 \ (typed by system) .•..• ~ •••••••••••••••••••••••. 14.10,23 ] 14.13,16 t (use in comments) 14.41 * 46 • • • • • • • • • • • • • • • • ••••••••••••••••••••••• 4' ••••••••••••••••••••••• INDEX. 14 .5 SECTION 15 DEBUGGING - THE BREAK PACKAG£l 15.1 Debugging Facilities Debugging a collection of LISP functions involves isolating problems within particular functions and/or determining when and where incorrect data are being generated and transmitted. In the INTERLISP system, there are three facilities which allow the user to (temporarily) modify selected function definitions so that he can follow the flow of control in his programs, debugging information. package. and obtain this These three facilities together are called the break All three redefine functions in terms of a system function, break1 described below. Break modifies the definition of its argument, a function fn·, so that if a break· condition (defined by the user) is satisfied, the process is halted temporarily on a call to fn. The user can then interrogate the state of the machine, perform any computation •. and continue or return from the call. Trace modifies a definition of a function fn so that whenever fn is. called, its arguments (or some other values specified by the user) are printed. value of fn is computed it is printed also. When the (l.!:!£! is a special case of break) . i---T~;-b;;;k-~;~k;;;-;;;-;;i;;;~-b;-W:-T;i;;i;;~:----------------------------- 15.1 Breakin allows the user to insert a breakpoint inside an expression defining a function. the user) When the breakpoint i.s reached and if a break condition (defined by is satisfied, a temporary halt occurs and the user can again investigate the state of the computation. The following two examples illustrate these facilities. the user traces the function fa'ctorial. In the first example, trace redefines factorial so that it calls break1 in such a way that it prints some information, in this case the arguments and value of factorial .• and then go~s on with the computation. When an error occurs on the fifth recursion. break1 reverts to interactive mode, and a full break occurs. The situaltion is then' the same as though the user had originally performed"BREAK(FACTORIAL) instead of TRACE(FACTORIAl), and the user can evaluate various' INTERLISP forms and direct the course of the computation. In this case, the user examines the variable rr, 1 as the value of this cell to factorial. The rest of the tracing proceeds without inCident. and instructs break1 to return The user would then presumably edit factorial to change l to 1• In the second example, the user has constructed a non-recursive definition of factorial. He usesbreakin to insert a call to break1 just after the PROG label lOOP. This break is to occur only on the last two iterations, i.e., when !! is less than 2. When the brElak occurs, the user looks at the value of !!.. mistakenly typing NN. However, the break is maintained and no damage is done. After examining !!. and m the user allows the computation to continue by typing OK. A second break occurs after the next iteration, this time with N=O. When this break is released, the function factorial returns its value of 120. 15.2 .. pp FACTORIAL (FACTORIAL [LAMBDA (N) (COND «ZEROP N L) (T (ITIHES N (FACTORIAL (SUB1.N]) FACTORIAL "TRACE(FACTORIAl) (FACTORIAL) "FACTORIAl(4) FACTORIAL: N = 4 FACTORIAL: N =3 FACTORIAL: N =2 FACTORIAL: N :: 1 FACTORIAL: N :: 0 U.B.A. L (FACTORIAL BROKEN) :N o :RETURN 1 FACTORIAL :: 1 FACTORIAL 1 FACTORIAL = 2 FACTORIAL = 6 FACTORIAL :: 24 III .. 24 15.3 ... pp FACTORIAL (FACTORIAL [LAMBDA (N) (PROG «M 1» LOOP(COND «lEROP N) (RETURN H») (SETQ M (ITIMES H N» (SETQ N (SUBt N» (GO LOOP]) FACTORIAL "'BREAKIN(FACTORIAL (AFTER LOOP) (ILESSP N 2] SEARCHING ... FACTORIAL "'FACTORIAL(5) «FACTORIAL) BROKEN) :NN U.B.A. NN (FACTORIAL BROKEN AFTER LOOP) :N 1 :M 120 :OK (FACTORIAL) «FACTORIAL) BROKEN) :N o :OK (FACTORIAL) 120 ... 15.2 Break1 The basic function of the break package· is break1. Whenever INTERLISP types a message of the form (- BROKEN) followed by':' the user is then 'talking to' break1, and we say he is 'in a break.' break1 allows the user to interrogate the state of the world and affect the course of the computatiori. It uses the prompt character ':' to indicate it is ready to accept input(s) for evaluation, in the same way as evalqt uses ' .. '. The user may type in an expression for evaluation as with evalqt, and the value will be printed out, followed by another:. Or the user can type in one of the commands specifically recognized by break1 described below. 15.4 Since break1 puts all of the power of INTERLISP at the user's command, he can do anything he can do at evalqt. For example, he can insert new breaks on subordinate functions simply by typing: (BREAK fnt fn2 .•• ) or he can remove old breaks and traces if too much information is being supplied: (UNBREAK fnJ fn4 ••• ) He can edit functions, including the one currently broken: EDITF(fn) For example. the user might evaluate an expression. see that the value was incorrect, call the editor, change the function. and evaluate the expression again, all without leaving the break. Similarly, the user can prettyprint functions, define new· functions or redefine old ones, load a file, compile functions, time a computation, etc . . In short, anything that he can do at the top level can be done while inside of the break. In addition the user can examine the pushdown list, via the functions described in Section 1.2, and even force a return back to some higher function via the function retfrom or reteval. It is important to emphasize that once a break occurs, the user is in complete control of the flow of the computation, and the computation will not proceed wi thout specific instruction from him. If the user types in an expression whose evaluation causes an error, the break is maintained. 15.5 Similarly if the user aborts a computation 2 in.ltiated from within the break, maintained. the break is Only if the user !Qives one of the coounands that exi ts from the break, or evaluates a form which does a retfrom or reteval back out of break1, will the computation continue. 3 Note that break1 is just another INTERLISP function, not a special system feature like the interpreter or the garbage collector. It has arguments which are explained later, and return!) a value, the same as cons or cond or any other function. ~ or The value returned by break1 is called 'the value of the break.' The user can specify th:ls 'value explicitly by using the RETURN conunand described below. But in most cases, the value of a is given implicitly, via a GO or OK conunand. and is the result of evaluating I the break expression,' brkexp. which is one of the arguments to break1. The break expression is an exprossion equivalent to the computation that have taken place had no break occurred. wo~ld For example, if the user breaks on the function FOO, the break express.1on is the body of' the definition of FOO. When the user types OK or GO, the body of FOO is evaluated, and its value returned as the value of the break, i.e. to whatever function called FOO. The effect is the same as though no break had occurred. In other words, one can th ink of break1 as a fancy eval, which p4!rmits interaction before and after evaluation. The break expression then corresponds to the argument to eval. 2-----------------------------------------------------------------------------By typing control-E, see Section 16. 3 Except that break 1 does n01~ 'turn otf' control-D, i.e. a control-D will force an immediate return back to the top level. 15.6 Break Conunands GO Releases the break and allows the computation to proceed. break t evaluates brkexp, its firs t argument, prints the value of the break. brkexp is set up by the function that created the call to break1. For break or trace, brkexp is equivalent to the body of the definition of the broken function. For breakin, using BEFORE or AFTER. brkexp is NIL. For breakin AROUND, brkexp is the indicated expression. See breakin, page 15.19. OK Same as GO except the value of brkexp is not printed. EVAL Same as GO or OK except that the break is maintained after the evaluation. The user can then interrogate the value of the break which is bound on the variable ! value. and continue wi th the break. Typing GO or OK following EVAL will not cause reevaluation but another EVAL will. EVAL is a useful command when the user is not sure whether or not the break will produce the correct value and wishes to be able to do something about it if it is wrong. RETURN form or RETURN fn[args] The value of the indicated computation is returned as the value of the break. for example. one might use the EVAL command and follow this with RETURN (REVERSE !VALUE). t Calls error! and aborts the break. i.e. makes it "go away' without returning a value. This is a useful way to unwind to a higher level break. All other errors, including those encountered while executing the GO, OK, EVAL, and RETURN commands, maintain the break. !EVAL function is first unbroken, then evaluated. and then rebroken. Very useful for dealing with recursive functions. !OK Function is first unbroken, evaluated, rebroken, and then exited, 1.e. !OK is equivalent to !EVAL followed by OK. !GO function is first unbroken, evaluated, rebroken, and exited with value typed, i.e., 'EVAL followed by GO. 15.7 UB unbreaks brkfn, e.g. (FOO BROKEN' :un FOOl and FOO is now unbroken @ resets the variable lastpos, which establishes a context for the commands ?=, ARGS, BT, BTV, BTV*, and EDIT, and IN? described below. lastpos is the position of a function calIon the push-down stack. It is initialized to the function just before the call to breakl, i.e. stknth[-I;BREAK1] 1~reats the rest of the teletype line as its argument( s) . It first resets las tpos ,to stknth[-1;BREAK1] and then for each atom on the line. , searches backward, for a call to that atom. The following atoms are treated specially: @ ,(!) do not reset las tpos to stknth[-l;BREAKl] but leave ,it as it was, and continue searching from that point. numbers if negative, move lastpos back that number of calls, if positive, forward, i.e. reset lastpos to stknth[n;lastpos] .. search 'forward for next atom I the next atom is, a number and can be used to specify more than one call e.g. @ FOO I 3 is equivalent to @ FOO FOO FOO Example: if the push-down stack looks like BREAK1 FOO SETQ COND PROG FIE COND FIE COND FIE COND PROG FUM (13) (12) (11) (10) (9) (8) (7) (6) (5) (4) (3) (2) (1) then @ FIE COND will set lastpos to the position corresponding to (7); @ @ COND will then set lastpos to (5); @ FUM .. FIE to (4); and @ FIE I 3 -1 to (3). If , cannot successfully complete a search, 15.8 it types (fn. NOT FOUND), where fn is the name of the function for which it was searching. When @ finishes, it types the name of the function at lastpos, i.e. stkname[lastpos] @ can be used on brkcoms. In this case, the next command on brkcoms is treated the same as the rest of the ,teletype line. 1= This is a multi-purpose command. Its most common use is' to interrogate the value( 5) of the arguments of the broken function, e.g. if FOO has three arguments (X Y Z), then typing 1- to a break on FOO, will produce: ' : 1= X= Y =. Z• value of X value of Y value of Z 1= operates on the rest of the teletype line as its arguments. If the line is empty. as in the above case, it prints all of the arguments. If the user types 1= X (CAR V), he will see the value of X, and .the value of (CAR Y). The difference between using 1= and typing X and (CAR Y) directly to break1 is that 7= evaluates its inputs as of lastpos, i.e. it uses stkeval. This provides a way of examing variables or performing computations as oJ a particular point on the .stacl. For example, @ FOO I 2 followed by 1= X will allow the user to examine the value of X in the previous call to FOO, etc. 1= also recognizes numbers as refering to the correspondingly numbered argument, i •e. it uses stkarg in this case. Thus :@ FIE FIE :1= Z will print the name and value of argument of FIE. the second 7= can also be used on brkcoms, in which case the next command on brkcoms is treated as the rest of the teletype line. For example, if brkcoms 1s (EVAL 1= (X Y) GO), brkexp will be evaluated, the values of X and Y printed, and then the function exited with its value being printed. BT Prints a backtrace of Junctton names only starting at lastpos. (See discussion of @ above) The several nested calls in system packages such as break, edit,and the top level executive appear as the single entries ·-BREAK··, •• EDITOR •• , and ·-TOP*. respectively. 15.9 BTV Prints a back trace of function variables beginning at lastpos. names BTV* Same as BTV except also prints arguments internal calls to eva!. (See Section 12) BTV! Same as BTV except prints el1eruthtng on stack. (See Section 12). wt th of BT, BTV, BTV*, and BTV! all permit an optional functional argument which is a predicate that chooses functions to be skipped on the backtrace, e.g., BT SUBRP will skip all SUBRs. BTV (lAMB04A (X) (NOT (MEMS X FOOFNS») will skip all but those functions on FOOFNS. If used as a brkcom the functional argument is no longer optional, i.e. the next brkcom must either be the functional argument, or NIL if no functional argument is to be applied. For BT, BTV, BTV*, and BTV!, if control-P is used to change a printlevel during the backtrace. the printlevel will be restored after the backtrace is completed. ARGS Prints the names of the variables bound at lastpos, i.e. variables[lastpos] (Section 12). For most cases. these are the arguments to the func:tion entered at that posi tion. i. e. arglist[stkname[lastpos]]. The following two conunands are for use only with unbound atoms or undefined function breaks (see Section 16). = form, = fn[args] for the break follo,ing an unbound atom error. Sets the atom to the value of the form, or function and arguments, exits from the break returning that value, and continues the computation, e.g. only U.B.A. (FOO BROKEN) := (COpy FIE) sets; FOO and goes on. 15.10 -> expr for use either with unbound atom error, or undefined function error. Rep\rces the expression containing the error with expr (not the value of expr) e.g •• U.D.F. (FOOl BROKEN) :-> FOO changes the computation. FOOl to FOO and continues the expr need not be atomic, e.g. U.B.A. (FOO BROKEN)· :-> (QUOTE Foo) For U.D.F. breaks. the user can specify a function initial arguments, e.g. and U.D.F. (MEHBERX BROKEN) :-> MEMBER X Note that in the case of a U.D.F. error occurring immediately following a call to ~, e.g. (APPLY X Y) where the value of x is FOO and FOO is undefined, or a U.B.A. error immediately following a call to eval, e.g. (EVAL X), where the value of x is FOO--and FOO is unbound, there is no expression containing the offending atom. In-this case, - > cannot operate, so ? is printed and no action taken. EDIT designed for use in conjunction with breaks caused by errors. Facilitates editing the expression causing the break: NON-NUMERIC ARG NIL (IPLUS BROKEN) :EOIT IN Foo .•• (IPLUS X Z) EDIT ~(3 Y) *OK FOO and user can continue by typing OK, EVAl, etc. 4--~·--~-----~---~--~·~~-------------------~---------------------------------~- - > does not change just brkexp; it changes the function or expression containing the erroneous form. In other words, the user does not have to perform any additional editing. 15.11 This command is very simple conct!ptually, but complicated in its implementation by all of the exceptional cases involving inteactions with compiled functions, breaks on Therefore, user we functions, error breaks, breaks within breaks, et a1. shall give the following simplified explanation which will account for 90% of the situations arising in actual usage. For those others, EDIT will print an appropriate failure message and return to the break. EDIT begins by searching up the stack beginning at lastpos (set by @ command, initially position of the break) looking for a form, i.e. an internal call to eval. Then EDIT continues from that pOint looking for a call 'to an interpreted function, or to eval. It then calls the editor on either the EXPR or the argument to eval in such a way as. to look for an expression !!l to the form that it first found. begin. It then prints the form, and permits interactive editing to Note that the user can then type successive O's to the editor to see the chain of superforms for this computation. If the user exits from the edit with an OK, the break expression is reset, if possible, so that the user can continue with the computation by simply typing OK. 6 However, in some situation~, the break expression cannot be reset. For example, if a compiled function FOO incorrectly called putd and caused the error ARG NOT ATOM followed by a break on putd, EDIT might be able to find the form headed' by FOO, function. and also find that form in some higher interpreted But after the user cor'rected the problem in the FOO-form, if any, he would still not have in any way informed EDIT what to do about the immediate problem, i.e. the incorrect call to putd. EDIT would find the putd form j~tself, However, if FOO were tnterpreted so that when the user corrected that form, EDIT could use the new corrected form to reset the break expression . . The two cases are shown below: 6-----------------------------------------------------------------------------Evaluating the new brkexp will involve reevaluating the form that causes the break, e.g. if (PUTD (QUOTE (FOO» big-computation) were handled EDIT, big-computation would be reevaluated. 15.12 by ARG NOT ATOM (FUM) (PUTD BROKEN) :EOIT IN FIE ... (FOO X) EDIT "(2 (CAR X» "OK NOTE: BRKEXP NOT CHANGED FIE :?= U = (FUM) :(SETQ U (CAR U» FUM :OK PUTO IN? ARG NOT ATOM (PUlO BROKEN) :EOIT IN FOO .•• (PUTD X) EDIT *(Z (CAR X» *OK FOO :OK PUTO similar to EDIT, but just prints parent form, and superform, but does not call editor, e.g. ATTEMPT TO RPLAC NIL T (RPLACO BROKEN) :IN? FOO: (RPLACD X Z) Although EDIT and IN? were designed for error breaks, they can also be useful· for user breaks. For example, if upon reaching a break on his function FOO, the user determines that there is a problem in the call to FOO, he can edit the ca~ling form and reset the break expression with one operation by using EDIT. The following two protocol's with and without the use of EDIT, illustrate this: 15.13 (FOO BROKEN) :1= (FOO BROKEN) :1= X = (A B C) X = (A Y Y = == 0 :EOIT IN FIE ... (FOO V U) EDIT *(SW 2 3) *OK 8 FIE :OK FOO :8T FOO SETQ COND PROG FIE find which function FOO is called! from (aborted with tE) :EOITF(FIE) EDIT -F FOO P (FOO V U) -(SW 2 3) *OK FIE :(SETQ Y X) B C) 0 edit it reset X and Y (A'B C) : (SETQQ X 0) o :1= X = 0 Y = (A B C) :OK FOO check them !Jrkcoms The fourth argument to break1 is brkcoms. a list of break commands that break1 interprets and executes as though they were teletype input. One can think of brkcorns as another input file which always has priority over the teletype. Whenever brkcoms=NIL, break! Ireads its next command from the teletype. Whenever brkcoms is not NIL, break1 takes as its next convnand car[brkcorns] and sets brkcoms to cdr[brkcoms]. value of the variable x after For example, suppose the user wished to see the ,8 function was evaluated. He would set up a break wi th brkcoms= (EVAL (PRINT X) OK), which would have the desired effect. The function trace uses brkcoms: it sets up a break with two commands; the first one prints the arguments oj: the function, or whatever the user specifies, 6-------------------------------··---------------------------------------------and have not been changed, but brkexp has. See previous footnote. ~ ~ 15.14 and the second is the command GO, which causes the function to be evaluated and its value printed. If brkcoms is not NIL, the value of 8 break command is not printed. If you desire to see a value, you must print it yourself, as in the above example with the command (PRINT X). Motel whenever an error occurs. brkcoms is set to break. occurs. NIL, and a lulL interactive Brkfile The break package has a facility for redirecting ouput to a file. The variable brkfile should be set to the name of the file, and the file must be opened. All output resulting from brkcoms will be output to brkfile, e.g. output due to TRACE. Output due to user typein is not affected. and will always go to the terminal. brkfile is initially T. Breakmacros Whenever an atomic command is given break1 that it does not recognize, either via brkcoms or the teletype, it searches the list breakmacros for the command. ( .•. (macro command 1 command Z ••• command n ) •.• ). If the command is defined as a macro, break1 simply appends its definition, The form of breakmacros is which is a sequence of commands, to the front of brkcoms, and goes on. command is not contained in breakmacros. If the it is treated as a function or variable as before. Example: the command· ARGS could be defined by including on breakmacros: (ARGS (PRINT (VARIABLES lASTPOS T»). 15.15 15.3 Break Functions break1[brkexp;brkwhen;brkfn;brkcoms;brktype] is an nlambda. brkwhen determines whether a break is to occur. If its value is NIL, brkexp is evaluated and returned as the value of break1. Otherwise a break occurs and mes,sage is printod using brkfn. taken from interpreted. brkcoms or an identifying Commands are then the teletype GO, !GO, The commands, and OK, !OK, RETURN and t, are the only ways to leave breakl. The command EVAL causes brkexp to be evaluated, and saves the value on the variable 'value. commands can be defined for is NIL for Other break1 user via breakmacros. brktype breaks. INTERRUPT for control-H breaks, and ERRORX for the input buffer is cleared and saved. (For control-H err'or breaks. For error breaks. breaks, the input buffer was cleared at the time the control-H was typed, see Section 16.) In both cases, if the break returns a value, i.e., is not aborted via t or control-D, the input buffer will be restored (see Section 14). breakO[fn;when;coms] set~i up a break on the function fn by redefining fn as a call to break1 with brkexp an equivalent deflni tion of fn, and when. brkfn. brkcoms. brk~,hen. fn, and corns, as Puts property BROKEN on property list of fn wi th value a gensym defined with the original definition. Puts property BRKINFO on property list of fn with value (BREAKO when coms) (For use in conjunction with rebreak). 15.16 Adds fn to the front of the list brokenfns. Value is fn. If fn is non-atomic and of the form (fnl IN fn2), breakO first calls a function which changes the name of fnt wherever it appears inside of fn2 to that of a new function, initially defines as fnt. rnt-IN-fn2, which it Then breakO proceeds to break on fnl-IN-fn2 exactly as described above. This procedure is useful for breaking on function that is called from many places, a but where one is only interested in the call from a specific function, (PRINT IN FIE), etc. e.g. (RPlACA IN FOO), It is similar to breakin described below, but can be performed euen when FN2 is compiled or blockcompiled, whereas breakin only works on interpreted functions. If fnt is not found in fn2, breakO returns the value (fnl NOT FOUND IN fn2). If fn t is found in fn2, in addition to breaking fnt-IN-fn2 and adding fnt-IN-fn2 to the list brokenfns, breakO adds fnt ,to the property value for the property NAMESCHANGED on the property list of ~ and adds the property ALIAS with the value (fn2. fnl) to the property list of rnt-IN-fn2. This will enable unbreak to recognize what changes have been made and restore the function fn2 to its original state. 15.17 If fn is nonatomic and not of the above form, bre,akO is called for each member of fn using the sam!9 values for when, ~, and file specified in this call to breakO. This distributivity permits the user to specify complicated break conditions on several functions without excessive retyping, e. g. , breakO[(FOOt «PRINT PRINt) IN (F002 FOOl»); (NEQ X T);(EVAL 1= (Y Z) OK)] will break on FOOt, PRINT-IN-FOO2, PRINT-IN-F003, PRINt-IN-F002 and PRINt-IN-FOO3. If In is non-atomic, the value of breakO is a list of the individual values. break[x] is a nospread nlambda. for each atomic argument, it performs breakO[atom;T]. performs apply[BREAKO;list]. for each list, For it example, breilk[FOOl (FOO2 (GREATERP N 5) (EVAL»] equ:lvalent to breakO[FOO1,T] is and breiikO[ FOOl; (GREATERP N 5); (EVAL)] trace[x] is a nospread nlambda. For each atomic argument, it performs breakO[atom;T;(TRACE 1= NIL GO)]? For each list argument, £!.!: is the function to be traced, and cdr the forms the user wishes to see, i.e. trace performs: breakO[car[list];T;list[TRACE;1=; cdr[list],GO]] 7-------------------------------··---------------------------------------------The flag TRACE is checked for in breakt and causes the message 'function :' to be printed instead of (function BROKEN). 15.18 for example, TRACE(FOOI (FOOl Y» FOOl and FOOl to be traced. will cause both All the arguments of FOOl will be printed. only the value of Y will be printed for FOO2. In the special case that the user wants to see onlu the value, he can perform TRACE«fn». This sets up a break with commands (TRACE 1- (NIL) GO). Note: the user can always call breakO himself to oetain combination of options of break1 not directly available with break and trice. These two functions merely provide convenient ways of calling breakO, and will serve for most uses. Breakin Breakin enables the user to insert a break. i.e. a call to break1, specified location in an interpreted function. at a For example, if !.2.!! calls fie, inserting a break in !22 before the call to fie is similar to breaking fie. However. break in can be used to insert breaks before or after prog labels, particular SETQ expressions, or even the evaluation of a variable. This is because breakin operates by calling the editor and actually inserting a call to break1 at a specified point inside of the function. The user specifies where the break is to be inserted by a sequence of editor commands. These commands are preceded by BEFORE, AFTER, or AROUND, which break in uses to determine what to do once the editor has found the specified point, i.e. put the call to break! BEFORE that point, AFTER that point, or AROUND that point. For example, (BEFORE COHD) will insert a break before the first occurrence of cond, (AFTER COHO Z 1) will insert a break after the predicate in the first clause, (AFTER BF (SETQ X &» X is set. ~ after the la&t place Note that (BEfORE TTY:) or (AFTER TTY:) permit "the user to type in cOlMlands to the editor. locate the correct pOint, and verify it for himself 15.19 breakin[fn;where;when;coms] breakin is an nlambda. to when and ~ when and £Qm! are similar for breakO, except that if when is NIL, T is used. where specifies where in the definition of 'fn the call to breakl is to be inserted. (8ee earlier discussion). If fn is a compiled function, break in returns (fn UNBREAKABLE) as its value. If fn is int'erpreted, breakin types SEARCHING ..• while it calls the editor. If specified by where is not found, (NOT FOUND) and exits. the location break in types If it is found, breakin adds the property BROKEN-IN with, value T, and the property BRKINFO with value (where when coms) to the property list of fn. and adds fn to the front of the list brokenfns. Multiple break points, can be inserted with a single call to breakin by using a list of the form ( (BEFORE ••• ) (AROUND ••• ) ) for where. It is also possible to call break or trace on a function which has been modified by breakin, and conversely to break in a function which has been redefined by a call ,to break or trace. unbreak[x] unbreak 1s a nospread nlambda. It takes an indefinite number of functions modified by break, trace, or breakin and restores original state by calling unbreakO. of values of unbreakO. 15.21 them to their' Value is list unbreak[] will unbreak all functions on brokenfns, in reverse order. It first sets brkinfolst to NIL" unbr'eak[ T] unbreaks just the first bro~~en fns, i. e., the most function on recently broken fun(:tion. unbreakO[fn] fn to its original state. res1~ores If fn was not broken, value is (NOT BROKEN) and no changes are mado. If fn was modified by breakin, unbreakin is called to edit it back to its original state. If fn 'tas created from (fnl IN fn2), i.e. if it has a property ALIAS, the function in which fn appears is restored to its original state. All functions break that were created eliminated. by the dununy are Adds property value of BRKINFO to (front of) brkinfolst. Note: unbreakO[(fnl IN fn2)] is allowed: unbreakO will operate on fnl-IN-fn2 instead. unbreakin[fn] performs the appropriate editing operations to eliminate all changes made by break in . fn may be either function. the name or Value 15 fn. unbl~eak definition of a Unbreakin is automatically called by if fn has property BROKEN-IN with value T on its property list. rebreak[x] is an nlambda, nospread function for rebreaking functions that 15.22 were previously broken without having to respecify the break information. For each function on !, rebreak searches brkinfolst for break(s) operation. and performs Value is the a corresponding list of values corresponding to calls to breakO or breakin. If no information is found for a' particular function, value is (fn - NO BREAK INFORMATION SAVED). rebreak[] rebreaks everything on brkinfolst, i.e., rebreak[] is the inverse of unbreak[]. rebreak[T] rebreaks brkinfolst, i.e., just the the first function break most on recently unbroken. changename[fn;from;to] changes all occurrences of from to may be compiled or blockcompiled. ~ in fn. fn Value is fn if from was found, otherwise NIL. Does not perform any modifications of property lists. Note that from and to do not have to be functions, e.g. they can be names of variables, or any other literals. virginfn[fn;flg] is the function that knows how to restore functions to their original state regardless of any amount of breaks, breakins, ,advising, compiling and saving exprs, etc. It is used by prettyprint, compiler. f.!a=NIL, as. define, and the If for prettyprint, it does not modify the definition of fn in the process of producing 8 ·clean· version of the definition, i.e. it works on a copy. 15.23 If f1s.=T as for the compiler and define, it physically restores the function to its original state. malting t e. g. and prints the changes it fOO UNBROKEN, FOO UNADVISED, NAMES RESTORED, etc. is FOO Value is the virgin function definition. baktrace[posl;pos2:skipfn:varsflg:-form-flg:a11f1g] ~~ to pos2. If sktpfn[ stkname[ pos]] prints skipfn is back trace is T. (including all variables). var-sflg=T for back trace a la BTV var'sflg=T, -form-flg=T - BTV~sf1g=T. a11flg=T - BTV! 15.24 pos not from NIL, is and skipped Index for Section 15 Page Numbers AFTER (as argument to break1n) ••.••••••••.•••.•• ALIAS (property name) ..•.••.••••.•••.••••••.••.•• ARGLIST[X] .........• e ••••••••••••••••••••••••••• ARGS (break command) .•.....••••••••••••••••••••. AROUND (as argument to break1n) ••.••••••••.••.•• back trace II •••••••••••••••••••••••••••••••••••••• BAKTRACE[FROM;TO;SKIPFN;VARSFLG~·FORM·FlG;ALLFLG]. BEFORE (as argument to breakin) ..•.•.••••••••.••• BREAK[ X] NL* . lit •••••••••••••••••••••••••••••••••• break conunands ........•..•••••..••••.••.•••••••• break expression •..... ~ .•••..••.•••• ~ ••••••••••• BREAK INSERTED AFTER ~typed by break1n) ••••.•••• break package ............•..•••••••••••••••••••• BREAKO[FN;WHEN;COMS;BRKFN;TAIL] ...•.•••.••••.•.• BREAKl[BRKEXP;BRKWHEN;BRKFN;BRKCOHS;BRKTVPE] NL BREAKIN[FN;WHERE;WHEN;BRKCOMS] NL ••.••••..••.••• BREAKMACROS (break variable/par~eter) •••••••••• ....... ~ ..... breakpoint It •••••••••••••••••••••••• BRKCOMS (break variable/parameter) •••••••••.•••• BRKEXP (break variable/parameter) •••••••••••••.• BRKFILE (break variable/parameter) ••••••••••.••• BRKFN (break variable/parameter) ••••.•••••••••••• BRK INFO (property name) ......•:..••.•••••••••.••. BRKINFOLST (break variable/parameter) •••••••.••• BRKTVPE (break variable/parameter) •••••••••••••. BRKWHEN (break variable/parameter) •••••••••••••• BROKEN (typed by system) ..•.•••.•••••••••••••••• BROKEN-IN (property name) •.•••••.••••••••••••••• BROKENFNS (break variable/parameter) ••••.••••••• BT (break command) ...••••••••••••••••••••••••••• BTV (break command) ..••••••••••••••••.•••••••••• BTV! (break command) •••••.••••••••••••••••••••.• BTV· (break command) •..•..•.•••••.•••.•••••••••• CHANGENAME[FN;FROH;TO] .••••••.••••.•••••••••..•• control-D control-E control-H control-P debugging ...................................... . s •••••••••••••••••••••••••••••••••••••• ... ............ .................•................ 0 •••••••••••••••• 00 1' •••••••••••••••••• •••••••••••••••••••••••••• e •••• EDIT (break con:unand) ..•.•••....••••••••••.••••.• editing compiled functions ••••.•.••••••••••••.•• ERROR! [] SUBR ••••••••••••••••••••• ,. ••••••••••••• EVAL (break command) ............................ . EVALQT[ CHAR] ..........•...•....••••.•••••••••••• (fn - NO BREAK INFORMATION SAVED) •••.••••••..••• ( fn 1 IN fn2) .. 0 •• " •••••••••••••••••••••••••••••• ( fn 1 NOT FOUND IN fn2) fnl-IN-fn2 •••.•••• .................. GENSYM[CHAR]' III 0 ••••••••• eo • • • • • • ••••••••••••••••••• •••..••••••••••••••••••••••••••••••• GO (break command) ...•..•.•.•••••••••••••••••••• IN? (break conunand) .....•...•••••••••••••••••••• input buffer ............................ 0 ••••••• LASTPOS (break variable/parameter) •••••••••••••• NAMES RESTORED (typed by system) •••••.•••••••••• NAMESCHANGEO (property name) ..••••••••••••.••••• NOBREAKS (break variable/parameter) ••••••••••••• INDEJ('15.1 15.7,19-20 15.17,22 15.10 15.8,10 15.7,19-20 15.9-10,24 15.24 15.7,19-20 15.1,7,18-19,21 15.7-14 15.6,12 15.20 15.1-24 15.16-19,21,23 15.1-2,4,16,18-19,21 15.2,7,17,19,21-23 15.15,,16 15.2 15.9,14-16 15.6-7,9,11-12,14,16 15.15 15.8,16 15.16,21-22 15.22-23 15.16 15.16 15.4,16 15.21-22 15.17,21-22 15.8~9 15.8,10 15.10 15.8,10 15.23 15.6,16 15.6,20 15.16 15.10 15.1 15.8,11-13 15.23 15.7 15.7,14,16.20 15.5 15.23 15.17,22 15.17 15.17,22 15.16 15.6-7,15-16 15.8,13 15.16 15.8-10,12 15.24 15.17 15.20 Page Numbers ( NO T BROK EN) •••••.•••••••••••••••••••••••••••••• (NOT FOUND) (typed by break) •••••••••••••••••••• (NOT FOUND) (typed by break1n) •••••••••••••••••• NOTE: BRKfXP NOT CHANGED. I( typed by break) •••••• OK (break command) •••••••••••••••••••••••••••••• prompt character •••••••••••••••••••••••••••••••• REBREAK[ X] NL* ••••••••••.••••••••••••••••••••••• RETEVAl[POS;FORM] SUBR ••.••••••••••••••••••••••• RETFROM[POS;VAlUE] SUBR ••••••••••••••••••••••••• RE TURN (break command) .......................... . SEARCHING .•• (typed by break1n) ••••••••••••••••• STKARG[N;POS] SUBR •••••••••••••••••••••••••••••• STKEVAl[POS;FORM] SUBR •••••••••••••••••••••••••• STOP (edit conunand) ••••••••••••••••••••••••••••• TRACE[ X] NL* ...••.....•...••••••••••.•••.•.••••• Try: (edit cornrnand) ••••••••••••••••••••••••••••• U.B.A. breaks ................................... . U.O.F. breaks ........•..•••..•••••••.•••••.•.••• UB (break command) •••••••••••••••••••••••••••••• UNADVISED (typed by system) ••••••••••••••••••••• UNBREAK[X] NL* •••••••••••••••••••••••••••••••••• UNBREAKO[ FN; TAIL] ••••••••••••••••••••••••••••••• (UNBREAKABLE) ••••••••••••••••••••••••••••••••••• UNBREAK IN[ FN] ••••••••••••••••••••••••••••••••••• UNBROKEN (typed by system) •••••••••••••••••••••• value of a break •••••••••••••••••••••••••••••••• VARIABlES[POS] •••••••••••••••••••••••••••••••••• VIRGINfN[FN;FlG] .••••••••••••••••••••••••••••••• 'EVAL (break command) ••••••••••••••••••••••••••• ! GO (break command) ••••••••••••••••••••••••••••• ! OK (break corrunand) ••••••••••••••••••••••••••••• !VAlUE (break variable/parameter) ••••••••••••••• *·BREAK*· (in backtrace) •••••••••••••••••••••••• --EDITOR·· (in backtrace) ••••••••••••••••••••••• --TOp·· (in backtrace) •••••••••••••••••••••••••• -) (break command) •••••••••••••••••••••••••••••• : (typed by sys tern) ••••••••••••••••••••••••••••• = (break command) •••••••• '.•••••••••••••••••••••• 1= (break command) •••••••., •••••••••••••••••••••• @ (break command) ............................... . t (break conunand) ••••••••..•••••••••••••••••••••• ~ (typed by system) ••••••••••••••••••••••••••••• INDEX.15.2 15.22 15.9 15.20-21 15.12 15.6-7,12,14,16 15.4 15.16,22-23 15.5 15.5 15.6-7,16 15.21 15.9 15.9 15.20 15.1,7,14,18-19,21 15.19-20 15.10 15.11 15.8 15.24 15.17,21-22 15.22 15.21 15.22 15.24 15.6 15.10 15.23 15.7 15.7,16 15.7,16 15.7,16 15.9 15.9 15.9 15.11 15.4 15.10 15.8-9 15.8-9,12 15.7,16 15.4 SECTION 16 ERROR HANDLING 16.1 Unbound Atoms and Underi~ed Functions Whenever the interpreter encounters an atomic form with no binding on the pushdown list, and whose value contains the atom NOBIND. 1 the interpreter calls the function faul teval. Similarly, fauI"teval is called when a list is encountered, £!r of which is not the name of a function or a function object. 2 The value returned by faulteval is used by the interpreter exactly as though it were the value of the form. faulteval is defined to print either U.S.A., for yn~ound !tom, or U.D.F., for yn!!efined function, and then to call break1 giving it the offending form as brkexp.8 Once inside the break, the user can set the atom, define the function, return a specified value for the form using the RETURN command, etc., or abort i---~---------------·--~--~---------------------------------~------------------ All atoms are initialized (when they are created by the read program) with their value cells (car of the atom) NOSIND, their function cells NIL, and their property lists (cdr of the atom) NIL. 2 See Appendix 2 for complete description of INTERLISP interpreter. 8 If DWIM is enabled (and a break is going to occur), faulteval also prints the offending form (in the case of a U.S .A., the parent form) and the name of the function which contains the form. For example,' if FOO contains (CONS X FIE) and FIE is unbound, faulteval prints: U.B.A. FIE [in FOO] in (CONS X FIE). Note that if DWI" is not enabled, the user can obtain this information after he is inside the break'via the IN? command. 16.1 the break using the t command., If the break is exited with a value, the computation will proceed exactly as though no error had occurred. 4 The decision over whether or nlot to indu.ce a break depends on the depth of computation. and the amount of time invested in the computation. algorithm is described in detail below it to say that i~ The actual the section on breakcheck. Suffice the parameters affecting this decision have been adjusted empirically so that trivial type-in errors do not cause breaks, but deep errors do. 16.2 Teletype Initiated Breaks Control-H Section 15 on the break package described how the user could cause a break when a specified function was entered. The user can also indicate his desire to go into a break at any time while a program is running by typing control-H. 6 At the next point a function is about to be entered, the function interrupt is called instead. interrupt types INTERRUPTED BEFORE followed by the function 4-----------------------------------------------------------------------------A similar procedure is follo'wed whenever ~ or apply· are called with an undefined function. i.e. OnE! whose ~ is NIL. In this case, faul tapply 1s called giving it the function as its first argument and the list of arguments to the function as its second argument. The value returned by faul taJ~I!_~ is used as the value of ~ or !Q~. faultapply is defined to print U.D.F. and then call break1 giving it (APPLY (QUOTE fn) QUOTE args» as brkexp. Once inside the break, the user can define the function, return a specified value, etc. If the break is exi ted wi th a value, the computation will proceed exactly as though no error had occurred. faultapi2!I is also called for undefined function calls from compiled code. 6 As soon as control-H is typed, INTERLISP clears and saves the input buffer, and then rings the bell, indicating that it is now safe to type ahead to the upcoming break. If the break returns a value, i.e., is not aborted via t or control-D, the contents of the input buffer before the control-H was typed will be restored. 16.2 name, constructs an appropriate break expression, and then calls break1. user can then examin~ The the state of the computation, and continue by typing OK, GO or EVAl, and/or retfrom back to some previous point, exactly as with a user break. Control-H breaks are thus always 'safe'. Note that control-H breaks are not affected by the depth or time of the computation. However, they onlu occur when a function is called, since it is only at this time that the system is in a ·clean· enough state to allow the user to interact. Thus, if a compiled program is looping without calling any functions, or is in a 1/0 wait, control-H will not affect it. Control-B, however, will. Control-B Control-B is a stronger interruption than control-H. It effectively generates an inunediate error. This error is treated like any other error except that it always causes a break, regardless of the depth or time of the computation. 6 Thus if the function FOO is looping internally, typing control-B will cause the computation to be stopped, the stack unwound to the point at which FOO was called, and then cause a break. Note that the internal variables of FOO are not available in this break, and Similarly, FOO may have already produced some changes in the environment before the control-B was typed. Therefore whenever pOSSible, it is better to use control-H instead of control-B. Control-E If the user wishes to abort a computation, without causing a break, he should type control-E. Control-E does not go through the normal error machinery of scanning the stack, calling breakcheck, printing a message, etc. as described below, but simply types a carriage-return and unwinds. a-----------------------------------------------------------------------------However, setting helpflag to N~L will suppress the break. See discussion of breakcheck below. 16.3 16.3 Other Types of Errors In addition to U.B.A. and U.O.F. errors, there are currently 28 other error typei etc. 1n INTERLISP, e.g. P-STACK OVERFLOW, NON-NUMERIC ARG, FILE NOT OPEN, A complete list 1s given later in this section. When an error occurs, the decision about whether or not to break is handled by breakcheck and is the same as with U.B.A. and U.O.F. errors. If a break is to occur, the exact action that follows depends on the type of error. to occur following evaluation ATTEMPT TO RPlAC NIL error), of For example, if a break is (RPlACA NIL (ADDI 5» the message printed will be (which causes an (RPlACA BROKEN), brkexp will be (RPlACA U V W), U will be bound to NIL, V to 6, and W to NIL, and the stack will look like the user had broken on rplaca himself. Following a NON-NUMERIC ARG error. the sy:stem will type IN followed by the name of the most recently entered function, and then (BROKEN). effectively be in a break inside of this function. The system will then brkexp will be a call to ERROR so that if the user types OK or EVAl or GO, a ? will be printed and the break maintained. However, if the break is exited with a value via the RETURN command,7 the computation will p."oceed exactly as though no error had occurred. 16.4 Breakcheck - When to Break The decision as to whether or not to induce a break when an error occurs is handled by the function breakcheck. 8 The user can suppress all error breaks by setting the variable helpflag to NIL (initially set to T). decision is affected by two factors: the length If helpflag=T, the of time spent in the 7--------------------------------·----------------------------------.----------Presumably the value will be a number, or the error will occur again. 8 Breakcheck is not actually available to the user for adVising or breaking since the error package is block-compiled. 16.4 computation, and the depth of the computation at the time of the error. 9 If the time is greater than helptime or the depth is greater than helpdepth, breakcheck returns T, meaning a break will occur. Since a function is not actually entered until its arguments are evaluated,10 the depth of a computation is defined to be the sum of the number of function calls plus the number of internal calls to eval. expression Thus if the user types in the [MAPC FOO (FUNCTION (LAMBDA (X) (COND «NOT (MEMBX FIE» for evaluation, and FIE is not bound~ (PRINT Xl at the point of the U.B.A. FIE error, two functions, mapc and cond, have been entered, and there are three internal calls to corresponding (CONO «NOT (MEMB X FIE» to the evaluation of the forms (PRINT X»), (NOT (MEMB X FIE»,· and (MEMB X FIE).ll The depth is thus 5. breakcheck begins by searching back up the parameter stack looking for an errorset. 12 At the same time, it counts the number of internal calls to eval, as indicated by pseudo-variable bindings called eval-blips. See Section 12. As soon as (if) the number of eval-blips exceeds helpdepth, breakcheck can stop searching for errorset and return T, since the position of the errorset is only needed when a break is not going to occur. ' Otherwise, breakcheck continues 9--~-----------------~-------------------------------- ------------------------- Except that control-B errors always break. 10 Unless of course the function does not have its arguments evaluated, i.e. is an FEXPR, FEXPR*, CFEXPR, CFEXPR*, FSUBR or FSUBR*. 11 for complete discussion of the stack and the interpreter, see Section 12. 12 errorsets are simply markers on the stack indicating how far back unwinding is to take place when an error occurs, i.e. they segment the stack into sections such as that if an error occurs in any section, control returns to the point at which the last errorset was entered, from which NIL is returned as the 'value of the errorset. See page 16.14. 16.5 search ing un til either an errorset is found 13 or the top of the stack is reached. Breakcheck then complet~s the depth check by counting the number of function calls between the error and the last errorset, Qr the top of the stack. If the number of calls I)lus the number of eval-blips (already counted) is greater than or equal to helpdepth, initially set to 9,14 breakcheck returns T. Otherwise, it records the position of the last errors~t, and the value of errorset • s second argument, which is used in deciding whether to print the error messaga, and returns NIL. breakcheck next measures the length of time spent in the computation by subtracting the value of the variable helpclock from the value of (CLOCK 2).16 If the difference is greater than helptime milliseconds, initially set to 1000,' then a break wi 11 occur, i. e. , breakcheck returns T, otherwise NIL. variable helpclock is rebound to the current value of (CLOCK Z) The for each computation typed in to lispx or to a break. The time cri terion for breaking can be suppressed by .setting helptime to NIL (or a very big number), or by binding helpclock to NIL. Note thats'etting helpclock to NIL will not have any effect because helpclock is rebound by lispx and by break. If breakcheck is NIL, i.e., a break is not going to occur, then if an errorset was found, NIL is returned (via retfrom) as the value of the errorset, after first printing the error message if the errorset's second argument was TRUE~ ij--------------------------------------------------------~-------------------- If the second argument to the errorset is INTERNAL, the errorset is ignored and searching continues. See discussion of errorset, page 16.14. 14 Arrived at empirically, tak9s into account the overhead due to lispx or break. 16 Whose value is number of milliseconds of compute t'ime. 16.6 See Section 21. If there was no errorset, the message is printed, and control returns to evalgt. This procedure is followed for all types of errors. Note that for all error breaks for which a break occurs, break1 will clear and save the input buffer. t If the break returns a value, i.e., is not aborted via or control-D, the input buffer will be restored as described in Section 15. 16.5 Error Types There are currently twenty-ei~ht listed below by error number. error types in the INTERLISP system. They are The error is set internally by the code that detects the error before it calls the error handling functions. It is also the value returned by errorn if called subsequent to that type of error, and is used by errormess for printing the error message. Most error types will print the offending expression following the message, e . g., NON-NUMERIC ARG NIL is very common. Error type 18 (control-B) always causes a break All other errors cause breaks if (unles~ helpflag ,is NIL). breakcheck returns T. o NONXMEM reference to ~-e!istent ~ory. Usually indicates system is very sick. Currently not used. 1 2 P-STACK OVERFLOW . occurs when computation is too deep, either with respect to number of function calls, or number of variable bindings. Usually because of a non- tenm1nating recursive computation, i.e. a bug. 16.7 3 ILLEGAL RETURN call to return when not inside of an interpreted pr(]i1. 4 ILLEGAL ARG - PUTD second argument to putd (the definition) is not NIL, a list, or a pointer to compiled code. 5 ARG NOT ATOM - SET first argument to set, setg, or !!1gg (name of the variable) is not a literal atom. 6 ATTEMPT TO SET NIL via set or setq 7 ATTEMPT TO RPlAC NIL attempt either to rplaca or to rplacd NIL with something other than NIL. 8 UNDEFINED OR ILLEGAL GO DQ 'when not inside of a ~, or 9Q to nonexistent label. 9 FILE WON'T OPEN From infile or outfile, Section 14. 10 NON-NUMERIC ARG a numeric function e.g. iplus, itimes, igreaterp, exp l9cted a number. 11 ATOM TOO LONG > 100 characters. 12 ATOM HASH TABLE FULL no .'"oom for any more (new) atoms. 13 FILE NOT OPEN frollil an 14 ARG NOT ATOM 15 TOO MANY FILES OPEN l 16 1/0 function, e.g. read, print, closer. 1~cluding 16.8 teletype. 16 END OF FILE from an input function, e.g. read, readc, ratom. Note: the file will then be closed. 17 ERROR call to !!.!:!!!:. 18 BREAK control-B was typed. 19 ILLEGAL STACK ARG a stack function expected a stack position and was gi,ven something else. This might occur if the arguments to a stack function are reversed. Also occurs if user specified a stack position with a function name, and that function was not found on the stack. 20 FAULT IN EVAL artifact See Section 12. of bootstrap. Never occurs after faulteval has been defined as described earlier. , 21 ARRAYS FULL system will first initiate a GC: 1, and if no array space is reclaimed, will then generate this. error. 22 DIRECTORY FULL no new files can be created until user deletes some old ones and expunges. 23 FILE NOT FOUND file name does not correspond to a file in the corresponding directory. Can also occur if file name is ambiguous. 24 FILE INCOMPATIBLE - SYSIN 25 UNUSUAL CDR ARG LIST from sysin, Section 14. a form ends in a non-list other than NIL, e.o. (CONS T • 3). 16.9 26 HASH TABLE FULL seel hash link f.unctions, Section 7. 27 ILLEGAL ARG Catch-all error. Currently used by evala, arg, funarg, allocate, rplstring, and sfptr. 28 ARG NOT ARRAY elt or seta given an argument that is not a pointer to the beginning of an array. 29 ILLEGAL OR IMPOSSIBLE BLOCK from getblk or relblk. See Section 21. 30 currently not used. 31 LISTS fULL following a GC: 8, if a sufficient amount of list words have not been collected, and there is no un- allocated space left in the system, this error is generated. Many system functions, e.g. define, arglist, advise, !.Qjz, expt, generate errors with appropriate messages by calling ~ etc, also (see page 16.12) which causes an error of type 16. Error handling by error type Occasionally the, user may want to treat certain error types different than others, e.g. always break. never break, or perhaps take some corrective action. This can be accomplished via errortypelst. errortypelst is a list of elements of the form (n expression). where n is one of the 28 error numbers. breakcheck has been completed, but before any other action is After taken, errortypelst is searched for an element with the same error number as that 16.10 causing the error. If one is found, and the evaluation of the corresponding expression produces a non-NIL value. the value is substituted for the offender, and the function causing the error is reeentered. for this application, the following three variables may be useful: errormess ~ is the error number, cadr the ·offender· e.g. (10 NIL) corresponds to NON-NUMERIC ARG NIL error. errorpos position of the function in which the error occurred, e.g. stkname[errorpos] might be IPLUS, RPLACA, INFILE. etc. breakchk va lue of breakcheck p i. e • T means a break will occur. NIL means one will not. for example, putting [10 (AND (NULL (CADR ERRORHESS» (SELECTQ (STKNAME ERRORPOS) . «IPLUS ADDl SUB1) 0) (ITIHE5 1) (PROGN (SETQ BREAKCHK T) NIL] on errortypelst would specify that whenever a NON-NUMERIC ARG - NIL error occurred. and the function in question was IPLU5. ADD1, or SUB1. 0 should be used for the NIL. If the function was ITIHES, 1 should be used. always break. Otherwise, Note that the latter case is achieved not by the value returned, but by the effect of the evaluation. i.e. setting BREAKCHK to T. (16 (SETQ BREAKCHK HIL.» Similarly, would prevent END OF FILE errors from ever. breaking. 16.11 16.6 Error Functions errorx[erxm] is the entry to the error routines. 'If erxm=NIl, errorn[] is used to determine the error-message. Otherwise, seterrorn[erxm] is ,performed, • setting I the error and err~rx[(10 either (10 type T)~ errorx argument. (PLUS T), T)] or calls Thus following errorn[] breakcheck, and is either induces a break or prints the message and unwinds to the last errorset. Note that errorx'can be called by any program to intentionally induce an error any of applications, However, ~ype. the function error \-- most for will be more useful. error[messl ;mess2;nobreak] The message that is (will be) printed is mess1 (using prinl), followed by a space if messl is an atolD, otherwise a carriage return., Then mess2 is prilllted, using othtsrwise print. print if mess2 a is string, e. g.. errore "NON-NUMERIC ARG·; T] will print NON,·NUMERIC ARG T and error[FOO;"NOT A FUNCTION"] will pri,nt FOO NOT A FUNCTION. ,( If both mess 1 and mess2 are NIl~ the message is simply ERROR.) If nobreak=T, calJLs ~ error! . prints its message and then Otherwise err()rx[(17 (mess1 • mess2»], i.e. it calls generates an error of type 17, in which case the decision as to 16.12 whether or not to break, and whether or not to print a message, is handled as per any other error'. help[mess1;mess2] prints mess1 and mess2 a la !!.!:.Q!:. and then calls break1. If both mess1 and mess2 are NJl, HElPf is used for the message. help is a convenient way to program a default condition, or to terminate some protion of a program which theoretically the computation is never supposed to reach. errort[]16 programmable control-E, i.e., immediately returns from last errorset or resets. reset[ ] Programmable control-D, 1. e. immediately returns to the top level. errorn[] returns information about the last error in the form (n x) where rr is the error type number and ~ is the expression which was (would have been) printed out after the error message. Thus following (PLUS T), errorn[] is (10 T). errormess[u] prints message corresponding to an errorn that yielded y. For example, errormess[ (10 T)] would print NON-NUMERIC ARG T i6----~--~-------------------------------------------- ------------------------- Pronounced -error-bang-. 16.13 errorset[u;v]17 performs eval[u 1. type of function, Note that errorset is a lembdaand that its arguments are evaluated be/ore it 1s entered, i.e. errorset[x] means eval is called with the ualue of!. In most cases, ersetg and n lsetg (deScrib'd' below') are more useful. If no error occurs in the evaluation of y, the value of errorset is a list containing one element, the value of eval[u]. If an error did occur, the value of errorset is NIL. The argument y controls the printing of error mes.sages if an error occurs. If yeT ,the error message is printed; if y=NIL it is not. If y=INTERNAl, the errorset is ignored' for the pUrjl)ose of deciding whether or not to break or print a message. However, the errorset is in effect for the purpose of flow of control,-i.e. if an error occurs, this errorset returns NIL. ersetq[ersetx] nlalnbda, performs . (ER:5ETQ (FOO» (ERI~ORSET nlsetq[nlsetx] nlmnbda, ---- errorset[ersetx;t], i.e. equivalent to is (QUOTE (FOO» T). performs errorset[nlsetx;NIL]. j~----------------------~-----------------~----------------------.-----~------- errorset is a subr, so the names ·u· and ·v· don't actually appear on the stack nor wil~ they affect the evaluation. 16.14 Index for Section 16 Page Numbers APPLY[FN;ARGS] SUBR ..........•••.•••••••••..•.•• 16.2 APPLY~[FN;ARGl; ... ;ARGn] SUBR..••••••••...••••• 16.2 ARG[VAR;M] FSUBR ............•...•••••••••••••... 16.10 ARG NOT ARRAY (error message) •••••••••••••••.••• 16.10 ARG NOT ATOM (error message) .................... . '16.8 ARG NOT ATOM - SET (error message) ••••••••••.••• 16.8 ARRAYS FULL (error message) .....•••••••••••••••• 16.9 ATOM HASH TABLE FUll (error message) •••••••••••• 16.8 ATOM TOO LONG (error message) •..•••••••••••••••• 16.8 ATTEMPT TO RPlAC NIL (error message) •••••••••••• 16.8 ATTEMPT TO SET NIL (error message) ••••••.••••••• 16.8 bell (typed by system) ..•..••..•••••••••.••••••• 16.2 BREAK (error message) ..•.•.•.••.•••••••••••••••• 16.9 BREAKl[BRKEXP;BRKWHEN;BRKFN;BRKCOHS;BRKTYPE] NL 16.1-3,7,13 BREAKCHECK ••.• 16.2-7,10,12 BRKEXP (break variable/parameter) ••••••••••...•• 16.1-2,4 (BROKEN) (typed by system) •••••••••••••••••••••. 16.4 control-B •..••.•.•..••• 16.3,5,7,9 control-D ••..••• 16.2,7,13 control-E .•.......•••..•.•••••• ~ 16.3,13 control-H ...........••....•••••••••••••••••••••• 16.2"'3 DIRECTORY FULL (error message) •••••••••••••••••• 16.9 OWIH ••••••••• '." •••••••••••••••••••••••••••••••••• 16.1 ElT[A;N] SUBR ••••••••••••••••••••••••••••••••••• 16.10 END OF FILE (error message) •.•••••••.•••••..•••• 16.9 ERROR[MESSl;MESS2;NOBREAK] •••..••••••.••••..•••• 16.6,9-10,12 ERROR (error message) .•••.•••••••••••••••••••..• 16.9 error handling •....•••••.•••••••••••••••••.••••• 16.1-14 error number •••••••.•.••••••••••••••••••••••••.• 16.7 error types ..••....•••••••.••••••••••••••••••••• 16.7 ERROR' [] SUBR ••••••••••••••••••••••••••••••••••• 16.12-13 ERRORMESS[ U] •••••••••••••••••• ., 16.7,13 ERRORN[] SUBR .......•.•.••••••••••.•.•••••.••••• 16.7,13 ERRORSET[U;V] SUBR .......•.••.••.•....••.•••..•. 16.5-6,12-14 ERRORTYPElST (system variable/parameter) ••••.•.• 16.10-11 ERRORX[ERXH] ...........•..••..•.•••..••.••.•.•.. 16.12 ERSETQ[ERSETX] NL ...•••••••••••••••••••••••••••• 16.14 EVAl (break cominand) ••••.•••••••••••••••••••.••• 16.3-4 EVAl[X] SUBR •• ·•••••••••• 16.14 eval-blip .....•..•..••...••••••••••••••••••••••• 16.5 EVALA[ X; A] SUBR ..............•..•..•...•••.•.•.• 16.10 FAULT IN EVAL (error message) ••.••••••••••••.••• 16.9 FAUlTAPPLY[FAUlTFN;FAUlTARGS] •••••.•..•.••.••••. 16.2 FAUlTEVAl[FAULTX] NL~ .......••••.••.•••••.••.•.• 16.1,9 FILE INCOMPATIBLE - SYSIN (error message) ••••••. 16.9 FILE NOT rOUND (error message) •••••••••••••••••• 16.9 FILE NOT OPEN (error message) •••••••••••••• e • • • • 16.8 FILE WON'T OPEN (error message) ••••••••••••••.•. 16.8 FUNARG ••••••••••••••••••••••••• 16.10 function definition cell ..•..•••••••••••••••.••• 16.1 function objects •.•••••••.•••••.••••.••••••••.•• 16.1 GC: 1 (typed by system) •.••••••••••••••••••••••• 16.9 GETBlK[N] SUBR ....•••...•.•.•••.••••.•••••.•• ~ •• 16.10 GO (break command) ..••.•..••••••••••.•••••••.••• 16.3-4 HASH TABLE FUll (error message) •••••.••••••••••• 16.10 HElP[HESS1;HESS2] ~ •...•••••••••••••••••••••••••• 16.13 e, • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • It 0 •••••••••••••••••••••••• • • • • • • • • "• • • • • • • • • • • • • • • • • • • • • • • o ••••••••••••• 0 0 •• ................ . ....................... . G •••••••••••••••• INDEX.16.1 Page Numbers HELP! (typed by system) .........•..••••••.••..•• HELPCLOCK (system variable/parameter) ••.•..•.•.. HELPDEPTH (system variable/parameter) •••• ~ •...•. HELPFLAG (system variable/parameter) .••.••.•.••. HELPTIME (system variable/lparameter) ....••....•• ILLEGAL ARG (error message) ....••••...•••.•..••• ILLEGAL ARG - PUTD (error message) ••.•••.••.•.•• ILLEGAL OR IMPOSSIBLE BLOCK (error message) ILLEGAL RETURN (error message) .•••••.•••••.••••• ILLEGAL STACK ARG (error message) •••••••••••..•• IN (typed by system) ..•..•.•••.••••..••••••••••• IN? (break command) ..........•.•.•••.••••.•.•••• input buffer ...................................... . interpreter ............. '....................... . INTERRUPT[INTFN;INTARGS;INTYPE] •••••.•••••.••••• INTERRUPTED BEFORE (typed by system) ..•.••..•••• LISTS FULL (error message) ...••••••••••••••••••. NLSETQ[NLSETX] NL ....... NOBIND .....•..•.......•. n ••••••••••••••••••••••• 0 ••••••••••••••••••••••• NON-NUMERIC ARG (error message) ••••..•••.•.•••.• NONXMEM (error message) ..•.••.•••••••••••••••••• OK (break command) ........••..••••••.••....•..•• P-STACK OVERFLOW (error message) ••••.••••••••••• property 1 is t ............ .' ... .; .................. . RELBLK[ADDRESS;N] SUBR ..•.•.••..••••.•••.••••••• RESE T[] SUBR ..........•...••.•••••.•.•••.•••...• RETFROM[POSjVALUE] SUBR ...•.•••.••••.••••••••.•• RE TURN (break command) .•..••••••••••••.•..•••••• RPLSTRING[X;N;Y] SUBR •.•..•.•.••••••••••••.••••• SETA[A;N;V] ...........••••••.••• 6 ••••••••••••••• SFPTR[FILE;ADDRESS] SUBR ...•....••.•••.••••••••• SYSIN[FILE] SUBR ..........••.•••••••••.••••••••• teletype initiated breaks .•.....•••....•••.•.••. TOO MANY FILES OPEN (error message) •..••••••.••• U.B.A. (error message) .•.....•..••.•.••••••••••. U.0. F. (error message) •.•.•••.••.•••••••••.••••• unbound atom ............•..•..•.•..••••••••••.•• und~fin~d function .......••.•..••.•..•.••••....• UNDEFINED OR ILLEGAL GO (error message) •.••.•••. UNUSUAL CDR ARG LIST (error message) ..•.••••..•. value cell ...... ., .............................. . value of a break ...........••..••.•••••.•.•.•••. 7 (typed by system) ..••.•.••••••••••.•••••••.••• t (break command) ..•..•.••••••••••••.••••••••••• INI>EX.16.2 16.13 16.6 16.5-6 16.3-4,7 16.5-6 16.10 16.8 16.10 16.8 16.9 16.4 16.1 16.2,7 16.1 16.2 16.2 16.10 16.14 16.1 16.4,8 16.7 16.3-4 16.7 16.1 16.10 16.13 16.6 16.1,4 16.10 16.10 16.10 16.9 16.2-3 16.8 '16.1,4 16.1-2,4 16.1 16.1 16.8 16.9 16.1 16.2 16.4 16.2,7 SECTION 17 AUTOKATIC ERROR CORRECTION - THE OWl" FACILITY t 17.1 Introduction A surprisingly large percentage of the errors made by INTERLISP users are of the type that could be corrected by another LISP programmer without any information ~bout the purpose of the program or expression in question, e.g. misspellings, certain kinds of parentheses errors, etc. To correct these types of errors we have implemented in INTERLISP a OWIM facility, short for DO-WhatI-Mean. DWIM is called automatically whenever an evaluation of an INTERLISP expression. error2 occurs in the OWl" then proceeds to try to correct the mistake using the current context of computation plus information about what the user had previously been doing, (and what mistakes he had been making) as guides to the remedy of the error. If DWI" is able to make the correction, the computation continues as though no error had occurred. Otherwise, the procedure is the same as though DWI" had not intervened: a break occurs, or an unwind to the last errorset, as 'described in Section 16. The following protocol illustrates the operation of OWl". i-~------------~---~~~--~-~---~-~-~-------------------~---~~------------------OWl" was designed and implemented by W. Tei telman ~ It ,is discussed in [Tei2]. 2 Currently, errors. DWIPI only operates on unbound atoms and undefined function 17.1 Example The user defines 8 function f8C'~ of one argument,!. The value of fact(n] is to be n factorial. (LAMBDA (N) (COND «ZEROP N9 1) «T (ITIHES N (fACT 8SUBl N] (fACT) ~OEFINEQ«fACT ~ Note that the definition of fa4::t contains several mistakes! Itimes and fact have been misspelled; the 9 in 1~9 was intended to be a right parenthesis, but the shift key was not depressed; similarly, the 8 in 8SUBl was intended to be a left parenthesis; and finally, there is an extra left parenthesis in (ront of th~ T that begins the final clause in the conditional. [1] [2] [3] ~PRETTYPRINT«fACCT] =PRETTYPRINT =FACT - (fACT [LAMBDA (N) (CONO «ZEROP N9 1) «T (ITIM5 H (FACCT 8SUBl H]) (FACT) . After defining fact, the uselr wishes to look at its definition using PRETTYPRINT, which he unfortunately misspells.[ 1] Since there is no function PRE TTYPRINT in the system, aU. D. F. error occurs. and DWI" is called. DWIPI invokes its spelling corrector, which searches a list of functions frequently used (by this user) for the best possible match. close, Finding one that is extremely DWIr1 proceeds on the a!isumption that PRETTYPRINT meant PRETTYPRINT, notifies the user of this, [2] and calls prettyprint. At this point, PRETTYPRINT would normally print (fACCT HOT PRIHTABlE) and exit, since facet has no definition. Note that this is not an INTERLISP error 17.2 condition. so that OWl" would not be called as described above. However, it is obviously not what the user meant. This sort of mistake is corrected by having prettyprint itself explicitly invoke the spelling corrector portion of DWI" whenever given a function with no expr definition. Thus with the aid of DWI". prettyprint is able to determine that the user wants to see the definition of the function fact.[3] and proceeds accordingly. "FACT(3] N9 [IN FACT] -> [IN FACT] (CONO (CONO ITIM5 [IN FACT] FACCT [IN FACT] 85U81 [IN FACT] [4] N )? «T (T YES --») -> --» -) ITIHES -> FACT -> (SUBt? YES [5] 6 .. pp FACT [6] (FACT [LAMBDA (N) (CONO «ZEROP N) 1) ..FACT (T (lTMES N (FACT (SUB1 N]) The user now calls his function fact.[4] During its execution, five errors occur, and DWIM is called five times.[5] At each point, the error is corrected, a message printed describing the action taken, and the computation allowed to continue as i fno error had occurred printed, the value of fact(3). 4 Following the last correction, 6 is Finally, the user prettyprints the new, now correct, definition of fact.[6] In this particular example, the user was shown operating in TRUSTING mode, which gives DWIM carte blanche for most corrections. The user can also operate in CAUTIOUS mode, in which case DWI" will inform him of intended corrections before they are made, and allow the user to approve or disapprove of them. 17.3 For most corrections, if the user does not respond in a specified interval of time, DWIM automatically proceeds with the correction, user need intervene only when he does not approve. Sample output is given below. Note that second, and fifth questions; DWI" the user responded to the first, so that the responded for him on the third and fourth. "FACT(3) N9 [IN FACT] -) N )? YES U.D.F. T [IN FACT] FIX? YES [IN FACT] (COND «T --») -> (COND (T --» ITIMS [IN.FACT] -> ITIHES? ... YES FACCT [IN FACT] -> FACT? •• oYES 8SUBl [IN FACT] -> (SUB1? NO U.B.A. (8SUBI BROKEN) We have put a great deal of ef'fort into making DWI" [1] [2] [3] [4] [5] t smart t , and experience with perhaps fifty different users indicates we have been very successful; DWIH seldom fails to correct an err'or the user feels it should have, and almost never mistakenly corrects an error. However, it is important to note that even when OWIH is wrong, no harm is done: 3 since an error had occurred, the user wou ld have had to intervene anyway if DWI" took no action. mistakenly corrects an error, Thus, if DWI". the user Simply interrupts or aborts the computation. UNDOes the DWU1 change using UNDO described in Section 22, and makes the correction he would have had to make without DWl". It is this benign quality of DWIM that makes it a valuable part of INTERLISP. a-----------------------------------------------------------------------------Except perhaps if DWIM's correction mistakenly caused a destructive computation to be initiated, and information was lost before the user could interrupt. We have not yet had such an incident occur. 17.4 17.2 Interaction with OWl" DWIM is enabled by performing either OWIH[C], for CAUTIOUS mode, or DWIH[T] for TRUSTING mode. 4 In addition to setting dwimflg to T and redefining faulteval and faultapply as described on page 17.14, DWIH[C] sets approveflg to T, while OWIH[T] sets approveflg to NIL. The setting of approve fIg determines whether or not the user wishes to be asked for approval before a correction that will modify the definition of one of his functions. In CAUTIOUS mode, approveflg=T. OWl" will ask for approval; in TRUSTING mode. OWIMwill not. i.e. for corrections to expressions typed in by the user for immediate execution,6 OWl" always acts as though approveflg were NIL, i.e. no approval necessary. 8 In either case, DWI" always informs the user of its action as described below. Spelling Correction Protocol The protocol used by OWIM for spelling corrections is as follows: correction occurs in type-in. print = followed by the correct If the spelling, followed by a carriage-return, and then continue, e.g. 4-~-------~--~--~-----------~-~-----~--~-------------- ------------------------- INTERLISP arrives with DWIM enabled in CAUTIOUS mode. OWl" can be disabled by executing OWIH[] or by setting dwimflg to NIL. See page 17.23. 6 Typed into lispx. lispx is used by evalqt and break, as well as for process ing the editor's E command. Functions that call the spelling corrector directly. such as editdefault (Section 9), specify whether or not the correction is to be handled as type-in. For example, in the case of editdcfault, commands typed directly to the editor are treated as type-in, so that corrections to them will never require approval. Conunands given as an argument to the editor, or resulting from macro expansions, or from IF, LP, ORR conunands etc. are not treated as type-in, and thus approval will be requested if approveflg=T. 6 For certain types of corrections, e. g. run-on spelling corrections, 8-9 errors t etc., dwim always asks for approval, regardless of the setting of approveflg. 17 .. 5 user types: DWIr.. types: .. (5ETQ IFOO (NCOCH FIE FUM» eNCONC I f the correction does not occur in type-in, print the incorrect spelling., followed by [IN function-name], ITIMS [IN FACT] -> e). and then the correct ITIHES as s;hown on page 17.3. 7 Then, spelling. e.g. if approveflg=NIL. print a carriage return, make the correction and continue. Otherwise, print a few spaces and a ? and then wait for approval. 8 The user then has six options. He can: 1. Type Y; OWl" types ES, and proceeds with the correction. 2. Type Hi OWl" types 0, and does not make the correction. 3. Type t; DWH1 does not :make the correction, and furthermore guarantees that the error will not cause a break. See footnote on page 17.15. 4. Type control-E; for error correction, this has the same effect as typing H. Do nothing i 1.n which celse OWIP1 will wait a specified interval, 9 and if the use~ohas not responded, DWI" will type followed by the default answer. 5. 6. Type space or carriage-return; in which case DWI" will ~ait indefinitely. This option is intended for those cases where the user wants to think about his answer, and wants to insure that DWI" does not get 'impatient' and answer for him. 7-----------------------------------------------------------------------------The appearance of -) is t(t call attention to the fact that the user's function will be or has been changed. 8 Whenever an interaction is about to take place and the user has typed ahead, DWJr1 types severa I be lIs to warn the user to stop typing, then clears and saves the input buffers, restoring them after the interaction is complete. Thus if the user has typed ahead before a DWI" interaction. DWI" will not confuse his type ahead with the answer to its question, nor will his type ahead be lost. 9 Equal to dwimwai t seconds. DWI" operates by dismissing for 500 milliseconds, then checking to see if anything has been typed. If not, it dismisses again, etc. until dwimwait seconds have elapsed. Thus', there will be a delay of at most liZ second before OWl" responds to the user's answer. 10 The default is always YES unless otherwise stated. 17.6 The procedure analogous. for If spelling correction on other than the correction is being handled INTERLISP errors as type-in, is DWI" prints = followed' by the correct spelling, and returns it to the function that called DWI". e.g. cFACT as shown on page 17.2. Otherwise, DWIPI prints the incorrect spelling, followed by the correct spelling. Then if approveflg=NIL, DWU1 prints a carriage-return and returns the correct spelling. DWI" prints a few spaces and a ? and then waits for approval. Otherwise, The user can then respond with Y. N, control-E, space, carriage return, or do nothing as described. Note that since the spelling corrector its~lf is not errorset protected, typing N and typing control-E may have different effects when the spelli~g corrector is - called directly.11 The former simply instructs the 'spelling corrector to return NIL. and lets the calling function decide what to do next; the latter causes an error which unwinds to the last errorset, however far back that may be. Parentheses Errors Protocol As illustrated earlier on page 17.3, OWIPI will correct errors conSisting of typing 8 for left parenthesis and 9 for right parenthesis. In these cases, the interaction with the user is similar to that for spelling correction. error occurs in type-in, DWI" types user types: DWH1 types: lispx types: = followed Ir the by the correction, e.g. FOO aCONS FIE FUM] CONS (A B C 0) ~(SETQ =( Otherwise, OWl" prints the offending atom, [IN function-namel, ->, the proposed 1j-------------------------·--------------------------------------------------The OWl" error correction routines are errorset protection. 17.7 correction, a few spaces and a " and then N9 [IN FACT] -> N ) , as shown on page 17.3. waits for approval, e.g. The user then has the same six options as for spelling correct,ion .12 If the user types Y, DWI" then operates exactly the same as when approveflg=NIl. i.e. makes the correction and prints its message. U.D.F. T Errors Protocol DWH1 corrects certain types of parentheses errors involving a T clause in a conditional, namely errors of the form: 1. (CONO _e) (T _e), i.e. the T clause appears outside and immediately following the CONO; 2. (CONO -- (-- & (T _e»~)"~ i.e. the T clause appears inside a previous clause; and 3. (CONO -- «l around it. 13 --»), i.e. the T clause has an extra pair of parentheses If the error occurs in type-i.n, DWIPI Simply types T FIXED and makes the correction. Otherwise if approveflg=NIL, DWIPI makes the correction, and prints a message consisting of [IN function-namel, incorrect forms of CONo, followed by e). followed by one of the above then on the next line the corresponding correct form of the CONO, e.g. 12----------------------------------------------------------------------------except the waiting time is 3*dwimwait seconds. 13 For U.O.F. T errors that are not one of these three types, DWI" takes no corrective action at all, i.e. the error will occur. 17.8 [IN FACT] (CONO (COND «T (T _e»~) -> _e»~ as shown on page 17.3. If approveflg=T, ownl prints U.D.F. T, followed by [IN function-name], several spaces, and then FIX? and waits for approval. The user then has the same options as for spelling corrections and parenthesis errors. If the user types Y or defaults, OWl" then proceeds exactly the same as when approveflg=NIL, i.e. makes the correction and prints its message, as shown on page 17.4. Having made the correction, OWl" must then decide how to· proceed with the computation. In ca·se 1, (COND --) (T --), DWI" cannot know whether the last clause of the CONo before the T clause succeeded or not, i.e. if the T clause had been inside of the CONO, would it have been entered? Therefore DWI" asks the user 'CONTINUE WITH T CLAUSE' (with a default of YES). If the user types N, DWI" continues with the form after the CONo, i.e. the form that originally followed the T clause. In case 2, (CONo -- (-- & (T --»), OWl" has a different problem. After moving the T clause to its proper place, OWl" must return as the value of the COND, the value of the expression corresponding to &. Since this value is no longer around, .DWI" asks the user, 'OK TO REEVALUATE' and then prints the expression corresponding to &. reevaluating &, If the user types Y, or defaults, OWIPI continues by otherwise OWU1 aborts, and a U.O.F. T error will then occur (even though the CONO has in fact been fixed).14 14----------------------------------------------------_____ u __________________ _ If OWIM can determine for itself that the form can safely be reevaluated, it does not consult the user before reevaluating. OWl" can do this if the form is atomic, or car of the form is 8 member of the list okreevalst, and each of the arguments can safely be reevaluated, e.g. (SETQ X (CONS (IPlUS. Y Z) W» is safe to reevaluate because SETQ, CONS, and IPLUS are all on okreevalst. 17.9 In case 3. (CONO -- «T --»), there is no problem with continuation, so no further interaction is necessary. 17.3 Spelling Correction The spelling corrector is given as arguments a misspelled word (word means literal atom), a spelling list (a list of words), and a number: and reI respectively. splst, Its task is to find that word on splst which is closest to xword, in the sense describEtd below. xword. ~, This word is called a re~pelltnf1 of reI specifies the minimum 'closeness' between xword and a respelling. If the spelling corrector cannot. find a word on splst closer to xword than reI, or if it finds two or more words. equally close, its value is NIL, otherwise its value is the respelling. 16 The exact algorithm for comput:Lng the spelling metric is described later on page 17.20, but briefly 'closeness' is inversely proportional to the number of disagreements between the two words, and directly proportional to the length of the longer word, e.g. PRTTYPRNT is 'closer' to PRETTYPRINT than CS is to CONS even though both pairs of words have the same number of disagreements. The spelling the corrector operates b:..- proceeding down splst, and computing closeness between each word andl xword, and keeping a list of those that are closest. Certain differences b~tween words are not counted as disagreements, for example a single transposit.ion, e.g. CONS to CNOS, or a doubled letter, e.g. CONS to CONSS. etc. In the event that the spelling corrector finds a word on splst with no disagreements, it will stop searching and return this word as the respelling. Otherwise, the spelling corrector continues through the entire i~----------------------------------------------------------------------------- The spelling corrector can also be given an optional functional argument, fn, to be used for selecting out a subset of splst, i.e. only those members of splst that satisfy fn will be considered as possible respellings. 17.10 spelling list. Then if it has found one and only one 'closest' word, returns this word as the respelling. For example, spelling corrector will probably return CONS if xword is VONS, as the respelling. it the However, if xword is CONZ, the spelling corrector will not be able to return a respelling, since CONZ is equally close to both CONS and CONO. finds an acceptable respelling, If the spelling corrector it interacts with the user as described earlier. In the special case that the misspelled word contains one or more al t-modes, the spelling corrector operates somewhat differently. Instead of trying to find the closest word as above, the spelling corrector searches for those words on splst that match xword, where an alt-mode can match any number of characters (including 0). e.g. FOOl matches Foot and FOO, but not NEWFOO. all three. SFOOS matches In this case, the entire spelling list is always searched, and if more than one respelling is found, the spelling corrector prints AMBIGUOUS, and returns NIL. on For example, CONS would be ambiguous if both CONS and CONO were the spelling list. If t~e spelling corrector finds one and only one respelling, it interacts with the user as described earlier. For both spelling correction and spelling completion, regardless of whether or not the user approves of the spelling corrector's choice, the respelling is moved to the front of splst. Bince many respellings are of the type wit~ no disagreements, this procedure has the effect of considerably reducing the time required to correct the spelling of frequently misspelled words. Spelling Lists Although any list of atoms can be used as a spelling list p e.g. editcomsa, brokenfns. filelst, etc •• four lists are maintained espeCially for spelling 17.11 correction: spellings1, spellin,~, spellings3, and userwords. 18 Spellings1 is a list of functions used for spelling correction when an input is typed in apply format, and the function is undefined, e.g. EOTIF(FOO). Spellings1 is initialized to cClntain defineq, break, makefile, editf, tcompl, load, etc. Whenever lispx is gliven an input in apply 'format, i.e. a function and arguments, the name of the function is added to spellingsl. 17 For eX¥lple, typing CALLS(EOITF) will cause CALLS to be added to spellings1. Thus if the user typed CALLS(EOITF) and later typed CALLLS(EDITV), since spellings1 would then contain CAllS, DWI" would be sUt:cessful in correcting CALLlS to CALLS. 18 Spellings2 is a list of functions used for spelling correction for all other undefined functions. !!1!pend, cond, cons, It is initialized to contain functions such as add1, JlQ, list, nc~, lispx is given a non-atomic 1rorm, spe 11 1n9s2. print, 1!.!:.QJl. return, setq, etc. the name of the function for example. typing (RETFROM (STKPOS (QUOTE FOO) would add retfrom to spellings2. Function names are also Z» add~d Whenever is added to to a break to spellings2 by define, defineq, load (when loading compiled code)e unsavedef, editf, and prettyprint. Spellings3 is a list of words used for spelling correction on all unbound atoms. Spellings3 is initialized to editmacros, breakmacros. brokenfns, and advisedfns. Whenever lispx is gliven an atom to evaluate, the name of the atom ---------------------~----------------------~--------------------------------~16 All of the remarks on maintaining spelling lists apply onill when DWIPI is enabled, as indicated by dwimflg=T. 17 Only if the function has a 18 If CALllS(EDITV) were typedl before CALLS had been 'seen' and added to spellings1. the correction would not succeed. However, the alternative to using spelling lists is to soarch the entire oblist, a procedure that would make spelling correction intolerably slow. d~finition. 17.12 is added to spellings3. 19 Atoms are also added to spellings3 whenever they are edited by editv, and whenever they are set via ~ or~. For example, when a file is loaded. all of the variables set in the file are added to spellings3. Atoms are also added to spellings3 when they are set by a lispx input, e.g. typing (SETQ FOO (REVERSE (SETQ FIE --») will add both FOO and FIE to spellings3. Userwords is a list containing both functions and variables that the user has referred to e.g. by breaking or editing. correction by arglist, unsavedef. Userwords is initially NIL. load, (when Userwords is used for spelling prettyprint, break, editf. advise, etc. Function names are added to it by define, defineq, loading compiled code, or loading unsavedef, editf, editv, editp, prettyprint, etc. exprs to property lists) Variable names are added to userwords at the same time as they are added to spellings3. In addition, the variable lastword is always set to the last word added to userwords, i.e. the last function or variable referred to by the user, and the respelling of NIL is defined to be the value of lastword. Thus, if the user has just defined a function, he can then edit it by simply typing EDITf(~, or prettyprint it by typing PP(). Each of the above four spelling lists are divided into two sections separated by a NIL. The first section contains the 'permanent' words; the second section contains the temporary words. New words are added to the corresponding spelling list at the front of its 'temporary section. 20 (If the word is already in the temporary section, it is moved to the front of that section; if the word is in the permanent section. no action is taken.) If the length of the 19----------------------------------------------------------------------------Onl~ if the atom has a value other than NOBINO. 20 Except that functions added to spellings1 or spellingsZ by added to the end of the permanent section. 17.13 lis~ are always temporary sect ion then exceeds a specified number, the las t (oldes t) word in the temporary section is for~otten, i.e. deleted. spelling lists from becoming cluttered ~ith This procedure prevents the unimportant words that are no longer being used, and thereby slowing down spelling correction time. the spelling corrector moves each word selected as a resp~lling Since to the front of its spelling list, the word is thereby moved into the permanent section. Thus once a word is mispelled and c:orrected, it is considered important and will never be forgotten. The maximum length of the temporary section for spellingsl, spellings2, spellings3 and userwords is gi'ven by the value of #spellings1, #spellings2, Ispellings3, and luserwords, initialized to 30, 30, 30, and 60 respectively. Using these values, the average length of time to search a spelling list for one word is about 4 milliseconds. 21 17.4 Error Correction As described in Section 16, whenever the interpreter encounters an atomic form wi th no binding, or a non-atomic form £.!!: of which is not a function or function object, it calls the function faulteval. given an undefined function, :it calls faultapply. Similarly, when applY is When DWI" is enabled, faulteval and faultapply are redefined to first call dwimblock, a part of the DWIl'I package. If the user abclrts by typing control-E, or if he indicates disapproval of Dwnl' s intended .:orrection by answering N as described on page 21------------------------------·----------------------------------------------If the word is at the front of the spelling list, the time required is only 1 millisecond. If the word is not on the spelling list, i.e. the entire list must be searched, the time is proportional to the length of the list; to search a spelling list of length 60 takes about 7 milliseconds. 17.14 17.6, or if DWI" cannot decide how to fix the error, dwimblock returns NIL.22 In this case, faulteval and faultapply proceed exactly as described in Section 16, by printing a U.B.A. or U.D.F. message, and going into a break if the reqUirements of breakcheck are met, otherwise unwinding to the last errorset. If DWI" can (and is allowed to) correct the error, dwimblock exits by performing reteval of the corrected form. as of the posi tion of the call to faulteval or faultapply. Thus in the example at the beginning of the chapter, when DWI" determined that ITIHS was ITIHES misspelled, DWI" called reteval with ( IT IMES N (FACeT 8SUB 1 N». Since the interpreter uses the value returned by faulteval exactly as though it were the value of the erroneous fOnD, the computation will thus proceed exactly as though no error had occurred. In addition to continuing the computation, DWI" also repairs the cause or the error whenever possible. 23 Thus 1n the above example, DWI" also changed (with rplaca) the expression (ITIHS N (FACeT 8SUBl N» that caused the error. Error correction in DWI" is divided into three categories: unbound atoms, undefined cars of form, and undefined function in!!llix. Assuming that the user approves if he is asked, the action taken by DWI" for the various types of errors in each of these categories is summarized below. The protocol of DWIM'$ interaction with the user has been described earlier. 22------------------------------------·---------------------------------------If the user answers with t, (see page 17.6) dwimblock is exited by performing reteval[FAULTEVAL;(ERRORt)]. i.e. position of the call to faulteval. 23 an error is generated at the If the user's program had computed the form and called eval, e.g. performed (EVAl (LIST X V»~ and the value of x was a miss'pel1ed function; it would not be possible to repair the cause of the error, a1 though DWI" could correct the misspelling each time it occurred. 17.15 Unbound Atoms 1. If the first character of the unbound atom is " OWIPI assumes that the user (intentionally) typed latolD for (QUOTE atom) and makes the appropriate change. No message is typed, and no approval requested. If the unbound atom is just • itself, OWIH assumes the user wants the next expression Quoted, e.g. (CONS X '(A B C» will be changed to (CONS X (QUOTE (A B C»). A.gain no message will be printed or approval asked. (If no expression follows the " OWIPI gives up.) 2. If CLISP (Section 23) is enabled, and the atom is part of a CLISP construct, the CLISP transformation is performed and the result returned, e.g. N-l is transformed to (SUB1 N). 3. If the atom contains an 8, OWIH assumes the 8 was intended to be a left parenthesis, and calls thE! editor to make appropriate repairs on the expression containing the atom. OWIH assumes that the user did not notice the mistake, i.e. that the entire expression was affected by the missing left parenthesis. For example, if the user types (SETQ X (LIST (CONS 8CAR Y) (COR Z» V), the expression will be changed to (SETQ X (lIST (CONS (CAR Y) (COR Z» Y». The 8 docs not have to be t.he first character of the atom, e.g. DWI" will handle (CONS X8CAR Y) correctly. 4. If the atom contains a 9, OWIPI assumes the 9 was intended to be a right parenthesis and operates as in number 3. 5. I f the a tom begins with a 7, the 7 is treated as a', e. g. 7FOO becomes 'FOO, and then (QUOTE FOO). 6. I r the atom is an edi t command (a member of edi tcomsa), and the error occurred in type-in. the f!ffect is the same as though the user typed [OITF(). followed by the atom, i.e. ' OWIPI assumes the user wants to be in the editor editing the la~.t thing he referred to. Thus, if the user defines the function foo and then types P, he will see =FOO, followed by EDIT, followed by thepril1ltout associated with the execution of the P command. followed by *, at w'hich point he can continue editing foo. 7. If dwimuserfn=T. OWIM calls dwimuserfn, and if it returns a non-NIL value, DWH1 returns this value. dw'imuserfn is discussed below. 8. If the unbound atoms occurs in a function, OWIPI attempts spelling correction using as a spelling list the list of lambda and prog variables of the function. 9. If the unbound atom occurred in a type-in to a break, DWI" attempts spe lling correction using 'the lambda and prog variables of the broken function. 10. Otherwise, DWI" attempts spelling correction using spellings3. If all fail, DWIM gives up. 17.16 Undefined car of Form 1. If car of the form is T, DWIM assumes a misplaced T clause and operates as described on page 17.B. 2. If car of the form is F IL, OWIM chcanges the FIl to FUNCTION(LAMBOA,e.g. (F/L (Y) (PRINT (CAR V») is changed to (FUNCTION (LAMBDA (V) (PRINT (CAR V»~). No message is printed and no approval requested. If the user omits the variable list, DWI" supplies (X), e.g. (F/L (PRINT (CAR X») becomes (FUNCTION (LAMBDA (X) (PRINT (CAR X»». DWIM determines that the user has supplied the variable list when more than one expression follows FIL, £!r of the first expression is not the name of a fUnction. and every element in the first expression is atomic. for example, OWl" will supply (X) when correcting (F/L (PRINT (CDR X» (PRINT (CAR X»). 3. If car of the form is If, if, or one of the ClISP iterative statement opera tors. e. g. FOR, WHILE. 00 at ai, the indicated transformation is performed, and the result returned as the corrected form. 4. I f car of the form has a function definition. OWIH attempts spelling correction on ~ of the definition using the spelling list (LAMBDA NLAMBDA). 5. If car of the form has an EXPR property, OWl" prints car of the form, followed by 'UNSAVED', performs an unsavedef. and continuos. No approval is requested. 6. If car of the form has a property FILEDEF, the definition is to be found on a fi Ie. If the value of the property is atomic, the entire file is to be loaded. I f a 1 is t, car is the name of the fi Ie and cdr the re levan t functions, and loadfns will be used. OWl" first checks to-$ee if the file appears in tbe attached directory, 's directory. or XTR. 31 17.7 DWI" Functions dwim[x] If ~=NIL, disables DWI"; value is NIL. If !=C, enables DWIM in cautious mode; value is CAUTIOUS. If !=T. enables DWnl in trusting mode; value is TRUSTING. For all other values of !. generates an error. dwimify[x] ! is a (orm or the name of a function. dwimify performs all corrections and transformations that would occur if ! were actually run. dwimify is undoable. ow edit macro. addspell[x;splst;n] Adds ! dwimifies current expression. to one of the four spelling lists as and to follows: 32 if splst=NIL. spellings2. adds ! to userwords Used by def1neq. 81-----------------------------------·----------------------------------------Transpositions are also not counted when fastypeflg=T, for example, IPULX and IPLUS will be in 80X agreement with fastypeflg=T, only 60X with fastypeflg=NIL. The rationale behind this is that transpositions are much more common for fast typists, and should not be counted as disagreements, whereas more deliberate typists are not as likely to combine tranpositions and other mistakes in a single word, and therefore can use more conservative metric~ fastypeflg is initially NIL. 32 If ?f is already on the spelling list, and in its temporary section, addspell moves! to the front of that section. See page 17.13 for complete description of algorithm for maintaining spelling lists • . 17.23 If splst=O, adds! to userwords. loading exprs to property 1 is ts. wh~m If splst.t, adds ! per'manent section). if Used by load splst=2, to (at end of (at end of Used by lispx. adds ! permanent section). spellingsl to spellingsZ Used by lispx. If splst=3, adds! to userwords and spellings3. llist can also be a spelling list, in which case !!. is the (optional) length of the temporary section. addspell sets lastword to ! whensplst.NtL, 0 or' 3. If ! is not a literal atom, addspell takes no action. misspelled?[xword; rei ;splst; fig; 'tail; fn] If prints xword=NIL = followed or alt-mode, misspelled? by the value of lastword, and returns this as the respelling, without asking for app.-oval. Otherwise, misspelled? checks to see if ~'d is really misspelled, i.e. if fn applied to ~~ is true, or xword is already contained on spls~. In this case, misspelled? simply returns ~~. Otherwise misspelled? computes and returns fix,s.pell[xword ;rel ;splst: fIg; tail ;fn]. 17.24 fixspall[xword;rel;splst;flg;tail;fn]33 The value of fixspell is either the respelling of xword or NIL. interactions fixspell performs described all of the including earlier, requesting user approval if necessary. If xword=NIL or :I (al t-mode) t the respelling is the value of lastword. and no approval is requested. If !!i=NIL, the correction is handled in type-in mode, i.e. approval is never requested p and xword is not typed. If !!.U=T, xword 15 typed (before the .) and approval 15 requested if approveflgaT. If tail is successful, not NIL, £!t of and the tail \ is respelling (using Irplaca). correction replaced by is the In addition, fixspell will correct misspellings caused by running two words together. 34 In this case, £!! of tai I is replaced by the two words, fixspell first is the one. and For the value of example, if fixspell is called to correct the edit cOlIIDand (HOVE TO AFTERCOND 3 Z) with tail=(AFTERCOND 3 Z), 1!il wou ld be changed to (AFTER COHD Z 3). and 33---~---~-·----------------------~-----------~---------~-------------------~-- fixspell has some additional arguments, for internal use by DWI". 34 In this case, user approval is always requested., In addition, if the first word contains either fewer than 3 characters, or fawer characters than the second word, the default will be N. 17.25 fixspell would return. ~FTER (subject to user apl)roval where necessary). 36 flJcspell generates an error if xword is already on !l!Jls t . The time required for a call to fixspell with a spelling list of length 60 when the entire list must be searched is .5 seconds. If fixspell determines that the first word on the spellingl list is the respelling and does not need to search any further, the time required is .02 seconds. In other words, the time required is proportional to the number of words with which xword is compared, with the time for one comparisol1l, i.e. one call skor. being roughly .01 seconds (varies slightly with the number' of characters in the words being compared.) The function chooz is provided for users desiring spelling correction without any output or interaction: chooz[xword;rel;sPlst;tail;tieflg;fnl38 cor'rected per·forms The spelling no of value of chooz is the xword37 or NIL; chooz interaction and no output. If tief!D=T and a tie occurs, i.e. more than one word on splst is found with the same closeness, chooz returns the first word. If tieflg=NIL, and a tie occurs, chooz returns NIL. a5-----------------~---------------------------------- ------------------------- If tail=T, fixspell will also perform run-on corrections, returning a dotted pair of the two words in the event the correction is of this type. 36 chooz has some additional arguments, for internal use by DWI". 87 chooz does not perform spelling completion, only spelling correction. 17.26 If tail is misspelling not NIL, ccmsisting together, e. g. chooz of (BREAKFOO) will correct running two a words for (BREAK FOO). The value of chooz in this case is a dotted pair" of the two words, e.g. (BREAK. FOO). Both DWI" and the editor use this option. fncheck[fn;no~essflg;spellflg] The task of fncheck is to check whether fn is the name of a function and if not, to correct its spelling. a8 If fn is the name of a function or spelling correction is successful, fncheck adds the (corrected) name of the function to userwords using addspell. and returns it as its value. nomessflg informs fncheck whether or not the calling function wants to handle the unsuccessful case: if nomessflg is T. fncheck simply returns NIL, otherwise it prints fn NOT A FUNCTION and generates a non-breaking error. fncheck calls misspelled? correction, so that if lastword will be returned. to misspelled?' s fourth to perform fn=NIL, the spelling value of spelIflg corresponds argument, flo:. If spellflo=T. approval will be asked if DWI" was enabled in CAUTIOUS mode, i.e. if approveflg-T. 38----~-~------~-------·-~--------------------~---------------~----~----------- Since fncheck is called by many low level functions such as arglist, unsavedef, etc.. spelling correction only takes place when dwimflg=T. so that these functions can operate in a small INTERLISP system which does not contain OWl". 17.27 fncheck is currently used by argl1st, unsavedef, prettypr1nt, breakO, breakin, chngnm, advisf!, printstructur'~. firstfn, lastfn, calls, and edita. For example, breakO calls fncheck with nomessflg-T since if fncheck cannot produce a function, breakO wants to define a dummy one. printstructure however calls fncheck with nomessflg=NIL, since it cannot operate without a function. Many other system functions call misspelled? or rixspell directly. example. breakl calls fixspell on unrecognized atomic inputs before For attem~tin~ to evaluate them, using as a spelling list a list of all break commands. Similarly. lispx calls fixspell on atomic inputs using a list of all lispx commands. When unbreak is given the name of 8 function that is not broken, it calls fixspell with two different spelling lists, first with brokenfns, and if that fails. with userwords. spelling list. call misspelled? !!!Iakefile calls m'isspelled? using filelst as a Finally. load, bcompl, brecompile, tcompl, and recompile all if their input file(s) won't open. 17.28 Index for Section 17 Page Numbers AOOSPELL[X;SPLST;N] .......•..•.•••••••••••..••.• alt-mode (in s~elling correction) •••.••••••••••• AMBIGUOUS (typed by dwim) •.•••••••••.••••••••••• approval (of dwim corrections) ••.•••.•••••.••••• APPROVEFLG (dwim variable/parameter) ••.••••••••• be 11 (typed by dwim) .....••....•..••.•••.••.•••• BREAK1[BRKEXP;BRKWHEN;BRKFN;BRKCOMS;BRKTVPE] NL BREAKCHECK ............................. "••••••••••• BROKENFNS (break variable/parameter) .••••••••••• CAUTIOUS (OWIM mode) ....•..••.•.••...••••••••••• CHOOZ[XWORO;REL;SPLST;TAIl;TIEFLG;FN;NOBLS~CLST] •• CLISP ......•........... '...•..••.....•.•..••••.•• CONTINUE WITH T CLAUSE (typed by dwim) control"E OW (error message) DWIM[X] OW 1M •••••.•••• ................... _.............•...... ....•.••••••••.•••••.••••••••• ......................................... . •••.•••••••••••••••••••••••••••••••••••••••• OWIM interaction with user DWIH variables .. I •••.•••••••••••••••••• .••••••••••••••••••••••••••••••• OWIMFLG (dwim variable/parameter) ••••••••••••••• OWIMIFV[X;L] ...•.............•..•.••.•••••••••.• OWIMUSERFN (dwim variable/parameter) ••.••••••••• OWIMWAIT (dwim variable/parameter) •••••••••••••• EOITCOMSA (editor variable/parameter) •••••••.••• EOITCOMSl (editor variable/parameter) •••.••••••• EDITDEFAUL T ....•.. flo ••••••••••••••••••••••••••••• error correction ....•.••.••••••••••••••••••••••• ERRORSET[U;V] SUBR •.•.••••••.••••.•••••••••••••• EXPR (property name) ..•.•.••.••••••••••••••••••• FI L ••••••••••••••••••••••••••••••••••••••••••••• FASTVPEFLG (dwim variable/parameter) .••••••••••• FAULTAPPLY[FAULTFN;FAUlTARGS] •.••.••••.•••••.••• FAUL TEVAL[ FAUL TX] NL* ...•.•.••••••.••.••••.•.••• FIlEOEF (property name) ..•...•.........••••••••• FILELST (file package variable/parameter) ••••••• FIXSPELl[XWORO;REL;SPLST;FLG;TAIL;FNjCLST; APPROVALFlG] ......•...••.•.••••••••••.•• FNCHECK[FN;NOMESSFLG;SPELlFLG;PROPFLG] ••••••.••• LASTWORO (dwim variable/parameter) ••••••••.••••• LISPX ............... ".................•••••.••••. MAKEFILE[FILE ;OPTIONS] .........•••••.••••••••••. MISSPELLEO?(XWORO;REL;SPLST;FLG;TAIL;FN] •••••••• MOOEL33FLG (dwim variable/parameter) ••••••• OK TO REEVALUATE (typed by dwim) •••••••••••••••• OKREEVALST (dwim variable/parameter) •••••••••••• RETEVAL[POS;FORM] SUBR ...••••••••••••••••••••••• run-on spelling corrections •••••.••••••••••••••• SHALL I LOAD (typed by dwim) •••••••••••••••••••• 00 • • • SKOR •..........•..••••.••••••••••••••••••••••••• spelling completion ...•. e • • • • • • • • • • • • • • • • • • • • • • • spelling correction protocol •••••••••••••••••••• spelling corrector •.•••.•••.•••••••••••••••••••• spelling lists ...............•..•.••••••••••.••• SPELLINGSl (dwim variable/parameter) •••••••••••• SPELLINGSZ (dwim variable/parameter) •••••••••••• SPELLINGS3 (dwim variable/parameter) •••••••••••• INDEX.17.1 17.23-24,27 17.11,25 17.11 17.3,5,25 17.5,18,25,27 17.6 17.28 17 .. 15 17.28 17.3,5,23,27 17.20-21,26 17.16-18 17.9 17.6-7,14 17.23 17.5,23 17.1-28 17.5 17.19 17.5,12,21 17.23 17.16-19 17.6,8 17.16,18 17.17-18 17.5 17.1-28 17.15 17.17-18 17.17 17.23 17.5,14-15,19 17.5,14-15,19 17.17-18 17.28 17.25-26,28 17.27 17.13,24-25,21 17.5,12 .. 13,28 17.28 '17.24,27 .. 28 17.21 17.9 17.9 17.15 17.5,25-27 17.17 17.21-22 17.11 17.5-7 17.2,10,20,26 17.11-14 17.12-14,18,24 17.12-14,18,23-24 17.12,14,16,24 Page Numbers T FIXEO (typod by dwim) ..•.••.•••••..••••.•••••• TRUSTING (OWIH mode) ..•.•.•..•••••••••.••.•••••• U.S.A. (error message) ..•.•••••.••••.••••••••.•• U.O.F. (error message) ....•••...••••••••••••.••• U.O.F. T (typed by dwim) •.•.•.•.••••••••••.••.•• U.O.F. T FIX? (typed by dwim) •..•.••.••••••••••• unbound a tom .........•..•..••••.•••••••••••••••.• undefined function .......•.•..•.••••.• ' •••••••••• UNDO (prog. asst. command) .••••••••••••••••••••• UNSAVEO (typed by dwim) ...••••••.•.••••••••••••• UNSAVEOEF[ X; TYP] ...................•••••••.••••• USERWOROS (dwim variable/parameter) •..••••••••.• ISPELLINGSI (dwim variable/parameter) .•••••••••• ISPELLINGS2 (dwim variable/parameter) •••.••••••• ISPELLINGS3 (dwim variable/parameter) •••••••.••• IUSERWOROS (dwlm variable/parameter) •••••••••••• S (alt-mode) (in spelling correction) •••.•••.••. • • •••••••••••••••••••••• It ••••••••••••••••••••••• -) (typed by dwim) ....•...•••••••.••.••••••••..• . .. (typed by dwim) ............................. . 7 8 9 = (instead of I) ........ u ••• j9 ••••••••••••••••••• (instead of left parenthes1s) .•••••••••••••••• (instead of right parenthesis) ••••••••.••••••• (typed by dwim) •••••••.' ••••••••••••••••••••••• ? (typed by dwim) ...••••.••••.•••••••••••••••••• INOEX.17.2 17.8 17.3,5,23 17.15 17.2,15 17.8 17.8 17.14-18 17.14-18 17.4 17.17-18 17.17-18 17.13-14,23,27-28 17.14 17.14 17.14 17.14 17.11,25 17.16 17.3-4,6-7 17.4,6 17.16 17.2,7,16-18 17.2,7,16-17 17.5,7 17,.6-7 SECTION 18 THE COMPILER AND ASSEMBLER1 18.1 The Compiler The compiler is available in the standard INTERLISP system. It may be used to compile individual functions as requested or all function definitions in a standard format LOAD file. The resulting code may be stored as it is compiled, so as to be available for immediate use, or it may be written onto a file for subsequent loading. The compiler also provides a means of specifying sequences of machine instructions via ASSEMBLE. The most common way to use the compiler is to compile from a symbolic (prettydef) fi.le, producing a corresponding file which contains a set of functions in compiled form which can be quickly loaded. An alternate way of using the compiler is to compile from functions already defined in the user's INTERLISP system. In this case, the user has the option of specifying whether the code 1s to be saved on a tile for subsequent loading, or the functions redefined, or both. In either case, the compiler will ask the user certain questions concerning the' compilation. The first question is: 1-----------------------------------------------------------------------------The compiler itself,' i.e. the part that actually generates code, was written and documented by. and is the responsibility of A.K. Hartley. The user interfaces, i.e. tcompl,. recompile, bcompl, and brecompile, were written by W. Teitelman. 18.1 LISTING? The answer to this question controls the generation of a listing and is explained in full below. However. for most applications, the user will want to answer this Question with either ST or E. which will also specify an answer to the rest of the questions which would othe,rwise be asked. ST means the user wants the compiler to STore the new definitions; E means the user is only interested in compiling to a Eile. and no storing of definitions is perfonmed. In both cases, the compiler will then ask the user one more question: OUTPUT FILE: to which the user can answer: N or NIL no output file. File name file is opened if not already opened. and compiled code is written on the file. Example: FACTI FACTZ» LISTING? 5T OUTPUT FILE: FACT.COM (FACT COMPILING) ~COMPILE«FACT (FACT REDEFINED)2 (FACT2 REDEFINED) (FACT FACTI FACT2) j------~----------------------------------------------------~------------------ compi ler output and error messages are explained on 'page 18.48-52. 18.2 This process caused the functions FACT. FACTI, and FACiz to be compiled, redefined, and the compiled definitions also written on the file FACT.COM for subsequent loading. 18.2 Compiler Questions The compiler uses the free variables Iaprlg, strf, svflg, lcfil and Istfil which determines various modes of operation. answers to the 'compset' questions. These variables are set by the When any of the top level compiling functions are called, the function compset is called which asks a number of questions. V, or T Those that can be answered 'yes' or 'no' can be answered with YES, f~r YES; and NO, N, or NIL for NO. 1. The questions are: LISTING? The answer to this question controls the generation of a listing. Possible answers are: 1 Prints output of pass 1. the LAP macro code. 8 2 Prints output of pass 2, the machine code. YES Prints output of both passes. NO Prints no listings. The variable lapflgis set to the answer. If the answer is affirmative, compset will type FILE: to allow the user to indicate where the output is to be written. The variable 1stfil is set to the answer. 3---------~--------~--------------------~------------- ------------------------- The LAP and machine code are usually not of interest but can be helpful in debugging macros. 18.3 There are three other possible answers to LISTING? - each of which specifies a complete mode for compiling. They are: S Same as last setting. F Compile to [ile (no definition of functions). ST STore new definitions. Implici t in these three are the answers to the questions on disposition of compiled code and expr's, so questions Z and 3 would not be asked if 1 were answered with S, F. or ST. z. REDEFINE? YES Causes each function to be redefined as it is compiled. The compiled code is stored and the function definition changed. The variable strf is set to T. NO Causes function definitions to remain unchanged. The variable strf is set to NIL. The answer ST for the first question implies YES for this question, F implies NO, and S makes no change. 3. SAVE EXPRS? I f answered YES, svflg is set to T, and the exprs are saved on the property 1 is t of the function name. Otherwise they are discarded. the first question implies YES for this question, F change. 18.4 impl~es The answer Sf for NO, and S makes no' OUTPUT FILE: 4. If the compiled definitions are to be written for later loading, you should provide the name of a file on which you wish to save the code that is generated. If you answer T or TTY:, the output will be typed on the teletype (not particularly useful). done. If you answer N, NO, or NIL, output will not be If the file named is already open, it will continue to be used. The free variable lcfil is set to the name of the file. 18.3 Nlambdas When compiling the call to a function, the compiler must prepare the arguments to the function 1n one of three ways: 1. Evaluated (SUBR, SUBR*, EXPR, EXPR*. CEXPR, CEXPR*) 2. Unevaluated, spread (FSUBR. FEXPR, CFEXPR) 3. Unevaluated. not spread (FSUBR*, FEXPR*, CFEXPR*) In attempting to determine which of these three is appropriate, the compiler will first look for a definition among the functions in the file that is being compiled. If the function is not contained there, the compiler will look for other information which can be supplied by the user by including nlambda nospread functions on the list nlama (for nlambda !toms), and including nlambda spread functions on the list nlaml (for nlambda list), and including lambda functions on the list lams. 4 If the function is not contained in the file,6 or 4-~----------------------------------------------------------~---~----~-------- Including functions on lams is only necessary to override in-core nlambda defini tions, since in the absence of other information, the compiler assumes the function is a lambda. 6 The function can be defined anywhere in any of the files given as arguments to bcompl, tcompl. brecompile or recompile. 18.5 on the list nlama, nlaml, or lams, the compiler will look for a current definition. If the function is defined, its function type is assumed to be the desired type. If it is not defined, the compiler assumes that the function 1s of type I, i.e. its arguments are to be evaluated. 6 7 In other words, if there are type 2 or 3 functions callod from the functions being compiled, and they are only defined in a separate file, they must be included on nlama or nlaml, or the compiler will incorrectly assume that their arguments evaluated, and compile the calling function correspondingly. are to be Note that this is only necessary if the compiler does not 'know' about the function. If the function 1s defined at compile time, or is handled via a macro, or is contained in the same group of files as the functions that call it, the compiler will automatically handle calls to that function correctly. 18.4 Globalvars Another top level free variable that affects compilations is globalvars. Any variables that appear on the list globalvars, and are used freely in a compiled function, reference are always accessed 1through their value cell. to the value of this variable In other words, a is equivalent to (CAR (QUOTE variable», regardless of whether or not it appears on the stack, ~-----------------------------~---------------------------------~~-------~----- Before making this assumption, if the value of compileuserfn is not NIL, the compiler calls (the value of) compileuserfn giving it as arguments cdr of the form and the form itself, i.e. the compiler does (APPlY~ COMPIlEUSERFN (COR form) form). If a non-NIL value is returned, it is compiled instead of form. If NIL is returned, the compiler compiles the original expression as a call to a lambda-spread that is not yet defined. CLISP (Section 23) uses compileuserfn to tell the compiler how to compile iterative statements, IF-THEN-ElSE statements, and pattern match constructs. 7 The names of functions 50 treated are added to the list alams (for assumed lamdas). alams is not used by the compiler; it is maintained for the user's benefit,~ so that the user can check to see whether any incorrect assumptions were made. 18.6 i.e., the stack is not even searched ror this variable when the compiled function is entered. Similarly, (SETQ variable value) is equivalent to (RPLACA (QUOTE variable) value); i.e., it sets the top-level value. All system parameters, unless otherwise specified, are GLOBALVARS, i.e. are members of the list globalvars, e.g. brokenfns, editmacros, Irpars, dwimflg. et al. 8 Thus, rebinding these variables will not affect the behavior of the system: instead, the variables must be reset to their new values. and if they are to be res tored to their original values. reset again. For example, the user might write .•. (SETQ globalvar new-value) form (SETQ globalvar old-value). Note that in this case, if an error occurred during the evaluation of form, or a control-D was typed. original value. the global variable would not be restored to its The function resetvar (described in Section convenient way of resetting global variables in such 8 5) provides a way that their values are restored even if an error occurred or control-D is typed. 18.5 Compiler Functions Note: when a function is compiled from its in core definition, compile (and certain calls to re~ompile), i.e.. via as opposed to \compl (which uses the defini tions on a file), and the function has been modified by break, trace, breakin, or advise, it is restored to its original state, and a message printed out, e.g., FOO UNBROKEN. Then, if the function is not defined as an expr, its property list is searched for the property EXPR (see savedef, Section 8). If there is a property EXPR, its value is used for the compilation, otherwise, the compiler prints (fn NOT COHPILEABLE), and goes on to the next function. 8-----------------------------------------------------------------------------Since the stack does not have to be searched to find the values of these variables, a considerable savings in time is aChieved, especially for deep computations. 18.7 compile[x;flg] ~ Jls a list of functions (if atomic, list[x] is use,d). compile first asks the standard compiler que!sti()ns, and then compiles each function on !. using its in-core definition. Value is !. If compiled definitions are being dumped to a file. the file is closed unless f!H=T. compilel[name;def] comlpiles def. redefining!!!!!!! if strf=T. 9 compile1 is used by compile. tcompl, and recompile. dwimifycompflg is T,· or def contains If CLISP a declaration, def is dwimified before compiling. See Section 23. tcompl[f.tles] tcompl is used to 'compilefiles' symbolic load file (e.g.. i.e., given a t one created by prettydef) t it produces a file that contains the same S-expressions as the original symbolic file, except that every defineq corresponding compiled is replaced by definitions. the This 'compiled' file can be loaded into any INTERLISP system with load. fil!! is a list of symbolic files to be compiled (if atomic, list[files] is used). standard compiler OUTPUT FILE: Instead, questions, the tcompl asks the except output from for the compilation of each symbolic file is written on a 9------------------·-----------------~---------------------------------------~- strf is one of the variables set by compset, described earlier. 18.8 file of the same name suffixed with COM, e.g., tcompl[(SYMl SYMZ)] produces two files, SYM1.COM and SYMZ.COM. 10 tcompl processes each file one at a time, reading in the entire file. Then, for each DEFINEQ, tcompl adds any NLAHBDA's in the DEFINEQ to nlama or nlaml,11 and adds lambdas to the list lams,12 so that calls to these functions will be compiled correctly. Expressions beginning with DECLARE can be used to affect the compilation, e.g. set up MACROS. tcompl evaluates each expression in (cdr of) the DECLARE, presumably for effect .18 tcompl then compiles each function in the DEFINEQ's. finally, all other expressions in the file, e.g. RPAQO's, DEFLIST's, etc., are written onto the output f11e. 14 io----------------------------------------------------------------------------The file name is constructed from the name field only, e. g. tcompl[ nly.13 treepaths[x;y;type;must;avoid;only] Like paths, except prints paths as a' treo structure. as shown at [6] in Figure 20-3. must, avoid, and only have the same meaning as 'fith paths. 14 ~, 13--~~~~~~----;-;----~;ii;~-----;~;----~~~i1;h----~~~~-;;----;;----~~~-----f~;~: "WHAT ARE THE PATHS FROM x TO y?". Such questions can be modified with subordinate clauses to indicate values for must, avoid, and/or only, e.g. "WHAT ARE THE PATHS FROM FOO TO FIE WHICH ONLY GO THROUGH FOOFNS AND AVOID FIEFNS?" 14 treepaths is called for Engli,sh inputs of the form "SHOW ME HOW x CALLS y", "DISPLAY THE PATHS FROM x TO y., etc. 20.16 lookat[x] Builds the initial data base describing the system ~, where ~ is either the name of a function, the name of a variable which evaluates to a list of functions, clumpget[object;relation;universe) o~ the list of functions itself. Value is a list of objects (functions or variables) which have the indicated relation with respect to returns a object, list of clumpget[X;SMASHERS) e.g. clumpget[FOO;CALLERS) functions a list of that call FOO, functions that smash the variable X, etc. A complete list of the possible values for relation is given below. 16 · object can be a list of objects (or a variable which evaluates to a list of objects), in which case the value returned by clumpget is the list of all objects which have the indicated relation to anu of the members of object. Similarly. unive~ can be a list of objects (or a variable which evaluates to a list of objects}, in which case the value returned by clumpget is the list of all objects in universe which have the indicated relation members to object of (or any of object), the e.g. clumpget[X;SMASHERS;FOOFNS). i5--i;-~~~~~~~~--;;-;;;~~-;-~~;~~-~~~--;;;;;;;;-~~~~-~~-~~~~--;;;-;~~~~~;;~:-~~ will attempt spelling correction, and if that fails, generate an error. If given a valuo for object that it has not seen before, it will type "I don't know anything about object, shall I analyse a system?" and go into analysis mode. ' 20.17 Finally" universe can be a relation, which is equivalent to supplying clumpget[object;universe] in place of object, i.e. the value returned is the list of all objects which have the indicated relation to any of the members of the {set of all objects which bear the relationship universe to object} . For example, clumpget[FOO;CALLERS;CALLEOFNS] is a list of all functions that call any of the functions (CALLERS) that are directly called by clumpget[FOO;FREEUSERS;LOCALVARS] FOO (CALLEOFNS). is a list of functions that use freely any of the variables that are bound locally.by FOO. Currently. the following relations are implemented: CALLERS list of functions that directly call object. CALLEOFNS list of functions directly called by object. CALLCAUSERS list of functions indirectly. CALLSCAUSEO list of call In called English: by object, "WHO DOES SOMEHOW?" ABOVE union of object with CALlCAUSERS. BELOW union of object with CALLSCAUSED. ARGS arguments of object. 20.18 object, perhaps In English: "WHO CALLS FOO SOMEHOW?". functions indirectly. that perhaps FOO CALL ARGBINOERS list of functions that have object as an argument. LOCALVARS list of variables that are locally bound in object, e.g. PROG vars. LOCALBINOERS list of functions that bind object as a local variable. FREEVARS list of variables used freely by object. FREEUSERS list of functions .that use object freely. LOCALFREEVARS list of variables that are used freely in object, but are bound in object before they are used, e.g. clumpget[FOOiLOCALFREEVARS;BELOW] gives a list of those variables used freely below FOO, but are bound above the place that they are used .16 In English: "WHAT ARE THE LOCAL fREE VARS (VARIABLES) BELOW FOO?" GLOBALFREEVARS list of variables used freely in object without previously being bound in object. ENTRYFNS list of each function called by any itself, e.g. function in object which in object is other not than clumpget[fOOFNSjENTRYFNS]. 16----------------------------------------------------------------------------Note that if .2.!Uect is the name of a function and universe is NIL, LOCALFREEVARS will always be NIL, and GLOBALFREEVARS the same as fREEVARS. It is only in connection with collections of functions that LOCAlFREEVARS and GLOBALFREEVARS become interesting. 20.19 SELFRECURSIVE list of function$ in ob~ect which call themselves directly. CAUSESELFCALL list of functions in object which could call cause some themselves, perhaps indirectly. CAUSERECURSION list of functions in object which function to call itself, perhaps indirectly. list of variables that are changed by object. CHANGEVARS where 'changed' means anu flavor of ass ignmen t, i.e. via SETO. SETQO. RPAO, SETN, or even an expression of the form (RPLACA (QUOTE atom) value) (or FRPLACA, IRPLACA, SAVESET, etc.)17 CHANGERS list of functions that change object. Note: 'set' in English input means anu Ilauor 01 assignment, and translates the same as 'change'. SMASHVARS list of variables whose value are smashed by object, where 'smash' means the variable appears as the first argument to one of the functions on smasherslst. 18 list of 17----------------------------------------------------------------------------c Il1!!!p~ wi 11 accept as rEtlations SETOVARS, SETQERS, SETVARS, SETTERS, SETQQERS, SETQQVARS, etc., in case the user wants to distingUish between the various flavors of assi!Jnments. In English. "WHAT ARE THE SETQERS OF X1", etc. 18 (RPLACA RPLACD FRPLACA FRPLACD IRPLACA IRPLACD NCONC NCONCl ATTACH IATTJ\CH RPLNODE IRPLNODE RPLNODE2 IRPLNODE2). As with assignments, clumpgct will accept as relations RPLACAERS, RPLACAVARS, RPLACOERS. RPLACDVARS. etc., in case the user wants to distinguish the different types of smashing. Initially INCONC INCONCI 20.20 SMASHERS list of functions that smash object. TESTVARS list of variables that are tested by object, where 'tested' means they appear as the first argument to one of the list of functions on testerslst, initially (ATOM lISTP NUMBERP NlISTP STRINGP EQ EQP EQUAL NUll). or anywhere in an AND or OR, or as the predicate in a COND clausei or as the first argument to SELECTQ. etc. TESTERS list of functions that test object. USEVARS list of variables that are used in object, where 'used' means actually appear in the body of the function, i.e. if a variable is simply bound, but not actually used anywhere, it included in the value of USEVARS. TESTVARS are subsets of USEVARS. USERS list of functions that use object. 20.21 will not be CHANGEVARS and Index for Section 20 Page Numbers ALLCALLS[ FN: TREELST] ....••.•.••.•..•.•••••••..•. CALLS[FN;EXPRFLG;VARSFLG] .......••••••••.••••.•• CLISP .............................••••.•....•••. CLUMPGET[OBJECT;RELATION;UNIVERSE] dobugging .•.••..••••••• ...................................... . OONELST (printstructure variable/parameter) OWIMIFY[X;L] .......•.•...••.....•••••••••••• " ••• EXPR (property name) ............•..•..•..••..••• EXPRFLG (printstructure variable/parameter) FIRSTfN[FN] ...............•...•..•. 4 •••••••••••• FREEVARS[FN;EXPRFLG1 .........•.••..•..••.••.•.•. INTERSCOPE ......................•.......•.•.•..• IS NOT DEFINED (typed by PRINTSTRUCTURE) .•.••••. LAST-PRINTSTRUCTURE (printstructure variable/parameter) ....•.•. LASTFN[FN] ......................•.•....••.•.••.• LOOKA-T[ X] •••••••••••••••••••••••••• 6 •••••••••••• NIL: .........................................••. NOFNS (printstructure variable/parameter) .•.•.•• NOTRACEFNS (printstructure variable/parameter) P.P.E. (typed by PRINTSTRUCTURE) .........••....• PATHS[X;Y;TYPE;MUST;AVOID;ONLY] ........•...•..•. PROEPTH (printstructure variable/parameter) PRINTSTRUCTURE[X;EXPRFLG;FILE] ...........••..•.• QUOTEFNS (printstructure variable/parameter) TENE X .........•••..•.•.•..••.••••••••••••••••••• TREELST (printstructure variable/parameter) TREEPATHS[X;Y:TYPE;MUST;AVOID;ONLY] .....•••.•••• TREEPRINT[X;N] ...........••.......•••••.••.••••• VARPRINT[DONELST;TREELST] .........•.....••.••••. VARS[FN;EXPRFLG] ............••..•..•...••••••••• YESFNS (printstructure variable/parameter) ••• ~ •. *** (in interscope output) ....•..••••••••••••••• -*CUTOFF** (typed by PRINTSTRUCTURE) •••••••••••• INIlEX.20.1 20.9 20.10 20.5 20.17 20.5 -20.8 20.5 20.7 20.6,9 20.4,9 20.10 20.11-21 20.5 20.6,8-9 20.4,9 20.13,17 20.6 20.3 20.4 20.5,8 20.14-15 20.4 20.1-10 20.4 20.6 20.8 20.16 20.9 20.9 20.10 20.3 20.15 20.4 SECTION 21 "ISCELLANEOUS 21.1 Measuring Functions time[timex;timen;timetyp] is an nlambda function. It executes the computatiQn timex, and prints out the number of . conses and computation time. Garbage collection time 1s subtracted out. (QUOTE PRETTY) (QUOTE PROP] FILE CREATED 7-HAY-71 12:47:14 ~TIHE«LOAD GC: 8 582, 10291 FREE WORDS PRETTYFNS PRETTYVARS 3727 CONSES 10.655 SECONDS PRETTY If timen is greater than 1 (timen=NIL equivalent to timen=1), time executes timex timen number of times and prints out number of conses/timen, and computation time/timen. This is useful for more accurate measurement on small computations,e.g. (QUOTE (A B C») 10) 30/10 = 3 CONSES .055/10 = .0055 SECONDS (A 8 C) ~TIHE«COPY 21.1 If ~timetype is 0, time measures and prints total real time as well as computation time, e.g. (QUOTE PRETTY) (QUOTE PROP» FILE CREATED 7-MAY-71 12:47:14 ~TIME«LOAD 1 0] CiC: 8 !j8Z, 10291 FREE WORDS PRETTYFNS PRETTYVARS ~~7Z7 CONSES :ll . 193 SECONDS 27.378 SECONDS, REAL TIME PRETTY If ,timetyp • 3, time measures and prints garbage collection time as well as computation time, e.g. (QUOTE PRETTY) (QUOTE PROP» FILE CREATED 7-MAY-71 12:47:14 ~TIME«LOAD 1 3] (iC: 8 582, 1091 FREE WORDS PRETTYFNS I)RETTYVARS :~ 7Z 7 CONSES :lO.597 SECONDS 1.487 SECONDS, GARBAGE COLLECTION TIME IJRETTY Ano1~her mea~.ures option is timetype=T, in which case time and prints the number of pagefaul ts. The value of time is the value of the last evaluation of timex. date[ac3] If !!c3=NIL, obtains date and time from TENEX and returns it as single string in format -dd-mm-yy hh:aw:ss-, where dd is day, mm is month, yy year, hh hours, mm minutes, -14-MAY-71 14:26:08-. 21.2 55 seconds, e. g. , Other values of ac3 can be used to specify other formats, e.g. day of week, time zone, etce as described in TENEX JSYS Manual. clock[n] for !!.=O current value of the time of day clock i.e., number of milliseconds since last system start up. for !!.=1 value of the time of day clock when the user started up this INTERLISP. 1.e., difference between clock[O] and clock[l] is number of milliseconds (real time) since this INTERLISP was started. for !!=2 number of milliseconds of compute time since user started up this INTERLISP (garbage collection time 1s subtracted ofr) . for !!=3 number of milliseconds of compute time spent in garbage collections (all types).l dismiss[n] dismisses program for!!. milliseconds, during which time program is in a state similar to an 1/0 wait, i . e • , it uses no CPU time. control-D, control-E, or 21.3 Can be aborted by control~B. conscount[n] conscount[] returns the number of conses since IN1'ERLISP started up. If!l is not NIL, resets conscount to !!. boxcount[type;n] number of boxing operations (see Section 13) since INl'ERLISP started up. If ~=NIL, returns number of large integer boxes; type-FLOATING, returns number of floating boxes. 2 If!l is not NIL, resets the corresponding counter to !l. gctrp[ ] number of conses to next GC: 8, i. e ., number of list words not in use. Note that an intervening GC of another type could collect as well allocate additional list words. as See Section 3. gctrp[n] can be used to cause an interrupt when value of gctrp[]-n, see Section 10. pagefaults[] number of page faults since INTERLISP started up. logout[ ] returns to TENEX. a A subsequent CONTINUE command will enter the INTERLISP program, return NIL as the value of the call to logout, and continue the computation exactly as if nothing had happened, i.e., logout is a programmable control-C. As with control-C, a REENTER convnand following a logout will reenter INTERLISP at the top level. 2--------~-----------~----------------------------------~----------------~----- These counters are directly accessible via the COREVAL$ IBOXCN and FBOXCN. 8 If INTERLISP was started a~t a subsidiary fork (see subsys, page 21.18), is returned to the higher fork. con~rol 21.4 logout[] will not affect the state of &ny open files. 21.2 Breakdown 4 Time gives analyses by computation 0 Breakdown is available to analyze the breakdown of computation time (or any other measureable quantity) function by function. The user calls breakdown g.iving it a list of functions of interest. These functions are modified so that they keep track of the "charge" assessed to them. The function results gives the analysis of the statistic requested as well as the number of calls to each function. Sample output is shown' below. 6 SUB PRINT COMMENT!) (SUPERPRINT SUBPRINT COMMENT1) ~.PRETTYOEF( (SUBPRINT) FOO) (SUBPRINT) ... RESULTS() FUNCTIONS TIME I CALLS SUPERPRINT 25.294 458 SUBPRINT 32.96 169 COMMENTl 7.833 12 TOTAL 66.087 639 NIL ~BREAKDOWN(SUPERPRINT The procedure used for measuring1s such that if one function calls other and both are 'broken down'. then the time (or whatever quantity is being measured) spent in the inner function is not charged to the outer function as well. 6 4-----------------------------------------------------------------------------breakdown was written by W. Teitelman. 6 This is with an interpreted prettyprint. 6 breakdown will not give accurate results if a function being measured 1s not returned from normally, e.g. a lower retfrom (or error) bypasses it. In this case, all of the time (or whatever quantity isbeing measured) between the time that function is entered and the time the next function being measured is entered will be charged to the first function. 21.5 To remove functions from those being monitored, simply unbreak the functions, thereby restoring them to their original breakdown on the new functions. functions not on the new list. state. To add functions, call This will not reset the counters for any IHowever breakdown[] can be used for zeroing th~ counters of all functions being monitored. To use breakdown for some other' statistic, before callin'g breakdown, set the variable brkdwntype to the qU8:,ntity of interest, e.g., TIME, CONSES, etc. Whenever breakdown is called with brkdwntype not NIL, breakdown performs the necessary changes to its internal state to conform to the new analysis. particular, In if this is the fir'st time an analysis is being run with this statistic, the compiler may be called to compile the measuring function.? When breakdown is through ini tializil1lg, it sets brkdwntype back to NIL. Subsequent calls to breakdown will measure the new statistic until brkdwntype is again set and a new breakdown performed. ~SET(BRKOWNTYPE CONSES Sample output is shown below: CONSES) CONSTRUCT) (MATCH CONSTRUCT) ~FLIP«A BCD E F G H C Z) ( •• S1 (A B 0 E F G H Z) ~BREAKOOWN(MATCH 12 •• ) ( •• 13 •• » ~RESULTS() FUNCTIONS HATCH CONSTRUCT TOTAL NIL The value of brkdwntype CONSES 32 47 79 is uSied 1 CALLS 1 1 2 to search the information necessary to analY2:e this statistic. list brkdwntypes for the The entry on brkdwntypes corresponding to brkdwntype should be of the form (type form function), where form computes the statistic, and function (optional) converts the value of form to some more interesting quantity, e.g. 7------~-~----------------------··-------------------------------------~-------The measuring functions for TIME and CONSES have already been compiled~ 21.6 (TIME (CLOCK 2) (LAMBDA (X) (FQUOTIENT X 1000»)8 measures computation time and reports the result in seconds instead of milliseconds. defined on brkdwntypes, an error is generated. If brkdwntype is not brkdwntypes currently contains entries ,for TIME, CONSES, PAGEFAULTS, BOXES, and FBOXES. More Accurate Measurement Occasionally, a function being analysed is sufficiently fast that the overhead involved in measuring it obscures the actual time spent in the function. If the user were using time, he would specify a value for timen greater than 1 to give greater accuracy. A similar option is available for breakdown. The user can specify that a function(s) be executed a multiple number of times for each measurement, and ~he average value reported, by including a number in the list of functions given to breakdown, e.g., BREAKDOWN(EDITCOM EDIT4F 10 EDIT4E EQP) means normal breakdown for editcom and edit4f but executes (the body of) edit4e and ~ 10 times each time they are called. Of course, the functions so measured must not cause any harmful side effects, since they are executed more than once for each call. The printout from results will look the same as though each function were run only once, except that the measurement will be more accurate. 8-~~-----~----~--------------------------------------- ------------------------- for more accurate measurement. the form for TIME 1s not (CLOCK Z) but (ASSEMBLE NIL (HOVEl 1 • -5) (JSYS 13) (SUB 1 , GCTIM». 21.7 21.3 Edita 9 Edi ta is an editor for arrays. However , its most frequent application is in edi ting compiled functions (whi'ch are also arrays in INTERLISP). and a great deal of effort in implementing !ldi ta, and most of its special features, are in this area. For example, edita knows the format and conventions of INTERLISP compiled code, and so, in addition to decoding instructions a la DDT,10 edita can fill in the appropriate C:OREVALS, symbolic names for references to literals, linked function calls, etc. a index registers, The following output shows sequence of instructions in a compiled function first as they would be printed by DDT, and second by edita. 466716/ 466717/ 466720/ 466721/ 4667221 4667231 466724/ 466725/ 466726/ 466727/ 466730/ 4667311 4667321 4667331 466734/ 466735/ 4667361 466737/ 466740/ 466741/ 4667421 466743/ PUSH 16,LISP&KNIL PUSH 16,LISP&KNIL HRRZ 1,-12(16) CAME l,LISP&KNIL JRST 466724 HRRZ 1,@467575 PUSH 16,1 LISP&IOFIL,,467576 -3,,-3 HRRZ 1,-14(16) CAMN 1,467601 JRST 466734 CAME 1,467602 JRST 466740 PUSH 16,467603 PUSH 16,467604 LISP&FILEN,,467605 JRST 467561 CAME 1,467606 JRST 466754 HRRZ 1,@-12(16) PUSH 16,1 PUSH PP,KNIL PUSH PP,KNIL HRRZ 1,-10(PP) 51 61 CAME l,KNIL .11 JRST 9 71 HRRZ 1,@'BRKFILE 81 PUSH PP,l 91 101 PBINo 'BRKZ 111 '!"524291 121 HRRZ 1,-12(PP) 13/ CAMN I, 'OK 141 JRST 17 151 CAME I, 'STOP 161 JRST 21 171 PUSH PP,'BREAKI 18/ PUSH PP,'(ERRORI) 191 CCALL 2,'RETEVAL 201 JRST 422 211 CAME 1,'GO 22/ JRST 33 23/ HRRZ l,@-10(PP) 241 PUSH PP,l 3/ 4/ i---------------------~-------------------------------------------------------edita was written byW. Teitelman. 10 DDT is one of the oldest debugging systems still around. For users unfamiliar with it, let us simply say that edita was patterned after it because so many people are feLJDiliar with it. - - 11 Note that edi ta prints the addresses of cells contained in the function relative to the origin of the, function. 21.8 Therefore, rather than presenting !Q!!! as an array editor with some extensions for editing compiled code, we prefer to consider it as a facility for editing compiled code, and point out that it can also be used for editing arbitrary arrays. Overview To the user, edita looks very much like DDT with INTERLISP extensions. It is a function of one argument, the name of the function to be edited. 12 Individual registers or cells in the function may be examined by typing their address followed by a slash,13 e.g. 6/ HRRZ 1,-10(PP) The slash is really a command to edita to open the indicated register. 14 Only one register at a time can be open, and onlu open registers can be changed. To change the contents of a register, the user first opens it, types the new contents, and then closes the register with a carriage-return,16 e.g. 7/ CAMEt," CAMN 1,",) 13 Underlined characters were typed by the user. edi ta uses its own read program, so that it is unnecessary to type a space before the slash or to type a carriage return after the slash. 14 edt ta also converts absolute' addresses of cells within the function to relative address on input. Thus, if the definition of foo begin~ at 85660, typing 6/ is exactlu the same as typing 85666/. --- 15 Since carriage-return has a special meaning, edita indicates the balancing of parentheses by typing a space. 21.9 If the user closes a register without specifying the new contents, the contents are left unchanged. Similarly. if an error occurs or the user types control-E, the open register, if any, is closed without being changed. Input Protocol Edita processes all inputs not recognized as commands in the same way. If the input is the name of an instruction (i.e. an atom with a numeric OPD property), the corresponding number is added to the input value being assembled, 16 and a flag is set which specifies that th~ input context is that of an instruction. The general form of a machine instruction is (opcode ac , @ address (index» described in Section 18. as TherftJfore, in instruction context, edita evaluates all atoms (i f the atom has a COREVAL property, the value of the COREVAL is - used), and then if the atom corresponds to an ac,17 shifts it left 23 bits and \ adds it to the input value, otherwise adds it directly to the input value, but performs the arithmetic in the low 18 bits. 18 Lists are interpreted as specifying index registers, and the value of f.!!: of the list (again COREVALs are permitted) is shifted left j,8 bits. Examples: 16------------------------------'----------------------------------------------The input value is initially o. 17 i.e. if a " I has not been seen, and the value of the atom is less than 16, the low 18 bits of the input value are all zero. and 18 If the absolute value of 'the atom is greater than 1000000Q, full word ari thmetic is used. For e:lCample. the indirect, bit is handled by simply binding @ to 20000000Q. 21.10 PUSH HRRZ CAME JRST PP, KNIL 1,-10(PP) 1, 'GO 33 ORG 19 The user can also specify the address of a literal via the • command, see page 21.14. For example, if the' literal • UNBROKEN" is in cell 85672, HRRZ 1,'· UNBROKEN" is equivalent to HRRZ 1, 85672. When the input context is not that of an instruction, i.e. no OPO has been seen, all inputs are evaluated (the value of an atom with a COREVAl property is the COREVAL.) Then numeric values are simply added to the previous input value; non-numeric values become the input value. 20 The only exception to the entire procedure occurs when a register is open that is in the pointer region of the function, i.e. literal table. atomic inputs are not evaluated. In this case, For example, the user can change the literal FOO to fIE by simply opening that register and then typing fIE followed by carriage-return, e.g. FOO Note that this is equivalent to 'FOOl fOO (QUOTE FIE») 19----------------------------------------------------------------------------edi ta cannot in general know whether an address field in an instruction that is typed in is relative or absolute. Therefore, the user must add ORG, the origin of the function, to the address field himself. Note that edita would print this instruction, JRST 53 ORG, as JRST 53. 20 Presumably there is only one input in this case. 21.11 Edita Commands and Variables ~ (carriage-return) If a register is open and an input was t~¥ed, store the input in the register and close it. If a register is open and nothing was typed, close the register without changing it. If a register is not open and input was typed, type its value. ORG Has the value of the address of the first instruction in the function. i.e. loc of getd of the function. I Opens the register specified by the low ,18 bits of the quantity to the left of the /, and types its contents. If nothing has been typed, it uses the last thing typed by edita, e.g. 351 JRST 53 L CAME 1, 'RETURN If a register was open, changing its contents. / L closes RETURN it without After a / command, edita returns to that state of no input having been typed. tab (control-I) Same as carriage-return, followed by the address of the quantity to the left of the t'ab, e.g. 351 53/ JRST 53 tab CAME 1,' RETURN Note that if a register was openl and input was typed, tab will change the open register before closing it, e.g. 351 541 351 (period) JRST 53 JRST 70 JRST 54 JRST 54 tab 1. has the value of the address of the current (last) register examined. 2i----------------------------------------------------------------------------If the register is in the unboxed region of the function, the unboxed value is stored in the register. 21.12 line-feed same as carriage-return followed by (ADD1 .)1 i.e. closes any open register and opens the next register. t same as'carriage-return followed by (SUB1 .)1 SQ (alt-modeQ) has as its value the last quantity typed by edita e.g. 351 .1 JRST 53 JRST 54 ~ LITS has as value the (relative) address of the first literal. BOXED same as LITS $ (dollar) has as value the relative address of the literal in the function. = Sets radix to -8 and types the quantity to the left of the = sign, i. e. if anyth ing has been typed, types the input value, otherwise, types SQ, e.g. 351 JRST 54 last !254000241541Q JRST 54=254000000066Q Following =, radix is restored and edita returns to the no input state. OK leave edita ? return to I no input ' state. ? is a 'weak' control-E, i.e. it negates any input typed, but does not close any registers. addressl, address21 prints22 the contents of registers address 1 through address2. . is set to address2 after the completion. 22----------------------------------------------------------------------------output goes to file. initially set to T. The user can also set file (while in edita) to the-nime of a disc file to redirect the output. (The user is responsible for opening and closing file.) Note that file only affects output for the addressl, address21 command. -- 21.13 IX corresponds to the I in LAP. The next expression is read, and if it is a small number, the appropriate offset is added to it. Otherwise, the literal table is searched for x, and the value of IX is the (absolute) address -of that cell. An err'or is generated if the literal is not found, i.e. I cannot be used to create literals. :atom defines atom to an address (1) the value of SQ if a register is open, (2) the input if any input was typed, otherwise (3) the value of ,.,.28 For example:' JRST 54 : FOO) :FIE.> FIEI JRST FOO ..:.!:35 351 Edi ta keeps its symbol' tables on two free variables, usersyms and !mIst. Usersyms is a li·st of elements. of the form (name • value) and is used for encoding input. i.e., all variables on usersyms are bound to corresponding values during evaluation of any expression inside edita. their Symlst is a list of elements of the form (value • name) and is used for decodi ng addresses. Usersyms is initially NIL, while symlst is set to a list of all the corevals. Since the : command jildds the appropriate information to both these two lists, new definitions will remain in effect even if the user exits from edita and then reenters it later. Note that the user can effectiv1sly define symbols without using the command by appropriately binding usersym.! andlor symlst before calling edita. Also, he can thus use different symbol tables for different applications. SW (alt-modeW) search command. Searching consists of comparing the object of the search with the contents of each register, and printing thosa that match, e.g. 23---------~-~------------------··--------------------------------------~------- Only the low 18 bits are used and converted to a relative address whenever possible. 21.14 HRRZ @ SW,.> HRRZ 1,@'BRKFILE 23/ HRRZ 1,@-10(PP) 281 HRRZ 1,@-lZ(PP) 81 The SW command can be used to search either the unboxed portion of a function, i.e. instructions, or the pointer region, i.e. literals, depending on whether or not the object of the search is a number. If any input was typed before the SW. it will be the object of the search, otherwise the next expression is read and used as the object. 24 The user can specify a starting point for the search by typing an address followed by a 't' before calling SW, e.g. 1, JRST SW. If no starting point is specified, the search will begin at 0 if the object is a number, otherwise at LITS, the address of the first literal. 26 After the search is completed, , ., is set to the address of the last register that matched . If the search is operating in the unboxed portion of the function, only those fields (i.e. instruction, ac, indirect, index. and address) of the object that contain one bits are compared. 26 For example, HRRZ @ SW will find all instances of HRRZ indirect, regardless of ac, index, and address fields. Similarly, 'PRINT SW will find all instructions that reference the literal PRINT. 21 24----------------------------------------------------------------------------Note that inputs typed before the SW will have been processed according to the input protocol, i.o. evaluated; inputs typed after the SW will not. Therefore, the latter form 1s usually used to specify searching the literals, e.g. SW FOO is equivalent to (QUOTE FOO) SW. 26 Thus the only way the user can search the pOinter region for a number is to specify the starting point via '.'. 26 Alternately. the user can specify his own mask by setting the variable mask (while in edita), to the appropriate bit pattern. 27 The user may need to establish instruction context for input without giving a specific instruction. For example, suppose the user wants to find all instructions with ac=1 and index=PP. In this case, the user can give & as a pseudO-instruction, e.g. type & I, (PP). 21.15 If the search is operating in the pointer region, a 'match' is as defined in the editor. For example, SW (8.:) will find all registers that contain a list consisting of a single expression. SC (alt-modee) like SW except only prints the first match, then prints the number· of matches when the search finishes. Editing Arrays Edita is called to edit a fun(:tion by giving it the name of the function. Edita can also be called to edit an array by giving it the array as its (irst argument,28 in which case the following differences are to be not~d: 1. decoding - The contents of registers in the unboxed region are boxed and printed as numb4!rS, i. e. they are never interpreted as instructions, as when editing a function. 2. addressing convention - Whereas 0 corresponds to the first instruction of a function, the first element of an array by convention is element number 1. 3. input protocols - If a register is open, lists are evaluated, atoms are not evaluated (except for SO which is always evaluated). If no register is open, all inputs are evaluated, and if the value is a number, it is added to the 'input value'. 4. left half - If the left half of an element in the pointer region of an array is not all 0'5 or NIL, it is printed followed by a 21.16 ;~ e.g. 101 (A B) T Similarly, if a register is closed, either its left half, right half, or both halves can be changed, depending on the presence or absence, and position of the ; e.g. changes left ~ 101 (A B) ; T .:l.. B T NIL~ .:l.. B NIL A .:l.. A changes right C') ., C changes both If ; is used in the unboxed portion of an array, an error will be generated. The SW command will look at both halves of elements in the pointer region, and match if either half matches. Note that SW A ; B is not allowed. This ends the section on edita. 21.4 Interfork Communication The functions described below permit two forks (one or both of them INTERLISP) to have a common area of address space for communication by providing a means of assigning a block of storage guaranteed not to moue during garbage collectio'ns. getblk[n] Creates a block !!. pages in size (512 words per page). Value is the address of the first word in the block, which is a multiple of 512 s1.nee the block will always begin at a page boundary. not enough pages are available, error ILLEGAL OR IMPOSSIBLE BLOCK. 21.17 generates If the Note, the block can be used for storing unboxed numbers onlu. To store a number in the block, the following function could be used: [SETBLOCK (LAMBDA (START N X) (CLOSER (IPLUS (LOC START) N) X] Some boxing and unboxing can be avoided by making this function ~ompile open via a substitution macro. Note, getbllt. should be usedspaT'ingll/ since selleral unmollable regions 01 memorll ca,n make it difficult or impossible Jor the garbage collector to lind a contiguous region large enough for expanding arrag space. relblk[addressin] releases a block of storage beginning at address and extending for ! Causes pages. an error ILLEGAL OR IMPOSSIBLE BLOCK if any of the range 1s not a block. 21 .5 Value is address. SUbsYS29 This section describes a funct:Lon, subsys, which permits the user to run a TENEX subsystem, such as SNDMSG, SRCCOM, TECO, or even another INTERLISP, from inside of an INTERLISP without destroying the latter. In particular, SUBSYS(EXEC) will start up a luwer exec, which will print the TENEX herald, followed by @. The user can then d~ anything at this exec level that he can at the top level, without affecting his superior INTERLISP. For example, he can start another INTERLISP. perfonlD a sysin, run for a while. type a control-C returning him to the lower exec, RESET, do a SNDMSG, etc. The user exits from the lower exec via the command QILlIT, which will return control to subsys in the 21.18 higher INTERLISP. Thus with subsys. the user need not perform a sysout to save· the state of his INTERLISP in order to use a TENEX capability which would otherwise clobber the core image. Similarly. subsys provides a way of checking out a sysout file in a fresh INTERLISP without having to commandeer another teletype or detach a job. While subsys can be used to run any TENEX subsystem directly, without gOing through an intervening exec, this procedure is not recommended. The problem is that control-C always returns control to the next highest exec. Thus if the user is running an INTERLISP in which he performs SUBSYS(LISP), and then types control-C to the lower INTERLISP, control will be returned to the exec above the first INTERLISP. The natural REENTER command would then clear the lower INTERLISP,30 but any files opened by it would remain open (until the next @RESET) • I f the user elects to call a subsystem directly, he must therefore know how it is normally exited and always exit from it that way.81 Starting a lower exec does not have this disadvantage, since it can onlu be exited via QUIT, i.e., the lower exec is effectively 'errorset protected' against control-C. subsys[file/forkjincomfile;outcomfilejentrypointflg] If file/fork=EXEC. otherwise runs starts up lower 1) n (n move forward n events, 1.e. in direction of inl:reasing event number. If given as the first 'cc)lMland,' !1 specifies the event with event number n. n (n .s ... atom -1) move backward -n events. search backward for an event whose Junction matches atom (i.e. for ~ format only), e.g. whe!reas FIE would refer to event FIE would refer to event 44. Similarly, EOS would specify event 51, whereas .. EOS event 48. 17, .. search backward for an event whose input contains an expression that matches pat as described in Section 9. ... I next search is to go forward instead of backward, (if given as the first •command', next search begins with last, i.e. oldest, event on history 1is t), e. g. .. LAMBDA refers to event 38; HAKEFIlES .. RECOMPILE refers to event 51. F next object is to be searched for, regardless of what it is, e.g. F -2 looks for an event containing a -2. = next search is to look at uaLues, instead of 8---~:;~-~~~~~=~~~;~-----------------------·----------------------------------9 i.e. anything else except for .. , -, described above. 22.12 and which are, interpreted as inputs, e.g. =UNDO refers to event 49; 45 = FIE refers to event 43; ~ = LAMBDA refers to event 37. specifies the event last located. Note: each search skips the current event, i.e. each command always moves the cursor. For example, if FOO refers to event !l. Foo FIE will refer to some event before event !l, even if there is a FIE in event !l. An event specification specifies. one or more events: FROM #1 THRU 12 sequence of events from the wi th address (11 through event wi th address '2, e.g. FROM GETD THRU 49 specifies events 47, 48, and 49. 11 can be more recent than 12, e.g. FROM 49 THRU GETP specifies events 49, 48, and 47 (note reversal of order). FROM 11 TO 12 11 TO 12 Same as THRU but does not include event 12. FROM 11 Same as FROM 11 THRU -1, e.g. FROM 49 specifies events 49, 50, 51, and 52. THRU 12 Same as FROM -1 THRU '2, e.g. THRU 49 specifies even ts 52, 51, 50, and 49. Note reversal of order. TO Same as FROM -1 TO '2. #1 AND 12 AND ..• AND In i. e. a sequence of event addresses separated by AND's,.e.g. FROM 47 TO LOGOUT would be equivalent to 47 AND 48 AND MAKEFILES. empty i.e. nothing specified, same as -1, unless 1ast event was an UNDO, in which case same as -2. 11 11 THRU 12 the eve2h 10----------------------------------------------------------------------------i.e. the symbol #1 corresponds to all words between FROM and THRU in the event specification, and #2 to all words from THRU to the end of the event specification. for example, in FROM Foo 2 THRU FIE -1, 11 is (FOO 2), and 12 is (FIE -1). 11 For example, if the user types (NCONC Foo FIE), he can then type UNDO, followed by USE NCONC1. 22.13 @ atom refers to the events named by atom, via the NAME conunand, page 22.25 e.g., if the user names a pclrticular event or events FOO, @ FOOspecifies those events. @@ ~ ~ is an event specification and interpreted as above, but with respect to the archived history list, as specified on page 22.27. 22.4 History Commands All history cOl7D1land.s can be iTl'put a.s either lists, or a.s line.s (.see readltne Section 14. and also page 22.47). t is u.sed to denote an event .specification. Unle.ss specified otherwise, omitted is the same as t z-l, e.g. REDO and REDO -1 are the same. REDO ~ USE vars FOR args IN t redoes the event or events specified by REDO FROM -3 redoes the last three events. SUbstitutes ill! for args in re!'iult, e.g. t. If t, e. g. and redoes the USE LOG ANTILOG FOR ANTILOG LOG IN -2 AND -1. Substitution is done by esubst, Section 9, and is carried out as described below. USE vars 1 FOR args 1 AND •.. AND vars FOR args n IN t Mor"e general form of USE command. See description of SUbstitution algorithm below. Every USE command involves thr,ee pieces of information: the variables to be substituted, the arguments to be substituted for, and an event specification, which defines the expression (input) in which the substitution takes place. 12 If args are omitted, i.e. the form of the· command is USE vars IN ~, or just USE vars (which is equivalent to USE vars IN -1), and the ·event referred to was itself a USE conunand, the argument's and expression substituted into are the same as for the indicated USE cmnmand. In effect, this USE command is thus a i2------------------------------··---------------------------------------------The USE command is parsed by a small finite state parser to distinguish the variables and arguments. be parsed correctly. Fo." example, USE FOR FOR AND AND AND FOR FOR will 22.14 continuation of the previous USE command. For example, on page 22.7, when the user types (LOG (ANTILOG 4», followed by USE 4.0 40 400 FOR 4, followed by USE -40.0 -4.00007 -19., the latter command is equivalent to USE -40.0 -4.00007 -19. FOR 4 IN -2. If args are omitted and the event referred to was not a USE command, substitution is for the operator in that command, i.e. if a lispx input, the name of the function, if an edit command, the name of the command. For example ARGLIST(FF) followed by USE CALLS is equivalent to USE CALLS FOR ARGLIST. If is omitted, but args are specified, the first member of args is used for ~, e.g. USE PUlO FOR @UlD is equivalent to USE PUlD FOR @UTD IN F @UTO. 13 If ~ the USE command has the same number of expressions as arguments, sUbstitution procedure is straightforward, 14 i.e. the USE X Y FOR U V means substitute X for U and Y for V, and is equivalent to USE X FOR U AND Y FOR V. However. the substituting USE command several also permits expressions for distributive the same substitutions, argument. For i.e. example, USE ABC FOR X means first substitute A for X then substitute B for X (in a new copy of the expression), then substitute C for X. as three separate USE commands. equivalent to The effect is the same Similarly, USE ABC FOR D AND X Y Z FOR W is USE A FOR D AND X FOR W, followed by USE B FOR 0 AND Y FOR W, ia----------------------------------------------------------------------------The F is inserted to handle correctly the case where the first member of is a number. e.g. USE 4.0 4.0 400 FOR 4. Obviously the user means find the event containing a 4 and perform the indicated substitutions, whereas USE 4.0 40 400 FOR 4 IN 4 would mean perform the substitutions in event ar~ number 4. 14 Except when one of the arguments and one of the variables are the same, e.g. USE X Y FOR Y X, or USE X FOR Y AND Y FOR X. This situation is noticed when parsIng the command, and-handled correctly: 22.15 followed by USE C FOR 0 AND Z FOR W. USE ABC FOR 0 AND X FOR y16 corresponds to three substitions, the first with A for 0 and X for Y, also the second with B for 0, and X for Y, and the third with C for 0, and again X for Y. However. error. USE ABC FOR 0 AND X Y FOR Z is ambiguous and will cause an Essentially, the USE cOltDmand operates by proceeding from left to right handling each 'AND' separately. Whenever the number of expressions exceeds the number of expressions available~ the expressions multiply.16 FIX ~ puts the user in the editor looking at a copy of th{1 input( s) for ~, Whenever the user exits via. OK, the result is unread and reexecuted exactly as with REDO. FIX is provided for those cases when the modifications to the input(s) are not of the type that can be specifie!d by USE, i.e. not substitutions. ~(OEFINEQ For example: FOO (LAMBDA (X) (FIXSPELL SPELlINGS2 X 70] INCORRECT DEFINING FORM FOO .. FIX EDIT .p (OEFINEQ FOO (LAMBDA & &» • (LI 2) OK (FOO) .. The user can also specify the edit command(s) to lispx, by typing - followed by the command(s) after the event ~ipecirication, e.g. FIX - (LI 2). In this case, the editor will not type EDIT, or wait for an OK after executing the commands. 16 Thus USE ABC 0 FOR E F metans substitute A for E at the same time as subs ti tuting B for F, then in another copy of the indicated expression, substi tute C for E and 0 for F. Note that this is also equivalent to USE A C FOR E AND 8 0 FOR F. 22.16 Implementation of REDO, USE, and FIX The input portion of an event is' represented internally on the history list simply as a linear 'sequence of the expressions which were read. an input in For example, format is a list Consisting of two expressions, an an input in eval format is a list of just one expression. 17 Thus if the user wishes to ~ convert an input 'in ~ format to eval format, he simply moves the function name inside of the argument list: (F/l (AND (EXPRP X) (PRINT Xl ~MAPC(FOOFNS NIL ~EXPRP(F001) T MAPC EDIT -P (MAPC (FOOFNS -(BO 2) -elI 1) -P «MAPC FOOFNS ~FIX &» &» OK FOOl FIE2 FUM NIL ... By Simply converting the input from two expressions to one expression, the desired effect, that of mapping down the list that was the value of foofns, was achieved. REDO, USE, and FIX all operate by obtaining the input portion of the corresponding event, processing the input (except for REDO), and then storing 17----------------------------------------------------------------------------For inputs in eval format, i.e. single expressions, FIX calls the editor so that the current expression is that input, rather than the list consisting of that input - see the example on the preceding page. However, the entire list is actually being edited. Thus if the user typed t P in that example, he would see «DEFINEQ Foo &». 22.17 it on the history list as thl9 input portion of a new event. command completes operating by simply unreading the input. subsequently 'reread.', The history When the input is the evont which already contains the input will be retrieved and used for recording the value of the operation, saving sideeffects, etc., instead of creating a new event. Otherwise the input is treated exactly the same as if it had been typed in directly. If ~ specifies more than one event, the inputs for the correspondin~ events are simply concatenated into a linear sequence, with special markers representing carriage returns 18 inserted between each input to indicate where new lines start. to by i. inputs The result of this concatenation is then treated as the input referred For example, when the user typed REDO FROM F ([7] on page 22.3) the for the corresponding six events were concatenated to produce (F PUTO 10 (1 MOVD) 10 3 10 (Xnt 2) 10 0 10 (SW 2 3». Similarly, if the user had typed USE @UTO FOR PUTO IN 15 THRU 20, (F PUTO #0 (1 MOVO) 10 3 10 (XTR 2) #0 0 10 (SW 2 3» would have b'ten constructed, and then @UTO substituted for PUTO throughout it. The same convention is used for representing multiple inputs when a USE command involves sequential SUbstitutions. For example, if the user types GETO(FOO) and then USE FIE ,FUM FOR FOO, the input sequence that will be constructed is· (GETO (FIE) #0 GETO (FUM», whic:h is the result of substituting FIE for FOO in (GE TO (FOO» concatenated with the resul t of subs ti tuting FUM for FOO in ( GE TO (FOO». Once such a multiple input is constructed, it is treated exactly the same as a single input, i.e. the input sequence is recorded in a new event, and then 18----------------------------------------------------------------------------The value of (VAG 0) is currently used to represent a carriage return on the grounds that it cannot be typed in by the user, and thus cannot cause ambiguities. 22.18 unread, exactly as described above. When the inputs are 'reread,' the 'pseudo- carriage-returns' lispxread are treated by and readline carriage returns, i.e. they serve to distinguish between exactly ~ as real and eval formats on inputs to lispx, and to delimit line commands to the editor. Note that once this multiple input has been entered as the input portion of a new event, that event can be treated exactly the same as one resulting from type in. In other words, no special checks have to be made when referencing an event, to see if it is simple REDO FROM F, or ([10] multiple. page 22.3) Thus, when the user types REDO does not even notice retrieved from the previous event is(F PUlO 10 input, it simply records this input and unreads it. (SW 2 3» REDO that following the input i.e. a multiple Similarly. when the user then types USE @UlO FOR PUlO on this multiple input, the USE command simply carries out the substitution, and the result is the same as though the user had typed USE @UlO FOR PUlO IN 15 lHRU 20. In sum. this implementation permits ~ to refer to a single simple event, or to several events, or to a single event originally constructed from several events (which may themselves have been multiple input events, etc.) without having to treat each case separately. History Commands Applied to History Commands Since history commands themselves do not appear in the input portion of events (although they are stored elsewhere in the event), they do not interfere with or affect the searching operations of event speCifications. In effect, history conunands are invisible to event specifications. 19 As a result, history conunands themselves cannot be recovered for execution in the normal way. For example, 19----------------------------------------------------------------------------With the exception described below under "History Commands that Fail". 22.19 if the user types USE ABC FOIl D and follows this with USE E FOR 0, he will not produce the effect of USE ABC fOR E (but instead will simply cause E to be substituted for D in the effect, i.e. USE ABC FOR E. last event containing a 0). To produce this the user should type USE D FOR E IN USE. The appearance of the word REDO, USIE or FIX in an event address specifies a search for the corresponding his toru c:onunand. (for example, the user can also type UNDO REDO.) It also specifies that the text of the history command itself be treated as though it were the input. - However, the user must remember that the context historll. in tllhich a histoTII command i.s not the original Icontext. reexecuted is'that of the current For example, if the user types USE FOO FOR FIE IN -1, and then later types REDO USE, the -1 will refer t'o the event before the REDO, not bofore the USE. Similarly, if the user types REDO REDO followed by REDO REDO, he would cause an infinite loop, except for the fact that a special check detects this type of situation. History Commands that fail The one exception to the statement that 'history commands are invisible to event specifications' occurs whelll a history command fails to produce any input. For example, causing lisp~ suppose the user types USE LOG FOR ANTILOG AND ANTILOG FOR lOGG, to respond LOGG 7. Since the USE command did not produce any input, the user can repair it by typing USE LOG FOR LOGG (i.e. does not have ,to specify IN USE). This latter USE command will invoke a search for LOGG, which will find the bad USE command. Jispx then performs the indicated substitution, and unreads USE lOG FOR ANTILOG AND ANTILOG FOR lOG. In turn, this USE command invokes a search for ANTILOG, which, because it wa.s not tllped in but reread. ignores the bad USE command which was found by the earlier search for LOGG, and which is still on the history to li~it. In other words, historll conunands that fail produce input are visible to searches ari.sing from event .specification.s typed in by the u.ser. but not to .secondarll event specification.s. 22.20 In addition, if the most recent event is a history conunand which failed to produce input, a secondary event specification will effectively back up the history list one event so that relative event specification will not count the bad history conunand. user types numbers for that event For example, suppose the USE lOG FOR ANTILOG AND ANTILOG FOR lOGG IN -2 AND -1, and after lispx types lOGG 1, the user types USE lOG FOR lOGG. He thus causes the command USE LOG FOR ANTILOG AND ANTILOG FOR lOG IN -2 AND -1 unread. to be constructed and In the normal case, -1 would refer to the last event, i.e. the 'bad' USE command, and -2 to the event before 1t. However, in this case, -1 refers to the event before the bad USE command, and the -2 to the event before that. In short, the caveat that "the user must remember that the context in which a h is tory conunand is reexe,cuted is that of the ~urrent history. not the original context" does not apply if the correction is performed immediately. More History Conunands RETRY t. similar to REDO except sets helpclock so that any errors' that occur while executing t. will cause breaks. ... vars similar to USE except substitutes for the (first) operand. For example, EXPRP(FOO) followed by ••• FIE FUM is equivalent to USE FIE FUM FOR Foo. See also event 52 on page 22.9. 17 t. prints history list. If t. the entire history list, recent events. Otherwise events specified in t. specified), e.g. 11 -1, 11 is omi tted, 77 prints beginning with most 11 prints only those (and in the order 10 THRU 15, etc. 71 commands are not entered on the history list, and so do not affect relative event numbers. In other words, an event specification of -1 typed following a 17 command will refer to the event immediately preceding the 11 command. 22.21 11 will print the history command, if any, associated with each event as shown at [9] on page 22.3 and page Note that these history conunands are not preceded by prompt characters, indicating they are not stored as input. 20 2~~.7. 11 prints multiple input events under one event number (see page 22.7). Since events are initially stored on the history list with their value field equal to bell (control-G), if an operation fails to complete for any reason, e.g. causes an error, is aborted, etc., its 'value' will be bell. This is the explanation for the blank line in event 2, page 22.7, and event 50, page 22.9. 17 is implemented via the function printhistory, page 22.60, which can also be called directly by the user. * UNDO undoes the side effects of the specified events. For each event undone, UNDO prints a message: e.g. RPLACA UNDONE, REDO UNDONE etc. If nothing is undone because nothing was saved, UNDO types NOTHING SAVED. If nothing was undone because the event(s) were already undone, UNDO types ALREADY UNDONE. If t is empty, UNDO searches back for the last event that contained side effects, was not undone, and itself was not an UNDO ~ 20----------------------------------------------------------------------------REDO, RETRY, USE, ... , and FIX commands, i.e. those commands that reexecute previous events, are not stored as inputs, because the input portion for these events are the expres.sions to be 'reread'. The history commands UNDO, NAME RETRIEVE, BEFORE, and AFTER are recorded as inputs, and 11 prints them exactly as they were typed. t 2Z.2Z conunand.21 22 UNDO t. For EaCh. xi refers to a message printed by DWIM in the event(s) specified by~. The side effects of the corresponding DWIM corrections, and only those side effects, are undone. example, if the message PRINTT [IN FOO] -) PRINT UNDO : PRINTT or UNDO: PRINT would undo the correction. 23 were printed, • • is a special form of the USE conunand for conveniently specifying character $ substitutions. In addition, it has a number of useful default options in connection with events that involve errors. :& x FOR y equivalent to USE Ix$ FOR $y$ For example, the user types MOVD(FOO FOOSAVE T), he can then type S FIE FOR FOO to perform MOVD(FIE FIESAVE T). Note that USE FIE FOR FOO would perform MOVD(FIE FOOSAVE T). 21----------------------------------------------------------------------------Note that the user can undo UNDO commands themselves by specifying the corresponding event address, e.g. 22 UNDO -3 or UNDO UNDO~ UNDOing events in· the reverse order from which they were executed is guaranteed to restore all pointers correctly, e.g. to undo all effects of last five events, perform UNDO THRU -5, not UNDO FROM -5. Undoing out of order may have unforseen effects if the operations are dependent. For example, if the user performed (NCONC1 FOO FIE), followed by (NCONCI FOO FUM), and then undoes the (NCONC1 FOO FIE), he will also have undone the (NCONC 1 FOO FUM). I f he then undoes the (NCONC 1 FOO FUM), he will cause the FIE to reappear, by virtue of restoring FOO to its state before the execution of (NCONCI FOO FUM). For more details, see page 22.42. 23 Some portions of the messages printed by DWIM are strings, e.g. the message FOO UNSAVED is printed by printing FOO and then " UNSAVED". Therefore, if the user types UNDO : UNSAVED, the DWIM correction will not be found. He should ins teadtype UNDO :FOO or UNDO : SUNSAVEDS (al t-modeUNSAVEDal tmode, see R command in editor. section 9). ZZ.Z3 An abbreviated form of , is available: $ y x 'x FOR y, sarne as can also $ y -) i.e. yls are changed to be written as $ y TO x, $ Y = x, or x. does event location the sarne as the USE command, $ XiS. i.e. if IN -- is not specified, it searches for l.24 After $ .. finds the event, it llooks. to see if an error was involved in that event,25 and if the indicated 4::haracter substitution can be performed in the offender. If so, , assumes the substitution refers to the offender, performs the substitution, and then substitutes the result for the offender throughout. For example. the ·user types U.S.A. FOOOVARS error message. (PRETTYOEF FOOFNS IFOO FOOVARS) causing a The user can now type S 00 0, which will change FOOOVARS to FOOVARS. but not change FOOFNS or FOO. If an error did occur in the specified event, the user can also omit specifying in which case the offender is used. ~, above example Thus, the user could have corrected the by simply typing S FOOVARS. 8imilarly, if the user types LOAD(PRSTRUC PROP), causing the error FILE NOT FOUND PRSTRUC, he can request the file to be loaded from esubst is used (R PRSTRUC . can now type protection. in an indefinite number of lines of input, The user under errorset The input lines are saved and unread when the user exits the type- ahead loop with the conunand SGO (alt-modeGO). While in the type-ahead loop, 11 can be used to print the type·-ahead. FIX to edi t the type-ahead, and SQ to erase the last input (may be used repeatedly). 22.28 For example: "'TYPE-AHEAD )SYSOUT(TEM) )MAKEFILE(EDIT) )BRECOMPILE«EDIT WEOIT» )F )$Q \\F )$Q \\BRECOMPILE )LOAD(WEDIT PROP) )BRECOMPILE«EDIT WEOIT» )F )MAKEFILE(BREAK) )LISTFILES(EDIT BREAK) >SYSOUT(CURRENT) >LOGOUT] >11 )SYSOUT(TEM) )MAKEFILE(EOIT) )LOAD(WEOITPROP) )BRECOMPILE«EDIT WEOIT» )F . 29 . )MAKEFILE(BREAK) )LISTFILES(EOIT BREAK) )SYSOUT(CURRENT) )LOGOUT] )FIX EDIT *(R BRECOMPILE BCOMPL) *p «LOGOUT) (SYSOUT &) (LISTFILES &) (HAKEFILE &) (F) (BCOHPL &) (LOAD &) (HAKEfIlE &) (SYSOUT&» *(OElETE LOAD) ·OK )SGO The TYPE-AHEAD conunand may be aborted by SSTOP; control-E simply aborts the current line of input. 29----------------------------------------------------------------------------Note that type-ahead can be addressed to the compiler, since it uses lispxread for input. Type-ahead can also be directed to the editor, but type-ahead to the editor and to .lispxcannot be intermixed. 22.29 SBUFS (alt-modeBUFS) Whenever an error occurs 1n * * * is a command for recovering the input buffers. e~:ecuting a lispx input or edit command, or a control-E or control-D 1s typed, the input buffers are saved and cleared. The SBUFS command is used to restore the input buffers, i.e. its effect is exactly the same as though the user had retyped what was 'lost.' For example: *(-2 (SETQ X (COND «NULL Z) (CONS (user typed control-E) *p (COND (& &) (T Be» *2 *SBUFS (-2 (SETQ X (COND «NULL Z) (CONS and user can now finish typing the (-2 .. ) conunand. Note: the type-ahead does not have to have been seen by INTERLISP, i.e., echoed, since the system buffer is also saved. Input buffers are not saved on the history list, but on a free variable. Thus, only the contents of the input buffer as of the last clearbuf can ever be recovered. However, input buffers cleared at evalgt are saved independently from those cleared by break or the editor. The procedure followed when the user types SBUFS is to recover first from the local buffer, otherwise from the top level buffer. 30 Thus the user can lose input in the editor, go back to evalgt. lose input there. then go back into the editor, recover the editor'S 30---------------------------------------------------------------------------The local buffer is stored on lispxbufs; the top level buffer on to~l is~)U fs. The forms of both buffers are (CONS (LINBUF) (SYSBUF» (see Section 14). Recovery of a buffer is destructive, i.e. SBUFS sets the corresponding variable to NIL. If the user types SBUFS when both lispxbufs and toplispxbufs are NIL, the message NOTHING SAVED is typed, and an error generated. 22.30 buffer, etc. Furthermore, a buffer cleared at the top can be recovered in a break, and vice versa. * * The following four corrunands, DO, !F. !E, and !N, are only recognized in the editor: 00 com allows the user to supply the command name when it was omitted. (USE is used when a command name is incorrect). For example, suppose the user wants to perform (-2 (SETQ X (LIST Y Z») but instead types just (SETQ X (LIST Y Z». The editor will type SETQ 1, whereupon the user can type 00 -2. The effect is the same as though the user had typed FIX, followed by (LI 1), (-1 -2). and OK, i • e. the command (-2 (SETQ X (LIST Y Z») is executed. 00 also works if the last command is a line command. !F same as 00 F. In the case of IF, the previous command is always treated as though it were a line command, e.g. if the user types (SETQ X &) and then !F, the effect is the same as though he had typed F (SETQ X &), not (F (SETQ X &». !E same as DO E. Note !E works correctly 'commands' typed in eval or ~ format. !N same as 00 N. 22.31 for • control-U • when typed in at any point during an input being read by lispxread, permits the user to edit the input before it is returned to the calling function. This feature is useful for correcting mistakes noticed in typing be/ore the input is executed, instead of waiting till after execution and then performing an UNDO and a FIX. For example t if the user types (OEFINEQ (FOO (lAMBDA (X) (FIXSPEll X and at that point notices the missing left parenthesis, instead of cClmpleting the input and allowing the error to occur, and then fixing the input, he can simply type control-U,31 finish typing normally, whereupon the editor is called on (FOO (LAMBDA (X) (FIXSPElLX -- 1, which the user can then repair, e.g. by typing ell 1). If the user exits from the edi tor via OK, the (corrected) expression will be returned to whoever called lispxread exactly as though it had been typed. 32 If the user exits via STOP, the expression is returned so that it can be stored on the history list. However it wi 11 not be executed. In other words, the effect is the same as though the user had typed control-E at exactly the right instant. ai-----------------------------Control-U can be typed at clOy q point, even in the middle of an atom; it simply sets an internal flag checked by lispxread. --------------------- ------------------------- 82 Control-U also works for calls to readline, i.e., for line commands. 22.32 * * * is an nlambda function for obtaining the value 95 a particular event, e.g. (VAlUEOF -1), (VAlUEOF ~FOO -2). valueof The value of an event consisting of several operations is a list of the values for each of the individual operations. Note: the value field of a historll entrll is initialized to bell (control-G). Thus a value oj bell indicates that the corresponding operation did not complete. i.e. was aborted or caused an error (or else returned bell). *- prompt#flg * is a flag which when set to T causes the current event number to be printed before each ~,: and * prompt characters. See description of promptchar, page 22.51. promptlflg is initially NIL. * archivefn allows the user to automatically archived. specify events to be When archivefn is set" to T, and an event is about to drop off the end of the history list and be forgotten, archivefn is called giving it as its first argumen~ the input portion of the event p and as its second argument, the entire 88----------------------------------------------------------------------------Al though the input for valueof is entered on the history list before valueof is called, valueof[-l] immediately before the valueof history list up one entry Similarly. (VAlUEOF FOO) will contains a FOO. still refers to the value of the expression input, because valueof effectively backs the when it retrieves the specified event. find the first event before this one that 22.33 event. 34 If archivefn returns T, the event is archived. users like to keep a record e)f all calls to load. (LAMBDA (X Y) (EQ (CAR X) (QUOTE LOAD») archivefn must be will both set and defined. some Defining archivefn as: accomplish archivefn For example, is this. Note initially that NIL and undefined. • lispxmacros • • provides a macro facility for lispx. lispxmacros allows the user to diefine his own lispx commands. elements of the form (command def). It is a list of Whenever command appears as the first expression on a line in a lispx input, the variable lispxline is bound to the rest of the evaluated. line, the event :l.s recorded on the history list, and def is Similarly. whenever command appears as car of a form in a lispx input. the variable lispxline is bound to cdr of the form, the event recorded, and def is evaluated. (See page 22.60 for an example of a RETRIEVE, BEFORE, and AFTER are implemented as lispxmacros. SNDMSG, TECO, and EXEC are subsys (section 21), Finally, DIRECTORY SY and DIR commands lisp~nacros lispxmacro). In addition, LISP, which perform the corresponding calls to and CONTIN is a lispxmacro which performs (SUBSYS T). are lispxrnacros which respectively. OIR can perform the be given EXEC, SYSTAT, arguments, and e.g~, DIR *.SAV;*. 84------------------------------··---------------------------------------------In case archivefn needs tOI examine the value of the event, its side effects, lists. etc. See page 22.44 for discussion of the format of history 22.34 * * lispxuserfn * provides a way for a user function to process selected inputs. When ~xlJserfn i.s set to T, it is applied 36 to all inputs not recognized as one of the commands described above. If lispxuserfn decides to handle this input, it simply processes it (the event was already stored on the history list before lispxuserfn was called), sets returns T. store lis.~ lispxvalue lisp~value to the value for the event, and will then know not to call eval or into the value slot for the ~, event, lispxuserfn returns NIL, lispx proceeds by calling eval or way. and will Simply and print ~ it. If in the usual Thus by appropriately defining (and setting) lispxuserfn, the user can with a minimum of effort incorporate the features of the programmer's assistant into his own executive (actually it is the other way around). 35----------------------------------------------------------------------------Like archivefn, lispxuserfn must be both set and defined. 22.35 The following output illustrates such a coupling. 36 **SETQ(ALTFORH (HAPCONC NA50IC (f/L (GETP X 'ALTFORH5] =NASOICT (AL26 BE7 C056 C057 C060 C13 H3 MN54 NA22 5C46 534 T144) **(GIVEMELINE5CONTAININGC08ALT) . CITATION SAMPLE PHASE CONSTIT. CONTENT UNIT 510002 OVERALL C056 40.0 OPH/KG 070-237 C13 8.8 070-228 DEL DPH/KG H3 314.0 HN54 28 [1] **GETP(COBALT ALTFORHS) (C056 C057 C060 C13 H3 MN54 NA22 5C46 534 T144) **UNOO MAPCONC SETQ UNDONE. **REOOGETP (C056 C057 C060) **REOO COBALT SAMPLE PHASE CONSTIT. CONTENT UNIT 510002 OVERALL C057 40.0 DPM/KG S10003 OVERALL CO 15.0 14.1 C056 43.0 DPM/KG 43.0 C057 C060 1.0 **USE MANGANESE FOR COBALT [3] [2 ] TAG 0 0 [4] [5] [6] CITATION 070-237 070-203 070-216 070-237 070-241 TAG 0 0 0 0 The user is running under his o'm executive program which accepts requests in the form of sentences, which it first parses and then executes. The user first 'innocently' computes a list of all ALTERNATIVE-FORMS for the elements in his system [1]. He then inputs a request in sentence format [2] expecting to see under the column CONSTIT. only cobalt, CO, or its alternate forms, C056, C057, or C060. Seeing C13. H3, and f1N54 , he aborts the output, and checks the property ALTFORH5 for COBALT [3]. The appearance of C13, H3, MN54, he aborts the output, and checks the property ALTFORHS for COBALT [3]. The appearance of C13, H3. MN54 et aI, remind him that the mapconc is destructive, and that in the process of making a list of the ALTFORMS. he has inadvertently· strung them all together. Recovering from this situation would require him to individually i~----------------------------------------------------------------------------- The output is from the Lunar Sciences Natural Language Information System being developed for the NASA Manned Spacecraft Center by William A. Woods of Bolt Beranek and Newman Inc., Cambridge, Mass. 22.36 examine and correct the ALTFORMs for each element in his dictionary. a tedious process. ALTFORM Instead, he can simply UNDO HAPCONC, [4] check has continue. been corrected [5], to make sure the then redo his original request [6] and The UNDO is possible because the first input was executed by lispx; the (GIVE ME LINES CONTAINING COBALT) is possible because the user defined lispxuserfn appropriately; and the REDO-and USE are possible because the (GIVE ME LINES CONTAINING COBALT) was stored on the history list before it was transmitted to lispxuserfn and the user's parsing program. lispxuserfn is a function of two arguments, ~ and line, where x is the first expression typed, and line the rest of the line, as read by readline (see page 22.47). For example, if the user types FOO(A B C), if the user types (FOO A B C), types FOO ABC, ~:FOO and line=«A Be»; ~=FOO, ABC), and line=NILj and if the user ~=(FOO and line=(A B C). Thus in the above example, lispxuserfn would be defined as: [LAMBDA (X LINE) (COND «AND (NULL LINE) (lISTP X» (SETQ LISPXVAlUE (PARSE X» T] Note that since lispxuserfn 1s called for each input (except for p.a. commands). it can also be used to monitor some condition or gather statistics. * * In addition to saving inputs and values, lispx saves most system ,messages on the history list, e.g. FILE CREATED --, (fn REDEFINED), (var RESET), output of TIME, BREAKDOWN, STORAGE, DWIM messages, event, this functions output 1s replicated. lispxpr1nt, lispxprinl, etc. When printhistory prints This facility is lispxpr1n2, 22.37 implemented via 11spxspaces, 11spxterpri, the the and lispxtab. 37 In addition to performing the corresponding output operation, these functions store an appropriate expression on the history event under the property LISPXPRINT. 88 This expression is used by printhistory to reproduce the output. • * * In addition to the above features. lispx checks to see if car or cdr of NIL o~ car of T have been clobbered, B.nd if so, restores them and prints a message. Lispx also performs spelling corrections using lispxcoms, a list of its commands, as a spelling list whenever it is given an unbound atom or undefined function, i.e. before attempting to evaluate the input. 89 22 .. 6 Undoing The UNDO capability of the proglrammer's assistant 1s implemented by requiring that each operation that is to be undoable be responsible itself for saving on the history list enough information to enable .reversal of its side effects. other words. the assistant does not destructive operation, i.e. I In know' when it is about to perform a it is not constantly checking or anticipating. Instead, it simply executes operations, and any undoable changes that occur are 87------------------------------'-------~--------------------------------------- In fact, all six of these functions have the same definition. When called, this function looks back on the stack to see what name it was called by, and determines what to do. Thus, if the user wanted to make any other output function, e.g. printdef, record its HOVD(LISPXPRINT LISPXPRINTOEF), and then use lispxpr1ntde[ for printdef. (This will work only for functions of three or fewer arguments.) 38 unless lispxprintflg is NIL. 39 lisp2S is also responslblefor rebinding helpclock, used by breakcheck, Section 16, for computing the amount of time spent in a computation, in order to determine whether to go into a break if and when an error occurs. 22.38 automatically saved· on the history list by the responsible function. 40 The operation of UNDOing, which involves recovering the saved information and performing the corresponding inverses, works the same way, so that the user can UNDO an UNDO, and UNDO that etc. At each point, until the user specifically requests an operation to be undone, the assistant does not know, or care, whether information has been saved to enable the undoing. Only when the user attempts to undo an operation does the ass is tant check to see whether any 'information has been saved. I f none has been saved, and the user has specifically named the event he wants undone, the assistant types NOTHING SAVED. (When the user simply types UNDO, the assistant searches for the last undoable event, ingnoring events already undone as well as UNDO operations themselves.) This implementation minimizes the overhead for undoing. Only those operations wh ich actually make changes are affected, and the overhead 1s small: two or three cells of storage for saving the information, and an extra function call. However, even this small price may be too expensive if the operation is sufficiently primitive and repetitive, i.e. if the extra overhead may seriously degrade the overall performance of the program. 41 Hence not every destructive operation in a program should necessarily be undoable; the progranuner must be allowed to decide each case individ~ally. 40---------------------------------------------------------------------------When the number of changes that have been saved exceeds the value of #undosaves (initially set to 50), the user is asked if he wants to continue savin9lthe undo information for this event. The purpose of this feature is to· avoid tying up large Quantities of storage for operations that will never need to be undone. The interaction is handled by the same routines used by DWIM, so that the input buffers are first saved and cleared, the message typed, then the system waits dwimwait secon~s. and if there is no response, assumes the default answer. which in this case 1s NO. Finally the input buffers are restored. See page 22.56 for details. 41 The rest of the discussion applies only to lispx; the editor handles undoing itself 1n a slightly different fashion. as described on page 22.61. 22.39 Therefore for each primi tive dC3structive operation, we have implemented two separate functions, one which always saves information, i.e. is always undoable, and one which does n01~. e.g. Irplaca and rplaca, Iput and ru!!.42 In the various system packages, the appropriate function is used. For example, break uses Iputd and Iremprop so as to be undoable. and OWl" uses Irplaca and Irplacd, when it makes a correction. 43 Similarly the user can simply use the corresponding I function if he wants to make a destructive operation in his own program undoable. When the I function is called, it will save the undo information in the current event on the history list. However, all operations that are tuped in to lispx are made undoable, simply by subs ti tuting the corresponding I funct'ion 44 for any destructive function through-out the input. 46 For example, on page 22.8, when the user typed (MAPCONC NASOIC (F/L ... » evaluated. it was (/MAPCONC NASOIC (F/L •.• » that was Since the system cannot know whether efficiency and overhead are serious considerations for the execution of an expression in a user program, the user must decide, e.g. call Imapconc if he wants the operation undoable. 42------------------------------'----------------------------------------------The 'slash' functions eUI~rently implemented are laddprop, lattach, Idreverse, /dsubs~. Ileone, Imapeon, Imapcone, Imovd, Inconc, /put, Iputd, Iputdg, Iputhash, Iremprop, Irplaca, Irplacd, /set, /seta, /setd, and Itcone. Note that Isetq and /setqq are not included. If the user wants a set operatlon undoable in his program, he must see /set, or /rplaca. /dre!!l~:Y.~' /~c~~£!, 48 44 45 The effects of the following functions are always undoable (regardless of whether or not they are typ1ed in): define, defineq, defc (used to give a function a compi led code defini tion), deflist. load, savedef, unsavedef, broilk. unbreak, rebreak, trill, breakin, unbreak.Til""; changename, edi tfns, editf, editv, editp. edite, ~~ditl, esubst, advise, unadvise, readvise, plus any changes caused by DWIM. Since there is no Isetq, set~s appearing in type-in are handled specially by substituting a call to sa,.Y!!,.et, page 22.43. The subs ti tution is performc!d by the function lispx/, described on page 22.58. 22.40 However, expressions that are typed-in rarely involve iterations or lengthy computations directlu. Therefore~ if all primitive destructive functions that are immediately contained in a type-in are made undoable, there will rarely be a significant loss of efficiency. eva lua ting it. Thus lispx scans all user input before and subs ti tutes the corresponding undoable function primitive destructive functions. for all Obviously with a more sophisticated analysis of both user input and user programs, the decision concerning which operations to make undoable could be better advised. However, we configuration described here to be a very satisfactory one. have found the The user pays a very small price for being able to undo what he 'types in, and if he wishes to protect himself from malfunctioning in his own programs, he can have his program specifically call undoable functions, or go into testmode as described next. Testmode Because of efficiency considerations, the user may not want certain functions undoable after his program becomes operational. However, while debugging he may find it desirable to protect himself against a program running wild, by making primitive destructive operations undoable. The function testmode provides this capability by temporarily making everything undoable. testmode[flg] testmode[ld redefines all primitive destructive functions with their corresponding undoable versions and sets testmodeflg to T. testmode[ ] restores the oriij~al defini tions, and sets testmodeflg to NIL. ---------------------------------~~------~---------~--------~--------~--------46 i.e. the 'slash' functions; see footnote on page 22.40. 47 testmode will have no effect on compiled mapconc's, since they compile open with frplacd's. 22.41 Note that setq' s are not undoab]le, even in testmode. To make the corresponding operation undoable in testmode, set or rplaca should be used. Undoing Out of Order Irplaca and Irplacd operate by saving the pointer that is to be changed and its original contents (i.e. Irplac,~ Irplaca and Irplacd simply (RPLACA Faa saves £!!: and Irplacd saves cdr). re~.tores the pointer. Thus, Undoing if the user types 1), followed by (RPLACA FOO Z), then undoes both events by undoing the most recent event first, then undoing the older event, FOO will be restored to its s ta te before either lli.aca operated. However if the user undoes the first event, then the second event, (CAR FOO) will be 1, since this is what was in car of FOO before (RPlACA FOO Z) was executed. Similarly, if the user performs' (NCONCI FOO 1) then (NCONC1 Foo 2), undoing just (NCONCI FOO 1) will remove both 1 and 2 from FOO. The problem in both cases is that the two operations are not 'independent.' In general, operations are always independent if they affect different list:; or different sublists of the same list. 48 Undoing in reverse order of execution, or undoing independent operations, is always guaranteed to do the 'right' thing. However, undoing dependent operations out of order may not always have the predicted effect. 48----------------------------------------------------------------------------Property list operations, (i.e. put, addprop and remprop) are handled spec ia lly so that they are always independent, even when they affect the same property list. for example, if the user types PUT(FOO FIEI FUMl) then PUT(FOO FIE2 FUM2), then undoes the first event, the FIEZ property will remain, even though COR(FOO) may have been NIL at the time the first event was executed. 22.42 Saveset Sctq's are made undoable on type in by substituting a cal~ to savesct (described in detail on page 22.55), whenever setq is the name of the function to be appl ied, or car of the form to be evaluated. In addition to saving enough information on the history list to enable undoing, saveset operates in a manner analogous to savedef when it resets a top level value, i.e. when it changes a top level binding from a value other than NOBINO to a new value that is not equa! to the old one. In this case, saveset saves the old value of the variable being set on the variable's property list under the property VALUE, and prints the message (variable RESET). The old value can be restored via the function unset,49 which also saves the current value (but does not print a message). ~ and Thus unset can be used to flip back and forth between two values. ~ are implemented via calls to·saveset. Thus old values will be saved and messages printed for any variables that are reset as the result of l~ading a file. 60 Calls to set and ill.qg, appearing in type in are also converted to appropriate calls to saveset. For top level variables. saveset also adds the variable to the appropriate spelling list, thereby noticing variables set in files via ~ or rpaqq, as well as those set via type in. ~~---------------------~------------------------------------------------------- Of course, UNDO can be used as long as the event containing this call to saveset is still active. Note however that the old value will remain on thEt-property list, and therefore be recoverable via unset, even after the original event has been forgotten. 50 To complete the analogy with define, saveset will not save old values on property lists if dfnflg=T, e.g. when load is called with second argument T, (however. the call to saveset will still be undoable,) and when dfnflg=ALLPROP, the value is stored directly on the property list under property VALUE (the latter applies only to calls from ~ and ~). 22.43 22.7 Format and Use of the History List There are currently two histolry lists, lispxhistory and edithistory. Both history lists have the same format, and in fact, each use the same function, historysave, for recording implementing conunands events, that refer and to the the same history set list, of functions e.g. for historyfind, printhistory, undosave, etc. 61 Each history list is a list of the form (! eventl size mod), where! 15 the list of events with the most recent event first, event# is the event number for the mos t recent event on !, maximum length of on page is the size of the time-slice, i. e. the !. and mod is the highest possible event number (see footnote 22.8) . (NIL 0 30 100). ~iize lispxhistory and edithistory are both initialized to Setting lispxhistory or edithistory to NIL is permitted, and simply disables all history features, i.e. lispxhistory and edithistory act like flags as well as repositories of events. Each individual event on ! is a list of the form (input id value • props), where input is the input sequence for the event, as described on page 22.17-19, id the prompt character, e.g. ~, :, .,62 and value is the value of the event, and is initialized to bell. 68 51----------------------------------------------------------------------------A third history list, archivelst, is used when events are archived, as described on page 22.27. It too uses the same format. 62 id is one of the arguments to lispx and to historysave. A user can call 1 ispx gi vi ng it any prompt character he wishes (except for It, since in certain cases, lispx must use the value of id to tell whether or not it was called from the editor.) For example, on page 22.36, the user's prompt, character was **. 53 On edithistory. conunand. this field is used to save the side effects of each 22.44 I!..ro~ is a property list, i.e. of the form (property value property value --). props can be used to associate arbitrary information with a particular event. Currently, the properties SIDE, GROUP, ERROR, and lISPXPRINT are being used. the side effects of the event. undolispx, page 22.58). The HISTORY, PRINT, USE-ARGS, ••• ARGS, The value of property SIDE is a list of (See discussion of undosave, page 22.56, and HISTORY and GROUP properties commands that reexecute previous events, i.e. REDO, RETRY, USE, are ... , used for and FIX. The value of the HISTORY property is the history command itself, i.e. what the user actually typed, e.g. printing the event. REDO FROM F, and is used by the 11 command for The value of the property PRINT is also for use by the 11 command. when special formatting is required, for example, in printing events corresponding to the break commands OK, GO, EVAl, and 1=_ USE-ARGS and •.• ARGS are used to save the arguments and expression for the corresponding history command. ERROR is used by the $ command. lISPXPRINT is used to record calls to lispxprint, lispxprinl. et aI, See page 22.37. When lispx is given an input, it calls historysave to record the input in a new event. 54 Normally, historysave returns as its value cddr of the new event, i.e. car of its value is the value field of the event. lispx binds lispxhist to the value of historysave, so that when the operation has completed, lispx knows where to store the value, namely in £!r of lispxhist. 65 lispxhist also provides access to functions the property list for the current event. are all implemented to call undosave, For example, which simply the adds I the corresponding information to lispxhist under the property SIDE, or if there is no property SIDE, creates one, and then adds the information. 66 Note that by the time it completes, the operation may no longer correspond to the most recent event on the history list. For example, all inputs typed to a lower break will appear later on the history list. 22.45 After binding lispxhist, lispx the input, stores its value in car of ex~cutes lispxhist, prints the value, and returns. When the input is a REOO, RETRY, USE, •.• , or FIX command, the procedure is similar, except that the event is also given a GROUP property, initially NIL, and a HISTORY property, and lis~ simply un reads the input and returns. When the input is 'reread', it is historysave, not lispx, that notices this fact, and finds the event from which the input originally came. 66 historysave then adds a new (value . props) ent.ry to the GROUP property for this event, and returns this entry as the 'new (.vent. I lispx then proceeds exactly as when its input was typed directly, i.e. it binds lispxhist to the value of historysave, executes the input. stores the value in car of lispxhist. prints the value, and returns. input, In fact, lispx never notices whether it is working on freshly typed or input that was reread. Similarly, undosave will store undo information on lispxhist under the property SlOE the same as always, and does not know or care that lispxhi:st is not the entire event, but one of the elements of the GROUP property. Thus when the event is finished, its entry will look like: (input id value HISTORY command GROUP «value1 SIDE side1) (value2 SIDE side2) ... ) ) 67 This implementation removes the burden from the function calling historysave of distinguishing between new input and·reexecution of input whose history entry 60------------------------------··--------------------------------------------If t-istory~_ave cannot find the event, for example if ,a user program unreads the input directly, and not via a history command, historysave proceeds as though the input were typed. 67 In this case, the value field is not being used; valueof instead collects each of the values from the GROUP property, i.e. returns mapcar[get[event;GROUP];CAR]. Similarly, undo operates by collecting the SIDE properties from each of the elements of the GROUP property. and then undoing them in reverse order. 22.46 has already been set up.68 22.8 lispx and readline lispx is called with the first expression typed on a line as its first argument, lispxx. If this is not a list, lispx olwollS does a readline, and treats lispxx plus, the line as the input for the event, and stores it accordingly on the history list. 69 Then it decides what to do with the input. i.e. if it is not recognized as a command, a lispxmacro, or is processed by lispxuserfn, call eval or apply.60 readline normally is terminated either by (1) a carriage return that is not preceeded by a space, or (2) a list that is terminated by a ], or (3) an unmatched ) or ], which is not included in the line. However, when called from lispx, readline operates differently in two respects: (1) If the line consists of a single ) or ], readlinereturns (NIL) instead of NIL, i.e. the) or lis included in the line. This permits the user to type FOO) or Foo], meaning call the function' FOO with no arguments, as opposed to FOO) (FOOcarriage-return). meaning evaluate the variable FOO. (2) If the first expression on the line is a list that is not preceded by 58----------------------------------------------------------------------------Although we have not yet done so, this implementation, i.e. keeping the various 'sub-events' separate with respect to values and properties, also permits constructing commands for operating on just one of the sub-events. 69 If lispxx is a list car of which is LAMBDA or NLAMBDA, lispxrcad to obtain the arguments. 60 If the input consists of one expression, eval is called; if two, apply; if more than two, the entire line is treated as a single form and eval is called. 22.47 lispx calls any spaces, the list terminates the line regardless of whether or not it is terminated by]. This permits the user to type EDITF(FOO) as a single input. Note that if any spaces are inserted between the atom and the left parentheses or . bracket, readl ine will assume that the list does not terminate the line. This is to enable the user to type a line command such as USE (FOO) FOR FOO. In this case, a carriage return wtll be typed after (FOO) followed by" described in Section 14. It as Thererore, if the user accidentially puts an extra space between a function and its arguments, he will have to complete the input with another carriage return. e.g .. .. EOITF_(FOO) •••.> EDI'T * 22.9 Functions lispx[ lispxx; lispxid; lispxxmacro!;; lispxxuserfn ]81 lispx is like eval/~. It carries out a single computation, and returns its value. The first argument, lispxx is the result of a single call to lispxread. lispx will call readline, if necessary as described on page 22.47. lispx prints the value of the computation, as well as saving the 61------------------------------.. ---------------------------------------------lispxid corresponds to id on page 22.44. Lispx also has a fifth argument, lispxflg, which is used by the E command in the editor. 22.48 input and value on lispxhistory.62 If lispxx is a history command, lispx executes the command, and returns bell as its value. If the value of the fourth argument, lispxxmacros, is not NIL, it is used as the lispx macros, otherwise the top level value of lispxmacros is used. If the lispxxuserfn, lispxuserfn. value is not of the NIL, fifth . it is argument, used as In this case, it is not necessary to both set and define lispxuserfn as described on page 22.35. The overhead for a call to lispx is approximately 17 milliseconds, of which 12 milliseconds are spent in maintaining the spelling lists. In INTERLISP, the user pays 17 more milliseconds for each eval or other words, in ~ input over a conventional LISP executive, in order to enable the features described in this chapter. userexec[lispxid;lispxxmacros;lispxxuserfn] repeatedly calls lispx under errorset protection specifying lispxxmacros and lispxxuserfn, and using lispxid (or .. if lispxid=NIL) as a prompt character. Userexec is exited via the lispxmacro OK, or else with a retfrom. 62----------------------------------------------------------------------------Note that the history is not one of the arguments to lispx, i.e. the editor must bind (reset) lispxhistory to edithistory before calling lispx to carry out a history command. . Lispx will continue to operate as an eval/~ function if lispxhistory is NIL. Only those functions and commands that involve the history list will be affected. 22.49 lispxread[file] is a generalized read. per"forms value. call read[ file], If readbuf=NIL, lispxread which it returns as its ( I f the user types control-U during the to read, lispxread calls the editor and returns the edited value.) If readbuf is not NIL, lispxread 'reads' the next expression on readbuf, i.e. essentially returns (PROGl (CAR READBUF) (SETQ READBUF (CDR READBUF»).63 readline, reading. described in Section 14, also uses this generalized notion of When readbuf is not 'UL, readline 'reads' expressions from readbuf until it e1 ther reaches the end of readbuf, or until it reads a (VAG 0). both cases, it returns a list of the expressions it has 'read'. In (The (VAG 0) is not included in the list.) When readbuf is not NIL, both lispxread and readline actually obtain their input by performing (APPLY* set to READ. LISI~XREADFN FILE), where lispxreadfn is initially Thus. if the user' wants lispx, the editor, break, et al to do their reading via a different input function, e.g. uread, he simply sets lispxreadfn to the name of that function (or an appropriate LAMBDA expression). lispxreadp[ fIg] is a generalized readp. If f~=T, lispxreadp returns T if there is any input waiting to be 'read', a la lispxread. If f!.g=NIL, lispxreaQQ returns T only if there is any input waiting to be 'read' on thts ltne. In both cases, leading spaces 63--~~~~~~--~~~~--~;;~~~:~;;;~~~~;--;;~~;~;:--;;--;;~;;;;~~;~--b;--(VAG-O):--;;; ignored, i.e. skipped. Lispxread also sets rereadflg to NIL when it reads via read, and sets rereadflg to the value of readbuf when rereading. 22.50 are ignored, i.9. skipped over with reade, so that if only spaces have been typed. lispxreadp will return NIL. lispxunread[lst] unreads 1st, a list of expressions to be read. If readbuf is not NIL. 1ispxunread attaches 1st at the front of readbuf, separating it from the rest of readbuf with a (VAG 0). The definition of lispxunread is: (LISPXUNREAD [LAMBDA (lST) (SETQ READBUF (COND «NULL READBUF) LST) (T (APPEND LST (CONS (VAG 0) READBUF]) promptchar[id;flg;hist] prints the prompt character ide promptchar will not print anything when the next input will be 'rereado, i.e. readbuf is not NIL. promptchar will also not print when readp[ ]=T. unless f.!.9 is T. Thus the editor calls promptchar with flg=NIL so that extra when the user types several commands on one line. promptchar with f!9=T since it always wants the ~ ~'s are not printed However, evalqt calls printed (except when 'rereading'). Finally. if prompt#flg is T and hist is not NIL, promptchar prints the current event number (of hist) before printing id. 22.51 lispxeval[lispxform;lispxid] eVilluates lispxform (using eval) the same as th(mgh it were typed in to 1ispx, i •e . the event is recorded, and the evaluation is made undoable by substituting the slash functions for the corresponding destructive functions, as described on page 22.40. lispxeval returns the value of the form, but does not print it. historysave[history;id;inputl;input2;input3;props] records one event on history. NIl., input the is' If input1 is not of the form (inputl input2 • input3). If input1 is NIL, and input2 is not NIL, input (input2 . input3). the is of the form Otherwise, the input is just !ill!ut3. histor~save creates a new event with the corresponding input, id, value field initialized to bell, and I!!.f!J!! • If the histor~ has reached its full size, the last event is removed and canlnibalized. The value of historysave is cddr of the event. How1ever, if rereadflg is not NIL, and is a tail of the input of the most recent event on the history lis't, and this event contains a GROUP property, historysave does not create a new event, but simply adds a (bell. props) entry to the GROUP property and returns that entry. on I)age 22.46. 22.52 See discussion lispxfind[history;line,type;backup] line is an event specification, ~ specifies the format of the value to be returned by lispxfind, and can be either ENTRY, ENTRIES, COPY, COPIES, INPUT, or REDO. historyfind lispxfind lispxfind parses line, and uses to find then the corresponding assembles and events. returns the appropriate structure. lispxfind incorporates the following special features: (1) if backup=T, lispxfind interprets line in the context of the history list before the current event was added. This feature is used, for example, by valueof, so that (VALUEOf -1) will not refer to the valueof event itself; (2) if line=NIL and the last event is an UNDO, the next to the last event is taken. (3) This permits the user to type UNDO followed by REDO or USE; lispxfind recognizes @@, and substitutes archivelst for history (see page 22.14); and (4) lispxfind recognizes @, and retrieves the corresponding event(s) from the property list of the atom following @ (see page 22.14). historyfind[lst;index;mod;x;y] searches 1st and returns the tails of beginning with the event corresponding to x. 1st 1st, index, and mod are as described on page 22.44. ~ is an event address, 22.11-14, 22.53 e. g. as described (43), (-1), on page (fOO FIE), (LOAD" FOO), etc. 64 If historyflnd cannot find !, it generates an error. hi~;t entry#[hist;x] is a history list, i.e. of the form described on page 22.44. i. Et. x is one of the events on hist, (HEHB X (CAR HIST» The value of is true. en1;ryl is the event number for !. valueof[x] is an nlambda, nospread function for obtaining the value of the (VPILUEOF -1), event speci fied (VALUEOF LOAD 1), by etc. 2!, e. g. valueof ret.urns a list of the corresponding values if x specifies a multiple event. changeslice[n;history]66 changes time-slice for history to!!.. is NIL, changes both edithistory and Note: lispxhisto~y. the effect of increasing a time-slice is gradual: the history list is simply allowed forgotten. of If history the However, to grow to the corresponding length before any events are Decreastng a time-slice will immediately remove a sufficient number older events changeslice recoverable. to bring the history list down is undoable, so that these to the proper size. events are (temporarily) Thus if the user wants to recover the storage associated with these events without wai ting !! more events for the changeslice event to be forgotten, he must perform a FORGET command. 64------------------------------~---------------------------------------------- If y.. is given, e.g. ~=(FOO 65 ~=(FOO the event address is the list difference between x and X:, FIE AND \ -1), l=(AND \ -1) is equivalenf to FIE), y"=NIL. changeslice has changeslice. a third argument used 22.54 by the system for undoing a saveset[name;valuejtopflg;flg] an undoable set. (see page 22.43). savesct scans the pushdown list looking fpr the last binding of ~, sets name to value, and returns value. I f the, binding changed was a top leve 1 binding, name is added to spellings3 (see Section 17). Furthermore. if the old value was not NOBIND, and was also not equal to the new value, saveset calls the file package to update the necessary file records. Then. if dfnflg is not equal saveset prints (name RESET), and saves value on the property list of property VALUE. ~, to T, the old under the If f1Jl=NOPRINT. saveset saves the old value, but does not print the message. This option is used by unset. If topflg=T, saveset operates as above except that it does not scan the pushdown list but goes right to name's value cell, e.g. rpaqq[x;y]' is simply saveset[x;y;T]. When topflg is T, and dfnflg is ALLPROP and the old value was not NOBINO, saveset simply stores value on the property list of ~ under the property VALUE. and returns value. This option is used for loading files without disturbing the current value of variables (see Section 14). If flg=NOSAVE, saveset does not save the old value on the property list, nor does it add name to spellings3. undoable. However, the call to saveset is still This option is used by Iset. 22.55 unset[name] if ~ does not contain a property VALUE, unset generates an error. with the ~, Otherwise unset calls saveset property value, topflg=T, and flg=NOPRINT. undosave[undoform]66 if lispxhist is not NIL (see discussion on page 22.45), and get[lispxhist;SIOE] is not equal to NOSAVE, undosave adds undoform to the value of the property SIDE on lispxhist, creating a property if one does not already exist. of undoform is (fn . args), 67 i. e. The form undoform is by undone SIDE performing apply[car[undoform];cdr[undoform]]. example~ For if the definition of FOO is def, Iputd[FOO;newdef] cause will a undo save call with undoform =(/PUTO FOO def). car of the SIDE property 'undosaves', i.e. length of is the cdr of number the property. which is the list of undoforms. of SIDE Each call to undosave increments this count, and adds undoform to the front of the list, i.e. just after the count. When the count reaches the value of lundosaves (initially 50),68 undosave prints a 66----------------------------------------------------------------------------Undosave has a second optional argument. histentry, which can be used to specify lispxhist directly. saving the time to look it up. histentry and lispxhist are NIL. undosave is a NOP. 67 Except for Irplnode, as described below. 68 lundosavcs=NIL is equivalent to #undosaves=infinity. Z2.56 If both message asking the user if he wants to continue saving. If the user answers NO or defaults, undosave makes NOSAVE be the value of the property SIDE, which disables any further saving for th is If the user answers YES, undosave changes event. the count to -1, which is then never incremented, and continues saving. 69 lrplnode[x;a;d] Undoably Value is performs and rplacd[x;d]. The principle advantage of Irplnode ~. is that when rplaca[x;a] ~ is a list, Irplnode saves its undo information as - cons[x;cons[car[x);cdr[x]]], (x originalcar • originalcdr), and 1.e. therefore requires only 3 cells of storage, instead of the 8 that would be required for a Irplaca and a Irplacd nE~w/fn[ fn] that saved earlier. 70 their information Irplnode has a BLKLIBRARYOEF~ as described After the user has defined Ifn, new/fn performs the necessary housekeeping operations to make fn be undoable. 70 Actually, Irplaca and Irplacd also use this format for saving their undo information when their first arguments are lists. However, if both a Irplaca and Irplacd are to be performed, it 1s still more efficient to use Irplnode (3 cells versus 6 cells). 22.57 For example, the user could define Iradix as perform then (LAMBDA (X) (UNDOSAVE (LIST (QUOTE IRADIX) (RADIX X») and new/fn[radix], and radix would then be undoable when typed in or in testmode. lispx/[x;fn;vars] performs the substitution of thEI name of a function, and is' its argument ! If fn is NIL, ! is a form. returns substitutions. for If fn is not NIL, it is destructive functions. lis;t. functions I In both cases, appropriate the with Vars is a list of bound variables (optional). lis,pxl incorporates information about the syntax and semantics example, of INTERLISP expressions. it does not bother to make For undoable ope'rations involving variables bound in x. It also be knows that substitution should not per'formed inside of expressions f.!!.!: of which is QUOTE, OEFINEQ, etc. 71 BREAK, Similarly, substitution should be performed in the arguments for' functions like ma~c, !:.l!!9., etc., since these contain expressions that will be applied. For example, mapc[(FOOl F002 F003);PUTO] if the the evaluated user putd or types must be replaced by Iputd. undolispx[line] lin! is an event specification. undolispx is the function that executes UNDO commands by calling undolispxl on the appropriate entry(s). ~i----------------------------------------------------------------------------- Any member of the list nosubstfns. 22.58 undolispxl[event;flg] undoes pne event. The value of undolispxl is NIL if there is nothing to be undone. If the event is already undone, undolispxl prints ALREADY UNDONE and returns T.72 Otherwise, undolispxl undoes the event, prints a message, e.g. SETQ UNDONE, and returns T. Undoing an event consists of mapping down (cdr of) the property value for SIDE, and for each element, applying £!!r. to cdr, and then marking the event undone by attaching (with lattach) a NIL to the front of its SlOt property. Note that the undoing of each element on the SIDE property will usually cause undosaves to be added to the current lispxhist, thereby enabling the effects of undolispxl to be undone. undonlsetQ[form] is an nlambda. function similar to nlsetq. undonlsetq evaluates form, and if no error occurs during the evaluation, returns list[ eval[ form]] and passes the undo information from form (if any) upwards. 78 If an error does occur, the value of undonlsetq functions is NIL, during and any changes made the evaluation of form by I are undone. 72--i;-;i~:~-~~~-~h;-;~;~~-~;-~i;;;~;-~~~~~;~-~;-~;-;~-~~~~-~~~~~~~-~~~~i~~~~~ takes no action and returns NIL. Undolispx uses this option to search for tho last event to undo. Thus when line=NIL, undolispx simply searchos history until it finds an event for which undo.!gm returns T, i.s. undolis~x performs (SOME (COAR LISPXHISTORY) (F/L (UNDOLISPXl X T») 73 Actually, undonlsetq does not rebind lispxhist, so that any undo information is stored directly on the history event, exactly as though thore were no undonlsetq. Instead, .undonlsetg simply marks the state of the undo information when it starts, so that if an error occurs, it can then know how much to undo. The purpose of this is so that if the user control-D's out of the undonlsetq, the event is still undoable. 22.59 undonlsetq compiles open. undonlse.!.g will operate even if lispxhistory or lispxhist are NIL, or if #undosaves is or has been exceeded for this event. Note that undonlsetq provides a limited form of backtracking. printhistory[history;line;skipfn;novalues] line is an event printhistory specification. prints the events on history specified by line, e.g. (-1 THRU -10). skipfn is an (optional) functional argument that is applied to each event before printing. If its value is true, the event is skipped, i.e. not printed. If novalues=T, or !!QYalues applied to the corresponding event is true, the value is not printed.?4 For example, the following lispxmacto will define 11' as a command for printing the history list while skipping all 'large events' and not printing any values. (11' (PRINTHISTORY LISPXHISTORY LISPXLINE (FUNCTION (LAMBDA (X) (IGREATERP (COUNT (CAR X» 5») T) ) 74------------------------------··---------------------------------------------For example, novalues is T when printing events on edithistory. 22.60 22.10 The Editor and the Assistant As mentioned earlier, all of the remarks concerning 'the assistant' equally well interactions with evalqt, break or the to us~r apply ed~tor. The differences between the editor's implementation of these features and that of Jispx are mostly obvious or inconsequential. However. for completeness, this section discusses the editor's implementation of the programmer's assistant. The edi tor uses promptchar to print its prompt character, 1 ispxreadp, input~ and readline for obtaining inputs. and lispxread, When the editor is given an it calls historysave to record the input in a new event on its history list, edithistory.76 Edithistory follows the same conventions and format as lispxhistory. value field However, since edit commands have no value, the editor uses the for saving side effects, rather than storing them under the property SIDE. The editor processes DO, IE, IF, and IN commands itself, since lispx does not recognize these commands. below. The editor also processes UNDO itself, as described ,All other history commands 76 are simply given to lispx for execution, after first binding (resetting) lispxhistory to edithistory. The editor also 76-------------------------~--------------------------------------------------- Except that the atomic commands OK, STOP, SAVE, P, 7, PP and E are not recorded. In addi tion, number commands are grouped together in a single event. For example. 3 3 -1 is considered as one command for changing position. 76 as indicated by their appearance on historycoms, a list of the history commands. editdefault interrogates historycoms before attempting spelling correction. (All of the commands on historycoms are also on editcomsa and cditcom~! so that they can be corrected if misspelled in the editor.) Thus if the user defines a lispxmacro and wishes it to operate in the editor as well, he need simply add it to historycoms. For example, RETRIEVE is implemented as a lispxmacro and works equally well in lispx and the editor. 22.61 calls lispx when given an E command as described in Section 9. 77 The major implementation diffel-ence between the editor and lispx occurs in undoing. Edithistory is a list of only the last!!. commands, where!!. is the value of the time-slice. However the editor provides for undoing all changes made in a single editing session, even if that session consisted of more than !!. edit commands. Therefore, the 'editor saves undo information independently of the edithistory on a list call undols t ~ndolst, (although it also stores each entry on in the field of the corresponding event on edi this tory.) Thus, the commands UNDO, !UNDO, and UNBLOCK, are not dependent on edithistory,78 i.e. UNDO speci fies undoing the last command on undolst, even if that event no longer appears on edi th is tory. history list specification. occurs when The only interaction between UNDO and the the user types followed by an event In this case, the editor calls lispxfind to find the event, and then undoes the corresponding entry on undolst. ~peciJied UNDO Thus the user can only undo a command within the scope of the edithistory. (Note that this is also the only way UNDO conunands themselves can be undone, that is, by using the history feature, to specify the corresponding event, e.g. UNDO UNDO.), The implementation of the actual undoing is similar to the way it is done 1n I ispx: each command that makes it change in the structure being edited does so via a function that records the change on a variable. After the command has completed, this variable contains a list of all the pointers that have been 77------------------------------··---------------------------------------------In this case, the editor us.es the fifth argument to lispx, lispxflg, to specify that any history cowaands are to be executed by a recursive call to lisp~, 'rather than by unreading. for example, if the user types E REDO in the edi tor, he wants the Itllst event on lispxhistory processed as lispx input, and not to be unread and processed by the editor. 78 and in fact will work if edithistory=NIL, or even 1n a system which does not contain lispx at all. 22.62 changed and their original contents. Undoing that command simply involves mapping down that list and restoring the pointers. ?oZ.11 The Statistics programmer' s ·assistant keeps various statistics about system usage, e.g. number of lispx inputs, number of undo saves, number of calls to editor, number of edit commands. number of p.a. commands. cpu time, console time, et al. Tbese can be viewed via the function lispxstats. lispxstats[] prints statistics. The us'er can' add his own statistics to the lis2x statisti.cs via the function addstnts 0 .. addstats[statlst] no spread, nlambda. of the form (statistic"name. message), (EOITCALLS CALLS UNDONE), etc. in an unboxed StatIst is a list of elements TO EDITOR) (UNOOSTATS e.g. CHANGES statistic-name is set to the cell array, statistic will be stored. where the corresponding This statistic can then be incremented by lispxwatch. lispxwatch[stat;n] increments stat by II (or 1 if rr=NIL). lispxwatch has a BlKlIBRARYOEF. The user can save his statistics for loading into a new system by performing MAKEFIlE(DUMPSTATS). After the file OUMPSTATS is loaded, the statistics printed by .t!~.? USERNAMEFILE. To change an existing initialization, or create a new one, a new USERNAMEFILE must be written. This is accomplished by loading the file USERNAMES, editing usernamelst, and then performing makeusernames[], which will create new versions of both USERNAHEFILE and USERNAMES. (Note that the person performing this operation must therefore either be connected to the LISP directory, or have write access to it.) llsernamelst is a list of elements of the form (username firstname T . forms), e. g., (TE ITELMAN WARREN T (CHANGESLICE 100) (SETQ DWIMWAIT 5». cadr of the list is used in the greeting message. cdddr is a list of forms that are evaluated. ~sernamelst can be edited just like any other list, e.g., with editv. USERNAMEF ILE, created by makeusernames, The file contains usernamelst along wi th an index block which contains for each user on usernamelst the address in the file 80--~~~~-~~~~~~~--;~~-~;--;:;;;;;s~-i-~;-~:~~~~~--;;;-~;~;;~i;-~;~:~~~:;--;;-~i~ (initially T). Alternatively, sysoutgag can be a list, in which case it is evaluated (if the user names are different), and thus the user can print his own message. 22.65 (i.e .. byte position) of the start of his entry. greet then simply does an sfptr and a read. If usernamelst contains an ele'ment for which the username is NIL, i.e.. an e lemen t of the form (NIL . forRls). this is interpreted to mean that forms are evaluated regardless of user name. This feature can be used to "patch" an INTERLISP system when a bug is found, or to change some default for INTERLISP' at a particular site, e.g., turn off DWIH, perform lowercase[T], etc. , Individual user initialization will still be performed following this system initialization. 22.66 Index for Section 22 Page Numbers AOOSTATS[STATLST] NL* .....•..................••. AFTER (prog. asst. command) .....•............... ALL PROP .......................•••••...•......... ALREADY UNDONE (typed by system) •.......•...•... AND (in event specification) .•...••..••..•••.••. AND (in USE command) .......•....••.•...•...•..•• ARCH IVE (prog. asst. command) ...••.•..••..••..•• ARCHIVEFN (prog. asst. variable/parameter) .•...• ARCHIVELST (prog. asst. variable/parameter) backtracking ................................... . BEFORE (prog. ass t. command) •.•.•.•••••..•.•••.• boll (in history event) ......•.•..••..••••••.•.. BLKLIBRARYOEF (property name) ...••••••.•...••.•• CtI ANG[S LIe E[ N; HIS TOR Y; L] ......•.••...•••.....•.• CLEARBUF[FILE;FLG] SUBR ...••..•..••..•.•...•...• CONTIN (prog. asst. command) ....•••...•..•.•.•.. CONTINUE SAVING? (typed by system) ••.•.•••.•..•. con t r 0 1 - 0 control-E control-U .". . • • • • '. . . . . • . .. . • • • • • • • • • • • • • • • • • • • • . • .................................. *' • • • • ...................................... . DFNFLG (system variable/parameter) •.••••.•.••••. oIR (prog. ass t. command) .•••.••••.•.••••..•..•. DO (edit conunand) .........•..•..••••••••.•..•••• 00 (prog. asst. conunand) .....•..••••.•••.•••.... OW 1M .............. It ............................... . DWIMWAIT (dwim variable/parameter) ••..•••.•••••• E (edit command) ....••..•.•..•••.•••.••.••..•••• EDITDEFAULT .•..••••••.•••.•••••.•••••••••••••.•• EDITHISTORY (editor variable/parameter) .••....•• ENTRYI[HISTiX] .............• ~ ••••••.•••••.•..•.. ERROR (property name) .......•••.••••••••••...••• ESUBST[X;Y;Z;ERRORFLG;CHARFlG] •••••...••..•.••.• ovent address ........•..•••..•••..••.•••.•..•... even t number .............••..•••..••.•••.•.••••• event specification ........•.••..•••.•.•...•.•.. EXEC (prog. asst. command) ..••••••.•.•••.....•.• F (in event address) ......•••.•.••••.•••.••••... F I X (prog. asst. command) .....•.•.••..•..•.•.•.. FOR (in USE command) ........•••.••.•.•.••.•..•.. FORGE T (prog. ass t. command) .•••••..••.••.....•. format and use of history list .......•...•.•...• FROM (in event specification) ..•..••......••.... GREET[NAME;FLG] ...................•..•..•..•.••. greeting and user initialization •..•...•••..•••. GROUP (pro~erty na~e) .........•......•..•..••.•. HElPCLOCK (system variable/parameter) .......... . HISTORY (property name) ..•...••..•.....••..•••.. h is tory commands ..........................•..... history commands applied to history commands history commands that fail ...••....•........•..• history list .................................... . HISTORYCOMS (editor variable/parameter) ........ . HISTORYFIND ...............•...•...•............. HISTORYSAVE[HISTORY;IDjINPUTl;INPUT2,INPUT3;PROPS] implementation of REDO, USE, and FIX .....•.••.•. IN (i n USE command) .....••••••••••••••••••.••••• INDEX.22.1 22.63 22.22,26,34 22.55 22.22,59 22.13 22.14 22.27 22.27,33-34 22.44,53 22.60 22.22,26,34 22.22,33,44,49,52 22.57,63 22.8,54 22.30 22.34 22.39,57 22.30 22.30 22.32,50 22.43,55 22.34 22.31,61 22.31 22.23 22.39 22.62 22.61 22.44,49,60-62 22.54 22.24,45 22.14 22.12-13 22.8,12,21,33,54 22.11-14,19-21 22.34 22.12 22.16"'17,22 22.14 ,22.27,54 22.44-47 22.13 22.64 22.64 22.45-46,52 22.21,38 22.45-46 22.10-27 22.19 22.20 22.6-14,44 22.61 22.53 22.11,44-46,52,61 22.17-19 22.14 Page Numbers IISP (prog. asst. conunand) ..•...............•.•• 22.34 lISPX[lISPXX~lISPXID;lISPXXMACROS;LISPXXUSERFN; LISPXFLG] ...........' ...•................•.. LISPX/[X;fN;VARS] ..........•......•..•..•..•..•• LISPXCOMS (prog. asst. variable/parameter) •.••.• LISPXEVAL[ LISPXFORM; LISPXIO] ................•..• LISPXFINO[HISTORY;lINE;TYPE;BACKUP;QUIETFLG] LISPXtlIS T (prog. asst. varj.able/parameter) .••... LISPXHISTORY (prog. asst. ,'ariable/parameter) LISPXtnS TORY (system variable/parameter) .••.•••• LISPXlINE (prog. asst. variable/parameter) ••••.• LISPXMACROS (prog. asst. variable/parameter) LISPXPRINT (property name) .....••••...•....••••• LISPXPRINT[X;Y;Z;NODOFLG] .........•..•........•. lISPXPRINTFlG (system variable/parameter) ..••••• LISPXREAD[FIlE] ......••.......•..•.•.•...••.•••. .......................................... LISPXREADFN (prog. asst. vCllriable/parameter) LISPXREADP[FLG] .•........•..•.•.••.•..•.•••••••• LISPXSTATS[FLG] ............•..•...•....•.•.....• LISPXUNREAD[LST] ............•.•..•...••••.••.•.. LISPXUSERFN (prog. asst. variable/parameter) LISPXWATCH[STAT;N] .......•................•...•. MAKEUSERNAHES ................•••..••.•...••.•.•• NAME (prog. asst. conunand) ..•.•••••••.•....••.•• NEW IFN[ FN] ..............•..••••••.••...••••••••• NlSETQ[NLSETX] NL ..........•...••.••...•••.•.••. NO VALUE SAVED: (error message) .•.•...•.••.••••. NOBIND NOS AVE ................•••••.•••••.••..•.•••••••• •••••••••••••••••••••••••••••••••••••••••• NOSUBSTFNS (prog. asst. variable/parameter) NOTHING SAVED (typed by system) ..•.•..•..••••... PRINT (property name) .................•.•••...•. PRINTltISTORY[ HISTORY; LINE :SKIPFN jNOVALUES] •.•... programmer's assistant ......••.•.•....•.••.••... programmer's assistant and the editor ..•..•••••. programmer's assistant commands .•••...•.....••.. prompt character .....•.......•.•.••..•....•••.•• PROMPTIFlG (prog. asst. variable/parameter) PROM PTCHAR[ I 0 ; FLG; HIS T] . . . . . . . • . . . . . . . . • . . . . . . . . READBUF (prog. asst. variable/parameter) .•...••• READLINE[L.INE;LISPXFLG] ......•.••....•••••••.••• .......................................... REDO (prog. asst. command) .......•..•.•.•••••... REREAOFLG (prog. asst. variable/parameter) •.•••• RESET (typed by system) ..•..•.•••••..••••••..•.• restoring input buffers .....••.•.••••.....•..••• RETRIEVE (prog. asst. command) ••..••.•.•.••.•... RETRY (prog.· asst. conunand) .•••..••••••..•...... RPAQ[RPAQX;RPAQY] NL ..........••.•••..••........ RPAQQ[X;Y] NL ....................•••.•.••..••••• SAVESET[NAME;VALUE;TOPFLG:FLG] ...•••.••••..•..•• SIDE (property name) ..............••••••••.••••• SNOHSG (prog. asst. command) ...•.•••••••.••••••• SPELLINGS3 (dwim variable/parameter) •••••••••••• INOEX.22.2 22.10-11,15-16,19-20,29, 34-35,37-38,40-41, 44-49,52,61-62 22.40,58 22.38 22.52 22.53,62 22.45-46,56,59-60 22.44,49,60-61 22.62 22.34 22.34,49 22.38,45 22.37,45 22.38 22.10,19,29,32,47-48,50, 61 22.50 22.50,61 22.63-64 22.51 22.35,37,47,49 22.63 22.65 22.14,22,25-26 22.57 22.59 22.56 22.43,55 22.56-57 22.58 22.22,39 22.45 22.22,37-38,60 22.1-48 22.61 22.10-31 22.10,33,51 22.33,51 22.33,51,61 22.50-51 22.14,19,32,37,47-48,50, 61 22.14,17,22 22.50,52 22.43,55 22.30 22.22,26,34 22.21-22 22.43 22.43 22.40,43,55 22.45-46,56-57,59,61 22.34 22.55 Page Numbers statistics ..................................... . SUBSYS[FILE/FORKjINCOMFIlEjOUTCOMFILE; ENTRYPOIN1FLG] .............•.•.•......•.•. SY (prog. asst. command) ..............•..•....•. SYSOUIGAG (system variable/parameter) .....•..•.• TECO (prog. ass t. command) ..•....••••.••.••.•.•• TESTMOOE[FlG] ..............................•.... TESTMODEFlG (prog. asst. variable/parameter) THRU (in event specification) •.•••.•.•••••.•.... time-slice (of history list) ..••••••••••.•...••• TO (in event specification) ...•..••..•.••....••. TYPE-AHEAD (prog. asst. command) .•••.•••..••..•• UNOO (prog. asst. command) .•.•...•••.•.••..••••. UNDO (ed it command) ....•.•.......•..••.......... lJ n (I 0 i. n 9 ..•....•..••••••••.•••••••••••••••••••••• undoing (in edi tor) .............••••...•......•. undoing DWIM corrections .....•••••.•..•.•.•...•• undoing out of order .........•.................. UNDOl ISPX[ LINE] •................•••....•..•..... UNOOlISPX1[EVENT;FlG;OWIMCHANGES] .•.....•.....•• UNOOLST (editor variable/parameter) ..........•.. UNOONE (typed by sys tern) ....••..•••..•••.•..•... UNDONLSEIQ[UNDOFORM;UNDOFN] NL ••.••••.••.••..•.. UNOOSAVE[UNOOFORM;HISTENTRY] ..•.••...•.•••.•.••• unrea{ling ....................................... . UNSE T[ NAME] ................................••... USE (prog. ass t. command) ....••..•••....••.••.•. USE-ARGS (property name) ...............•..•.••.. USfREXEC[lISPXIO;lISPXXMACROS;lISPXXUSERFN] USERNAME (prog. asst. variable/parameter) ....••• USfRNAMElST (prog. asst. variable/parameter) VALUE (property name) ....•.••••.•••..••..•.••.•• VALUEOF[X] NL" ............•••.••.•••..••..•..•.• !E (prog. asst. command) ..•.•••.••.••.•.....•.•. !E (edit command) ...........•.•.•........•.....• !F (prog. asst. command) ....•....••...•......... ! F (c d i t comma n d) .....................•••.....•.. !N (prog. asst. command) .....•.....•...••.••.... ! N (edi t command) ............•.•••.•....•..•••.. #0 (use in history commands) ..............•..... HUNDOSAVES (prog. asst. variable/parameter) S (a 1t-mode) (prog. asst. command) ...........•.. SBUFS (alt-modeBUFS) (prog. asst. command) ..... . ••• .... ATTENTION USER -- (typed by system) ....... . . .. (prog. ass t. command) •...•••••...•.•••...... . .. (typed by sys tem) .......•....••..•...•.•.... I functions .................................... . IRPLNODE[X;A;D] .............•.•..•..•.••••...•.• = (in event address) .....•...•....••............ ?? (prog. ass t . command ) ...••.•..•.............. @ (in event specification) ..•...••.•..••..••.... @@ (in event specification) •••.••.••............ \ (in event address) ....•..••....•.•...••....... ~ (in event address) ..••...•..••.•••.•.•.••••••. INDEX.22.3 22.63 22.34 22.34 22.65 22.34 22.41 22.41 22.13 22.8,54 22.13 22.28-29 22.13,22-23,43,58,61 22.61 22.5,38,55,62 22.62 22.23 22.23,42 22.58 22.59 22.62 22.22,59 22.59 22.45-46,56 22.10-11,18,51 22.43,56 22.14-15,17,22 22.45 22.49 22.65 22.65-66 22.43,55-56 22.33,46,54 22.31 22.31,61 22.31 22.31,61 22.31 22.31,61 22.18,50-51 22.39,56-57,60 22.23-25 22.30 22.65 22.21-22 22.48 22.40,57-58 22.57 22.12· 22.21-22 22.14,53 22.14,27,53 22.13 22.12 SECTION 23 1 CLISP - CONVERSATIONAL LISP The syntax of LISP is very simple, in the sense that it can be described concisely. but not in the sense that LISP programs are easy to read or write! This simplicity of syntax is achieved by, and at the expense of, extensive use of explicit structuring, namely grouping through parenthesesization. Unlike many languages, there are no reserved words in LISP such as IF, THEN, AND, OR, FOR, DO, BEGIN, END, etc., nor reserved characters like +, ., -, /, ~, etc. 2 =, This eliminates entirely the need for parsers and precedence rules in the LISP interpreter and compiler, programs straightforward. and thereby makes program manip~lation of LISP In other words, a program that "looks at" other LISP programs does not need to incorporate a lot of syntactic information. For example, a .LISP interpreter can be written in one or two pages of LISP code ([Meet], pp. 70-71). It is for this reason that LISP is by far the most suitable, and frequently used, progranuning language for writing programs that deal with other programs as data, e.g., programs that analyze, construct other 2 modify, or pro~~ams. except for parentheses (and period), which are used structure, and space and end-of-line, which are used identifiers. 23.1 for for indicating delimiting However, it is precisely this same simplicity of syntax that programs difficult to read and write (especially for beginners). down' is something programs do vel"y well, and people do poorly. makes LISP 'Pushing As an example, consider the following two 'equivalent' sentences: "The rat that the cat that the dog that I owned chased caught ate the cheese." versus It I own the dog that chased the cat that caught the rat that ate the cheese." Natural language contains many linguistic devices such as that illustrated in· the second sentence above for minimizing embedding, because embedded sentences are more di ffi cuI t to grasp and understand than equivalent non-embedded ones (even if the latter sentences are somewhat longer). Similarly, most high level programming languages offer syntactic devices for reducing apparent depth and complexity of a program: the reserved words and infix operators used in ALGOLlike languages simultaneously delimit operands and operations, and also convey meaning to the programmer. They are far more intuitive than parentheses. In fact. since LISP uses parentheses (i.e. lists) for almost all syntactic forms, there is vory little information contained in the parentheses for the person reading a LISP program, and so the parentheses tend mostly to be ignored: the meaning of a particular LISP expression for people is found almost entirely in the words, not in the structure. For example, the following expression (COND (EQ N 0) 1) (T TIMES N FACTORIAL «SUBl N») is recognizable as FACTORIAL evenl though there are five misplaced or missing parentheses. Grouping words together in parentheses is done more for LISP's benefi t, than for the programmer IS,. CLISP is designed to make INTERLISP programs easier to read and write by 23.2 permitting the user to employ various infix operators, If-THEN-ELSE statements, FOR-DO-WHILE-UNLESS-FROM-TO-etc. expressions, which are automatically converted to equivalent INTERLISP expressions when they are first interpreted. For example, FACTORIAL could be written in CLISP: (IF N=O THEN 1 ELSE N*(FACTORIAL N-l» Note that this expression would become a,n equivalent CONO after it had been interpreted once, so that programs that might have to analyze or otherwise process this expression could take advantage of the simple syntax. There have been similar efforts in other LISP systems, most notably the MLISP language at Stanford [Smit]. CLISP differs from these in that attempt to replace the LISP syntax so much as to augment it. it does not In fact, one of the principal criteria in the design of CLISP was that users be able to freely intermix LISP and CLISP without having to identify which is which. write programs, or type in expressions for evaluation, . in LISP, mixture of both. Users can CLISP, or a In this way, users do not have to learn a whole new language and syntax in order to be able to use selected facilities of CLISP when and where they find them useful. CLISP is Boction implemented via 17). Thus, the error correction machinery any expression that is in well-formed INTERLISP from (see INTERLISP's standpoint will never be seen by CLISP (i.e., if the user defined a function IF. he would interpreted effectively programs turn off that form • know' about CLISP at all. is invokes encountered, the expression the This question In fact. the INT~RLISP means pay for that its interpreter does It operates as before, and when an erroneous interpreter calls an error routine which Do-What-I-Mean in of CLISP). that do not use CLISP constructs do not availability by slower execution time. not part (DWIM) turns out analyzer which contains to be a CLISP construct, 23.3 CLISP. tho in If turn the equivalent INTERLISP form is returned to the interpreter. In addition, the original CLISP expression, is modified so that it becomes the correctly translated INTERLISP form. In this way, the analysis and translation are done only once. Integrating CLISP implementing features into the INTERLISP system (instead of, it as a separate preprocessor) makes possible for example, Do-What-I-Mean for CLISP constructs as well as for pure LISP expressions. for example, if the user has defined a function named GET-PARENT, CLISP would know not to attempt to interpret the form (GET-PARENT) as an arithmetic operation. infix (Actually, CLISP would never get to see this form, since it does not contain any errors.) If 'the user mistakenly writes (GET-PRAENT), CLISP would know he meant (GET-PARENT), and not (DIFFERENCE GET PRAENT), by using the information that PRAENT is not the name of a variable, and that GET-PARENT is the name of a user function whose spelling is "very close" to that of GET-PRAENT. Similarly, by using information about the program's environment not readily available to a preprocessor, CLISP can successfully resolve the following sorts of ambiguities: 1) (LIST X-FACT N), where FACT is the name of a variable, means (LIST (X-FACT) N). 2) (LIST X*FACT N), where FACT is not the name of a variable but instead is the name of a function, (LIST X*(FACT N», means i.e., N is FACT's argument. 3) (LIST X*FACT(N», FACT the name of a function (and not the name of a variable), means (LIST X*(FACT N». 4) cases (1),(2) and (3) with FACT misspelled! The first expression is correct both from the standpoint of CLISP syntax and 23.4 senlantics and the change would be made without the user being notified. In the other cases, the user would be informed or consul ted about what was taking place. example, For to take an extreme case, suppose the expression, (LIST X*FCCT N) were encountered, where there was both a function named FACT and a variable named FCT. misspelling of FCT. (LIST (X*FCT) N).8 The user would· first If he said YES, If he said NO, be asked if FCCT were the expression would be interpreted as the user would be asked if FCCT were misspelling of FACT, i.e., if he intended X*FCCT N to mean X*(FACT N). since FCCT a If he said YES to this Question, the indicated transformation would be performed. he said NO, a If the system would then ask if X*FCCT should be treated as CLISP, is not expression would be the name of a transformed, (bound) if NO, variable. 4 it would be If he said left alone, YES, i.e., the as (LIST X*FCCT N). Note that we have not even considered the case where X*FCCT is itself a misspelling of a variable name, e.g., a variable named XFCT (as with GET-PRAENT). This sort of transformation would be considered after the user said NO to X-FCCT N -) X*(FACT N). The graph of the possible interpretations for (LIST X*FCCT N) where FCT and XFCT are the names of variables, and FACT is the name of a function, is shown in Figure 23-1 below. a----------------------------------------------------------------------------Through th is discussion, we speak of CLISP or DWIM ask.ing the user. Actually, if the expression in question was typed in by the user for immediate execution, the user is simply informed of the transformation, on the grounds that the user would prefer an occasional misinterpretation rather than being continuously bothered, especially since he can always retype what he intended if a mistake occurs, and ask the pronrammer I s assistant to UNDO the effects of the mistaken operations if necessary. For trallsformations on expressions in user programs, the user can inform CLISP whether he wishes to operate in CAUTIOUS or TRUSTING mode. In the former case (most typical) the user will be asked to approve transformations, in the latter, CLISP will operate as it does on type-in, i.e., perform the transformation after informing the user. 4 This question is important because many INTERLISP users already have pronrams that employ identifiers containing CLISP operators. Thus, if CLISP encounters the expression AlB in a context where either A or Bare not the names of variables, it will ask. the user if AlB is intended to be CLISP, in case the user really does have a free variable named AlB. 23.5 FCCT- >FCT ? FCCT N - 2 >(FACT N)? X* FCCT- >XFCT X*FCCT TREAT AS CLISP? 4 FIGURE 23.6 23-1 5 The final states for the various terminal nodes shown in the graph are: 1: (LIST (TIMES X FCT) N) 2: (LIST (TIMES X (FACT N») 3: (LIST XFCT N) 4: (LIST (TIMES X FCCT) N) 5: (LIST X*FCCT N) CL ISP can also handle parentheses errors caused by typing 8 or 9 for , )' . •)" f (f or (On most terminals, 8 and 9 are the lower case characters for '(' and i . e ., • (' and '8 t appear on the same key, as do if the user writes N*8FACTORIAL N-l, example, detected and fixed before the infix operator function TIMES. * ')' and '9'.) For the parentheses error can be is converted to the INTERLISP CLISP is able to distinguish this situation from cases like N*8*X meaning (TIMES N 8 X), or N*8X, where 8X is the name of a variable, again by using information about integrating CLISP with DWIM, errors that the programming environment. In fact, by CLISP has been made sufficiently tolerant of almost everything can be' misspelled! For example, CL ISP can successfully translate the definition of FACTORIAL: (IFF N=O THENNI ESlE N*8FACTTORIAlNN-l) to the corresponding COND, while making 5 spelling corrections and fixing the parenthesis error. 6 This sort of robustness prevails throughout CLISP. For example, the iterative 5'-----------------------------------------------------------------------------CLISP also contains a facility for converting from INTERLISP back to CLISP, so that after running the above incorrect definition of FACTORIAL, the user could I CLISPIFY' the now correct LISP version to obtain (IF N=O THEN 1 ELSE N*(FACTORIAl N-l». 23.7 statement permits the user to' say things like: 6 FOR OLD X FROM M TO N DO (PRINT X) WHILE (PRIMEP X) However, the user can also write OLD (X~M), (OLD (OLD X~M). order of the operators, e.g., DO PRINT X TO N FOR OLD X~H permute the (X~M», WHILE PRIMEP X, omit either or both sets of parentheses, misspell any or all of the operators FOR, OLD, FROM, TO, 00, or WHILE, or leave out the word DO entirely! And, of course, he can also misspell PRINT, PRIMEP, H or N!7 CLISP is well integrated into the INTERLISP system. For example, the above iterative statoment translates into an equivalent INTERLISP form using PROG, CONO, GO, etc. 8 When the interpreter subsequently encounters this CLISP expression, it automatically obtains and evaluates the translation. 9 Similarly, the compi ler "knows" to compile the translated form. PRETTYPRINTs his program, at the corresponding PRETTYPRINT "knows" to print the original CLISP. However, point in if the user his function, Similarly. when the user edits his program, the editor keeps the translation invisible to the user. If 6---~~~~--~~~;~~~~~~--;~~~~~--~;·--;;ii-~-;p;:~:~~~~.--~~~~~~--~~~~~~i~--;~;--~~; operator OLD, which says X is to be the variable of iteration, i.e., the one to be stepped from N to M, but X is not to be rebound. Thus when this loop finishes execution, X will be equal to N+J. 7 8 In this example, the only thing the user could not misspell is the first X, since it specifies the name of the variable of iteration. The other two instances of X could be misspelled. , (PROG NIL (SETQ X M) SSlP(CONO «OR (IGREATERP X N) (NOT (PRIMEP X») (RETURN») (PRINT X) (SETQ X (AODI X» (GO SSLP» 9 See page 23.30, for discussion of how translations are stored. 23.8 the user modifies the CLISP, the translation is automatically discarded and recomputed the next time the expression is evaluated. In short, CLISP is not a language at all, but rather a system. ilnalagous to It plays a role that of the programmer's assistant (Section 22). Whereas the programmer' s assistant is an invisible intermediary agent between the user' s (:onsole requests and the INTERLISP executive, CLISP sits between the user's programs and the INTERLISP interpreter. Only a small effort has been devoted to defining the core syntax of CLISP. Instead, most of the effort has been concentrated on providing a facility which 'makes sense' out of the input expressions using context information as well as built-in and acquired information about user and system programs. It has been said t.hat communication is based on the intention of the speaker to produce an effect in the recipient. CLISP operates under the assumption that what the user said was intended to represent a meaningful operation, and therefore tries very hard to make sense ou t of it. The moti vat ion beh ind CL I SP is not to provide the user with many different ways of saying the same thing, but to enable him to worry less about the slIntactic aspects of his cOrIUnunication with the sys tern. In other words, it gives the user a' new degree of freedom by permitting him to concentrate more on the problem at hand, rather than on translation into a formal and unambiguous language. 23.2 CLISP ~~I~.tax Throughout CLISP, a non-atomic form, for a variable, example, and vice versa, i.e., a list, can always be substituted without changing the interpretation. For a, then if the value of (FOO X) is A, and the value of (FIE Y) is (LIST (FOO X)+(FIE V»~ has the same value as (LIST A+8). expression consists of a list of Jour elements: 23.9 Note that the first the atom 'LIST'. the list '(FOO X)'. the atom '+'. and the list '(FIE X)', whereas the second expression, (LIST A+B), consists of a list of only two elements: the atom 'LIST' and the atom Since 'A+B' . (LIST (FOO X)+(FIE (LIS T (FOO X) + (F IE Y» V»~ indistinguishable is from because spaces before or after parentheses have no effect on the INTERLISP READ program,10 to be consistent, extra spaces have no effect on atomic operands either. In other words, CLISP will treat (LIST A+_B), (LIST A_+B), and (LIST A_+_B) the same as (LIST A+B). 23.3 Infix Operators CLISP recognizes the arithmetic infix operators +, -, *, I, and converted to IPLUS, t. These are IDIFFERENCE (or in the case of unary minus, IMINUS), ITIMES, IQUOTIENT, and EXPT. ll The usual precedence rules apply (although these can be easily changed by the user),12 i.e., * has higher precedence than + so that A+B*C is the same as A+(B*C), and both * and I are lower than t so that 2*Xt2 is the same as 2*(Xt2). Operators of the same precedence group from left to right, e. g.. AlBIC is equl.valent to (AlB) IC. Minus is binary whenever possible, i.e., except when it is the first operator in a list, as in (-A) or (-A), or when it immediately follows another operator, as in A*_B. la 14 ------------------------------------------------------------------------------10 CLISP does not use its own special READ program because this would require the user to explicitly identify CLISP expressions, instead of being able to intermix INTERLISP and CLISP. 11 The I in IPLUS denotes integer arithmetic, i.e., IPLUS converts its· arguments to integers, and returns an integer value. INTERLISP also cont.ains floating point arithmetic functions as well as mixed arithmetic functions (seo Section 13). CLISP contains a facility for declaring which type of arithmetic is to be used, either by making a global declaration, or by separate declarations about individual functions or variables. See section on declarations, page 23.33. 12 The complete order of precedence Figure 23-2, page 23.15. 13 There are some do-what-I-mean features associated with Unary minus, as 1n (LIST -X V). See section on operation, page 23.64. 23.10 for CLISP operators is given in Note that grouping fuith parentheses can always be used to override the normal precedence grouping. or when the user is not sure how a particular expression lui il parse. (LISP also recognizes as infix operators =. GT, IT. GE, and lE,15 as well as various predicates, e.g., MEMBER, AND, OR, EQUAL, etc. t6 AND is higher than OR, B • g., (X OR Y AND Z) is the same as (X OR (Y AND Z», and both AND and OR are lower than the other infix operators, e. g., (X AND Y EQUAL Z) is the same as (X AND (Y EQUAL INTERLISP forms, Z». All of the infix predicates have lower precedence than i.e., (FOO X GT FIE Y) is the same as «FOO X) GT (FIE V»~, since it is far more common to apply a predicate to two forms, than to use a Boolean as an argument to a function, e.g. (FOO (X GT (FIE Y»). However. again, the user can easily change this. Note that only single character operators, e,g. +, ~, =, etc., can appear in the interior of an atom. All other operators must be set off f1~ identifiers loith spaces. For example. XlTY will not be recognized as CLISP. 14----------------------------------------------------------------------------Note that + in front of a number will disappear when the number is read, e.g .• (rOO x +2) is indistinguishable from (FOO X 2). This means that (FOO X +2) will not be interpreted as CLISP, or be converted to (FOO (IPLUS X 2», Similarly, (FOO X -2) will not be interpreted the same as (FOO X-2). To circumvent this, always type a space between the + or and a number if an infix operator is intended, e.g., write (FOO X + 2). 15 Greater Th~n, Less Than, Greater than or Equal to, and Less than or Equal to, resjlccti ve-ly. GT. LT. GE, and LE -are all affected by the -'same doclar~ations as + and *, with the initial default to use IGREATERP and ILESSP. 16 Currently the complete list is MEMBER, MEMB, FMEMB, IlESSP, IGREATERP, lESSP, GRfATERP, FGTP, EQ, NEQ, EQP, EQUAL, OR, and AND. New infix operators can be easily added. as described in the section on CLISP internal conventions, page 23.68. 17 In some cases, OWH1 will be able to diagnose this situation as a run-on spoIling error, in which case after the atom is split apart, CLISP will be able to perform the indicated transformation. 23.11 * * is an infix operator used in CLISP for extracting substructures from lists,18 e.g., X:3 specifies .the 3rd element of X, (FOO Y)::Z spe~ifies the second tail of (FOO V), i.e., (CDDR (FOO V»~, and Z:l:Z is the second element of the first element of Z, or (CADAR Z). Negative numbers may be used to indicate position counting from the end of a li.st, e.g., X:-l is the last element of X, or (CAR (LAST X», X::-l is the last tail, i.e., (LAST X).19 * ~ is used to indicate assignment, e.g., X~Y translates to (SETQ X y).20 21 In conjunction with: and ::, ~ can also be used to perform a more general type of assignment, namely one involving structure modification. means make the second element of X be Y, in For example, INTERLISP X:2~Y terms 18------------------------------'----------------------------------------------The rncord facility, page 23.48, provides another way of extracting substructures by allowing the user to assign names to the various parts of the structure and then retrieve from or s tore into the corresponding structure by name. The pattern match facility, page 23.36, also can be used to extract substructure. : is also used to indicate both record and pattern match operations. 19 The interpretation of negative numbers can be explained neatly in terms of edi t conunands: : -n returns what would be the current expression after execu t i ng the command -n. and :: -n returns what wou Id be the current expression after executing -n followed by UP. 20 I f x does not have a value, and is not the name of one of the bound variables of the function in which it appears, spelling correction is attempted. However, since this may simply be a case of assigning an initial value to a new frelB variable, DWIM will always ask for approval before making the correction. 21 Note that an atom of the form X~Y. appearing at the top level of a PROG, not be recognized as an assignment statement because it will be interpreted as a PROG label by the INTERLISP interpreter,and therefore will not cause an error, so DWIM and CLISP will never get to see it. Instead, one must write (X~Y). wi 11 23.12 (RPlACA (CDR X) y).22 23 Negative numbers can also be used, e.g., X:_2~y.24 ~ is also used to indicate assignment in record operations, page 23.48, ftnd pattern match operations, page 23.36 . ... has di fferent precedence on the left from on the right. "tight" operator, i.e., high precedence, so that On the right, .. has broader scope so that On typein, $~form men t ioned" . 26 For (alt-mode~form) example, is A~B+C A+B~C is the same as is the same as equivalent inunediate1y On the left, .. is a after to set A+(B~C). A~(B+C). the examining the "last thing value of LONGVARIABlENAME, the user could set it by typing $.. followed by a form. Prefix Operators 23.4 CLISP recognizes • and - as prefix operators. first character in an identifier, interior of an identifier. Thus, t means QUOTE when it is the and is ignored when it is used X='Y means (EQ X (OUOT£ means (EQ X CAN'T), not (EQ X CAN) followed by (QUOTE T). V»~, in the but X=CAN'T This enables users to have variable and function names with ' in them (so long as the • is not the first character). -------------------------------------------------------------------------------Noto that the value of this operation is the value of rplaca, which is the 2~~ corresponding node. 23 The user can indicate he wants Irplaca and Irplacd used (undoable version of [Qlafa and [pIacd, see Section 22), or frplaca and frplacd (fast versions of rplaca and rplacd, see Section 5), by means of declarations (page 23.33). The initial default is for rplaca and rplacd. 24 which translates to (RPlACA (NlEFT X 2) V). 26 i.e. is equivalent to (SETQ lastword form). See Section 17. 23.13 Following all operators are ignored for the rest of the identifier, e.g., I '*A moans (QUOTE *A), and IX=Y means (QUOTE X=Y), not (EQ (QUOTE X) y).20 On typein, 1$ Section 17). (i.e. 'alt-mode) is equivalent to (QUOTE value-of-lastword) (see For example, after calling prettyprint on LONGFUNCTION, the user could move its definition to FOO by typing (NOVO 'S 'FOO).27 ..... means NOT. - can negate a form, as in -(ASSOC X Y), or -X, or negate an infix operator, e.g., (A -GT a) 1s the same as (A LEQ a). Note that -A=a means (EQ (NOT A) B). --------------------------------------.---~----------------------------~-~----26 To write (EQ (QUOTE X) V). one writes V=IX, or 'X_=V. This is one place where an extra space does make a difference. 27 (MOVO $ 'FOO),. which would be equivalent to (MOVO LONGFUNCTION 'FOO), and would (probably) cause a U.B.A. LONGFUNCTION error, nor MOVO(S FOO), which would actually move the definition of S to FOO, since DWIM and the spelling corrector would never be invoked. Not 23.14 Order of Precedence of CLISP operators ~ (left precedence) 28 29 - (unary) • ..., t ", I ... , ~ (binar~y) (right precedence) :: INTERLISP forms LT, GT, EQUAL, MEMBER, etc. AND OR IF, THEN, ELSEIF, ELSE iterative statement operators Figure 23-2 28--:-~~~-~-~~-;;e~~~~--1;i;-~~~-~~~h;-;;;~;~;~~;:-~~~~~-~:~~c:~--;;-;~;-;;~~-~; In other words, scope on the right. A+(U~(C+D». ~ has minimal scope on the left and maximal -=, When - negates an operator, e.g., -LT, the two operators are treated as a single operator whose precedence is that of the second operator. Whennoga tes a function. e. g., (-FOO X Y) ~ it negates the whole form, 1. e. , (-( FOO X Y». 23.15 Constructing Lists - the <,) operators 30 23.~ Angle brackets are used in CLISP to indicate list construction. The appearance of a '(I corresponds to a Ie' and indicates that a list is to be constructed containing all the elements up to the corresponding ')'. for example, (A B (e» translates to (LIST A B (LIST C». expression is to be inserted in translates to (CONS A (CONS B C) ! can be used to indicate that the next the list as a segment, e.g., e> (A B and (! A ! B C) to (APPEND A B (LIST'C». !! is used to indicate that the next expression is to be inserted as a segment, and furthermore, all list structure to its right in the angle brackets is to be physically attached to it, e.g., need not be separate atoms, for exampl,e, which translates to (CONS (SETQ Faa (FIE X» ~pend, using V). CLISPIFY converts expressions in ~, list, nconc, nconc1, !nconc, and !nconc1 into equivalent CLISP expressions <, >, !, and !t. Note: angle brackets differ from other CLISP operators in that they act more like brackets than (LIST A 8 (QUOTE C» 31 32 operators. for example, (A B 'C) translates to even though following " all operators are ignored for the Not (NCONC (APPEND A B) C), which would have the same value, attach C to Bf and not attach either to A. but would The user can indicate !nconc or !nconc1 be used instead of and nconcl by declarations. 23.16 ll£QQ£ rest of the identifier:33 Note however that (A B '_C> D) (LIST A B (QUOTE C» i$ equivalent to 0). IF, THEN, ELSE 23.6 CLISP translates c:ondi tional expressions expressions. IFITHENIELSEIFIELSE employing The segment between into equivalent IF I ELSEIF and the next THEN corresponds to the predicate of a COND clause, and the segment between THEN and the next ELSEIELSEIF as the consequent(s). ELSE is the same as ELSElf T THEN. IF, THEN, ELSE, and· ELSEIF are of lower precedence than all infix and prefix operators, as well as INTERLISP forms, betweon IFIELSEIF, and THEN. so that parentheses can be omitted For example, (IF FOO X Y THEN --) is equivalent to (IF (FOO X Y) THEN __ ).34 Simi larly , CL ISP treats (IF X THEN FOO X Y ELSE -,-) as equivalent to (IF X THEN (FOO X Y) ELSE --) because it does not sense' also to evaluate a variable for effect. the E.ssen tiaIly, name of a variable, 'make In other words, even if FOO were (COND (X FOO X V»~ doesn't make sense. CL ISP determines whether the segment between THEN and the next ELSEIELSEIF corresponds to one form or several and acts accordingly.36 Thus, (IF -- THEN (FOO X) Y ELSE --) corresponds to a clause with two consequents. Similarly, 34 (IF -- THEN FO~X Y ELSE --) corresponds to a clause with two FOO is the name of a variable, IF FOO THEN -- is translated as (COND (FOO --» even if FOO is also the name of a function. If the functional interpretation is intended, FOO should be ene losed in parentheses, e.g., IF (FOO) THEN --. Similary for IF -- THEN FOO ELSElf If occasionally interacting with the user to resolve ambiguous cases. 23.17 consequents, and is equivalent ,to (IF -- THEN (FOo.-X) Y ELSE __ ).80 Iterative Statements 23.7 The following is an example of a CLISP iterative statement: (WHILE X"(REAI»-='STOP DO (PRINT (EVAL X») This statement says "READ an expression and set X to it. If X is not equal to the atom STOP, then evaluate X, print the result, and iterate."a7 The i.s. (iterative statement) in its various forms permits the user to specify complicated Rather than iterative the statements in a straightforward and visible manner. user having to perform the mental transformations to an equivalent INTERLISP form using PROG, MAPC, MAPCAR, etc., the system does it for him. The goal was to provide a robust and tolerant facility which could "make sense" out of a wide clilss of iterative statements. Ac'cordingly, the user should not feel obliged to read and understand in detail the description of each operator given below in order to usc iterative statements. Currently, the following i. s. operators are implemented: FOR, BIND, OLD, IN, ON, FROM, TO, BY, WHEN, WHILE, UNTIL, UNLESS, COLLECT, JOIN, 00, SUM, COUNT, ALWAYS, NEVER, THEREIS, AS, FIRST, FINALLY, EACHTIME. Their function is 36----------------------------------------------------------------------------To write the equivalent of a singleton cond clause, i.e., a clause with a predicate but no consequent, write either nothing following the THEN, or omit the THEN entirely, e.g., (IF (FOO X) THEN ELSEIF --) or (IF (FOO X) ELSEIF --), meaning if (FOO X) is not NIL, it is the value of tho condo 37 Tho statement translates to: (PROG NIL SSLP (COND «EQ (SETQ X (READ» (PRINT (EVAL X» (GO SSLP» 23.18 (QUOTE STOP» (RETURN») explained below. Misspellings of New operators can be defined as described on page 23.28. operators are recognized and corrected. The order of appearance of operators is not impo~tant;38 CLISP scans the entire statement before it begins to construct the equivalent INTERLISP form. 00 form specifies what is to be done at each iteration. other operator specifies an infinite loop. 00 with no If some explicit or implicit terminating condition is specified, the value of the i.s. is NIL. Translate to MAPC or MAP whenever possible. COLLECT form like DO, except specifies that the value of form at each iteration is to be collected in a list, which is returned as the value of the i.s. when it terminates. Translates to HAPCAR or HAPLIST whenever possible. J!OIN form SUM form like 00, except that the values are NCONCed. HAPCONC or HAPCON whenever Possible. 39 Translates to like 00, except specifies that the values of form at each iteration be added together and returned as the value of the i.s., e.g. (FOR I FROM 1 TO 5 SUH 1'2) is equal to 1+4+9+16+25. 40 38---------------'-------------------------------------------------------------nWIM and CLISP are invoked on iterative statements because car of the i.s. is not tho namo of a function, and hence generates an erro~ If the user defines il function by the sarno name as an i.s. operator, e.g. WHILE, TO, etc., the operator will no longer have the CLISP interpretation when it appears as car of a form, al though it will continue to be treated as an i.s. operator if it appears in the interior of an i.s. 39 INCONC, IHAPCONC, and IHAPCON are used when the declaration UNOOABLE is in effect. 40 iplus, fplus, or ,Rlus will be used for the translation depending on the declarations in effect. 23.19 COUNT pred 1 ike DO, except counts number of times that pred is true, and returns that count as its value. ALWAYS pred like DO, except returns T if the value of pred is non-NIL for all i terclltions (returns NIL as soon as the value of pr'ed is NIL), e.g. (FOR X IN Y ALWAYS (ATOM X» is the same as (EVERY Y (FUNCTION ATOM». like ALWAYS, except returns T if the value of pred is neuer NEVER pred true, i.e. NEVER pred is the same as ALWAYS -pred. THEREIS pred returns the first value of the non - NIL, first e . ~l • number i.v. for which (FOR X IN Y THEREIS NUMBERP) in v, is and pred returns equivalent is the to (CAR (SOME Y (FUNCTION NUMBERP»).41 00. COLLECT, JOIN, SUM, ALWAYS, NEVER, and THEREIS are ,examples of a certain kind of i.s. operator called an i.s.type. done at each iteration. function i.s.type, page The i.s.type specifies what is to be Each i.s. must have one and only one i.s.type. Z3.~8, provides a means of defining The additional i.s.types. FOR var specifies the. variable of iteration, or i.v., which is used in conjunction with IN, ON, FROM, TO, and BY. The variable is rebound for the scope of the i.s., except when modified by OLD as described below. 41----------------------------------------------------------------------------THEREIS returns the i.v. instead of the tail (as does the function some) in order to provide an interpretation consistent with statements such as (FOR I FROM 1 TO 10 THEREIS _a), whore there is no tail. Note that (SOME Y (FUNCTION NUMBERP» is equivalent to (FOR X ON Y THEREIS (NUMBERP (CAR X»). 23.20 FOR vars vars a list of variables, e.g., FOR (X Y 1) IN --. The first variab Ie is the i. v., the rest are dununy var iab les . See BIND below. OLD var indicates not is e. g. , rebound, be to (FOR OLD X FROM 1 TO N DO -- UNTIL --), BIND var. vars used to specify dummy variables, e.g., FOR (X Y 1) IN equivalent FOR X BIND (Y 1) IN --. to without FOR. can be used For example, in the i.s. shown on page 23.18, could X BIND is be (BIND X WHILE made X~(READ)-='STOP local by wri ting ... ). Note: FOR, OLD, and BIND variables can be initialized by using ... , e.g., (FOR OLD (X~form) IN form BIND (Y~form) ... ). specifies that the i.s. is to iterate down a list with the i.v. being reset iteration. (HAPC Y for to the element at each FOR X IN Y DO -- corresponds example, (FUNCTION -(LAMBDA corresponding (X) --»). If no i.v. to has been specified, a dummy is supplied, e.g., IN Y COLLECT CADR is equivalent to (MAPCAR Y (FUNCTION CADR». ON forom same as IN except that the i. v. corresponding tail at each iteration. is reset to the Thus IN corresponds to HAPC, MAPCAR, and HAPCONe, while ON corresponds to MAP, MAPLIST, and HAPCON. IN OLD var specifies that the i.s. is to iterate down var:. with var itself being iteration, reset e.g., to after the corresponding tail each (FOR X IN OLD L 00 -- UNTIL --) finishes, L will be some tail of its original value. 23.21 at IN OLD (var .. form) same as IN OLD Y!!.!:. except var is first set to value of form. ON OLD var same as IN OLD var except tho i. v. is reset to the current value of var at each iteration, instead of to car[var]. ON OLD (var .. form) same as ON OLD Y!!:,. except Y!!: is first set to value of form. WHEN pred provides a way of excepting certain iterations. For example, (FOR X IN V COLLECT X WHEN NUMBERP X) collects only the elements of Y that are numbers. UNLESS pred same as WHEN except for the difference in Sign, i.e., WHEN Z is the same as UNLESS -Z. WHILE pred WHILE pred evaluates provides a way of terminating the i.s. pred before each iteration, and if the value is NIL, exits. UNTIL pred Same as WHILE except for difference in sign, i. e. , WHILE PRED is equivalent to UNTIL -PRED. UNTIL n n a number, equivalent to UNTIL (i.v. GT n). FROM form is used to specify an ini tial value for a numerical i. v. The i.v. is automatically incremented iteration (unless BV is specified). specified, a by If no 1 after i.v. each has been dummy i.v. is supplied and initialized, e.g., (COLLECT SQRT FROM 2 TO 5) returns (1.414 1.732 2.0 2.236). TO form is used to specify the final value for a numerical i.v. Zl.ZZ If FROM is not specified, the i.v. is initialized to 1. i.v. has been speCified, initialized. If BY is If no a dummy i.v. is supplied and not specified, the i.v. is automatically incremented by 1 after each iteration. 42 When the i.v. is definitely being incremented, i.e. either BY is not specified, or its operand is a positive number, the 1.5. terminates when the i.v. exceeds the value of form (which is reevaluated each iteration) e.g .• (FOR X FROM 1 TO 10 ... _), is equivalent to (FOR X FROM 1 UNTIL (X GT 10) _e). Similarly, when the i.v. is definitely being decremented the i.s. terminates when the i.v. becomes less than the value of form (see description of BY). BY x (with INION) If IN or ON have been specified, the value of ~ determines the tai I for the next iteration, which 1n turn determines the value for the i. v. as described earl ier. i. e. the new i .v. is ~ of the tail for IN, the tail itself for ON. In conjunction with IN, the user can refer to the current tail within x by (FOR Z IN L BY (CDOR of the using !) ... ). the e.g. i. v., At translation time, the name internal variable which holds the value of the current tail is substituted for the i.v. throughout x. For example, (FOR X IN Y SY (CDR (MEMS 'FOO (COR X») COLLECT X) specifies that after each iteration, cdr of the current tail is to be searched for the atom FOO, and (cdr of) this latter tail to be used for the next iteration. 42----------------------------------------------------------------------------except when both the operands to TO and FROM are numbers, and TO's operand is less than FROM's operand, e.g. FROM 10 TO 1, in which case the i.v. is decremented by 1 after each iteration. In this case, the 1.5. terminates when the i.v. becomes less than the value of form. 23.23 BY x (without INION) If IN or ON have not been used, BY specifies how the If FROM or TO have i.v. itself is reset at each iteration. been specifiEtd, the i. v. is known to be numerical, so the new i. v. llS computed by adding the value of x (which is reevaluated each iteration) to the current value of the i.v., e.g., (FOR N FROM 1 TO 10 BY 2 COLLECT N) makes a list of the first five odd numbers. If ~ is a pClsitive number,43 the i.s. terminates when the value of the i. v. exceeds the value of' TO' s operand. If ~ is a negative number, the i.s. terminates when the value of the i.v. becomes than less operand, TO's (FOR I FROM N TO M BY -2 UNTIL (I LT M) ... ). e.g. Otherwise, the terminating condition for each iteration depends on the value of ~ < 0, the test is whether operand, if x > 0 the test is for that iteration: if the i. v. is less than TO' 5 ~ whether the i.v. exceeds TO's operand. otherwise if ~=O, the i.s. terminates unconditionally.44 If FROM or TO have not been specified, the i.v. is simply reset to the value of x (FOR I FROM N BY 2 ... ) (FOR I~N after is each iteration, equivalent e.g. to . BY (IPLUS I 2) ... ). 43----------------------------------------------------------------------------x itself, not its value, ,,,hich in general CLISP would have no way of knowing in advance. 44 A temporary variable is used so that x is only evaluated once. However, codo for TO's operand appea."s twice in- the translation, even though it is evaluated only once. 23.24 FIRST form form is evaluated once before the first iteration, e.g. (FOR X Y Z IN L -- FIRST (FOO Y Z», and FOO could be used to initialize Y and Z •. FINALLY form form is evaluated after the i.s. terminates. 45 For example, (FOR X IN L BIND FINALLY (RETURN EACHTIME form 00 (IF ATOM X THEN Y~O V»~ Y~Y+1) will return the number of atoms in L. form is evaluated at the beginning of each iteration before, and regardless of, any testing. For example, consider (FOR I FROM 1 TO N 00 (... (FOO I) ... ) UNLESS (... (FOO I) ..• ) UNTIL ( ... (FOO I) ••• ». The user might want to set a temporary variable to the value of (FOO I) in order to avoid computing it three times each iteration. However, wi thout knowing the translation, he would not know whether to put the assignment in the operand to 00, UNLESS, or UNTIL, i.e. which one would be executed first. problem by simply writing EACHTIME AS var He J~(FOO can avoid this I). is used to specify an iterative statement involving more than one iterative variable, (FOR X IN Y AS U IN V 00 --) corresponds to maple. e.g. The i.s. terminates when any of the terminating conditions are met, e.g. (FOR X IN Y AS I FROM I TO 10 COLLECT X) makes a list of the first ten elements of Y, or however many elements there are on Y if less than 10. ~i5--------------------------------~------------------ -------------------------- Except in the case of termination due to the appearance of a RETURN in some operand. See page 23.26. Thus in (FOR X IN Y THEREIS NUMBERP FINALLY --) the FINALLY operand would be evaluated if Y were exhausted, but not if a number was found. 23.25 The operand to AS. ~, specifies the new i. v. For the remainder of the i.s., or until another AS is encountered, all operators refer to the new i. v. For example. (FOR I FROM I TO Nt AS J FROM t TO N2 BY 2 AS K FROM N3 TO 1 BY -1 --) terminates when I exceedsNl, or J exceeds N2, or K becomes less than 1. After each iteration, I is incremented by I, J by Z, and K by -1. Miscellaneous 1. Lowercase versions of all i.s. operators are equivalent to the uppercase, e • 9 ., 2. (for X in Y ... ). Each 1.s. operator is of lower precedence than all INTERLISP forms, so parentheses around the operands can be omitted, and will be supplied where necessary, e.g., BIND (X Y Z) can be written BIND X Y Z, OLD (X... form) as OLD X"'form, WHEN (NUMBERP X) as WHEN NUMBERP X. etc. 3. RETURN or GO may be used in any operand. RETURN means return from the i.s. (with the indicated value), not from the function in which tho i.S appears. GO refers to a label elsewhere in the function in which the i.s. appears, except for (GO ITERATE), which means transfer control to the iterate portion of the loop, i.e. that part that resets the tail, increments the counter, or whatever, in preparation for the next iteration. The appropriate label will be substituted for ITERATE. 4. In the case of FIRST, FINALLY, EACHTIME, or one of the i.s.types, e.g. 00, COLLECT, SUM, etc., the operand can consist of more than one form, e.g., COLLECT (PRINT X:l) X:2, in which case a PROGN is supplied. 5. Each operand can be the name of a function, in which case it is applied to 23.26 the ( las t) 1. v. ,46 47 48 e. g. ; FOR X IN Y 00 PRINT WHEN NUMBERP, is the same as FOR X IN Y 00 (PRINT X) WHEN (NUMBERP X). Note that the 1. v. need not be explicitly specified, e.g., IN Y 00 PRINT WHEN NUMBERP will work. Errors in Iterative Statements An error will be generated and an appropriate diagnostic printed if any of the following conditions hold: 1. Operator with null operand, i.e. two adjacent operators, as in FOR X IN Y UNTIL DO 2. Operand consisting of more than one form (except as operand to FIRST. FINALLY, or one of the i.s.types), e.g., FOR X IN Y (PRINT X) COLLECT 3. Same operator appears twice. 4. Both IN and ON used on same i.v. 5. FROM or TO used with IN or ON on same i.v. 6. More than one i.s.type, e.g. a 00 and a SUM. In 3, 4, or 5, an error is not generated if an intervening AS occurs. If an error occurs. the i.s. is left unchanged. 46-" F~~ -~~ ~~ ~~~)~~: . -e-.-g-."- ~~~"~~~~E~~:-~O-I~-,--;h";"i~~~~~~~-~~" ~"l~~-Y"S- -~;;~i;~ -~~ the first i.v. in the i.s., whether explicity named or not. for example, (IN Y AS I FROM 1 TO 10 00 PRINT) prints elements on Y, not integers between 1 and 10. 47 Note that this feature does not make much sense for FOR, OLD, BIND, IN, or ON, since they "operate- before the loop starts, when the i.v. may not even be bound. In the case of BY in conjunction wi th IN, the function 1s applied to the current tail e.g., FOR X IN Y BY COOR .•.• 1s the same as FOR X IN Y BY (COOR X) ... See page 23.23. 23.27 If no DO, COLLECT, JOIN or any of the other i.s.types are specified, CLISP will first attempt FOR X IN Y is find an operand, consisting of more than one i£!~JNT-1U first form. error to WHEN ATOM X, and in this case will insert II form, 00 after tho (In this case, condition 2 is not considered to be met, and an not generated.) I feL ISP cannot find such an operand, 15 still translated. e.'!}. (WHILE form) can be used warning a However, the message is printed: NO DO, COLLECT, OR JOIN: followed by the i.s. 1.5. e.g., execute to form repeatedly until its value is NJl. Simi lar ly, UNTIL, ,TO, 1f no terminating t:ondi tion is detected, or a RETURN or GO, a warning POSSIBLE NON-TERMINATING ITERATIVE STATEMENT: i . e. no IN, ON, WHILE, message is printed: followed by the 1.s. However, since the user may be planning to terminate the i.s. via an error. control-E, or a retfrom from a lower function. the i.s. is still translated. Defining New Iterative Statement Operators The i.s.type specifies what is to be done at each iteration, e.g. collecting values on a list, adding numbers. searching for a particular condition, etc. Each i.s. can have one and only one i.s.type. The function i.s.type provides a means of defining new i.s.types. i.s.type[namo;form;init;val] nar~ is the name of the i.s.type. form to be evaluated at each iteration. forD! is the In form SSVAL can be used to reference the value being assembled, I. V. to reference the current value of the 1. v., BODY to reference the body of the s ta ternen t, and i .e • name's operand. For example. for COLLECT, form would be (SETQ SSVAL (NCPNCl SSVAL BODY», for 23.28 SUM: (SSVAL~SSVAL+800y),49 for HEVER: (AND BODY (RETURN NIL», and for THEREIS: (AND BODY (RETURN I.V.». ini t specifies the initial value for SSVAL, e. g. SUH, init is O. for val specifies the value to be returned when the i.s. terminates. i.s.type is undoable. Examples: 1) To define RCOLLECT, a version of COLLECT which uses cons instead of nconc1 and then reverses the list of values: i.s.type[RCOLLECT;(SETQ SSVAL (CONS BODY SSVAl»;NIL;(DREVERSE SSVAl)] 2) To define TCOLLECT, a version of COLLECT which uses tconc: i.s.type[TCOLLECTj(TCONC SSVAL BODY); (CONS); (CAR SSVAL)] 3) To define PRODUCT: i.s.type[PRODUCT;(SSVAL~SSVAL*BOOY);l;SSVAL] i.s.type performs the appropriate modifications to the property list for ilS ~, well as for the lower case version of name, and also updates the appropriate spell-ing lists. !.s.type can also be used to define synonyms for all i.s. operators, (not just those that are i.s.types). by calling i.s.type with i.s.type[WHERE;WHEN] makes WHERE be the same as WHEN. forman atom, e.g. Similarly, following 49--$$V~~:~~~Y-;~--~;;~-~~~~~~~--;i-(i;~US-SS~;L-B~~;):-~~--;h;;-~h~--C~;;~;-~; function used in the translation, i.e. iplus, fplus, or plus, will be determined by the declarations then in effect. 23.29 i.s.type[ISHIERE;THEREIS] one i.s.type[FINO;FOR] and can write (ISTHERE ATOM IN V). i.s.type[SUCHTHAT;THEREIS]. one and following can write (FINO X IN Y SUCH THAT X MEMBER Z).60 This completes the description of iterative statements. 23.8 CLISP Trunsl~tions The translation of infix operato~s CLISP CLISP by replacing the and IFITHENIELSE statements are handled in expr~ssion with the corresponding INTERLISP expression, and discarding the original CLISP, because (1) the CLISP expression is easily recomputable (by clis:.l!..!.!.l), 61 and (2) the INTERLISP expressions are simple and straightforward. In addition to saving the space required to retain both the CL ISP and the INTERL ISP. another reason for discarding the original CLISP is that it may contain errors that were corrected in the course of translation, e.g. the user writes FO~FOOO:l, N-8FOO X), etc. If the original CLISP were retained, either the user would have to go back and fix these errors by hand, thereby negating the advantage of having DWIM perform these corrections, or else DWIM would have to keep correcting these errors over and over. Where (1) or (2) are not the case, e.g. with iterative statements, pattern 50-----------------------------·----------------------------------------------In the current system, WHERE is synonymous with WHEN, SUCHTHAT and ISTHERE with THERE IS, and FINO with FOR. 61 Note that clispif~ is sufficiently fast that it is practical for the user to configur-c---fifsTNTERLISP system so that all expressions are automatically c~i~e!J~ed immediately before they are presented to him. For example, he can define an edit macro to use in place of P which calls clisp~ on the current expression before printing it. Similarly, he can inform prettyprint to call clispify on each expression before printing it, etc. 23.30 matches, record expressions, etc. 62 68 the original CLISP is retained (or a slightly modified vorsion thereof), and tho translation is stored elsewhere, usually in clisparra~, a hash array. The interpreter automatically checks this array using gethash when given a form car of which is not a function. Similarly, the compiler performs a gethash when given a form it does not recognize to see if it has a translation, which is then compiled instead of the form. Whenever the user changes a CLISP expresson by editing it, the editor automatically deletes its translation (if one exists), so that the next time it is evaluated or dwimified, the expression will be retranslated. and ~ the edit commands translations, see page 23.15. PPT and CLISP: are available The function for examining Similarly, if prettytranflg is T, prettyprint will print the translations instead of the corresponding CLISP expression. 54 If clisparray is NIL,66 translations are implemented instead by replacing the CLISP expression by expression an (CLISPX_ translation. CLISP-expression),66 e.g. of the form (FOR X IN Y COLLECT (CAR X» 62--;~~-~~~~~i;:-;~~-;;~~;i~;~~~-~~-;:;~;-~;-(~~~~~-(~~~-(~~~~~~-;»):-~~~~~-~; difficult to read. Therefore, such expressions are handled by retaining the CLISP and storing the translation elsewhere, as described below. 63 Tho handling of translations for IFITHENIELSE statements is determined by tho value of clispiftral}f!Q. If T, the translations are stored elsewhere, and the (modified) CLISP retained as described below. If NIL, the corresponding COND replaces the IFITHENIELSE expression. The initial value of clisp1ftranflg is NIL. &:1 Note that the user can always examine the translation himself by performing (GETHASU expression CLISPARRAY). 66 66 is initially NIL, and #clisparray is its size. The first time a translation is performed, a hash array of this size is created. Therefore to disable clisparra~, both it and #c11sparray should be set to NIL. cli~~arr~~ CLISP% is an atom consisting of the six ch.aracters C, L, I, S, P, and space, which must be preceded by the escape character % in ordor for it to be included as a part of an identifier. The intent was to deliberately make this atom hard to type so as to make it unlikely that it would otherwise appear in a user's program or data, since the editor and prettyprint treat it very specially, as described above. 23.31 would be replaced by (CLISPX_ (MAPCAR Y (FUNCTION CAR» the Both FOR X IN Y COLLECT (CAR X». editor and prettyprint know about CLISPX_ expressions and treat them specially by suppressing the translations: (unless prettytranflg=T, as Prettyprint described below), prints while just the editor the CLISP makes the translation completely invisible, e.g. if the current expression were the above CLISPX expression, F MAPCAR would fail to find the MAPCAR, and (3 ON) would replace IN with ON, i.e. the editor operates as though both the ClISPX_ and the MAPCAR were not there. As with translations implemented via clisparray, if the CLISP expression is changed by editing it, the translation is automatically deleted. CLISPX expressions will interpret and compile correctly: CLISP%_ is defined as an nlambda nospread function with an appropriate compiler macro. Note that if the user sets to NIL ~lisparray p he can then break, trace, or advise ClISPX_ to monitor the evaluation of iter'ative statements, pattern matches, and record operations. This technique will work even if clisparray was not NIL at the time the expressions were originally translated, since setting clisparray to NIL will effectively delete the translations, thereby causirig the CLISP expressions to be retranslated when they are first encountered. Note that if the user only wishes to moni tor the CLISP in a certain function, he can accomplish this by embedding its definition in (RESETVAR CLISPARRAY NIL .). If a ClISP% translation replaced is by expression is encountered and transferred to the hash array, just the CLISP. Setting clisparray is not NIL, the and the ClISPY._ expression prettytranflg to ClISPY._ causes prott)':print to print CLISP expressions that have been translated in the form of (ClISP%_ translation . CLISP-expression), even if the translation is currently stored in clisparray. These two features together provide the user with a way of dumping CLISP expressions together with their translations so that when reloaded (and run or dwimified). the transferred to clisparray. 23.32 translations will automatically be In summary, if prettytranflg=NIL, only the CLISP is printed (used for producing listings). If prettytranflg=T, exporting programs to systems only the translation is that do not printed provide CLISP. and (used for to examine translations for debugging purposes).67 If prettytranflg=CLISPX_, an expression of the form (CLISPX_ translation. CLISP) is printed, (used for dumping both CLISP and translations). The preferred method of storing translations is in so that if any ClISPX_ expressions are converted while clisparral .clisparr.~~, is not NIL, they will automatically be converted so as to use clisparray. !Clisparr~=NIl, If they will be left alone, and furthermore, new translations will be implemented using CLISPX_ expressions. Declarations 23.9 Declarations are used to affect the choice of INTERLISP function used as the translation of a particular operator. For example, A+8 can be translated as either (IPLUS A B). (FPLUS A B). or (PLUS A B), depending on the declaration in effect. Similarly (,1RPlACA X V). . X:l~Y can mean (FRPLACA X V), (RPLACA X Y), and (!!A B> either (NCONCl A B) or (/NCONCl A B). or The table below gives the declarations available in CLISP, and the INTERLISP functions they indicate. affcctcd by The choice oj Junction these declarations, i.e. on all CLISP transformations iteraiue statements. are pattern matche.s. record operations. as well as infix and preJix operators. The user ClISPOEC can make (change) and giving it as a global declaration by calling its argument (CLISPO[C (QUOTE (FLOATING UNDOABLE»). affect the speed of subsequent a list of the function declarations, e.g., Changing a global declaration does not CLISP transformations, since all CLISP 67----------------------------------------------------------------------------Noto tha t makeri Ie will reset prettytranflg to T, using resetvar, when called with the option NOCLISP. 23.33 transformation are table driven (i.e. property list), and global declarations arc accomplished by making the appropriate internal changes to CLISP at the time of tho declaration. If a function employs local declarations (described below), there will be a slight loss in efficiency owing to the fact that for each CLISP transformation, the declaration list must be searched for possibly relevant declarations. Declarations are implemented in the order that they are given, so that later declarations override earlier ones. for example, the declaration FAST specifies that FRPLACA, FRPLACD, FMEMB, and FLAST be used in place of RPLACA, RPLAcn, MEMB, and LAST; the declaration RPLACA specifies that RPLACA be used. Therefore, the declarations (FAST RPLACA RPLACD) will cause FMEMB, FLAST, RPLACA, and RPLACO to be used. Th~ initial global declaration is INTEGER and STANDARD. Table of Declarations Declaration INTERLISP functions to be used INTEGER or FIXED IPLUS, IMINUS, IDIFFERENCE, ITIMES, lQUOTIENT, ILESSP, IGREATEFlP FLOATING FPLUS, fMINUS, FDIFFERENCE, FTIMES, FQUOTIENT, LESSP, FGTP MIXED PLUS, I~INUS, DIFFERENCE, TIMES t QUOTIENT, LESSP. GREATER~t FAST FRPLACA, FRPLACD, FMEMB, FLAST, FASSOC UNDOABLE IRPLACA, IRPLACD, INCONC, INCONC1, IMAPCONC, IHAPCON STANDARD RPLACA, RPLACO, MAPCONC, MAP CON RPLACA, RPLACD, /RPLACA, ... corresponding function 23.34 HEMS, LAST, ASSOC, NCONC, NCONC1, Local Declarations The user can also make declarations affocting a selected function or functions inserting an expression of the form (CLISP: . declarations) inunediately following the argument list, i.e<.; as CADDR.of the definition. Such local by declarations take precedence over global declarations. Declarations affecting selected variables can be indicated by lists, where the first element is the name of a variable, variable. and the rest of the list the declarations For example, (CLISP: FLOATING (X INTEGER» for that specifies that in this function integer arithmetic be used for computations involving X, and floating arithmetic for all other computations. 58 The user can also make local record declarations by (ARRAYRECOR'D --). inserting etc., 1n a record the local declaration, declaration e.g. list. (RECORD --), Loca I record declarations override global record declarations for the function in which they appear. Local declarations can also be used to override the global setting of certain DWIM/CLISP parameters effective only for transformations within that function, (variable by including in the local declaration an expression of the form = value), e.g. (PATVARDEFAULT = QUOTE). The ClISP: eXJH"ession is converted to a comment of a special form recognized by CL I SP. about Whenever a CLISP transformation that is affected by declarations is to be performed in a function, this comment will be searched for a relevant declaration, and if one is found, the corresponding function will be used. Otherwise, if none are found, the global declaration(s) currently in effect will be used. - . 6,8 - -: ~ ~~~ ~ ~;I~ ~: ~~~~~ -;;;;e"" ~~; - :~~~~b~~. -i~~"e-l"f-"~;" ~~ - ~-p"e-;a-;d-." - - ;~; - ;~;~~ i; ~ with the declaration (FLOATING (X INTEGER» in effect, (FOO X)+(FIE X) would translate to FPLUS, i.e., use floating arithmetic, even though X nppears somewhere inside of the operands, whereas X+(FIE X) would translate to IPLUS. I f there are declarations involving both operands, e. g. X+Y, with (X FLOATING) (Y INTEGER), whichever appears first in the declaration list will he used. 23.35 Local declarations are effective in the order that they are given, so that declarations later can be used to override earlier ones, e.g. (CLISP: FAST RPLACA RPLACO) specifies that fMEMB, fLAST, RPLACA, and RPLACO be used. An exception to this is that declarations for specific variables take precedence of general, function-wide declarations, regardless of the order of appearance, as in (CLISP: (X INTEGER) FLOATING). Cl ispi fy- also checks the declarations in effect before selecting an infix operator to ensure that the corresponding CLISP construct would translate back to this form. in fact For example, if a FLOATING declaration is in effect, clispify will convert (FPlUS X Y) to X+Y, but leave (IPLUS X Y) as ,is. Note that if (FPlUS X Y) is CLISPIFVed while a FLOATING declaration is under effect, and then the declaration is changed to INTEGER, when X+Y is translated back to INTERLISP, it will become (IPLUS X V). The Pattern Match Compilar 69 23.10 CLISP contains a fairly general pattern match facility. The purpose of this pattern match facility is to make more convenient the speCifying of certain tests that would otherwise be clumsy to write (and not as intelligible), by allowing the user to give instead a pattern which the datum is supposed to match. Essentially, the user writes "Does the (expression) X look like (the pattern) P?" For example, X:(& 'A -- 'B) asks whether the second element of X is an A, and the last element a B. performed by computing (once) 1~he The implementation of' the matching is equivalent INTERLISP expression which will perform the indicated operation, and substituting this for the pattern, and not by invoking each time a general purpose capability such as that found in FLIP ~~--T------------------------------------------------------------------~-------- he pattern match compiler was written by L. M. Masinter. 23.36 or PLANNER. (AND for example, (EQ (CADR X) (QUOTE A» the translation (EQ-(CAR (LAST X» of X:(& fA -- '8) (QUOTE B»).' Thus is: the CLISP pattern match facility is really a Pattern Compiler, and the emphasis in its design and implementation has been more on the efficiency of object code than on generality and sophistication of its matching capabilities. The goal was to provide a facility that could and would be used even where efficiency was paramount, e.g. in inner loops. As a result, the CLISP pattern match facility does not contain (yet) some of the more esoteric features of other pattern Inatch languages, patterns, such recursion, as repeated patterns, disjunctive etc. However, the user can be and conjunctive confident that what facilities it does provide will result in INTERLISP expressions comparable to those he would generate by hand. 60 The syntax for pattern match expressions is form:pattern, where pattern is a list as described below. patterns, i.e., the As with iterative statements, corresponding INTERlISP expressions, flisparray, a hash array, as described on page 23.30. form:pattern, is replaced (MATCH form WITH pattern). by an the translation of are stored in The original expression, expression of the CLISP also recognizes expressions input form in this form. If form appears more than once in the translation, and it is not either a vari able. or an expression that (CDDR Z), etc., is easy to (re )compute, such as (CAR Y). a dummy variable will be generated and bound to the value of form so that .torm is not evaluated a multiple number of times. for example, the translation of (FOO X):(S 'A S) is simply (HEMB (QUOTE A) (FOO X», while the translation of (Foo X):('A '8 --) is: 60---------------------------------------------------------------------------Wherever possible, already existing INTERLISP functions are used in the translation, e.g., the translation of (S 'A S) uses HEHB, (S ('A S) S) uses ASSOC, etc. 23.37 [PROG (SS2) (RETURN (AND (EQ (CAR (SETQ SS2 (FOO X») (QUOTE A» (EQ (CADR SSZ) (QUOTE Bl. In the interests of efficiency, the pattern match compiler assumes that all lists end in NIL, i.e. there aro no LISTP checks inserted in the translation to check tails. For example, (AND (EO (CAR X) (QUOTE A» (A . B). translation the X:( 'A & --) of is (COn X». which will match with (A B) as well as Similarly. the pattern match compiler does not insert LISTP checks on elements, e.g. X:«'A --) --) translates simply as (EO (CAAR X) (OU01E A», and X: «S1 S1 --) --) as (CODAR X) .61 Note that the user can explicitly insert LISTP checks himself by using @. as described on X:«S1 S1 --)@lISTP --) translates as (AND (LISTP (CAR X» page 23.40, e.g. (CDDAR X». Pattern Elements A pattern consists of a list of pattern elements. Each pattern element is said to match either an element of a data structure or a segment. (cf. the editor's pattern matcher, "--" matches any arbitrary segment of a list, while & or a subpattern match only one element of a list.) Those patterns which may match a· segment of a list are called SEGMENT patterns; those that match a single element are called ELEMENT patterns. 61------------------------------·----------------------------------------------The insertion of LISTP checks for elements is controlled by the variable pi!_~LL~~p~h!:ck. X:« When ~atlistpcheck 'A --) --) translates as: is T, LISTP checks are inserted, e.g. (AND (LISTP X) (LISTP (CAR X» (EQ (CAAR X) (QUOTE A»). is initially NIL. Its value can be changed within a particular function by using a local declaration, as described on page ~atlistpcheck 23.35. 23.38 Element Patterns There are several types of element patterns, best given by their syntax: PATTERN MEANING 51. or & matches an arbitrary element of a list 'expression matches only an element which is equal to the given expression e.g., tA,62 t(A B). =form matches only an element which is equal to the value of form, e.g., =X, =(REVERSE V). ==form same as =, but uses an atom treatment depends on setting of ~ check instead of equal. ~atvardefault. If ~atvardefault is ' or QUOTE, same as 'atom. If ~atvardefault is = or EQUAL, same as =atom. If ~atvardefault is == or EQ. same as ==atom . If ~atvardefault is .. or SETQ, same as atom..&. ~atvardefault is initially =.68 Note: numbers and strings are always interpreted as though =, regardless of its setting. involving small ~, ~atvardefault were memb, and assoc are used for comparisons i~tegers. 62----------------------------------------------------------------------------!,~q, mcmb, and assoc are automatically used in the translation when the Quoted expression is atomic, otherwise equal, member, and sassoc. 63 p-atvardefault can be changed within a particular function by using a local declaration, as described on page 23.35. 23.39 matches a list (pattern 1 ... pattern n ) n ~ 1 patterns, e.n., (& &), (-- 'A). element-pattorn@function-object matches an which element if matches the given the element-pattern matches it, and the function-object (name of a functibn or a LAMBOA expression) applied to that element returns non-NIL, e.g. &@NUMBERP matches a number, ('A --)@FOO match~s a list whose first element is A, and for which FOO applied to that list is non-NIL. 64 matches any arbitrary If elemont. succeeds, the element which matched the the * entire match will be returned as the value of the match. Note: normally. the pattern match compiler constructs an expression whose value is guaranteed to be non-NIL However, if a if tho match succeeds and NIL if .it fails. * appears in the pattern, the express·ion generated will either return NIL if the match fails, or whatever matched the - even though that may be (AND NIL. (EQ For eXelmple, X:( 'A (COR X) (CADR X». (CAR X) (QUOTE A» -element-pattern matches an element if element-pattern, e.g. the -'A, * --) element -=X, translates is not matched as by -(-- 'A --). 64----------------------~------------------------------------------------------ For 'simple' tests, attempted with the (AND (LISTP (CAR X» the function-object is applied before a match is pattern, e.g. «-- 'A --)@LISTP --) translates as (MEMB (QUOTE A) (CAR X»), not the other way around. 23.40 Segment Patterns of zero The difference between $ and -- is in the type of search they generate. For $, matches or -- any segment of a list (including one length) . example, X:(S 'A 'B S) translates as (EQ (eADR (MEMB (QUOTE A) X» whereas X:(-- 'A 'B S) (AND (EQ SS2 (QUOTE A» (S 'A 'B S) would be translates as: [SOME X (FUNCTION (LAMBDA (SS2 SS1) (EQ (eADR SSI) (QUOTE BJ. II (QUOTE B», Thus, Is the element following the !tr~ a paraphrase of t A a B1", whereas a paraphrase of (-- 'A 'B $) would be -Is there anu A immediately followed by a B?" Note that the pattern employing $ will result in a more efficient search than tha t employing (X Y Z A M N 0 A B Essentially. searching, once However. e). a (S' A 'B S) wi 11 not rna tch wi th but (-- 'A 'B S) will. pattern whereas following produces a a $ matches, translation that searching until there is no possibility of success. the $ will never always resumes continue However, if the pattern match compilor can deduce from the pattern that continuing a search after a particular failure cannot possibly succeed, then the translations for both -nnd :& will be the same. For example. both translate as (eDDDR (MEMB (QUOTE A) X», X:(S 'A S3 $) and (-- 'A S3 --) because if there are not three (!lements following the first A, there certainly will not be three elements following subsequent A's, so there is no reason to continue searching, even for Similarly, (S 'A S2, $3, etc. $ 'B S) and (-- 'A -- '8 --) are equivalent. matches a segment of the given length. Note that $1 is not a segment pattern. !element-pattern matches any segment which the given element pattern would match as a list. For example, 23.41 if the value of FOO is !=FOO will match the segment ... ABC (A B C) Note that !. is permissible and means etc. Value-of-match~$, e.g. X:(S 'A ,.) translates to (COR (MEMB (QUOTE A) X». Note: since ! appearing in front of the last pattern specifies a match with some tail of the given expression, it also makes sense in this case for a ! to appear in front of a pattern that can only match with an atom, e.g., (S2 ! 'A) means match if cddr of the expression is the atom A. Similarly, X: ($ r"A) translates to (EQ (COR (LAST X» !atom treatment (QUOTE A». depends on setting or QUOTE, patvardefault, is I discussion) . patvardefault !=atom. If of patvardefault. same as as If patvardefault is == or EQ, same as !==atom. If ~ or SETQ, same as = or (see above same patvardefault is is ! 'atom If EQUAL, atom~$. The atom '.' is treated exactlu like! .66 In addition, if a pattern ends in an atom, the '.' is first changed to !. e.g., (S1 . A) and (S1 ! A) are equivalent, even though the atom I . , does not explicitly appear in the pattern. Segment-pattern@function-object matches it, matches and the corresponding segment a segment function (as a if the object list) segment-pattern applied returns to non-NIL, the e.g. ~~----------------------------------------------------------------------------- Wi th one exception. namely '.' preceding an assignment does not have the interpretation tha'~ ! has proceding an assignment (see page 23.43). For example, X:( 'A • FOO~'B) , translates as: (AND (EQ (CAR X) (QUOTE A» (EQ (CDR X) (QUOTE B» (SETQ Faa (COR X»), but X:( 'A ! FOO~'B) translates as: (AND (EQ (CAR X) (QUOTE A» (NULL (COOR X» (EQ (CAOR X) (QUOTE B» (SE TQ8)0 (COR X»). special 23.42 (S@COOR '0 S) matches (A B C 0 E) but not (A B 0 E), since CODR of (A B) is NIL. an Note: @ pattern applied to a segment will require computing the corresponding structure (with ldiff) each time the predicate is applied (except when tho segment in question is a tail of the list being matched). Assignments Any pat tern element may be preceded by a variable and a .... , meaning if the match succeeds (i.e., everything that pattern mat~hes). matc'fe~ X,:(S2 Y"'S3) will set Y to (C 0 E). entire match has succeeded. For element. what Thus, the variable given is to be set to example, if match with = (A B C 0 E), Assignments are not performed until the assignments cannot be used to specify a search for an element found earlier in the match, e.g. not X (A ABC ... ). 67 This type of match X:(Y"SI =Y __ )66 will is achieved by using place-markers, described below. If the variable is preceded by a !, ~he assignment is to the tail of the list as of that point in the pattern, i.e. that portion of the list matched by the remainder of the pattern. For example, if X is (A BCD E), X:(S !Y.. 'e '0 S) sets Y to (C 0 E), i.e. cddr of X. In other words, when precedes an assignment, it acts as a modifier to the .. , and has no effect whatsoever on the pattern itself, e.g. X:( 'A 'B) and X:('A !FOo..'B) match identically, and in the latter case. FOa will be set to CDR of X. 60---------------------------------------------------------------------------The translation of this pattern is: (COND «ANO (CDR X) (EQUAL (CADR X) (SETQ Y (CAR X» V»~ T». The AND is because if Y is NIL, the pattern should match with (A NIL), but not with just (A). The T is because (CAR X) might be NIL. unless, of course, the value of Y was A before the match started. 23.43 Note: *~pattern-element X:(S tA *~( and !*~pattern-element are acceptable, e.g~ '8 --) --) translates as: [PROG (SS2) (RETURN (AND (EQ (CAAOR (SETQ SS2 (MEMB (QUOTE A) X») . ,(QUOTE B» (CADR SS2] Place-markers Variables of the form In, !l a number, are called place-markers, interpreted specially by the pattern match compiler. and are Place-markers are used in a pattern to mark or refer to a particular pattern element. Functionally. they are used like ordinary variable!s, i.e. they can be assigned values, . or used freely in forms appearing in the pattern, e.g. the list (2 3). X:(#l~Sl =(ADDI II» will match However, they are not really variables in the sense that they are not bound, nor can a function called from within the pattern expect to be able to obtain their values. For convenience" regardless of the setting of patvarderault, the first appearance of a defaulted, place-marker is interpreted as though patv~rdefault as X:(#l =(ADDI /1». were ~. Thus the above pattern could have been written Subsequent appearances of a place-marker are interpreted as though patvardefault were =. For example, X:(II #1 --) is equivalent to X:(#l~Sl =#1 --), and translates as (AND (CDR X) (EQUAL (CAR X) (CAOR X».68 Replacements Any pattern element may be followed by a succeeds, I~' and a form, meaning if the match the part of the data that matched is to be replaced (e.g., with ~~----------------------------------------------------------------------------- Just (EQUAL (CAR X) (CADR X»),would incorrectly match with (NIL). 23.44 RPlACA or RPLACO)69 with the value of
Source Exif Data:
File Type : PDF File Type Extension : pdf MIME Type : application/pdf PDF Version : 1.3 Linearized : No XMP Toolkit : Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:56:37 Create Date : 2002:03:04 15:18:43Z Creator Tool : g4pdf Modify Date : 2014:10:16 11:24:56-07:00 Metadata Date : 2014:10:16 11:24:56-07:00 Producer : Adobe Acrobat 9.55 Paper Capture Plug-in Format : application/pdf Document ID : uuid:5b3d7d79-4f76-bc4d-834c-4548c63f546d Instance ID : uuid:382b16b2-b3df-3e48-b9da-ffeaea46c5a9 Page Layout : SinglePage Page Mode : UseOutlines Page Count : 715 Creator : g4pdfEXIF Metadata provided by EXIF.tools