A Machine-Independent MDL.
[pdp10-muddle.git] / doc / SYS.18.01.mss
1 @make(ptreport)
2 @device(dover)
3 @font(timesroman10)
4 @Define(Ins,Break,Continue,Above 1,Below 1,Fill,LeftMargin +1.3 inches,
5         Spaces Compact,Indent 0,Spacing 1)
6
7 @string(ptgdno="SYS.18.01")
8 @begin(titlepage)
9 @document(A Machine-Independent MDL
10 Design Document)
11 @author(Marc S. Blank and Chris Reeve)
12 @date(@value(date))
13 @end(titlepage)
14
15 @pageheading<Left="PTDD",Center="@value<page>",Right="SYS.18.01">
16
17 @chapter<Global Design>
18 @section<The MIM Virtual Machine>
19 There are a number of possible approaches to re-implementing MDL on
20 various processors; the one chosen for this design is to create a
21 virtual machine running a language called MIM (Machine-Independent MDL).
22 The approach is analogous to that taken with Pascal in that MIM is either an
23 interpreted or compiled language, and interpreters or compilers must be
24 written for each target
25 machine. MIM code will be generated from MDL code by a process called
26 MIMC (the MIM compiler, pronounced mimsy), which will be written in MDL.
27
28 At the point that an Apollo-MIM (for example) and MIMC are operational, a
29 MDL interpreter written in MDL (called MUM) can be compiled into MIM.
30 MIMC, which will also be written in MDL, can also be compiled into MIM,
31 thereby providing both an MDL interpreter and compiler running on the
32 Apollo.  It is also proposed that an order-code compiler for the various
33 target machines be written, to 'open-code' MIM into target machine
34 languages, with an increase in speed traded off for an increase in code
35 length.  While MIMOC (MIM Order Compiler) may well become a necessity
36 for runtime systems, it need not become operational for writing,
37 running, and debugging MDL code.
38
39 A major difference between Pascal P-CODEs and MIM M-CODES is that the
40 latter are in themselves a high-level language, with machine
41 instructions which handle such things as RESTing structures, creating
42 structures, etc.  Therefore, very little information of a
43 machine-dependent nature is stored in MIM machine code.  By keeping MIM
44 relatively independent of target machine design, better target machine
45 code can eventually be produced by the MIMOC process.
46
47 @section<MIM Design Goals>
48 MIM (Machine-Independent MDL) is designed to enable the MDL language to
49 be rapidly implemented on a variety of machines.  Although the language
50 specification is 'machine-independent', it is nonetheless designed with
51 8/16/32/36 bit processors in mind.
52
53 In the design of MIM, the goal has been to extract those features of
54 MDL which are 'primitive' and to make those 'primitives' machine instructions.
55 Thus, the MIM machine must understand the concept of an MDL object, MDL
56 structured primtypes, etc.  However, it is clear that most of the MDL
57 SUBR/FSUBR's are composites of 'primitives' and that in fact few of
58 the MDL SUBR/FSUBR's need be implemented as machine instructions.
59 For example, MEMQ need not exist given NTH, REST, and ==?.  More difficult
60 questions have involved such issues as whether READ can be written
61 efficiently in MDL given only READSTRING, and how much of the ATOM/OBLIST
62 system can be written in MDL.  
63
64 @chapter<MIM Machine Structure>
65 @tabclear<>
66 @tabset<1.3 inches,2.5 inches>
67 @section<MIM Instruction Format>
68 Each MIM instructions takes a number of arguments and a destination designator
69 for the result if any.
70
71 The arguments to a MIM instruction can be either local variable names or
72 quoted MDL objects.  The result of a MIM instruction can either be a local
73 variable or the atom STACK which directs the instruction to leave the
74 result on the stack.
75
76 In describing the instruction set the following convention will
77 be used in denoting operands:
78 @begin<format>
79
80         @i<operand-type:MDL-type-or-primtype>
81 @end<format>
82 where @i<operand-type> is one of local or any (meaning either a local or
83 constant) and
84 @i<MDL-type-or-primtype> indicates the legal value(s) for that operand.
85
86 @section<MIM Predicates>
87
88 Some MIM instructions are predicates.  These all have mnemonics which
89 end in a question mark (e.g. EQUAL?).  These instructions are all
90 followed by a + or - to indicate whether the branch should be taken
91 if the predicate is true or false.  After the + or -, the branch label
92 occurs.
93
94 @section<MIM Internal Variables>
95 MIM has a few internal variables, which may be read and set.  These variables
96 should not be confused with global or local variables in MDL.  They are more
97 like MIM state variables.
98
99 @begin<enumerate>
100 MINF - a UVECTOR of information about the machine on which MIM is running
101
102 PAGETB - a UVECTOR of information about the address space available to MIM 
103
104 BIND - the most recent binding on the STACK
105
106 FRAME - the current FRAME
107
108 ARGS - the number of arguments to the current FRAME
109
110 OBLIST- the global atom-table
111
112 ICALL - the @b(MSUBR) to CALL when an interrupt occurs
113
114 ECALL - the @b(MSUBR) to CALL when an error in order-code occurs
115
116 NCALL - the @b(MSUBR) to CALL when a non-globally-assigned @b(ATOM) or
117 an @b(ATOM) whose global value is not an @b(MSUBR) is CALLed 
118 @end<enumerate>
119
120 The last three internal variables are intended to be set once during
121 initialization of the MDL interpreter.  Extreme caution should be used
122 when setting the BIND, ARGS, FRAME, and OBLIST variables, as these
123 are used internally for @b(MSUBR) CALLing, etc.  
124
125 @section<MIM Objects>
126 A MIM object is a 64-bit or 72-bit structure which is roughly equivalent to
127 the PDP-10 MDL type/value pair.  A MIM object contains the following
128 items:
129 @begin<itemize>
130 Type Word - 16 or 18 bits specifying the type and primtype of the object.  See
131 @i<TYPE-WORD Format>.
132
133 Length Word - 16 or 18 bits. See @i<LENGTH-WORD Description>
134
135 Value - 32 or 36 bits, a pointer for structures or a value for non-structures.
136 @end<itemize>
137
138 @section<MIM Subroutines>
139
140 The unit of executable MIM code is the @b(MSUBR) (@b(M)dl
141 @b(SUBR)outine).  This has a format as diagrammed in @i<MSUBR Format>.
142 Briefly, an @b(MSUBR) is a primtype @b(VECTOR) which contains a pointer to
143 an @b(IMSUBR) which is a primtype @b(VECTOR) and contains a pointer to
144 runnable MIM instructions (a primtype @b(UVECTOR) of type @t(MCODE)), as
145 well as other MDL objects used by the @b(MSUBR).  By convention, the second
146 element of the MSUBR is its name (an @b(ATOM)), the third is the
147 type declaration for the MSUBR (a @b(LIST)) and the fourth is the offset
148 into the MCODE where the code for this MSUBR starts. When an MSUBR wants to
149 reference an MIM object, it refers to an offset in the IMSUBR.  The CALL
150 instruction makes the MIM program counter point to the appropriate element of
151 the @b(MCODE) for the called @b(MSUBR).
152
153 @section<MIM Stack>
154
155 MIM has a stack (referred to as the STACK) which is used for MSUBR
156 calling, bindings, local variables, temporaries, etc. All items on the
157 STACK are either legal MIM objects (i.e. 64-bit structures) or
158 structures placed there by MIM instructions (e.g. FRAME, BIND).
159
160 @chapter<MIM Instruction Overview>
161
162 @section<Stack & Variable Operations>
163
164 MIM has instructions for placing objects on the STACK (PUSH) and for
165 removing objects from the top of the STACK (POP).  In addition, the
166 instruction ADJ adjusts the STACK pointer either forward or backward by
167 a given number of MIM objects.
168
169 MIM local variables (located on the STACK) can be set with the various
170 SET instructions to either the value of another local variable, a slot
171 in the @b(IMSUBR) or a constant.
172
173 @section<MSUBR Calling>
174
175 In order to transfer control from one @b(MSUBR) to another, a STACK @b(FRAME)
176 must be created.  This is done using the FRAME instruction.  Such a
177 @b(FRAME) will contain enough inforiadio, to$anlow Dr\bMCUBTh\0Bet5xls,\ 5\bmulpip|d`6etur.1, !nd`MDL)style AGAIN." NL\ 3e the\0@v F\12AOE         is btHnT, the\r\bargumenlc un dhe @b(M\13FBR)(HiF@aFy       avE \10USId$ Knto thE QTACJ. `TIenL
178 tam \ 3A\rL ivsTruwty\7fn is!ayEcetem.\0\r\ e
179 Hgse\0kc an`a{`)\12mT(mf`tie0usg (iF`II\f awSmlbmq Da~gqege novatinli\0on 5(D\r\bcAM\f instbugtinn:\r\ 6@bggin<vewBc4km>
180 \v\r\ e        <FRAMA>    ('`   `( 0     $`      ; cre`tm\0` ctack Dramm
181 `     ` <P\15SH   NOO> "\0   \0  \0    \0 \00  ! \1f(push!th\ 4 hocil v`riablM DO\a\r\b   @`  H<PQ    B\r\18pQQ\11\a\ 1l gF'o|OOOO\ f\ eWOMKOGOM@_\ 6\ 2\ 5\ 3_\ 3\ 1\18\ f\ 1\10\1c\16\ 1O\0*\ 4\ 2\ 6\ e\ 1(\ f\1c^\ 4p0O\ fOGOOOKA\a\b\ 4\17_O_F\a@OOOOoOOOI_O_OoaO\ fNI=G\ 5\18\ 3P9:ysezE\ 6\17\ 6\ 4BB\ 4F\0\0cgw{x'/sg'ea_r\1e\ 2\18Sfd\ fd\ 3\1c      v\1842@`>\0)\0\0\10\ 2&\0\0(\ 26\0\0 \ 25\0\0\18\ 24\0\0\10\ 23\0\0\10\ 38\0\0(\ 4{\0\0 \ 4z\0\0\10\ 5)\0\00\bD\0\0(\bC\0\0 \bB\0\0\18        \ 2\0\0\10    \ 1\0\0\b\f\ 1\0\0\10\f\1c\0\0\18\fx\0\0\b\10:\0\0(\11t\0\0 \11s\0\0\18\11r\f%\14A\ 4\0\0\b\0\ 1\f(\1c?\e\0\0\b\ 1f\fA\13G\0\0\0\b\ 2$\fD\f[@\0\0 \ 2-\r5\1a\0\e\0\0\b\ 36\r5\19\7fd\0\0\10\ 4u\f\C`X\0\0\b\ 5'\v\ 3.LG\0\0\10\a\f\f\CO4\0\0\18\b=\f\D\1aw\0\0\b\bu\r\ e\13(X\0\0\10\b|
182 \|Pd\0\0\b\vU\r4zc   \0\0\b\f\0\r\ e\13m:\0\0\b\f\1a\rOi<\14\0\0\b\fl
183 M\0\1a[\0\0\b\fu
184 M\0\19`\0\0\b\rR
185 8\18      ^\0\0\b\r\\v\12KyP\0\0\18\ eM
186 M\0\19`\0\0\b\ f\10
187 ~s\0?\0\0\10\ f&
188 \7f\be,\0\0\10\ f<
189 \7f\ 2+\ 6\0\0\10\ fM\f\fQ7P\0\0\b\ f_\v\14D^\ e\0\0\b\10\b\v\14D^\b\0\0\b\10+\v\14D^\ e\0\0\b\109
190 \7f\12`;\0\0\b\11\b\rY]c"\0\0\10\11\17\f\D%:\0\0\b\11$\v>/g0\0\0\b\11.\v\12KyP\0\0\b\114\rT\ e\190\0\0\b\11C\f(I\17\1f\0\0\b\11Q
191 |T\15\ 2\0\0\18\11m\f"QO\ 1\0\0\b\12\19\0\ 18\0$\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0rnal representation of the various structure classes. 
192
193 @section<MIM Support for ATOMs and Bindings>
194
195 MIM supports the concepts of @b(ATOM)s and bindings.  This is necessary
196 in that a completely external simulation of atomic bindings would be
197 unreasonably expensive without some knowledge in the interpreter of
198 their structure.
199
200 A STACK binding (type LBIND) is created with the BIND instruction.
201 BIND does the following:
202 @begin(itemize)
203 Creates an LBIND and places it on the STACK
204
205 Points this new LBIND to the previous LBIND on the STACK
206
207 Updates the internal pointer to the most recent LBIND to be the one just
208 created. 
209 @end(itemize)
210
211 Code inside MUM does the remainder of the binding process, including
212 pointing the LBIND at the ATOM which is being bound and placing values
213 and declarations in the LBIND.  Additionally, an LBIND for a given ATOM
214 is pointed to the previous LBIND for that ATOM.  A number of MIM
215 instructions perform 'unbinding' of @b(ATOM)s (e.g. RETURN, RTUPLE, and
216 AGAIN) back to a given FRAME.
217 The steps in 'unbinding' are:
218 @begin(itemize)
219 Remove the LBIND from the STACK
220
221 Update the internal pointer to the most recent LBIND to be the previous
222 LBIND (as saved by the BIND instruction)
223
224 Update the LBIND slot of the ATOM pointed to by the LBIND to be the
225 previous LBIND (if any) for that ATOM.
226 @end(itemize)
227
228 @section<MIM Garbage Collector>
229
230 It is intended that MDL have two garbage collectors, a mark-sweep
231 garbage collector, and a full-copy garbage collector.  MIM instructions
232 for both are included in this document.
233
234 @section<MIM Bootstrap Routine>
235
236 In order for any @b(MSUBR) to run, it is necessary for MIM to have
237 'read' that @b(MSUBR).  Therefore, MIM must include a primitive MDL
238 reader, which must be capable of parsing the following MDL data types:
239 @b(IMSUBR), @b(MSUBR), @b(MCODE), @b(ATOM), @b(FIX), @b(FLOAT), @b(STRING),
240 @b(VECTOR), @b(LIST), and @b(CHARACTER).  By convention, the file
241 BOOT.MSUBR contains the bootstrap routines for loading a MDL.  The BOOT
242 file is a sequence of @b(MSUBR)s.  MIM must read these @b(MSUBR)s and
243 SETG the names of the @b(MSUBR)s accordingly (by convention, the name
244 of an @b(MSUBR) is the second element of the @b(MSUBR)).  Execution
245 commences with MIM CALLing the @b(MSUBR) named BOOT.  
246
247 @chapter<The MDL Interpreter Written in MDL - MUM>
248 @section<Overview>
249
250 @b(MUM) (@b(M)DL @b(U)nder @b(M)DL) is the name given to the MDL
251 interpreter which is written in MDL.  In most respects, MUM/MDL will be
252 identical to the current PDP-10 and TOPS-20 MDLs.  @b(MUM) will,
253 however, include some capabilities not found in the older MDLs.
254
255 @section<Modularity of the MDL Interpreter>
256
257 The new MDL interpreter (@b(MUM)) is composed of individual speCialty
258 modules (e.g. PRINT, READ, ASOC, ARITH).  Each od these modules consists
259 of`@b(MSUBB)s, as wnulD any other piece of \ fuser-code'.  The result is
260 that the`distinction`between interpreter And 'user-code' `as become
261 blurrmd.  To tie casual MDL user, thE interpreter will probably appear\1d
262 lareer than $ib-YB\16\r10 version, because some parts of the MDL
263 environment will be included.  However, to the production-systems
264 prWS^itSK` wsY^ eaS`t I_BexG\19ldeQC\18y\0_lFalh\ 1Zf  QJ MY\18\1a
265 imiHrpEKlerA]bomAEHinNAXoaYKJ, YK@vimNBa G[@llKdFanHABlec]Nr Wsbte:\\1e\1a\re\ 1fec    S^n>\13)\18M S[dlekK^ta\19SZn>J\14\1a
266 @\14Q\ 6TOjS` aeJFstekFtuEKd w\AbriKitpe\ 1\ 1\ 6\bRZ\a\1eRDRAlit`AJouDALlmsKZdsTAF
267 I\1fFalQAVnd\ 3]H (\11DPLBS\1c
268 ))\18AD gI\7fBalQEVnd\ 3]H (\11DPGBS\1d
269 ))PAB p\1dCXe\r$Q\ 4b\b\a)"INNRP,!S]H a\1cA\0b(/\ 5\1cISXVX ECi\14erQ_H taJ@fiegh!t\ f^Belc[Nnt\16ABanZ\15DlsN\ 1@e \ 2A\0b(]\ 3\18\13EBXFinYSGctS]H tQCh!tQK`e!CfFnoQY\ca\bA^r \1fY\baX\1a\12bi]IPNg\\0D@b!\1f\ 2LIW Ts aCje IQR scSJ siejctkeH a\ 6C\ 6b(c)\18M)V\B L_iH t\ 1Ch
270 \11DRATO\1aQs G]N @\14Q\18BLC',)sQCde ]_bmAHA\18IMAgjruginreFAhhiWPDca\1cABE\re[PniAkXatKHDasQC`e OiPerAgjrugihreV\F TQSf\0aIYXws\11CXl \e       \1f!"\0oo\7f@\7f\7f\7f\7f\7f support for
271 @b(AT_M)s and @b(OBLIST)c to Be wsitteN in MDL itself whth calls to NTH,        
272 REST, etc.
273 \f
274 The BIND instruction creates and returns an @b(LBIND) ol the STACK.
275 There is no need for a GBIND instruction, as a @b(GBIND) can be created
276 with the RECORD instruction.  As with @b(ATOM)s, @b(LBIND)s and
277 @b(\aBIND)s are primtype @b(RECORD)s which can be manipulated; thus, the
278 SUBR's SET and SETG turn into PUTs, as\0doH\0\15@\rDECL, and GDECL.
279
280 @section<Arithmetic and Bktwise Operations>
281
282 @b(FIX) is the only non-structured MIM primtype,!replacing the primtype WORD
283 in the current MDL.  All bitwise operations take any primtype @b(FIX) and
284 return a type @b(FIX).  The aritHmetic iNstructions take either pairs of
285 @b(FIX)es or @b(FLOAT)s and return objects of the same type.
286
287 @section<I/O>
288
289 MIM provides a very primitive I/O interface, which consists of OPEN,
290 CLOSE, and ctring read/print.  The MDL conversion I/O SUBRs (READ,
291 READCHR, PRILT, PRIN1, PRINC, PARSE, and UNPAR\13E) have all been written
292 uskng only these operapions.  Block-iode I/O SUBRs (PRINTB( READB,
293 PRINTSTRING, READSTRING) can also be!easily incorporated hnto this scheme.  
294 \1d
295 While these SUBRs cover mcNy MDL I/O applIcations, snme others will nEed
296 tn be\0levised.  Akong these is some form of core-image I/O, which
297 would provide fast, non-parsed I/O, and some machine-independent MDL I/O
298 scheme, which is being devised by an undergraduate at the present time.
299
300 The SAVE and RESTORE instructions provide the means for saving and
301 restoring a core-image, and is used mostly in the creation of large
302 subsystems.
303
304 @section<Associations>
305
306 There is no support in MIM for associative storage as implemented
307 in the existing MDL.  However, such a scheme has been implemented
308 in MDL. 
309
310 @section<Coroutines>
311
312 There is no coroutine/multiprocess facility in MIM.  The major issue
313 that coroutines encounter is that of the STACK, whether there should
314 be one for each coroutine, etc.  The possible inclusion of this
315 concept into the design of MIM will be considered at a later date.
316
317 @section<Interrupt Handling>
318
319 MIM has a very primitive interrupt system which interacts with a rather
320 sophisticated software interrupt system written in MDL, and based on the
321 old MDL's interrupt system.  When a non-emergent interrupt is received by
322 MIM, MIM CALLs the @b(MSUBR) specified by the SETS ICALL instruction
323 with one argument, a @b(FIX) between 0 and 35, which is the unique
324 identifier of that class of interrupt.  
325
326 To allow for terminal interrupts, the MIM instruction ATIC (Activate
327 Terminal Interrupt Character) takes a @b(CHARACTER) and returns a
328 @b(FIX) which is the unique identifier for a terminal interrupt on that
329 @b(CHARACTER).
330
331 Emergency interrupts (stack overflow, illegal memory read/write) may
332 require MIM to take some emergency action prior to CALLing the software
333 interrupt system.  Naturally, these interrupts are somewhat
334 machine-dependent, and will have to be dealt with for each target machine. 
335 l
336 @chapter<MIM Instruction Set>
337 @section<Stack Operations & Flow of Control>
338 @begin<format>
339 @b<PUSH>@\@i<any:any>
340 @begin<ins>
341 The PUSH instruction @i<pushs> its operand onto STACK.  The special destination
342 STACK for other instructions is another of placing objects on the stack.
343 @end<ins>
344
345 @b<POP>@\@i<local>
346 @begin<ins>
347 The POP instruction @i<pop>s the top element from the STACK
348 and moves it into a local variable.  Calling an MSUBR also removes the
349 arguments from the stack.
350
351 @end<ins>
352
353 @b<SET>@\@i<local:any>,@i<any:any>
354 @begin<ins>
355 The various SET instructions set a local variable to the value of
356 another local variable or a constant.
357 The use of local variable as destination also causes a SET of that variable
358 to occur. 
359 @end<ins>
360
361 @b<SETLR>@\@i<local:any1>,@i<local:frame>,@i<local:any2>
362 @begin<ins>
363 Sets local variable @i(any1) in the current frame to the value of
364 local variable @i(any2) in @i(frame).
365 @end<ins>
366
367 @b<SETRL>@\@i<local:frame>,@i<local:any1>,@i<local:any2>
368 @begin<ins>
369 Sets local variable @i(any1) in @i(frame) to the value of local variable
370 @i(any2) in the current frame.
371 @end<ins>
372
373 @b<ADJ>@\@i<any:fix>
374 @begin<ins>
375 Adjusts the STACK by @i<fix> objects, positive indicating @i<push>ing
376 and negative indicating @i<pop>ping.
377 @end<ins>
378
379 @b<FRAME>@\@i<no operands>
380 @begin<ins>
381 Creates a CALL @i<frame> on the STACK.
382 @end<ins>
383
384 @b<CFRAME>@\@i<no operands>
385 @begin<ins>
386 Returns the running @i<frame>.
387 @end<ins>
388
389 @b<ARGS>@\@i<any:frame>
390 @begin<ins>
391 Returns a TUPLE with the arguments to the @i<frame>.
392 @end<ins>
393
394 @b<TUPLE>@\@i<any:fix>
395 @begin<ins>
396 Returns a TUPLE containing @i<fix> elements from the top of the STACK.
397 @end<ins>
398
399 @b<RFRAME>@\@i<any:frame>
400 @begin<ins>
401 The return instruction which follows will cause values to be
402 returned to @i<frame>. Unbinding will occur back to @i<frame>.
403 @end<ins>
404
405 @b<CALL>@\@i<any:atom>,@i<local:fix>
406 @begin<ins>
407 Starts execution of an MSUBR.  This instruction must follow the
408 creation of a FRAME and the PUSHing of arguments.  If the global
409 value of @i(atom) is an MSUBR, execution starts immediately.  Otherwise,
410 the NCALL routine is executed.
411 @end<ins>
412
413 @b<INCALL>@\@i<local:any>
414 @begin<ins>
415 Builds a FRAME and performs a 'CALL' within the current MSUBR.  This is
416 useful for PROGs and REPEATs that have external ACTIVATIONS that maybe
417 RETURNed from or AGAINed.
418 @end<ins>
419
420 @b<MAKTUP>@\@i<local:any1>,@i<local:any2>...@i<local:anyn>
421 @begin<ins>
422 Builds and returns a TUPLE out of the arguments passed to an MSUBR.  The
423 arguments are the temporaries used in the MSUBR.
424 @end<ins>
425
426 @b<ACTIVATION>@\@i<no operands>
427 @begin<ins>
428 Saves the current offset into the MSUBR as the 'activation' for the
429 current FRAME.
430 @end<ins>
431
432 @b<AGAIN>@\@i<local:frame>
433 @begin<ins>
434 AGAIN restarts execution of the MSUBR running in @i<frame> from
435 the offset specified within that MSUBR by a call to ACTIVATION.
436 Unbinding will occur back to @i<frame>.
437 @end<ins>
438
439 @b<RETURN>@\@i<local:any>,@<local:frame>
440 @begin<ins>
441 Performs a CALL return with value as specified by the operand . 
442 The second argument is optional and defaults to the current frame.
443 Unbinding for will occur.
444 @end<ins>
445
446 @b<RTUPLE>@\@i<local:fix>
447 @begin<ins>
448 Performs a CALL return with any number of values, which have been
449 PUSHed onto the STACK, and whose number is specified by @i<fix>,
450 returning as the top of STACK a @i<tuple> pointing to the return values.
451 @end<ins>
452  
453 @b<JUMP>@\@i<label>
454 @begin<ins>
455 Unconditional branch to label.  JUMPs may only be used
456 locally (i.e. within an @i<msubr>).
457 @end<ins>
458 @end<format>
459
460 @newpage
461 @section<GC Interface>
462 @begin<format>
463 @b<MARKL>@\@i<local:list>,@i<local:fix>
464 @b<MARKU(U/V/S)>@\@i<local:ublock>,@i<local:fix>
465 @b<MARKR>@\@i<local:record>,@i<local:fix>
466 @begin<ins>
467 Marks a structure, setting to mark bit to @i(fix), which should be
468 either zero, one, or a "new address" for copy GC.  MARKL marks just one
469 element of the @i(list).
470 @end<ins>
471
472 @b<MARKL?>@\@i<local:list>,@i<constant:fix>
473 @b<MARKU(U/V/S)?>@\@i<local:ublock>,@i<constant:fix>
474 @b<MARKR?>@\@i<local:record>,@i<constant:fix>
475 @begin<ins>
476 Predicate, testing the marked state of a structure.  Unlike normal predicates,
477 these return either a fix or false.  The second argument is optional, its
478 existance indicates a relocation should be returned for marked objects.
479 @end<ins>
480
481 @b<SWNEXT>@\@i<local:any>
482 @begin<ins>
483 Performs the sweep phase of the garbage collector.
484 @end<ins>
485 @b<NEXTS>@\@i<local:fix>
486 @begin<ins>
487 Gets and returns a fix that can be used with CONTENTS to get the next item
488 on the stack.  For marking the stack.
489 @end<ins>
490 @b<CONTENTS>@\@i<local:fix>
491 @begin<ins>
492 Returns the next stack item.  The argument should be one received from NEXTS.
493 @end<ins>
494 @b<PUTS>@\@i<local:fix>,@i<local:any>
495 @begin<ins>
496 The opposite of CONTENTS, PUTS stores back into the stack.
497 @end<ins>
498 @b<ALLOCL>@\@i<local:fix>,@i<local:any>
499 @b<ALLOCU(U/V/S)>@\@i<local:fix>,@i<local:any>
500 @b<ALLOCR>@\@i<local:fix>,@i<local:any>
501 @begin<ins>
502 Allocates room for the object specified by the second argument at the address
503 specified by the first.
504 @end<ins>
505 @b<BLT>@\@i<local:fix>,@i<local:fix>,@i<local:fix>
506 @begin<ins>
507 Moves an object from the location specified by the first argument to the
508 location specified by the second argument.  The third argument is the length
509 in words (32 or 36 bit words).  This length should include the dopewords. 
510 @end<ins>
511 @b<RELL>@\@i<local:list>
512 @b<RELU(U/V/S)>@\@i<local:ublock>
513 @b<RELR>@\@i<local:record>
514 @begin<ins>
515 These instructions recycle the appropriate objects.
516 @end<ins>
517
518 @end<format>
519
520 @newpage
521 @section<Utility>
522 @begin<format>
523 @b<HALT>@\@i<no operands>
524 @begin<ins>
525 Halts MDL.
526 @end<ins>
527
528 @b<OBJECT>@\@i<local:fix>,@i<local:fix>,@i<local:fix>
529 @begin<ins>
530 Returns a MIM object, whose type, length, and value words are the three
531 operands, respectively.
532 @end<ins>
533
534 @b<GETS>@\@i<byte:fix>
535 @begin<ins>
536 Returns the value for the internal variable indicated by @i(fix).
537 @end<ins>
538
539 @b<SETS>@\@i<byte:fix>,@i<local:any>
540 @begin(ins)
541 Sets the value of the internal variable indicated by @i(fix) to @i(any).
542 @end(ins)
543
544 @end<format>
545
546
547
548 @newpage
549 @section<Type Manipulation>
550 @begin<format>
551 @b<TYPE>@\@i<local:any>
552 @begin<ins>
553 Returns the TYPE of @i<any>, as a @i<fix>.
554 @end<ins>
555
556 @b<TYPE?>@\@i<local:any>,@i<local:fix>
557 @b<TYPEW?>@\@i<local:any>,<word>
558 @begin<ins>
559 Predicate on TYPE of @i<any> being @i<fix>
560 @end<ins>
561
562 @b<CHTYPE>@\@i<local:any>,@i<local:fix>
563 @begin<ins>
564 Returns @i<any>, with its TYPE changed to @i<fix>.
565 @end<ins>
566
567 @b<NEWTYPE>@\@i<local:fix>
568 @begin<ins>
569 Returns a @i<fix>, a new TYPE whose primtype is the primtype of @i<fix>.
570 @end<ins>
571
572 @b<VALUE>@\@i<local:any>
573 @begin<ins>
574 Returns the 'value' 32 bits of @i<any>, as a @i<fix>.  This is
575 a utility instruction.
576 @end<ins>
577 @end<format>
578
579 @newpage
580 @section<Structure Creation>
581 @begin<format>
582 @b<LIST>@\@i<local:fix>
583 @b<LISTB>@\@i<byte>
584 @begin<ins>
585 LIST creates and returns a LIST containing @i<fix> elements which
586 are on the top of the STACK.
587 @end<ins>
588
589 @b<UBLOCK>@\@i<local:fix,local:fix,local:fix>
590 @b<UBLOCKB>@\@i<local:fix,local:fix,byte>
591 @begin<ins>
592 UBLOCK creates and returns a UBLOCK of the specified type (@i<fix1>),
593 with @i<fix2> elements from the top of the STACK.
594 @end<ins>
595
596 @b<RECORD>@\@i<local:fix,local:fix>
597 @b<RECORDB>@\@i<local:fix,byte>
598 @begin<ins>
599 RECORD creates and returns a RECORD of the specified type (@i<fix1>),
600 with @i<fix2> elements from the top of the STACK.
601 @end<ins>
602 @end<format>
603
604 @newpage
605 @section<Structure Manipulation>
606 @begin<format>
607 @b<NTHL>@\@i<local:list>,@i<local:fix>
608 @b<NTHLB>@\@i<local:list>,@i<byte>
609
610 @b<NTHR>@\@i<local:record>,@i<local:fix>
611 @b<NTHRB>@\@i<local:record>,@i<byte>
612
613 @b<NTHU>@\@i<local:ublock>,@i<local:fix>,@i<local:any>
614 @b<NTHUB>@\@i<local:ublock>,@i<byte>,@i<local:any>
615 @begin<ins>
616 Returns the @i<fix>th element of @i<structure>.
617 @end<ins>
618
619 @b<LENL>@\@i<local:list>
620 @b<LENR>@\@i<local:record>
621 @b<LENU>@\@i<local:ublock>
622 @begin<ins>
623 Returns the length of @i<structure>, as a @i<fix>.
624 @end<ins>
625
626 @b<EMPL?>@\@i<local:list>
627 @b<EMPR?>@\@i<local:record>
628 @b<EMPV?>@\@i<local:ublock>
629 @begin<ins>
630 Predicate on emptiness of @i<structure>.
631 @end<ins>
632
633 @b<PUTL>@\@i<local:list>,@i<local:fix>,@i<local:any>
634 @b<PUTLB>@\@i<local:list>,@i<byte>,@i<local:any>
635
636 @b<PUTR>@\@i<local:record>,@i<local:fix>,@i<local:any>
637 @b<PUTRB>@\@i<local:record>,@i<byte>,@i<local:any>
638
639 @b<PUTU>@\@i<local:ublock>,@i<local:fix>,@i<local:any>
640 @b<PUTUB>@\@i<local:ublock>,@i<byte>,@i<local:any>
641 @begin<ins>
642 Makes @i<any> the @i<fix>th element of @i<structure>.
643 @end<ins>
644
645
646 @b<RESTL>@\@i<local:list>,@i<local:fix>
647 @b<RESTLB>@\@i<local:list>,@i<byte>
648
649 @b<RESTU>@\@i<local:ublock>,@i<local:fix>,@i<local:any>
650 @b<RESTUB>@\@i<local:ublock>,@i<byte>,@i<local:any>
651 @begin<ins>
652 Rests @i<structure> by @i<fix> elements.
653 @end<ins>
654
655
656 @b<BACKU>@\@i<local:ublock>,@i<local:fix>
657 @b<BACKUB>@\@i<local:ublock>,@i<byte>
658 @begin<ins>
659 Returns @i<ublock> with @i<fix> previously RESTUed elements
660 replaced.
661 @end<ins>
662
663 @b<TOPU>@\@i<local:ublock>
664 @begin<ins>
665 Returns @i<ublock> with all previously RESTUed elements restored.
666 @end<ins>
667
668 @b<CONS>@\@i<local:any>,@i<local:list>
669 @begin<ins>
670 Returns a @i<list>, with @i<any> consed onto @i<primtype list>.
671 @end<ins>
672
673 @b<PUTREST>@\@i<local:list1>,@i<local:list2>
674 @begin<ins>
675 Returns @i<list1>, after making REST of it be @i<list2>.
676 @end<ins>
677 @end<format>
678
679 @newpage
680 @section<ATOM-Related Operations>
681 @begin<format>
682 @b<BIND>@\@i<no operand>
683 @begin<ins>
684 Creates and returns a BINDING on the STACK.
685 @end<ins>
686
687 @b<UNBIND>@\@i<local:lbind>
688 @begin<ins>
689 Unbinds STACK bindings until the top binding is @i(lbind).
690 @end<ins>
691
692 @b<FIXBIND>@\@i<no operands>
693 @begin<ins>
694 Ensures that each @t(ATOM) pointed to by a STACK binding points
695 back at that binding.
696 @end<ins>
697
698 @b<SETG>@\@i<local:atom>,@i<local:any>
699 @begin<ins>
700 Assumes that a global binding exists for @i(atom): stuffs @i(any) into
701 that global binding's value slot.
702 @end<ins>
703
704 @b<GVAL>@\@i<local:atom>
705 @begin<ins>
706 Assumes that a global binding exists for @i(atom): returns that global
707 binding's value slot.
708 @end<ins>
709
710 @end<format>
711
712 @newpage
713 @section<Input/Output>
714 @begin<format>
715
716 @b<OPEN>@\@i<local:fix1>,@i<local:fix2>,@i<local:string>
717 @begin<ins>
718 Opens a 'channel' to a file specified by @i(string).  Note
719 that the format of @i<string> is completely machine-dependent.
720 The direction of the 'channel' is specified by @i(fix1): 1 is 'print',
721 0 is 'read'.  The byte-size of the 'channel' is specified by @i(fix2):
722 usually this will be for character I/O (7 or 8) or word I/O (32 or 36).
723 The byte-size will be used by the READ and PRINT instructions in
724 determining the unit of I/O.
725  
726 Returns a @i<fix>, a unique 'channel' designator, or a @i<false>
727 containing an error code (a @i(fix)).
728 @end<ins>
729
730 @b<CLOSE>@\@i<local:fix>
731 @begin<ins>
732 Closes the 'channel' associated with @i<fix>, a 'channel' designator.
733 @end<ins>
734
735 @b<READ>@\@i<local:fix1>,@i<local:string>,@i<local:fix2>
736 @begin<ins>
737 Reads @i(fix2) items from 'channel' with identifier @i(fix1) into
738 @i(string). 
739 @end<ins>
740  
741 @b<PRINT>@\@i<local:fix1>,@i<local:string>,@i<local:fix2>
742 @begin<ins>
743 Prints @i(fix2) items to 'channel' with identifier @i(fix1) from
744 @i(string). 
745 @end<ins>
746  
747 @b<SAVE>@\@i<local:fix>
748 @begin<ins>
749 Saves the state of MDL on 'channel' @i<fix>.
750 @end<ins>
751
752 @b<RESTORE>@\@i<local:fix>
753 @begin<ins>
754 Restores the state of MDL from 'channel' @i<fix>.
755 @end<ins>
756 @end<format>
757
758 @newpage
759 @section<Arithmetic>
760 The following arithmetic instructions return the result of the
761 appropriate operation.
762 @begin<format>
763
764 @b<ADD>@\@i<local:fix>,@i<local:fix>
765 @b<ADDB>@\@i<local:fix>,@i<byte>
766 @b<ADDF>@\@i<local:float>,@i<local:float>
767
768 @b<SUB>@\@i<local:fix>,@i<local:fix>
769 @b<SUBB>@\@i<local:fix>,@i<byte>
770 @b<SUBF>@\@i<local:float>,@i<local:float>
771
772 @b<MUL>@\@i<local:fix>,@i<local:fix>
773 @b<MULB>@\@i<local:fix>,@i<byte>
774 @b<MULF>@\@i<local:float>,@i<local:float>
775
776 @b<DIV>@\@i<local:fix>,@i<local:fix>
777 @b<DIVB>@\@i<local:fix>,@i<byte>
778 @b<DIVF>@\@i<local:float>,@i<local:float>
779
780
781 @b<RANDOM>@\@i<local:fix>
782 @begin<ins>
783 Selects a RANDOM number between one and @i<fix>, inclusive.
784 @end<ins>
785
786
787 @b<FIX>@\@i<local:float>
788 @begin<ins>
789 Turns @i<float> into a @i<fix>.
790 @end<ins>
791
792 @b<FLOAT>@\@i<local:fix>
793 @begin<ins>
794 Turns @i<fix> into a @i<float>.
795 @end<ins>
796 @end<format>
797
798 The following are arithmetic conditional branch instructions.
799 @begin<format>
800
801 @b<GRTR?>@\@i<local:fix>,@i<local:fix>
802 @b<GRTRB?>@\@i<local:fix>,@i<byte>
803
804 @b<LESS?>@\@i<local:fix>,@i<local:fix>
805 @b<LESSB?>@\@i<local:fix>,<byte>
806 @end<format>
807
808 @newpage
809 @section<Bitwise Operations>
810 All of the following instructions take two operands of primtype @i<fix>
811 and return a type @i<fix>.
812 @begin<format>
813
814 @b<AND>@\@i<local:fix>,@i<local:fix>
815
816 @b<IOR>@\@i<local:fix>,@i<local:fix>
817
818 @b<XOR>@\@i<local:fix>,@i<local:fix>
819
820 @b<EQV>@\@i<local:fix>,@i<local:fix>
821
822 @b<LSH>@\@i<local:fix>,@i<local:fix>
823
824 @b<ROT>@\@i<local:fix>,@i<local:fix>
825 @end<format>
826
827 @newpage
828 @section<General Predicates>
829 @begin<format>
830 @b<EQUAL?>@\@i<local:any>,@i<local:any>
831 @begin<ins>
832 Conditional branch on equality of operands (i.e. ==? in the MDL sense).
833 @end<ins>
834
835 @b<VEQUAL?>@\@i<local:any>,@i<local:any>
836 @b<VEQB?>@\@i<local:any>,@i<byte>
837 @begin<ins>
838 Conditional branch on equality of 'value' words of operands only.
839 @end<ins>
840 @end<format>
841
842 @appendix<Sample MIM Assembly Code>
843
844 The following examples give representitive MDL code with the
845 corresponding MIM code, in assembly format.  Those familiar with the
846 PDP-10 MDL assembler format will be comfortable reading it. Basically,
847 each instruction is a @b(FORM), whose first element is an operation code
848 mnemonic, and whose remaining elements up to but not including the
849 special characters -, +, and = are operand descriptors.  Local operands
850 are denoted by 'names' (i.e. @b(ATOM)s). @b(MSUBR) operands can be any legal
851 MDL object (including @b(ATOMs), and are specified as the MDL object itself
852 (except for @b(ATOM)s, which are specified as '<name>). Predicate
853 instructions are followed by a word which describes a pc-relative jump
854 if the instruction succeeds or fails.  A + precedes a label to jump to
855 if a predicate condition succeeds; a - precedes a label to jump to if
856 the condition fails.  Instructions which return a value are followed by
857 a byte which describes the local variable in which to store the return
858 value.  This is described by the syntax = 'name' where 'name', as
859 before, is an @b(ATOM).  If an operation which returns a value does not have
860 an = 'name' or is the @b(ATOM) STACK, the value will be pushed on the
861 STACK. 
862
863 The pseudo-op FCN defines an @b(MSUBR), and is followed by the name of
864 the @b(MSUBR), its argument declaration (a @b(LIST)) and names of it's
865 arguments. The pseudo-op TEMP allocates temporary variables on the STACK.
866
867 Please note that the distinction between such operations as CALL and
868 CALLB is not made in assembly syntax.  The assember will generate the
869 correct instruction.  Similarly, all STACK-type operations will be
870 listed in their generic form (e.g. PUSH, SET).  This is for clarity
871 and readability.
872  
873 @newpage
874 @begin<verbatim>
875 @appendixsection<Simple MAPF>
876
877 MDL:
878
879 <DEFINE FOO (L)
880         #DECL ((L) LIST)
881         <MAPF ,LIST ,BAR .L>>
882
883 MIM:
884
885         <FCN    FOO ("VALUE" LIST LIST) L>
886         <TEMP   TMP0>
887         <EMPL?  L + END>
888 LOOP    <NTHL   L 1>
889         <CALL   'BAR 1>
890         <INC    TMP0>
891         <RESTL  L 1 = L>
892         <EMPL?  L - LOOP>
893 END     <LIST   TMP0>
894         <RETURN STACK>
895         
896 @newpage
897 If the argument to the function FOO were not DECLed, i.e. could
898 be either a primtype LIST, RECORD, or UBLOCK, the following
899 would result:
900
901         <FCN    FOO ("VALUE" LIST STRUCTURED) X>
902         <TEMP   TMP0 TMP1 TMP2>
903         <FRAME>
904         <PUSH   X>
905         <CALL   'EMPTY? 1 = TMP2>
906         <TYPE?  TMP2 <TYPE-WORD FALSE> + END>
907 LOOP    <FRAME>
908         <PUSH   X>
909         <PUSH   1>
910         <CALL   'NTH 2 = TMP1>
911         <FRAME>
912         <PUSH   TMP1>
913         <CALL   'BAR 1>
914         <INC    TMP0>
915         <FRAME>
916         <PUSH   X>
917         <PUSH   1>
918         <CALL   'REST 2 = X>
919         <PUSH   X>
920         <CALL   'EMPTY? 1 = TMP2>
921         <TYPE?  TMP2 <TYPE-WORD FALSE> - LOOP>
922 END     <LIST   TMP0>
923         <RETURN STACK>
924
925 @appendixsection<Recursive Factorial Function>
926
927 MDL:
928
929 <DEFINE FACT (N)
930         <COND (<L=? .N 1> 1)
931               (T
932                <* .N <FACT <- .N 1>>>)>>
933
934 MIM:
935
936         <FCN    FACT ("VALUE" FIX FIX) N>
937         <TEMP   TMP1>
938         <GRTR?  N 1 - LBL>
939         <FRAME>
940         <SUB    N 1 = STACK>
941         <CALL   'FACT 1 = TMP1>                
942         <MUL    N TMP1 = TMP1>
943         <RETURN TMP1>
944 LBL     <RETURN 1>
945         
946 @end<verbatim>
947