{Begin Chapter How To Use Interlisp} {Title How To Use Interlisp} {Text {note this chapter needs extensive work!!} {note intro paragraphs needed on: Interlisp is an interactive program development system, as compared to a simple compiler. The user starts Interlisp running, and then proceeds to give it commands to define functions, test functions, and interact with local o r remote files. Then, the user stops Interlisp, which can save the exact state of the Interlisp environment...} {Begin SubSec Starting/Stopping Interlisp} {Title Starting/Stopping Interlisp} {Text {note this section should be largely replaced with material from the users guide} Call Interlisp by typing LISP followed by a carriage return. Interlisp will type an identifying message, the date, and a greeting, followed by a "←".{index *PRIMARY* ← (Printed by System)} This prompt character{index *PRIMARY* prompt character} indicates that the user is "talking to" the top level Interlisp executive, called {fn EVALQT},{index *PRIMARY* EVALQT FN} (for historical reasons), just as "@" indicates the user is talking to the operating system.{index TENEX} {fn EVALQT} calls {fn LISPX} which accepts inputs in either {fn EVAL}{index eval format} or {index APPLY format}{fn APPLY} format: if just one expression is typed on a line, it is {fn EVAL}uated; if two expressions are typed, the first is {fn APPLY}-ed to the second. {fn EVAL}{index EVAL FN} and {fn APPLY}{index APPLY FN} are described in Section 8. In both cases, the value is typed, followed by "←" indicating Interlisp is ready for another input. {FnDef {FnName LOGOUT} {FnArgs } {Text returns control to operating system.{foot In Interlisp-10, if Interlisp was started as a subsidiary fork (see {fn SUBSYS}, page {PageRef Tag 10}), control is returned to the higher fork. }{comment endfootnote} In Interlisp-10, a subsequent {index CONTINUE (TENEX Command)}{lisp CONTINUE} command will enter the Interlisp-10 program, return {lisp NIL} as the value of the call to {fn LOGOUT}, and continue the computation exactly as if nothing had happened, i.e., {fn LOGOUT} is a programmable control-C. {fn LOGOUT} will not affect the state of any open files. }} {Begin SubSec Sysin and Sysout} {Title Sysin and Sysout} {Text {FnDef {FnName SYSOUT} {FnArgs FILE} {Text Saves the user's private memory on {arg FILE}. Also saves the stacks, so that if a program performs a {fn SYSOUT}, the subsequent {fn SYSIN} will continue from that point, e.g., {lisp (PROGN (SYSOUT 'FOO) (PRINT 'HELLO))} will cause {lisp HELLO} to be printed after {lisp (SYSIN 'FOO)}. The value of {fn SYSOUT} is {arg FILE} (full name). A value of {lisp NIL} indicates the {fn SYSOUT} was unsuccessful, i.e., either disk or computer error, or the user's directory was full. }} {it {fn SYSOUT} does {emphasize not} save the state of any open files.{foot However, the {fn WHENCLOSE} package, page {PageRef Tag WHENCLOSE}, can be used to associate with open files certain operations to be performed when a {fn SYSOUT} is started up, including reopening the file and repositioning the file pointer. }{comment endfootnote} } {it Whenever the Interlisp system is reassembled and/or reloaded, old {fn SYSOUT} files are {fn NOT} compatible with the new system.{index FILE NOT COMPATIBLE Error} } {fn SYSOUT} is advised to evaluate the expressions on {var BEFORESYSOUTFORMS} when executing the {fn SYSOUT}, and to evaluate the expressions on {index *PRIMARY* AFTERSYSOUTFORMS Var}{var AFTERSYSOUTFORMS} when coming back from a {fn SYSIN}, i.e., when the value being returned by {fn SYSOUT} is a list. {index *PRIMARY* BEFORESYSOUTFORMS Var}{var BEFORESYSOUTFORMS} includes expressions to: {Begin Numberedlist BEFORESYSOUTFORMS expressions} {item set the variable {index SYSOUTDATE Var}{var SYSOUTDATE} to {lisp (DATE)}, i.e. the time and date that the {fn SYSOUT} was performed; } {item if {arg FILE} is non-{lisp NIL}, to set the variable {var SYSOUTFILE} to (the body of) {arg FILE}. If {arg FILE} is {lisp NIL}, the value of {index SYSOUTFILE Var}{var SYSOUTFILE} is used instead. Thus, after an initial {fn SYSOUT}, the user can simply perform {lisp (SYSOUT)} to save the current state on the next higher version of a file with the same name as the previous {fn SYSOUT}; } {item if an extension and a version number are not specified, to use the value of {index SYSOUT.EXT Var}{var SYSOUT.EXT} as the extension (initially {lisp .SAV} for Tenex sites and {lisp .EXE} for TOPS-20 sites.) } {item to perform any necessary operations associated with open files specified by calls to {fn WHENCLOSE} (page {PageRef Tag WHENCLOSE}). } {End Numberedlist BEFORESYSOUTFORMS expressions} {var AFTERSYSOUTFORMS} includes expressions to: {Begin Numberedlist AFTERSYSOUTFORMS expressions} {item reset the terminal linelength appropriately (see discussion of {fn SETLINELENGTH} on previous page); } {item reset the terminal control characters if the systemtype has changed, i.e. from TENEX to TOPS-20 or vice versa. } {item if the value of {index SYSOUTGAG Var}{var SYSOUTGAG} is {lisp NIL} (its initial value), and the {fn SYSOUT} was made by the same user that is performing the {fn SYSIN}, to greet the user by printing the value of {index *PRIMARY* HERALDSTRING Var}{var HERALDSTRING} followed by a greeting message. If the {fn SYSOUT} was made by a different user, to warn the user that the user profiles may be different (see Section 22 on Greeting and User Profiles), e.g. {lispcode ****ATTENTION USER LEWIS: THIS SYSOUT IS INITIALIZED FOR USER HARTLEY. TO REINITIALIZE, TYPE GREET(). } if the value of {var SYSOUTGAG} is a list, to evaluate the list in lieu of printing a message. This permits the user to print his own message. for all other non-{lisp NIL} values of {var SYSOUTGAG}, no message is printed. } {item call {fn SETINITIALS}{index SETINITIALS FN} to reset the initials used for time-stamping (Section 9). {Begin Note} The function SETINITIALS is not formally defined anywhere. According to the index, it is only mentioned on page 14.37 ---mjs Date: 20 SEP 1979 1351-PDT From: TEITELMAN Subject: SETINITIALS was not setting initials or firstname undoably. now fixed. {End Note} } {item perform any necessary operations associated with previously opened files specified by calls to {fn WHENCLOSE} (page {PageRef Tag WHENCLOSE}). } {End Numberedlist AFTERSYSOUTFORMS expressions} {FnDef {FnName SYSIN} {FnArgs FILE} {Text restores the state of Interlisp from a {fn SYSOUT} file.{foot In Interlisp-10, {arg FILE} is a {it runnable} file, i.e., it is not necessary to start up an Interlisp and call {fn SYSIN} in order to restore the state of the user's program. Instead, the user can treat the sysout file the same as a {lisp SAV} file, i.e., use the operating system {lisp RUN} command, or simply type the file name to the operating system, and the effect will be exactly the same as having performed a {fn SYSIN}. }{comment endfootnote} Value is {lisp (CONS {arg FILE} {arg MAKESYS})}, where {arg MAKESYS} is the name of the parent system.{foot {fn SYSOUT} only saves that portion of the user's environment which is private (see Section 3.4 on Shared Interlisp). }{comment endfootnote} If {fn SYSIN} returns {lisp NIL}, there was a problem in reading the file. If {arg FILE} is not found, generates a {lisp FILE NOT FOUND}{index FILE NOT FOUND Error} error. }} {it Since {fn SYSIN} continues immediately where {fn SYSOUT} left off, the only way for a program to determine whether it is just coming back from a {fn SYSIN} or from a {fn SYSOUT} is to test the value of {fn SYSOUT}. } For example, {lisp (COND ((LISTP (SYSOUT 'FOO)) (PRINT 'HELLO)))} will cause {lisp HELLO} to be printed following the {fn SYSIN}, but not when the {index SYSOUT FN}{fn SYSOUT} was performed. {FnDef {FnName SYSOUTP} {FnArgs FILE} {Text predicate for determining whether {arg FILE} is a sysout file. Returns the name of the parent {fn MAKESYS} (Section 3) if the {arg FILE} is a {fn SYSOUT} file, {lisp NIL} otherwise.{foot In Interlisp-10, {arg FILE} can also be a JFN. }{comment endfootnote} }} }{End SubSec Sysin and Sysout} }{End SubSec Starting/Stopping Interlisp} {Begin SubSec Interacting With Interlisp} {Title Interacting With Interlisp} {Text Interlisp is normally exited via the function {fn LOGOUT}{index LOGOUT FN}, i.e., the user types {lisp (LOGOUT)}.{index control characters} However, typing control-C{index *PRIMARY* control-C} at any point in the computation returns control immediately to the operating system. The user can then {it continue} his program with no ill effects with the {index *PRIMARY* CONTINUE (TENEX Command)}{lisp CONTINUE} command, even if he interrupted it during a garbage collection.{foot Typing {lisp START} will attempt to re-enter Interlisp at top level {fn EVALQT}. However, there are many situations where this might leave the system in an inconsistent state. Thus control-C {lisp START} is definitely not adviseable unless no other recourse is available (e.g. user accidentally turns all interrupts off).} Typing control-D{index *PRIMARY* control-D} at any point during a computation will return control to {fn EVALQT}. If typed during a garbage collection, the garbage collection will first be completed, and {it then} control will be returned to Interlisp's top level; otherwise, control returns immediately. When typing to the Interlisp {fn READ} program, typing a control-Q {foot {index *PRIMARY* control-U (TOPS-20)}control-U for Interlisp-10 on TOPS-20.} {index *PRIMARY* control-Q} will cause Interlisp to print "##"{index ## (Printed by System)} and clear the line buffer, i.e., erase the entire line up to the last carriage return. Typing control-A{foot {index *PRIMARY* <del>}<del> for Interlisp-10 on TOPS-20.}{comment endfootnote}{index *PRIMARY* control-A} erases the last character typed in, echoing a \{index \ (Printed by System)} and the erased character. Control-A will not back up beyond the last carriage return. Typing control-W{index *PRIMARY* control-W} within a call to {fn READ} or {fn READLINE} will erase the last {it expression} typed, echoing a \\.{index \\ (Printed by System)} Control-W {it will} back up to previous lines. Control-O{index *PRIMARY* control-O} can be used to {it immediately} clear the output buffer{index clearing output buffer}, and <del>{index *PRIMARY* <del>} to {it immediately} clear the input buffer.{index clearing input buffer}{foot The action of control-Q takes place when it is {it read}. If the user has "typed ahead" several inputs, control-Q will only affect at most the last line of input. {index *PRIMARY* <del> (TOPS-20)}<del> {index *PRIMARY* control-Z (TOPS-20)}(control-Z on TOPS-20), however, is an interrupt character that will clear the entire input buffer as soon as it is {it typed}, i.e., even during a garbage collection.}{comment endfootnote} In addition, typing control-U{foot {index *PRIMARY* control-N (TOPS-20)}control-N for Interlisp-10 on TOPS-20.}{index *PRIMARY* control-U} will cause the Interlisp editor (Section 9) to be called on the expression being read, when the {fn READ} is completed. Appendix 1 contains a list of all control characters, and a reference to that part of the manual where they are described.{index control characters} Section 16 describes how the system's interrupt characters{index interrupt characters} can be disabled or redefined, as well as how the user can define his own interrupt characters.{index user interrupt characters}{index control characters} Since the Interlisp read program is normally{index line-buffering} line-buffered to make possible the action of control-Q,{foot Except following {index CONTROL FN}{lisp (CONTROL T)}, see Section 14.}{comment endfootnote} the user must type a carriage return before any characters are delivered to the function requesting input, e.g., {lispcode ←E T{CRsymbol} T } However, the read program {it automatically} supplies (and prints) this carriage return when a matching right parenthesis is typed, making it unnecessary for the user to do so, e.g., {lispcode ←CONS(A B) A . B } The Interlisp read program treats square brackets as "super-parentheses": a right square bracket{index *PRIMARY* ] (use in input)}{index square brackets (use in input)} 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., {lisp (A (B (C]} = {lisp (A (B (C)))}, {lisp (A [B (C (D] E)} = {lisp (A (B (C (D))) E)}. %{index % (escape character)} is the universal escape character{index escape character} for {fn READ}. Thus to input an atom containing a syntactic delimiter, precede it by %, e.g., {lisp AB% (C} or %%. See Section 14 for more details. ↑V (control-V){index control-V} can be used to type a control character that would otherwise interrupt the input process, e.g., control-D, control-C, etc. If the character following ↑V is A, B, ... Z, the corresponding control character is input, e.g., ↑VA↑VB↑VC is the atom control-Acontrol-Bcontrol-C. ↑V followed by any other character has no effect, i.e., FOO↑V1 and FOO1 are identical. For more details, see Appendix 1. Typing {lisp '}{index ' (as a read-macro)} immediately in front of any expression has the effect of quoting the expression, i.e., {lisp (A 'B C)} is read as {lisp (A (QUOTE B) C)}. See Section 14. At any point during input, the user can type ?={index ?=} followed by carriage-return and be given the argument names and corresponding values (if any) of the expression (form) being typed. Typing just ? carriage-return will cause the user{index ?} to receive information from the Interlisp manual about the expression or command being typed. In the following example underlined characters were typed by the user. {comment we are going to have to find some other way of specifying user input.} {comment also, this particular example is WRONG} {lispcode ←(SETQ FOO (ELT 3 ?={CRSYMBOL} A = 3 N = (ELT 3 ?{CRSYMBOL} (ELT {arg A} {arg N}) Value is {arg N}th element of the array {arg A}. {fn ELT} generates an error, {lisp ARG NOT ARRAY}, if {arg A} is not the beginning of an array. (ELT 3 ↑W\\3 A 3] } ?{index ? PACom} is also a programmer assistant command for use following an error. In many cases, the programmer's assistant can analyze the cause of the error (see example below). If not, the programmer's assistant simply presents information about the error from the manual. }{End SubSec Interacting With Interlisp} {Begin SubSec Example} {Title Example} {Text Most of the "basics" of on-line use of Interlisp, e.g., defining functions, error handling, editing, saving your work, etc., are illustrated in the following brief console session. Underlined characters were typed by the user. 1. The user calls Interlisp from {index TENEX}the operating system, in this case Tenex, Interlisp prints a date, and a greeting. The prompt character{index prompt character} ←{index ← (Printed by System)} indicates the user is at the top level of Interlisp. 2. The user defines a function, {fn FACT}, for computing factorial of n. In Interlisp, functions are defined via {lisp DEFINE}{index DEFINE FN} or {lisp DEFINEQ,}{index DEFINEQ FN} (Section 8). Functions may independently evaluate arguments, or not evaluate them, and spread their arguments, or not spread them (Section 4). The function {fn FACT} shown here is an example of an everyday run-of-the-mill function of one argument, which is evaluated. The function definition uses CLISP (Conversational LISP, Section 23). The CLISP will automatically be converted to LISP when the function is run. 3. The user "looks" at the function definition. Function definitions in Interlisp are stored in a special cell called the function definition cell,{index function definition cell} which is associated with the name of the function (Section 8). This cell is accessible via the two functions, {fn GETD}{index GETD FN} and {fn PUTD}{index PUTD FN}, ({fn DEFINE}{index DEFINE FN} and {fn DEFINEQ}{index DEFINEQ FN} use {fn PUTD}). Note that the user typed an input consisting of a single expression, i.e., {lisp (GETD (QUOTE FACT))}, which was therefore interpreted as a form for {fn EVAL}.{index EVAL FN} The user could also have typed {lisp GETD(FACT)}. 4. The user runs his function. Two errors occur and corrections are offered by DWIM{index DWIM} (Section 17). In each case, the user indicates his approval, DWIM makes the correction, i.e., actually changes the definition of {fn FACT}, and then continues the computation. 5. An error occurs that DWIM cannot handle, and the system goes into a break. At this point, the user can type in expressions to be eval-ed or apply-ed exactly as at the top level. The prompt character{index prompt character} ":"{index : (Printed by System)} indicates that the user is in a break, i.e., that the context of his computation is available. In other words, the system is actually "within" or "below" the call to {fn ITIMES} in which the error occurred. 6. The user types in the break command, {lisp BT},{index BT BreakCom} which calls for a backtrace{index backtrace} to be printed. In Interlisp, interpreted and compiled 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.{index pushdown list} The stack can be searched and/or modified in various ways (see Section 12). Break commands are discussed in Section 15, which also explains how the user can "break" a particular function, i.e., specify that the system go into a "break" whenever a certain function or functions are called. At that point the user can examine the state of the computation. This facility is very useful for debugging.{index debugging} 7. The user asks for the value of the variable {fn N}, i.e., the most recent value, or binding.{index variable bindings} The interpreter 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 {fn CAR} of the atom (Section 3). If there are no bindings, and the value cell contains the atom {lisp NOBIND{index NOBIND Litatom},} an unbound atom error is generated (Section 16).{index U.B.A. Error} 8. The user types ?, a command to the programmer's assistant (Section 22). The p.a. looks at the error and the context and using its information about {lisp ITIMES}, "explains" the error. 9. The user realizes his error, and calls the editor to fix it. (Note that the system is {it still} 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. 10. The user instructs the editor to replace all {lisp 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, {it as it is now being interpreted,} has been changed. {lispcode @LISP{CRSYMBOL}{super 1} INTERLISP-10 14-JUL-78 ... Good Evening. ←DEFINEQ((FACT (LAMBDDA (N) (IF N=0 THEN NIL ELSE N*(FACTT N-1]{super 2} (FACT) ←(GETD 'FACT){super 3} (LAMBDDA (N) (IF N=0 THEN NIL ELSE N*(FACTT N-1)) ←FACT(3){super 4} LAMBDDA {bracket below FACT} -> LAMBDA ? Yes FACTT {bracket in FACT} ? Yes NON-NUMERIC ARG{super 5} NIL IN ITIMES (broken) :BT{CRSYMBOL}{super 6} ITIMES COND FACT COND FACT COND FACT **TOP** :N{CRSYMBOL}{super 7} 1 :?{CRSYMBOL}{super 8} because ITIMES requires that each of its arguments be a number but in (ITIMES N (FACT (SUB1 N))) {bracket IN FACT}, the value of (FACT (SUB1 N)) is NIL when N=1 :EDITF(FACT){super 9} EDIT *(R NIL 1){super 10} *OK{CRSYMBOL}{super 11} FACT :RETURN 1{CRSYMBOL}{super 12} 'BREAK' = 1 6 ←PP FACT{CRSYMBOL}{super 13} (FACT [LAMBDA (N) (COND ((ZEROP 0) 1) (T (ITIMES N (FACT (SUB1 N]) FACT{super 14} ←MAKEFILES() ****NOTE: The following are not contained on any file: the functions: FACT want to say where they go? Yes (functions) FACT File Name: FACT{CRSYMBOL} new file? Yes FACT ... (<TEITELMAN>FACT.;1) ←LOGOUT() }{comment endlispcode} 11. The user exits from the editor and returns to the break. 12. The user specifies the value to be used by {fn ITIMES} in place of {lisp NIL} by using the break command {command RETURN}.{index RETURN BreakCom} This causes the computation to continue, and 6 is ultimately returned as the value of the original input, {lisp FACT(3)}. 13. The user prettyprints (Section 14) {lisp FACT}, i.e., asks it be printed with appropriate indentations to indicate structure. {fn PRETTYPRINT}{index PRETTYPRINT FN} also provides a comment facility. Note that both the changes made to {lisp FACT} by the editor and those made by DWIM are in evidence. 14. The user calls {fn MAKEFILES} (Section 14) to write out any changes he has made. The file package knows that the function {lisp FACT} has been changed, but doesn't know on which file it belongs, and asks the user as shown in the example. After this interaction, the symbolic file {lisp <TEIITELMAN>FACT.;1} is written out. This file can be loaded into Interlisp at a later date via the function {fn LOAD}{index LOAD FN} (Section 14), will cause {lisp FACT} to be defined as it currently is. There is also a facility in Interlisp for saving and restoring an entire core image via the functions {fn SYSOUT}{index SYSOUT FN} and {fn SYSIN}{index SYSIN FN} (Section 14). 15. The user logs out, returning control to {index TENEX}Tenex. However, he can still continue his session by re-entering Interlisp via the Tenex {index CONTINUE (TENEX Command)}CONTINUE command. }{End SubSec Example} }{End Chapter How To Use Interlisp}