The user interacts with PSL through toploop. The purpose of this loop is to read expressions typed at the terminal, evaluate them, and type the result back on the terminal. Such expressions may be entered to see what value they return or to produce a side-effect on the global environment.
An expression which has a side effect on the global environment
Another example of a side effect, the definition of a function
Evaluation, just to see what value the expression returns
A close approximation to the behavior of this loop is given by the following functional description:
The actual toploop of PSL is somewhat more complex than the simple one defined here because it provides a few extra features (these are described below). The important point is that the primitives required for writing such a loop are all available to the user.
Syntactically correct expressions have a well defined mapping into PSL data structures, read accomplishes this mapping. For example, linear list notation is converted into the internal tree structure representation, strings are stored in a more efficient non-list form, and numbers are internalized to a form compatible with the arithmetic unit of the machine. The most primitive piece of read is the scanner. This routine recognizes characters special to PSL. For example, space, (, and ). The scanner is also responsible for building the internal representation of identifiers. The scanner must make every reference to a particular id point to the same internal structure. This is accomplished at the time an id is created. The character sequence is compared against sequences which have already been converted into ids. This comparison employs an efficient search technique so that not every id is compared (currently a hash algorithm is used).
The eval function is responsible for the evaluation of data structures interpreted as programs. A through discussion of this can be found in Chapter 11.
Print displays data structures in a way which could later be typed back in to read. Some of the more interesting print routines do prettyprinting. That is, they format the output using conventions based on the structural nesting of the expressions.
Giving the user the power to invoke all of these operation from his code is a very powerful feature of LISP which sets it apart from most other languages.
|(hist)||Display full history.|
|(hist n m)||Display history from n to m.|
|(hist n)||Display history from n to present.|
|(hist -n)||Display last n entries.|
The following functions permit the user to access and resubmit previous expressions, and to re-examine previous results.