From: Jason Self Date: Thu, 30 Jun 2016 01:21:57 +0000 (-0700) Subject: Adding initial work on The Muddle Programming Environment X-Git-Url: https://jxself.org/git/?a=commitdiff_plain;h=5b42346253cce1fcb293b889a8f0c33852360f73;p=mudman.git Adding initial work on The Muddle Programming Environment --- diff --git a/md/environment.md b/md/environment.md new file mode 100644 index 0000000..b30763e --- /dev/null +++ b/md/environment.md @@ -0,0 +1,1303 @@ +# The Muddle Programming Environment + +By P. David Lebling + +MIT Technical Report 294 + +May 1980 + +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](http://copyright.cornell.edu/resources/publicdomain.cfm). 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. + +# Introduction + +The Muddle language is described in "The Muddle Programming Language", +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. + +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 and EMACS, TECO based text editors, understand much of the +syntax and many of the conventions of Muddle programs. + +## 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: +