Machine-Independent MDL for TOPS-20 and VAX.
[pdp10-muddle.git] / mim / mim.txt
1 MIM-Muddle differences
2
3 Beware:  ^A is now the `control-S' character--it halts whatever you're
4 doing, and returns to the previous listen loop.  ^S is normally just
5 used for flow control, as is standard on tops-20 and unix.  ^G is the
6 interrupt character, as before.
7
8 Changes in types
9
10 UVECTORs must be of UTYPE FIX.  In consequence, UTYPE and CHUTYPE no
11 longer exist.
12
13 BYTES always have byte size 8, so the BYTES and IBYTES routines no
14 longer take a byte size argument.
15
16 RSUBRs, RSUBR-ENTRYs, SUBRs, and FSUBRs are all represented by MSUBRs. 
17 The structure of compiled routines is now:
18 #MSUBR [name-of-IMSUBR:ATOM
19         name-of-routine:ATOM
20         decl:LIST
21         offset-in-code-vector:FIX]
22 This corresponds to the RSUBR-ENTRY in muddle.  An IMSUBR corresponds to
23 the RSUBR:  the first element is code, and the remainder of the elements
24 are external references.  Since the interpreter is written in muddle and
25 compiled, there's no need for special types for interpreter routines.
26
27 There are two new types of primtype ATOM:
28 GVAL evaluates to the global value of the atom, and prints as ,atom.
29 LVAL evaluates to the local value of the atom (in the current
30 environment), and prints as .atom.  The routines GVAL and LVAL still
31 exist as well, and are used for constructs where you're getting the
32 value of something that's not an atom.
33
34 Locatives no longer exist, except (in some sense) to globals and locals.
35 GBIND returns the global binding of an atom:
36 <GBIND FOO> will error if the atom is not GBOUND?; <GBIND FOO T> will
37 create the binding if necessary.
38 LBIND returns the local binding, and errors if the atom is not bound:
39 <LBIND FOO> returns the current binding; <LBIND FOO frame> returns the
40 binding relative to the specified frame.
41 GET-VALUE and PUT-VALUE will return/set the value slot of the binding.
42
43 All activation-like objects are now of type FRAME.  Something you used
44 to decl as <SPECIAL ACTIVATION> is now <SPECIAL FRAME>.
45
46 The structure of CHANNELs has changed completely.  See below for
47 details. 
48
49 The PRIMTYPE of FIXes, FLOATs, and friends is now FIX.  There is still a
50 type WORD.  There is no type LOSE; type UNBOUND is the nearest
51 equivalent, but not quite the same--an atom whose LVAL is of type
52 UNBOUND will give an error when you LVAL it, since it has no value.
53
54 OBLISTs are now primtype ATOM rather than UVECTOR.  All atoms are stored
55 in ,ATOM-TABLE, which is a hashed vector of lists.  To get all the atoms
56 in an OBLIST, you can call GET-OBLIST with the oblist name.
57
58 TUPLEs are now PRIMTYPE VECTOR, rather than TUPLE.
59
60 \f
61 Type declarations
62
63 DECLs may be used as before (objects of type DECL scattered around), but
64 are defaultly not checked by the interpreter (the compiler still uses
65 them).  To check old-style decls, invoke <CHECK-OLD-DECLS T>.  This
66 gives DECL an EVALTYPE, which does more or less the right thing.
67
68 Objects of type ADECL are recognized and checked by the interpreter
69 unless DECL-CHECK is false.  There are two uses, which have basically
70 the same syntax.
71 In argument lists (and binding lists for PROG/REPEAT/BIND), you may
72 follow the atom by its decl, thus:
73 <DEFINE F (X:FIX) ...>
74 The value of a function may be declared in the argument list, thus:
75 <DEFINE F (X:FIX "VALUE" FIX) ...>
76 The syntax is atom, followed by :, followed by the declaration.
77
78 ADECLs may also be used anywhere in your code.  Thus
79 <+ .X:FIX 1> declares that .X will return a FIX, regardless of what it's
80 decled to be elsewhere (of course, we assume that the other decl allows
81 FIX as a possibility).  In general, anything may be followed by : and a
82 decl; this builds an ADECL, which is a pair consisting of the object and
83 its decl.  When the ADECL is evaluated, the object inside is evaluated,
84 then the result is compared to the decl.  The compiler will cheerfully
85 use these.
86
87 GDECLs are as before.
88 \f
89 Interpreter changes
90
91 CASE is now built-in.  The syntax is
92 <CASE predicate expression (value stuff) ... DEFAULT (stuff)>, thus:
93 <CASE ,==? .A
94       (1 <FOO>)
95       (2 <BAR>)
96       DEFAULT
97       (<BLETCH>)>
98 Only ==? compiles efficiently.  More than one value may be associated
99 with a branch by using the following bizarre syntax:
100 <CASE ,==? .A
101       (!'(1 2 3) <FOO>)
102       (4 <BAR>)>
103
104 Functions may return more than one value (or no value).  The syntax in
105 the function is:
106
107 <MULTI-RETURN frame-or-false tuple-of-things-to-return>
108 If the frame argument is false, LPROG!-INTERRUPTS must be bound to a
109 FRAME somewhere; the easiest way to do that is by being inside a PROG or
110 REPEAT.
111
112 If the calling function does nothing special, it will see only the first
113 thing returned (an error results in this case if the MULTI-RETURN tuple
114 is empty.  In order to see all of the values, the function must be
115 called from a segment, which means you have to be doing something where
116 a segment is reasonable:  either another function call, or a structure
117 builder.  (MULTI-SET sort of exists, but isn't fully supported yet.)
118 Thus:
119 <+ !<FOO>>, where FOO does a MULTI-RETURN, will sum all the things it
120 returned.  This is of course indistinguishable from FOO returning a
121 structure, except that no structure is created.
122
123 EXIT is like QUIT, except that it takes a status code.  On UNIX, this
124 literally exits, with whatever status you supply (thus non-zero is bad);
125 on tops-20, it halts, but leaves the status code in AC2, with -1,,3 in
126 AC1.
127
128 OFFSETs now have three slots, rather than two.  The first two are the
129 same:  the index, and the type of object the offset may be applied to;
130 the third is the type of object allowed in the slot referenced.  The
131 third slot need not be supplied when an offset is created.  Thus:
132 <SETG MSUBR-DECL <OFFSET 3 MSUBR LIST>> returns something that must be
133 applied to an MSUBR.  If it's being used for PUT, the new object must
134 be a list; if it's being used for NTH, the object returned will be a
135 list.  This is useful because PUT doesn't check the type of the new
136 object.
137
138 Decls may still be associated with atoms, but the syntax is different. 
139 Before, one used <PUTPROP atom DECL 'decl>.  Now, one uses
140 <PUT-DECL atom 'decl>.  <GET-DECL atom> returns the decl, if it's there.
141 The same mechanism may be used to manipulate the decl associated with a
142 newtype.  PUT-DECL/GET-DECL may also be applied to GBINDs, LBINDs, and
143 OFFSETs.
144 \f
145 Stack objects
146
147 It is possible to build VECTORs, UVECTORs, STRINGs, and BYTES on the
148 stack (which is why TUPLEs are PRIMTYPE VECTOR).  This must be done at
149 toplevel in an argument list, except that a CHTYPE may be wrapped around
150 the stack build, and it may be the result of a macro expansion.  Thus:
151
152 <DEFMAC KEYWORD-STACK ('FOO)
153   <FORM CHTYPE <FORM STACK <FORM STRING .FOO>> KEYWORD>>
154
155 <DEFINE F (X "AUX" (KEY <KEYWORD-STACK .X>)) ...>
156 is legal.  The syntax is
157 <STACK structure-builder>, as:
158 <STACK <VECTOR .A .B .C>>
159 <STACK <IVECTOR 12>>
160 <STACK [.A .B .C]>
161 etc.  These objects are on the stack, and vanish when the function that
162 built them returns.  Aside from that, they are first-class objects.
163
164 \f
165 I/O
166
167 I/O is still done through objects called channels, and most of the
168 high-level routines (READ, PRINT, etc.) are roughly the same, but aside
169 from that everything's different.
170
171 There are three ways to get a channel:
172
173 OPEN takes a direction (a string), a file name (a string, possibly
174 empty), and optional defaults for NM1, NM2, DEV, SNM, and radix.  This
175 differs from muddle, which didn't take a radix argument, and didn't take
176 a name and all four defaults at the same time.  The direction may be one
177 of:
178 "READ":  read-only, ascii
179 "READB":  read-only, binary (36-bit on 20x, 32-bit on unix)
180 "PRINT":  create a new file, read/write, ascii
181 "PRINTB":  create a new file, read/write, binary
182 "PRINTO":  modify an existing file (therefore, read/write), ascii
183 "PRINTBO":  modify an existing file, binary
184 This returns a channel or a false, containing various error codes and
185 error messages.  The channel is ready to be used by READ, PRINT, and
186 friends, and can be found on <CHANLIST>.
187 <OPEN channel> makes the channel ready for READ/PRINT, and adds it to
188 CHANLIST if it's not already there.  (There are ways of making channels
189 that don't leave them ready for READ/PRINT, and don't put them on
190 CHANLIST.)
191
192 GEN-OPEN is more general than OPEN.  It takes a file name, a STRING, and
193 optionally:  the MODE, a string, default "READ"; the byte size, default
194 "ASCII"; and the device type, which is defaulted depending on what the
195 name points to.  The values of DEV, NM1, NM2, and SNM are used to
196 default the file name, just as they are for OPEN.
197 The MODE argument:
198 "READ":  open for read only
199 "CREATE":  make a new file (data may be read, once it's written)
200 "MODIFY":  modify an existing file
201 "APPEND":  append data to an existing file (write-only)
202 The BYTE-SIZE argument:
203 "ASCII":  7-bit on the 20, 8-bit on unix
204 "8BIT":  8-bit (uses BYTES rather than STRING)
205 "BINARY":  full-word transfers--36-bit on the 20, 32-bit on unix
206
207 I'll explain in a bit about the device type.  The two most commonly used
208 are DISK and TTY; GEN-OPEN defaults depending on what the system thinks
209 the file name refers to.  <GEN-OPEN "TTY:"> will generate a TTY-type
210 channel; <GEN-OPEN "<TAA>FOO.BAR"> will generate a DISK channel.
211
212 GEN-OPEN returns a channel or false, just like OPEN.
213
214
215 CHANNEL-OPEN is the most general (and least friendly) way of opening a
216 channel.  It takes:
217 Device type, an atom
218 File name, a string or false
219 Any other arguments required for the type of channel being opened.
220
221 Thus:
222 <CHANNEL-OPEN DISK "<TAA>FOO.BAR" "READ" "ASCII" <> T>
223 opens a DISK channel to <taa>foo.bar, read-only, 7-bit, unbuffered,
224 without modifying the read date.
225
226 <CHANNEL-OPEN TTY <>>
227 is how muddle creates INCHAN and OUTCHAN (which are the same object).
228
229 More on this later, when I explain channel types in their full glory.
230
231
232 High-level I/O
233
234 READ:  all arguments are optional.
235 A channel, default .INCHAN
236 Something to eval at end-of-file, default '<ERROR END-OF-FILE!-ERRORS>
237 A list of oblists, default .OBLIST
238 A vector, the read table.  Default .READ-TABLE or ,READ-TABLE.  (More on
239 this in a bit.)
240 [Modulo the difference in read tables, this is as before...]
241 READ from the TTY is more intelligent about unmatched parens...
242
243 TYI, NEXTCHR, READCHR, and READB all exist, unchanged.
244
245 READSTRING:
246 A string, the buffer to read into
247 "OPTIONAL"
248 A channel to read from, default .INCHAN
249 A fix, the number of characters to read, or a string, containing
250 characters to break on, default the length of the buffer
251 An object to evaluate at EOF, default <ERROR END-OF-FILE!-ERRORS>
252 A fix, magic.
253 READSTRING differs in three ways from old muddle's version:
254 1) The terminal character, when the third argument is a string, is
255 returned in the buffer.
256 2) When reading from the TTY, READSTRING falls into an equivalent of the
257 tops-20 TEXTI call; thus, if you specify a string as the third argument,
258 READSTRING will return immediately on reading one of the characters. 
259 There's no need for a muddle `wakeup' character.
260 3) The magic fifth argument specifies how many characters in the buffer
261 are good.  This is most useful when you're reading from the TTY, and the
262 buffer fills before the desired terminal character--you can make a
263 bigger buffer, and call READSTRING again with a fifth argument of the
264 old buffer length.  This is transparent to the user--it looks like one
265 call to READSTRING to him.
266
267 Two other magical things have been added.
268 If READ-PROMPT!- has a local value, and that's a STRING, the string will
269 become the prompt for keyboard input.
270 If READ-BREAKS!- has a local value that's a STRING, the characters in
271 that string will act like ESCAPE in READ and READSTRING, REPLACING
272 ESCAPE.  Because READ is fairly intelligent about handling unbalanced
273 parens, it is possible to make CRLF take the place of ESCAPE--typing a
274 multi-line form works because READ silently tries again until it has
275 something that's balanced.  [This does have efficiency problems; the
276 first lines of the form will be parsed many times in the process,
277 possibly building a lot of garbage in the process...]
278
279 Input from the TTY all goes through TEXTI, so ^R, ^W, ^U, ^L are all
280 standard.  ^D is like old muddle.  There is no particularly convenient
281 way to clear your input buffer, short of multiple ^U's or a ^A (which
282 loses if you aren't in a listen loop, of course...).
283