xref: /original-bsd/old/lisp/PSD.doc/ch13.n (revision 30d60fbe)
Copyright (c) 1980 Regents of the University of California.
All rights reserved. The Berkeley software License Agreement
specifies the terms and conditions for redistribution.

@(#)ch13.n 6.2 (Berkeley) 05/14/86

." $Header: /na/franz/doc/RCS/ch13.n,v 1.1 83/01/31 07:08:37 jkf Exp $ .Lc The CMU User Toplevel and the File Package 13 .ch 2 Introduction This documentation was written by Don Cohen, and the functions described below were imported from PDP-10 CMULisp. Non CMU users note: this is not the default top level for your Lisp system. In order to start up this top level, you should type (load 'cmuenv). .sh 2 User Command Input Top Level \n(ch 1 The top-level is the function that reads what you type, evaluates it and prints the result. The newlisp top-level was inspired by the CMULisp top-level (which was inspired by interlisp) but is much simpler. The top-level is a function (of zero arguments) that can be called by your program. If you prefer another top-level, just redefine the top-level function and type "(reset)" to start running it. The current top-level simply calls the functions tlread, tleval and tlprint to read, evaluate and print. These are supposed to be replaceable by the user. The only one that would make sense to replace is tlprint, which currently uses a function that refuses to go below a certain level and prints "...]" when it finds itself printing a circular list. One might want to prettyprint the results instead. The current top-level numbers the lines that you type to it, and remembers the last n "events" (where n can be set but is defaulted to 25). One can refer to these events in the following "top-level commands": .Eb TOPLEVEL COMMAND SUMMARY ?? prints events - both the input and the result. If you just type "??" you will see all of the recorded events. "?? 3" will show only event 3, and "?? 3 6" will show events 3 through 6. redo pretends that you typed the same thing that was typed before. If you type "redo 3" event number 3 is redone. "redo -3" redoes the thing 3 events ago. "redo" is the same as "redo -1". ed calls the editor and then does whatever the editor returns. Thus if you want to do event 5 again except for some small change, you can type "ed 5", make the change and leave the editor. "ed -3" and "ed" are analogous to redo. .Ee Finally, you can get the value of event 7 with the function (valueof 7). The other interesting feature of the top-level is that it makes outermost parentheses superfluous for the most part. This works the same way as in CMULisp, so you can use the help for an explanation. If you're not sure and don't want to risk it you can always just include the parentheses. .Lf top-level .Se .i top-level is the LISP top level function. As well as being the top level function with which the user interacts, it can be called recursively by the user or any function. Thus, the top level can be invoked from inside the editor, break package, or a user function to make its commands available to the user. .No The CMU .Fr top-level uses .i lineread rather than .i read. The difference will not usually be noticeable. The principal thing to be careful about is that input to the function or system being called cannot appear on the same line as the top-level call. For example, typing (editf foo)fP on one line will edit .i foo and evaluate P, not edit .i foo and execute the p command in the editor. .i top-level specially recognizes the following commands: .Lf valueof "'g_eventspec" .Re the value(s) of the event(s) specified by g_eventspec. If a single event is specified, its value will be returned. If more than one event is specified, or an event has more than one subevent (as for .i redo, etc), a list of vlaues will be returned. .sh 2 The File Package Users typically define functions in lisp and then want to save them for the next session. If you do (changes), a list of the functions that are newly defined or changed will be printed. When you type (dskouts), the functions associated with files will be saved in the new versions of those files. In order to associate functions with files you can either add them to the filefns list of an existing file or create a new file to hold them. This is done with the .i file function. If you type (file new) the system will create a variable called .i newfns. You may add the names of the functions to go into that file to .i newfns. After you do (changes), the functions which are in no other file are stored in the value of the atom .i changes. To put these all in the new file, (setq newfns (append newfns changes)). Now if you do (changes), all of the changed functions should be associated with files. In order to save the changes on the files, do (dskouts). All of the changed files (such as NEW) will be written. To recover the new functions the next time you run .Fr , do (dskin new). .Eb Script started on Sat Mar 14 11:50:32 1981 $ newlisp Welcome to newlisp... 1.(defun square (x) (* x x)) ; define a new function square 2.(changes) ; See, this function is associated ; with no file. <no-file> (square)nil 3.(file 'new) ; So let's declare file NEW. new 4.newfns ; It doesn't have anything on it yet. nil 5.(setq newfns '(square)) ; Add the function associated (square) ; with no file to file NEW. 6.(changes) ; CHANGES magically notices this fact. new (square)nil 7.(dskouts) ; We write the file. creating new (new) 8.(dskin new) ; We read it in! (new) 14.Bye $ script done on Sat Mar 14 11:51:48 1981 .Ee .Lf changes "s_flag" .Re Changes computes a list containing an entry for each file which defines atoms that have been marked changed. The entry contains the file name and the changed atoms defined therein. There is also a special entry for changes to atoms which are not defined in any known file. The global variable .i filelst contains the list of "known" files. If no flag is passed this result is printed in human readable form and the value returned is t if there were any changes and nil if not. Otherwise nothing is printed and the computer list is returned. The global variable .i changes contains the atoms which are marked changed but not yet associated with any file. The .i changes function attempts to associate these names with files, and any that are not found are considered to belong to no file. The .i changes property is the means by which changed functions are associated with files. When a file is read in or written out its .i changes property is removed. .Lf dc "s_word s_id [ g_descriptor1 ... ] <text> <esc>" .Re .i dc defines comments. It is exceptional in that its behavior is very context dependent. When .i dc is executed from .i dskin it simply records the fact that the comment exists. It is expected that in interactive mode comments will be found via .i getdef - this allows large comments which do not take up space in your core image. When .i dc is executed from the terminal it expects you to type a comment. .i dskout will write out the comments that you define and also copy the comments on the old version of the file, so that the new version will keep the old comments even though they were never actually brought into core. The optional id is a mechanism for distinguishing among several comments associated with the same word. It defaults to nil. However if you define two comments with the same id, the second is considered to be a replacement for the first. The behavior of .i dc is determined by the value of the global variable .i def-comment. .i def-comment contains the name of a function that is run. Its arguments are the word, id and attribute list. .i def-comment is initially .i dc-define. Other functions rebind it to .i dc-help, .i dc-userhelp, and the value of .i dskin-comment. The comment property of an atom is a list of entries, each representing one comment. Atomic entries are assumed to be identifiers of comments on a file but not in core. In-core comments are represented by a list of the id, the attribute list and the comment text. The comment text is an uninterned atom. Comments may be deleted or reordered by editing the comment property. .Lf dskin "l_filenames" .Se READ-EVAL-PRINTs the contents of the given files. This is the function to use to read files created by .i dskout. .i dskin also declares the files that it reads (if a .i file-fns list is defined and the file is otherwise declarable by .i file ), so that changes to it can be recorded. .Lf dskout "s_file1 ..." .Se For each file specified, .i dskout assumes the list named filenameFNS (i.e., the file name, excluding extension, concatenated with .i fns ) contains a list of function names, etc., to be loaded Any previous version of the file will be renamed to have extension ".back". .Lf dskouts "s_file1 ..." .Se applies .i dskout to and prints the name of each s_filei (with no additional arguments, assuming filenameFNS to be a list to be loaded) for which s_filei is either not in filelst (meaning it is a new file not previously declared by file or given as an argument to dskin, dskouts, or dskouts) or is in filelst and has some recorded changes to definitions of atoms in filenameFNS, as recorded by mark!changed and noted by changes. If filei is not specified, filelst will be used. This is the most common way of using dskouts. Typing (dskouts) will save every file reported by (changes) to have changed definitions. .Lf dv "s_atom g_value" .Eq (setq atom 'value). .i dv calls .i mark!changed. .Lf file "'s_file" .Se declares its argument to be a file to be used for reporting and saving changes to functions by adding the file name to a list of files, .i filelst. .i file is called for each file argument of .i dskin, .i dskout, and .i dskouts. .Lf file-fns "'s_file" .Re the name of the fileFNS list for its file argument s_file. .Lf getdef "'s_file ['s_i1 ...]" .Se selectively executes definitions for atoms s_i1 ... from the specified file. Any of the words to be defined which end with "@" will be treated as patterns in which the @ matchs any suffix (just like the editor). .i getdef is driven by .i getdeftable (and thus may be programmed). It looks for lines in the file that start with a word in the table. The first character must be a "(" or "[" followed by the word, followed by a space, return or something else that will not be considered as part of the identifier by .i read, e.g., "(" is unacceptable. When one is found the next word is read. If it matches one of the identifiers in the call to .i getdef then the table entry is executed. The table entry is a function of the expression starting in this line. Output from .i dskout is in acceptable format for .i getdef. .i getdef .Re a list of the words which match the ones it looked for, for which it found (but, depending on the table, perhaps did not execute) in the file. .No .i getdeftable is the table that drives .i getdef. It is in the form of an association list. Each element is a dotted pair consisting of the name of a function for which .i getdef searches and a function of one argument to be executed when it is found. .Lf mark!changed "'s_f" .Se records the fact that the definition of s_f has been changed. It is automatically called by .i def, .i defun, .i de, .i df, .i defprop, .i dm, .i dv, and the editor when a definition is altered.