% The Muddle Programming Environment % P. David Lebling % May 1980 MIT Technical Report 294 Laboratory for Computer Science Massachusetts Institute of Technology 545 Technology Square Cambridge, Massachusetts 02139 # Copyright This book was originally published in the United States in 1980 without a copyright notice and without subsequent registration with the U.S. Copyright Office within 5 years. Doing at least one of those was a requirement of United States copyright law at that time [^1]. This book is therefore in the public domain in the United States for failure to comply with the required formalities. This means you're free to download, modify and redistribute this book. People outside of the United States must check the copyright laws of their country before downloading or redistributing. [^1]: # Introduction The Muddle language is described in "The Muddle Programming Language" [^2], but in addition to the language itself, there is a rich and varied collection of software written in the language which facilitates the writing of programs and systems of programs in Muddle. The information describing this programming environment has been contained in various documents, some out of print or out of date, and in supplemental disk files describing changes and additions. Some of the packages of functions used to deal with Muddle code have never been formally documented. This manual brings together some of that scattered documentation. [^2]: S. W. Galley and Greg Pfister. *The Muddle Programming Language*. MIT Laboratory for Computer Science, 1979. The document's purpose is to flesh out the description of the language contained in "The Muddle Programming Language", giving a fuller description of the program writing and debugging aids available to Muddle users, to describe the methods for producing code usable by others, to describe the Muddle compiler and the many other techniques for producing and speeding up Muddle object code. The imagined reader of this document is someone who has read "The Muddle Programming Language", and now proposes to write programs in Muddle, possibly even very large programs. Muddle packages that they would find useful in the process of doing so are documented here: editors, debuggers, etc. Packages that they might wish to use within their program are not included: data-management systems, command interpreters, etc. This document is highly self-referent, as many of the components of the Muddle programming environment refer to reach other and adhere to the same conventions. Additionally, this document assumes that the read is familiar with the language itself (at least to some degree) and with the ITS, TENEX, or TOPS-20 operating systems. # Acknowledgments The programs described in this document are the products of many years of effort by many people. Most have been "touched" by several programmers, added to and improved over the years. Some of the people responsible for the programs mentioned in the document are Chris Reeve (Muddle, the compiler, `GLUE`); Brian Berkowitz (Muddle, the compiler, `TEMPLATE`, `SUBRFY`); Bruce Daniels (Muddle, the compiler, `PACKAGE`, `PPRINT`, `DEBUGR`, `ASSEM`); Tim Anderson (`PACKAGE`, the Library, `FINDATOM`, `DFL`, Combat, Mudinq); Neal Ryan (`EDIT`, `PDUMP`, the IPC interface); Marc Blank (Mat, Muxicom, `MONITR`, Combat, `EDIT`, `CURSOR`); Dave Lebling (`CRITIC`, `EDIT`); Michael Broos (the Library); Roger Banks (`TRACE`); Greg Pfister (`PPRINT`); Joel Berez (`EDIT`). Most of the documentation in this manual is from published and unpublished memos of the Programming Technology Division of the M.I.T. Laboratory for Computer Science. As a general rule, updates and revisions to this and other PTD documents concerning Muddle are available online in the directory "`MUDMAN`" at MIT-DMS. # Notation Anything which is written in the Muddle language or which is typed on a computer console appears here in in a typewriter font, as in `PPRINT` while a metasyntactic variable -- something to be replaced in actual use by something else -- appears as *channel*, in an italic font. Where a meta-syntactic variable is being used to denote a required argument to some function, it appears as before, but in bold, as **channel**. In the argument templates of Muddle functions, the individual arguments are often given in the form *argument:type*, where *argument* is a "descriptive" name for the argument, and *type* is its Muddle type (or range of types). In such cases, the "type" *boolean* indicates an argument that is only examined for truth or falsity, and not for any of its other qualities. Such arguments in Muddle are often declared ``. Finally, file names are given as though for the ITS operating system: device:sname;fnm1 fnm2 The analogous specification for TENEX or TOPS-20 would be device:fnm1,fnm2 Note that in the TENEX/TOPS-20 version of Muddle, the *fnm2* (which may include the *generation* number, *protection* and *account* fields) is by default `MUD` as opposed to \> for the ITS version. # 1\. Overview of the Muddle Programming Environment The part of the Muddle programming environment described in this document are primarily those dealing with the writing, debugging, sharing, and maintenance of code and programs written in Muddle. Most of the packages described herein are written in Muddle themselves: some are assembly language programs useful to Muddle programmers. The document is divided into chapters dealing with the major issues facing the notice (or even the experienced) Muddle programmer: - **The Package System** introduces the standard mechanism for lexical blocking and therefore, sharing of Muddle code. Understanding its use is fundamental to writing Muddle programs. - **Program Writing And Debugging Aids** is the largest chapter. It covers mechanisms for loading, dumping, editing and debugging Muddle code, whether interpreted or compiled, in a development or production system. - **The Library System** discusses the usage of libraries of Muddle programs. - **The Compiler** includes the specifics of interaction with the Muddle compiler, as well as an overview of the theory behind its operation. - **Making It Run Faster** covers the various methods for speeding up "production" Muddle code by removing mediated calls and compacting data structures. - **The Assembler** documents the Muddle assembler and some methods of debugging binary code. - **Informational Aids** discusses a few programs, mostly written in assembly language, rather than Muddle, which are useful to the Muddle programmer. # 2\. The Package System The portion of the Muddle environment which provides a uniform facility for lexical blocking is known as the Package System. In one sense it is the most basic part of the environment, since it enables many programmers to use each other's code without identifier conflicts. In addition, the Package System is interfaced to a library facility (see section 4) by which Muddle code may be stored and later loaded as needed. The Package System is so basic to use of the Muddle environment that (with a few exceptions) every subsystem or family of Muddle functions described in this document is a "package". ## 2.1. The Theory Of Lexical Blocking In Muddle Lexical blocking is implemented in Muddle by means of `OBLIST`s and `LIST`s of `OBLIST`s. Changes of lexical context are performed using the `SUBR`s `BLOCK` and `ENDBLOCK`. The Package System provides a high-level interface to these low-level constructs. The primary goal of a lexical blocking scheme is the prevention of identifier conflicts. Specifically, when your program references the variable `X`, it should be your `X` and not that of some other program. At the same time, it should not be necessary for a programmer to search every program previously written to verify that an identifier he wishes to use is not already "taken". It should be clear that the simplest solution, a single `OBLIST`, will not satisfy either of these goals. With only one `OBLIST` there would necessarily be identifier conflicts, necessitating exhaustive searching for unique identifiers. Obviously, programmers could put their program's identifiers on an `OBLIST` unique to that program. Unfortunately, such a solution addresses only half the program. What happens when some other programmer wishes to use some of this code? He could insert the unique `OBLIST` for that program into the `OBLIST` path for his program; but the moment that is done he gets all the identifiers for that program, including local variable, internal data structures, and so on. Consequently, we move to a situation where each program uses two `OBLIST`s: one for the identifiers that are local to the program, and one for the identifiers that are to be used by other programs. In the Package System, these are known as the "internal" `OBLIST` and the "entry" `OBLIST`. Most of the identifiers in a program are local to it, and want to be placed on the internal `OBLIST`. Therefore, in terms of an argument to the `BLOCK` `SUBR`, when a program is being loaded into Muddle, the `OBLIST` path wants to be: ( *internal-oblist entry-oblist* `` ) With this `OBLIST` path, most `ATOM`s (identifiers) will be on the internal `OBLIST` (as `READ` puts unknown identifiers on `<1 .OBLIST>`), but the `ATOM`s for the entries and the `ATOM`s for the usual `SUBR`s will be available. The only issue yet to be addressed is that of using an entry of a different program in your program. This is accomplished by adding the entry `OBLIST` of any such programs to the path after `ROOT`: ( *internal-oblist entry-oblist* `` *other-program-entry-oblist yet-another-program-entry-oblist* . . . ) As only the entry `OBLIST`, and not the internal `OBLIST`, of the program being used is added to the path, the chance of identifier conflict is lessened. All that remains is to introduce the functions by which these various operations are performed. ## 2.2. Package System Overview The functions which make up the Package System are: - `PACKAGE` - This indicates the start of a package of functions. - `ENDPACKAGE` - This indicates the end of the package of functions. - `ENTRY` - This indicates an `ATOM` which is to be made available outside the definition of this package of functions. All other `ATOM`s will not be directly available outside the package. - `USE` - This indicates a reference by name to another package of functions. - `USE-DATUM` - This indicates a reference by name to a data set. - `DROP` and `L-UNUSE` - These undo the effects of `USE` and `USE-DATUM`. These functions are themselves part of a package named `PKG`, which is preloaded into Muddle. ### 2.2.1. Sample Package A sample Muddle `PACKAGE` is given with comments in order to demonstrate the usage of these functions. ;"PACKAGE begins the package called HOUR-STRING." ;"The atom TIME-STRING is an entry to this package; it may be referenced by other packages by USEing HOUR-STRING." ;"Indicate that the package DATIME is used within the current package." > " o'clock">> ;"Define this little function which returns a string telling the last hour in a strange format." >> ;"Define an internal function which is available only within the HOUR-STRING package, since its name is not in any ENTRY statement. Note that this function refers to RTIME, which is an ENTRY in the DATIME package." ;"The end of this little demonstration package." ## 2.3. Package This function delimits the beginning of a package of functions. It takes one required argument, a `STRING`, which is the the name of the package. This `STRING` uniquely identifies the package within a library of packages (see section 4.) In a `PACKAGE` those `ATOM`s which are specified as entries live in a separate `OBLIST` of their own, called the entry `OBLIST`. The `ATOM` naming this `OBLIST` is on the `PACKAGE` `OBLIST` and has the same name as the package itself. Thus, an entry "X" of a `PACKAGE` "Y" would have as its "full-trailer" name: `X!-Y!-PACKAGE!-`. `PACKAGE` blocks (sets up) the current `OBLIST` path so that the `ATOM`s which are internal to the `PACKAGE` fall into an `OBLIST` which is not otherwise used. The `ATOM` naming this `OBLIST` is on the entry `OBLIST` of the `PACKAGE`, and is by default given a name created by putting the character I at the beginning of the `PACKAGE` name. An internal `ATOM` "Z" in the `PACKAGE` "Y" previously mentioned would have as its "full-trailer" name: `Z!-IY-Y!-PACKAGE!-`. `PACKAGE` also keeps track of the fact that the particular `PACKAGE` named has been defined in this Muddle process by putting its name on the `PACKAGE` `OBLIST`. `` `PACKAGE` takes three optional arguments in addition to the required one (the optional arguments are ignored if *name* is already a `PACKAGE`): - *iname* is the name of the internal `OBLIST` of the `PACKAGE`; by default is is the name of the `PACKAGE` with the letter "I" prefixed. - *size* is the number of buckets in the entry `OBLIST`; by default 19. - *isize* is the number of buckets in the internal `OBLIST`; by default 23. In addition to `PACKAGE`, there exists the obsolete function `RPACKAGE`, documented here only because some programs still use it. The difference between them is that the entry `OBLIST` for an `RPACKAGE` is the `ROOT` `OBLIST`. The implication of inserting an entry into the `ROOT` is that this requires the name of the entry be unique over all `PACKAGE`s, because the entry is, in effect, being promoted to the status of a `SUBR`. It is (in rare cases) useful to do this, but the correct way is with the function `RENTRY` (see section 2.3.1.) ### 2.3.1. Entry The `ENTRY` function applied to one or more `ATOM`s declares that these `ATOM`s are to be put into the `OBLIST` reserved for entries in this particular `PACKAGE`. Only `ATOM`s declared this way will be accessible (in the normal course of events) to functions outside this `PACKAGE`. It is possible to place some entries of a `PACKAGE` on the `ROOT` `OBLIST` using the function `RENTRY`. It is recommended that instead of using `RPACKAGE` in those rare cases where entries must go on the `ROOT`, `RENTRY` be used instead. All `ENTRY` statements should appear immediately after the `PACKAGE` or `RPACKAGE` statement. Note: never put a `USE` statement before the `ENTRY` statements; if you do, you may get the `ERROR` message `ALREADY-USED-ELSEWHERE`, meaning that the name of an entry is conflicting with an `ENTRY` in one of the packages you `USE`d. `ENTRY` will also give an `ERROR` if it is used outside the body of a `PACKAGE`. ### 2.3.2. USE This function takes as arguments one or more `STRING`s which are the names (as given to `PACKAGE`) of other `PACKAGE`s. `EXTERNAL` is a synonym of `USE`. `USE` causes the entry `OBLIST`s of the `PACKAGE`s named to be spliced into the current `OBLIST` path. Thus, references to entries of those `PACKAGE`s may be made after the `USE`, until the next `ENDPACKAGE` (or the next `DROP` or `L-UNUSE` if `USE` is being invoked outside a `PACKAGE` to load a file.) `USE` is consequently the mechanism for sharing code. If the `PACKAGE` being used is already loaded, its entries are made available; if not, the `PACKAGE` is loaded first (see section 4.1 for details on how this is accomplished.) ### 2.3.3. USE-DATUM `USE-DATUM` requires one `STRING` argument, the name of a data set. If the data set is not loaded, `USE-DATUM` loads it and creates an `ATOM` of the same name, on the `USE-DATUM` `OBLIST`, whose `GVAL` is the data set. `USE-DATUM` always `EVAL`s to the data set named, regardless of whether it had to be loaded or not. ### 2.3.4. DROP and L-UNUSE These function take the same arguments as `USE` and `USE-DATUM` and undo their effects. `DROP` simply splices the named packages out of the current `OBLIST` path. A `USE` of a `DROP`ped `PACKAGE` will not reload the `PACKAGE` but simply splice it back into the `OBLIST` path. `L-UNUSE` splices the `PACKAGE` out and removes its name from the `PACKAGE` `OBLIST`, which will cause the entire `PACKAGE` to be reloaded if it is `USE`d again. `L-UNUSED` of a data set will remove its `ATOM` from the `USE-DATUM` `OBLIST`. ### 2.3.5. ENDPACKAGE The `ENDPACKAGE` function of no arguments terminates the definition of the current `PACKAGE` and undoes the lexical blocking done by the `PACKAGE` function. The `ENDPACKAGE` statement should be the last one in the file. ### 2.3.6. PACKAGE Restrictions There are some restrictions on what the user may do inside a `PACKAGE`. These are enforced by the Library System when the user attempts to submit a `PACKAGE` to a library. A `PACKAGE` should not `FLOAD` or `LOAD` any file to obtain parts of itself. All such environment setup should be done with `USE` and `USE-DATUM`. A `PACKAGE` may not reference any `ATOM` whose `OBLIST` path goes through the `INITIAL` `OBLIST`. All of the non-entry `ATOM`s in a package should fall naturally into it's internal `OBLIST`. As mentioned before, the `RENTRY` of a package have the same `OBLIST` status as `SUBR`s, i.e., they must be unique among both all `SUBR`s and all `PACKAGE` entries. ### 2.3.7. ENTRY Name Conflicts It is possible to have two or more `PACKAGE`s (not `RPACKAGE`s) which have entries (not `RENTRY`s) with the same `PNAME`. If the user needs both `PACKAGE`s at the same time, he may `USE` them both and refer to the ambiguous entries by their "full trailer" names. All of the non-ambiguous entries in `PACKAGE`s may still be referenced by `PNAME` only. # 3\. Program Writing and Debugging Aids This chapter concentrates on editing and debugging aids for Muddle programming. The basis for editing and debugging in Muddle is twofold: First, Muddle is an interpreter, which permits interactive testing and debugging of software. Second, Muddle programs (even compiled Muddle programs) are structures and therefore may be manipulated by other Muddle programs. Packages useful in editing and debugging range from `EDIT` and `PPRINT`, which are preloaded, and which form the core of most editing or debugging systems, to more sophisticated aids such as `DEBUGR` and `TRACE`, which are more powerful, and useful for more complicated debugging. It should be noted that, in addition to the editors discussed below, RMODE [^3] and EMACS [^4], TECO based text editors, understand much of the syntax and many of the conventions of Muddle programs. [^3]: P. David Lebling, R. V. Baron and Bruce K. Daniels. *RMODE: A Real-time Edit Facility*. Technical Report SYS.04.07-1, MIT LCS Programming Technology Division, October 1977. [^4]: Richard M. Stallman. *EMACS*. Technical Report 519, MIT AI Laboratory, August, 1979. ## 3.1. Pretty-Printing The purpose of pretty printing is to clarify the structure of Muddle objects by printing them in a more human-readable format than that provided by the `SUBR`s `PRINT`, `PRIN1`, etc. Objects are pretty-printed through the judicious insertion of spaces, tabs, and new-lines between tokens. Pretty-printed objects are readable by the Muddle Reader. Pretty printing is an aid to understanding and debugging Muddle `FUNCTION`s or other objects. You will probably find pretty printing to be extremely helpful, especially if you are working without a listing or with an old listing. In fact, pretty-printing is one way to make a new pretty listing after editing. `PPRINT` is pre-loaded in most initial Muddles. The name of the package containing `PPRINT` is "`PP`". `` pretty-prints *any* on *channel*. The second argument is option, by default `.OUTCHAN`. If *any* is an `ATOM`, `PPRINT` will enclose it in an application of `DEFINE`, `DEFMAC`, `SETG`, or `SET`, as seems appropriate. `COMMENT`s found inside *any* are right-justified. `PPRINT` cannot output an `RSUBR` without `FIXUP`s (that is, one that was `READ` in while `KEEP-FIXUPS` (see section 3.4) had no `LVAL` or had a `FALSE` `LVAL`); it will give the `ERROR` message `CAN-NOT-BE-DUMPED`. `PPRINT` returns `.NULL` which is an `ATOM` whose `PNAME` is a single rubout, invisible on most consoles. `` pretty-prints all the contents of *in* into *outfile*. If *in* is an `ATOM` or a `LIST` of `ATOM`s, its `VALUE`(s) are the objects to be `PPRINT`ed. In this case, *outfile* is by default a file whose first name is produced by taking the `PNAME` of *in* (or *in*'s first element, if *in* is a `LIST`). If *in* is a `STRING`, it specifies a file containing objects to `PPRINT`. In this case, *outfile* is by default "`TPL:`". *width* is the maximum width of output lines (although output lines are prevented from being extremely long); it is optional, and by default `<13 ,OUTCHAN>`. *eval?* tells `PPRINF` whether or not to `EVAL` everything in the file; it is optional, by default a `FALSE` (don't `EVAL`). *eval?* is meaningless if *in* is not a `STRING`. `PPRINF` returns either "`DONE`" or a `FALSE` if it couldn't open *infile* or \*outfile(. `PPRINF` inserts page boundaries in *outfile*, between objects, every 60 lines or fewer; you may want to move these afterward to more logical places. `PPRINF` binds `KEEP-FIXUPS` and `REDEFINE` to `T`, and `QUICKPRINT` (see below) to a `FALSE`. ### 3.1.1. PPRINT Control Switches `PPRINT`'s output is affected by the local values of several `ATOM`s. Each value is examined only for truth. .QUICKPRINT If this `ATOM`'s `LVAL` is `FALSE`, you are in slow mode; otherwise (include the case of no `LVAL`), you are in fast mode. The behavioral difference is this: in fast mode, there may be `COMMENT`s in the pretty-printed object(s) which `PPRINT` misses. Also, fast mode is indeed faster than slow mode. Fast mode is the default, that is, `QUICKPRINT` is initially true. The modes are really distinguished by the depth of recursion to which PPRINT resorts. In slow mode, it recurses all the way down to every monad in the thing pretty-printed; in fast mode, it goes down only far enough to find something that will fit on a line. .LOOKAHEAD `PPRINT` uses full recursive lookahead to avoid packing things against the right margin and, as a result, not being able to fit things within the right margin. The lookahead results in very good formatting of deeply-nested `MAPF`ed and `FUNCTION`s; all but the most bizarre cases should be very legible. However, it can result in noticeable "pauses" in the printing operation and, in some cases, a net speed slightly less than with limited lookahead. Since this can be a disadvantage when using `PPRINT` interactively on a heavily-loaded system, the lookahead can be disabled: if the `LVAL` of `LOOKAHEAD` is a `FALSE`, no lookahead will be performed; otherwise it happens. `LOOKAHEAD` is initially true, that is, lookahead happens by default. .VERTICAL If `LOOKAHEAD` is a `FALSE`, the formatting can cause too many objects to be squeezed against the right margin. So that particular cases can be made legible, the format when lookahead is not in use can be manually set: if the `LVAL` of `VERTICAL` is non-`FALSE`, `PPRINT` will indent very little whenever indenting is called for. (`VERTICAL` being true means a "more vertical" format.) `VERTICAL` is initially `FALSE`. The value of `VERTICAL` is ignored when `LOOKAHEAD` is true; the lookahead effective chooses different values for `VERTICAL` for different parts of the object pretty-printed. ### 3.1.2. Lower-level Pretty Printing It is sometimes desirable to use some of the functions that `PPRINT` uses but in a different way. For example, a specialized pretty-printer for Program Abstracts would want to insert indented field names into the output and pretty-print field values with the same indentation. The names of lower-level pretty-print functions are included in the `ROOT` `OBLIST` for such purposes. `` pretty-prints *any* on `.OUTCHAN` to the right of *left-margin*. The second argument is optional, by default `` (see below.) `` `EPRIN1` is to `EPRINT` as `PRIN1` is to `PRINT`. .LEFT-MARGIN This is the `ATOM` that `EPRINT` binds to its second argument. You can `SET` it outside calls to `EPRINT` in order to make a permanent left margin. Its initial `LVAL` IS 0. `` outputs tabs and/or spaces to advance the output column (`<14 channel>`) to *column*, if it is not already past. `` pretty-prints *any* on *channel* (by default `.OUTCHAN`) between the margin *left-margin* (by default `<14 channel>`, the current column) and *right-margin* \*by default `<13 channel>`, the rightmost column.) All arguments but the first are optional. `COLPP` returns `,NULL`. For example, `` would leave a 10-character margin at left and right on an 80-column `OUTCHAN`. Also, > would result in output like AAAAAAAAAAAAAAA #FUNCTION ((X GGGGGGGGGGGGGGGGGGGGGG) <+ X 1>) `EPRINT`, `EPRIN1`, and `COLPP` are affected by the truth of `.QUICKPRINT`, `.LOOKAHEAD`, AND `.VERTICAL`. ### 3.1.3. Ampersand Printing "Ampersand printing" consists of printing any object on a single line by using the character `&` (ampersand) to mean "There's more stuff here." (This technique is borrowed by the InterLisp editor.) There are two ways in which `&` is used by this printer as an abbreviation: 1. An `&` appearing between some variety of brackets indicates that there is a big object of the indicated `TYPE` there. 2. The characters `..&` or `&..` on the left or right of a structure mean that there are more objects to the left or right which have not been printed. Example: #FUNCTION ((A B C D) <&>) This is a `FUNCTION` with four arguments in its argument `LIST`, and the `FUNCTION` body contains one `FORM` which was too big to print in the remainder of the line. > > <&> &..> This is a large `FORM`, namely a `PROG`. In addition to the elements printed, there are more elements to the right, and there is one `FORM` which was too big to print. Ampersand printing is effected by two pure `RSUBR`s: `&`, analogous to `PRINT`, and `&1`, analogous to `PRIN1`. A related `RSUBR`, `&LIS`, can be applied to no arguments to put you into an endless `READ-EVAL-&` loop, instead of the normal `READ-EVAL-PRINT` loop. ### 3.1.4. Examining the stack `` returns the *fix*th `FRAME` down from the top application of `ERROR` or `LISTEN`. `` pretty-prints *how-many* `FRAME`s (by printing the `FRAME` number (suitable as an argument to `FRM`), `FUNCT`, and `ARGS` of the `FRAME`), starting with ``. Both arguments are optional; *start* defaults to 0, and *how-many* defaults to a large integer. A `FRAME` whose `FUNCT` is an `ATOM` whose `VALUE` is an `FSUBR` is not printed, if the same information is found in the next lower `FRAME`. `` is like `FRAMES but uses ampersand printing instead of pretty printing. It is handy for summarizing`FUNCT`s and`ARGS`that are large or unprintable (like`RSUBR\`s with no fixups). `` is like `FRAMES` but gives an abbreviated view of the stack. It prints `FUNCT`s only, and only for `FRAME`s connected with named `FUNCTION`s, `RSUBR`s, and `RSUBR-ENTRY`s. It is handy when a `FRAME` contains a non-`LEGAL?` object. `` prints out the stacked bindings of *atom*, going through *how-many* `FRAME`s, starting with ``. The two numeric arguments are optional; *how-many* defaults to a large integer, and *start* defaults to 0. The format of the printing is two columns: the first column is the number of the `FRAME` in which *atom* has a binding; the second column is the value bound, or a message proclaiming the lack of a value. `\` is precisely the same as FRLVAL, except that the values are ampersand printed instead of `PRINT`ed. Finally, the "`FRMSP`" `PACKAGE` contains analogues of many of the preceding functions, but each takes as its first argument a `PROCESS`, by default ``. These are all named by adding a 'P' to the end of the usual name. For example, > Does does a `` in the `PROCESS` `MAIN`. There is one additional function of interest in "FRMSP". `` is like `FRAMES`, but gives only the `TYPE`s of the arguments to each. This is useful in those situations when the stack shows illegal `FRAME`s or other unprintable objects. ## 3.2. The Muddle Editor `EDIT` allows a Muddle user to make incremental changes in Muddle structured objects, without leaving Muddle and with the ability to save the results in a file, and to set or clear conditional breakpoints of various sorts in objects that will be evaluated, such as `FUNCTION`s. `EDIT` is an editor/debugger written in, written for, and running under Muddle. It comprises the package "`EDIT`" and several smaller packages which wi11 be mentioned later in this section. `EDIT` is preloaded in most initial Muddles. To start editing, apply `EDIT` to no arguments or to the name of the object you wish to edit: `` causes entry into `EDIT` and opens the last object edited; `` causes entry into `EDIT` and opens *object* for editing. Permissible *object*s include: - `ATOM`s. The `GVAL` (preferably) or the `LVAL` of the `ATOM` is opened. If it has no value, `EDIT` returns a `FALSE`. - A `PRIMTYPE` `LIST`. The `PRIMTYPE` `LIST` is opened. - A `FIX`. The stack frame with that number is opened (i.e., `>`). Part of `EDIT`'s efficiency comes from forbidding it to delve into objects that are not of `PRIMTYPE` `LIST`, that is, not `LIST`s, `FORM`s, `FUNCTION`s, etc. Attempts to edit objects of other `PRIMTYPE`s will result in error messages. These objects can, however. be treated as units when inserting. searching, etc.; or they can be changed into `LIST`s, edited, and then changed back to their original types. ### 3.2.1. The Edit 'LISTEN Loop' #### 3.2.1.1. The Reader When in `EDIT`, you are typing at a special, non-standard, input function: The `EDIT` Reader. The Reader allows you to type `EDIT` commands and have them executed, and also to evaluate Muddle expressions normally. Its characteristics are as follows: - As in the normal Muddle Reader, nothing is done until you type `ESC`. `DEL`, `Ctrl-L`, `Ctrl-D`, `Ctrl-G`, and `Ctrl-S` also work normally. - All `EDIT` commands are terminated when an `ESC` is encountered in the input stream. (In addition. most commands will terminate whenever the maximum number of arguments required has been input or whenever an argument of the wrong type is encountered. In the former case the next object is taken as a new command; in the latter case the object of the wrong type is taken as a new command. `EDIT` commands may be typed in either upper or lowercase. - If you type something that `EDIT` does not recognize as a command, normal Muddle evaluation and printing are performed on that something. This evaluation will have no effect on your position in the object you are editing. - While editing a function which is part of a `PACKAGE` (determined from an examination of the `OBLIST` containing the `ATOM` whose value is the function), `EDIT` causes the OBLIST path to be set up to what it was in the environment of that `PACKAGE`. This has the advantage of reducing the number of trailers printed, and causes newly entered `ATOM`s to fall on the correct `OBLIST` (the internal `OBLIST` of the `PACKAGE`). It has the slight disadvantage that it disables the dynamic loader (which depends on unbound variables falling on the `INITIAL` `OBLIST`). If the `GVAL` of `E-PKG` is a `FALSE`, this feature is disabled, and the normal `OBLIST` path is in effect during editing. Examples: R 5$ Causes execution of `EDIT` command R with argument 5. $ Causes application of the function R to 5. #### 3.2.1.2. The Ampersand Printer Your current position is displayed by "ampersand printing" (see section 3.1.3). This consists of printing any object on a single line by using the character `&` (ampersand) to mean "There's more stuff here." The ampersand printer used in `EDIT` is much like the standard one, with the addition that your current position (see below) is displayed by the glyph of a solid square: █. When you initially enter `EDIT`, you are in a mode called "non-verbose", in which ampersand printing is not automatically done following execution of `EDIT` commands. The `V` command is used to toggle you in and out of verbose mode (see below). Examples: `>` Indicates that your position is just to the left of a `FUNCTION`'s argument list. and the `FUNCTION` body contains one `FORM` which was too big to print. `<..& >` █ `> <&> *..>` Indicates that you are in the middle of a large `FORM` (e.g., a `REPEAT` or a `PROG`), positioned just to the left of the `>`. In addition to the objects printed, there are more objects to both the left and the right, and there is one `FORM` which was too large to fit on the line. ### 3.2.2. Edit Commands #### 3.2.2.1. General A sequence of `EDIT` commands is executed as soon as you type `ESC`. If one command fails, subsequent commands up to the `ESC` are ignored, and EDIT types out an appropriate error message. A failing `EDIT`command generally has no effect whatsoever; but see individual descriptions. Note that *all* arguments to `EDIT` functions must be legal Muddle objects. In particular, you can't search for ``'s aren't balanced. Nor can you insert it. (But you can, for instance, search for and insert ``.) If a command expects an argument and doesn't get one, an error message will be printed. Many `EDIT` commands take `FIX`es as arguments. Those that do interpret the `ATOM` \* as an argument to mean "as many as possible". Whenever you are in `EDIT`, you have a well-defined "position". A position is a "place" *inside* a Muddle structure: this "place" is either *between* two elements elements of the structure, or between an element and either end of the structure, or *inside* an empty structure. All editing, movement, and printing commands operate relative to your current position. The term "cursor" is used in the following descriptions to refer to an embodiment of a position. The format listed in each of the following command descriptions is: Command as Typed English Name Description #### 3.2.2.2. General Commands `?` `duh?` Causes a short summary of all EDIT commands to be typed out. The same summary appears later in this chapter. `??` `huh?` Similar to the above, but the summary is even shorter, and should fit entirely on the screen of an Imlac terminal. `Q` `Quit` Leave `EDIT` and return to Muddle. (Causes `EDIT` to return the `ATOM` `T`.) `QR` *fix* `Quit and Retry` Quit from `EDIT` and then retry the frame specified, or by default, the one originally given to an open command or, if none was given, the frame beneath the last `ERROR` or `LISTEN` frame. `Ctrl-F` `Control-F` This is not really an `EDIT` command; rather, it is a character, obtained from the input stream at interrupt level, which is used to return you to the `EDIT` Reader from some higher level of application, e.g., an `ERROR`'s `LISTEN`. It is the `EDIT` equivalent of `ERRET` with no arguments. `Ctrl-F` (or `Ctrl-S`) typed during execution of an `EDIT` command is similar to normal Muddle `Ctrl-S` but returns to the `EDIT` Reader instead of the Muddle `LISTEN` loop. `O` **object** `Open` Equivalent to `Q` followed by ``. Positions the cursor just to the left of the first element of the entire object specified. `OT` `Open This` If the object to the right of the cursor is an `ATOM`, or a `FORM` whose first element `ATOM`, and the `ATOM`'s value is openable, then it is opened. This command is useful when tracing a calling sequence through several functions. #### 3.2.2.3. Movement Commands `UT` `Up to the Top` Places the cursor at the position it had following an `O`. `R` *fix* `Right` Moves the cursor *fix* objects to the right, by default one. If *fix* is too large, i.e., there are not that many positions to the right of the current position, `EDIT` prints an error comment and the cursor stays where it is. `B` `Back` Moves the cursor as far to the right as possible. `L` *fix* `Left` Moves the cursor \*fix( positions to the left, by default one. If *fix* is too large, EDIT prints an error message. `F` `Front` Moves the cursor as far to the left as possible. `DL` `Down Left` Positions the cursor just to the right of the rightmost element within the object to the left of the cursor, if that object is of `PRIMETYPE` `LIST`. Visually, the cursor moves left over one "close bracket". `DR` `Down Right` Positions the cursor just to the left of the leftmost element within the object to the right of the cursor, if that object is of `PRIMTYPE` `LIST`. Visually. the cursor moves right over one "open bracket". If the cursor is to the left of an element that is not of `PRIMETYPE` `LIST`, `EDIT` prints an error message. `D` `Down` Equivalent to `DR`. `UR` *fix* `Up Right` Positions the cursor just to the right of the object the cursor is currently within. Does so `fix` times, by default once. `UL` *fix* `Up Left` Positions the cursor just to the left of the object the cursor is currently within. Does so *fix* times, by default once. `U` *fix* `Up` Identical to `UL`. `S` *object* Search Does a depth-first, left-first tree-walk. (i.e., left-to-right) starting with the object to the right of the cursor. until the cursor is just to the right of an object structurally equal (i.e., =?) to its argument. An occurrence of the object will not be found if it is inside anything not of `PRIMETYPE` `LIST`. On failure. the cursor does not move. If the argument is omitted, the last object searched for is used. `SR` *object* `Search Right` Same as `S`. `SL` *object* `Search Left` Same as `S`, but the tree-walk is depth-first, right-first (i.e., right-to-left) and you end up to the left of the object for which you were searching. #### 3.2.2.4. Printing Commands `The Empty Command` Causes the normal "ampersand print" to be done. This is principally useful when you are in "silent" mode; see the `V` command. By the way, an "empty" command is typed by typing `ESC` without having typed any visible characters before it. `P` `Print` `PPRINT`s (not "ampersand prints") the object to the right of the cursor. `PU` `Print Up` `PPRINT`s the object the cursor is in. This is similar to doing a `U` and then a `P`, although the cursor is not moved. `PT` `Print Top` `PPRINT`s the whole object you have open. `V` `Verbosity` Toggles the verbosity mode between "verbose" (most commands cause ampersand printing) and "silent" (printing of any sort is done only when some explicit print command is used, or when an error occurs.) The current state of verbosity is the `G-VAL` of `E-VERBOSE`. In silent mode, absolutely *nothing* is printed after each command, not even new-lines or prompts. However, normal Muddle evaluation still causes normal Muddle printing. #### 3.2.2.5 Editing Commands `I` **any** ... `Insert` Inserts all its arguments immediately to the right of the cursor. None of its arguments are evaluated; you can insert unevaluated `FORM`s without using `QUOTE`. The cursor ends up to the right of the last object inserted. `G` **any** ... `Get` Same as `I`, but its arguments are evaluated. This is useful in conjunction with the `X` command (see below.) `I:` *type:atom fix* `Insert Type` Grabs *fix* objects to the right of the cursor, inserts them into a newly created object of `TYPE` *type*, deletes them from the original structure, and inserts the newly created object in their place. In other words, it "inserts" the appropriate open and close brackets for *type* at the cursor and *fix* objects to the right. By default *fix* is one, *type* is `LIST`. An error message is printed if *fix* is larger than the number of objects to the right of the cursor. There is no way to directly insert or delete single parentheses, brackets, etc. using `EDIT`. Insert, use `K:` (see below) to remove pairs of brackets, and `I:` to insert them. `I*` *indicator:atom* **new-structure** `Imbed` Imbed looks for all occurrences of *indicator* in *new-structure* and replaces these occurrences with objects taken and deleted from the right of the cursor. In then inserts the result. If only *new-structure* is given, the *indicator* is the `ATOM` \*. If there aren't enough objects to the right of the cursor to replace each `indicator`, remaining indicators are left untouched and a warning message is printed. `I*` is generally used to insert one or more structures into another complex structure in one operation, instead of several. For example: `>` `I* > *)>$` `> <12 .Y>)>` █ `>` Places a protective conditional around an `NTH` to prevent an out-of-bounds error. `IG` **any** ... `Insert Into Group` Insert into a group. `IG` is similar to `I`, but assumes that the object you are in is a group (as produced by `GROUP-LOAD`). Arguments to `IG` which are not `ATOM`s are inserted as `I`, Objects which are `ATOM`s and which have a value insert a `FORM` which `DEFINE`s, `SETG`s, or `SET`s the `ATOM` as appropriate. Thus, to add a new function `F` to a group \`G1 one could type: O G$IG F$Q$ `K` *fix* `Kill` Deletes `fix` objects to the right of the cursor. Defaults to one. Negative `fix` causes deletion to the left of the cursor. `C` **any** `Change` Changes the one object to the right of the cursor so its single argument. Does not move the cursor. Does not evaluate is argument. `C` is more efficient than `K` plus `I`. `C:` **type:atom** `Change Type` Changes the type of object to the right of the cursor to *type*. Attempts to do something reasonable for every type change. If you tell it to change a `STRING` to a`LIST`, you get a `LIST` of `CHARACTER`s. If you attempt to change a structure whose elements are other than `CHARACTER`s and `STRING`s to a `STRING`, you will get a Muddle error. `K:` `Kill Type` Deletes the brackets around the object to the right of the cursor i.e. kills the object and inserts its elements into the structure of which it was a part. `SU` **new** **old** `Substitute` The Substitute command takes two arguments. All occurrences of *old* from the current location to the end of the open object (actually a search-right is done) are replaced by *new*. Once the search for *old* fails, the command terminates, and the number of substitutions performed is printed. The cursor is left after the last object replaced. `X` **atom** `Transfer` `SET`s the *atom* to the object to the right of the cursor. `X` can be used with `K` and `G` to move things around within the object being edited. `SW` `Swap` Swaps the two objects to right of the cursor, leaving the cursor pointing at the same object. The effect is to move the cursor and the object it points at one object to the right. Repeated `SW`s move cursor and object further and further to the right. #### 3.2.2.6. Macro Facility `M` **macro** `Macro` Takes either a `STRING` or something which `EVAL`s to a `STRING` and performs all of the commands in the `STRING`. For complete assurance that your commands will be done properly, put an ESC between commands. `IT` **fix** *macro* Iterate This command (also called DO) takes a *fix* and macro as if an argument to `M`. This command will loop through the *macro* *fix* times or until an error is generated. When the iteration ends, the user is told how many complete passes have been made of the `macro`. In both of the above commands, if an `EDIT` error is generated, the *macro* will be terminated, and the *macro* itself will be printed, with an arrow pointing to the offending command. The cursor wilt remain at the place where the last legal command left it. The SU command is, internally: `DO * "S` *old*`$L$C` *new*`$"` #### 3.2.2.7. Cursors Cursors are locations in objects being `EDIT`ed. In addition to the main cursor, which is where editing occurs, other locations (also called cursors) may be remembered. The main cursor may be moved to another cursor in a single operation, potentially saving many motion commands. In large `FUNCTION`s cursors may also reduce confusion by distinguishing among several similar areas of code. `UC` `Use Cursors` The `PACKAGE` for dealing with cursors is not normally loaded in an initial Muddle, so the UC command loads it and makes the cursor commands available. The `PACKAGE` loaded is "`CURSOR`". `CU` *atom* `Cursor` `CU` takes an `ATOM` argument and `SET`s the `ATOM` to an object of type `CURSOR`, which tries to be clever in the event you change the object. Also, if you use the `X` command to name a substructure and then move copy it with `G` or `I`, the cursors in the substructure will follow to the new location. There are some restrictions. Cursors in empty `LIST`s are okay but they will not follow the object to new locations. Also this "following" feature is effective only at the first `G` or `I` after the `X`. To move the substructure again you have to `X` again. `I*` is somewhat incompatible with `CURSOR`s. Cursors in Imbedded structures will sometimes disappear. `GO` **cursor** `Go` `GO` takes a *cursor* (normally the `LVAL` of an `ATOM` previously given as an argument to `CU`) and `GO`es to that position. If the *cursor* is illegal (not in the current top-level structure), an error message will be printed and you will remain in your previous position. `KC` **atom** `Kill Cursor` Kill the cursor assigned to *atom*. `PC` `Print Cursors` Prints all cursors in the structure to the right of the main cursor. `PA` Prints all cursors in the currently open structure. #### 3.2.2.8. Breakpoints `BK` *predicate* *any* ... `Breakpoint` Inserts a breakpoint "around" the object to the right of the cursor. Takes any number of arguments. Subsequently, whenever that object would have heen evaluated, you instead hit a breakpoint function which: 1. Evaluates *predicate*. If the value is `FALSE`, evaluation continues as if there were no breakpoint. If the value is non-`FALSE`, or `BK` was given no arguments: 2. Types `**BREAK**`. 3. For each argument after the first that you gave `BK`, types *arg = EVAL of arg* 4. Enters `LISTEN`. You continue by applying `ERRET` to one argument, just as from an `ERROR`; the argument's value is ignored. Breakpoints are implemented by inserting a `BREAKR` (a `PRIMTYPE` `LIST` with `APPLYTYPE` `FORM`) which consists of the function `BREAKR` and arguments, including the object breakpointed. A breakpoint prints as a glyph similar to the cursor: `B` *object* If the `ATOM` `SHORT-PRINT` is assigned `FALSE`, the actual `BREAKR` `LIST` is printed. The breakpoint function returns `EVAL` of the thing it is put "around", and there are cases where this does not work. There are always equivalent places that do work. 1. Breakpoint on the first element of a `FORM` does not work. Put it on the whole `FORM`. 2. Breakpoint on a `LIST` which is an argument to a `COND` does not work. Put it on the first `FORM` in the `LIST`. `BA` *predicate* *any* `Break After` Similar to `BK`, but puts the breakpoint *after* the object at the cursor. Its action is like that of `BK` except that the break occurs after the object it is on is `EVAL`ed. This sort of breakpoint prints like the "before" sort. but with the glyph after the object broken: object `B` The *predicate* for a `BA` breakpoint may check the value returned by `EVAL` for the object the hreakpoint is on. This value is assigned by `BREAKR` to the `ATOM` `VALUE`. `KT` `Kill This` Removes the breakpoint (if any) from the object to the right of the cursor. `KB` `Kill Breakpoints` Removes all breakpoints in the currently open object. #### 3.2.2.9. Edit Monitors There are several commands in `EDIT` which provide a simple interface to the "`MONITOR`" `PACKAGE`. These allow placing of monitors on references to or modifications of `LVAL`s in interpreted Muddle code. For a more complete discussion of the use of monitors, see section 3.7. `UM` `Use Monitors` The `PACKAGE`s for dealing with monitors are not normally loaded in an initial Muddle, so the `UM` command loads them and makes the three commands for creating monitors available. The `PACKAGE`s loaded are "`MONITR`", which is the general monitor `PACKAGE`, and "`EMONIT`", which is the interface between `EDIT` and "`MONITR`". `RW` **atom** *predicate* *any* ... `Read-write Monitor` The most general type of monitor that can be set is a read-write monitor. It will catch any reference to or attempt to modify the `LVAL` of the *atom* specified. The restrictions on placement of breakpoints also apply to monitors, with the addition that a monitor on an `LVAL` must be placed after that `LVAL` has become `ASSIGNED?`. The second, third (and so on) arguments to `RW` are the same as those for `BK`. The *predicate* may be dependent on either the new or old value of the variable: These are available as the `LVAL`s of `NEWVAL` and `OLDVAL`, respectively. When a monitor is triggered, it prints the type of monitor, the variable being monitored, and any other information requested by the user, and then calls `LISTEN`. A monitor prints as yet another glyph: