ITS Muddle.
[pdp10-muddle.git] / MUDDLE / c.ubd026
1
2 <PACKAGE C>
3
4 <EXTERNAL TOOL!-PACKAGE>
5
6 <DEFINE <ENTRY MESSAGE> (SEVERITY STR "TUPLE" TEXT)
7         <TERPRI>
8         <PRINC "*** ">
9         <PRINC .SEVERITY>
10         <PRINC "        ">
11         <PRINC .STR>
12         <REPEAT ()
13            <COND (<EMPTY? .TEXT> <RETURN 0>)
14                  (<==? <TYPE <1 .TEXT>> ATOM> <PRINC <1 .TEXT>>)
15                  (ELSE <PRIN1 <1 .TEXT>>)>
16            <PRINC " ">                                                  ;"Space"
17            <CHOP TEXT>>
18         <COND (<==? .SEVERITY ERROR> <EXIT .COMPILER "COMPILATION ABORTED">)
19               (<==? .SEVERITY STOP> <LISTEN>)>>
20
21 <INTERNAL SETUP>
22
23 <EXTERNAL OP!-PACKAGE GLOBAL!-PACKAGE>
24
25 <DEFINE BLOCK:INITIAL () 0>
26
27 <DEFINE BRANCH (TAG) <EMIT <INSTRUCTION JRST .TAG>>>
28
29 <DEFINE SUBR:CALL (ADR ARG-NUMBER) <EMIT <INSTRUCTION MCALL .ARG-NUMBER .ADR>>>
30
31 <DEFINE BINDINGS:INITIAL () 0>
32
33 <DEFINE BINDINGS:FINAL () 0>
34
35 <DEFINE TEST:TRUE (TAG)
36         <EMIT <INSTRUCTION HLRZ O* A>>
37         <EMIT <INSTRUCTION CAIE O* TFALSE>>
38         <EMIT <INSTRUCTION JRST .TAG>>>
39
40 <SETG INSTRUCTION #SUBR *000000402161*>
41
42 <DEFINE BINDING:INITIAL () 0>
43
44 <DEFINE BINDING:ATOM (ATM)
45         <REFERENCE .ATM>
46         <EMIT <INSTRUCTION HRRI A* -1>>
47         <STACK:ARGUMENT>>
48
49 <DEFINE TAGMAK ("OPTIONAL" (STR "TAG"))
50         <SET STR <STRING .STR <UNPARSE ,TAG:COUNT>>>
51         <SETG TAG:COUNT <+ ,TAG:COUNT 1>>
52         <OR <LOOKUP .STR <MOBLIST INITIAL>> <INSERT .STR <MOBLIST INITIAL>>>>
53
54 <DEFINE VARIABLES () ((REFERENCES ()) (CODING ()) (TAGS ()))>
55
56 <DEFINE STACK:ARGUMENT ()
57         <EMIT <INSTRUCTION PUSH TP* A>>
58         <EMIT <INSTRUCTION PUSH TP* B>>>
59 \f
60 <DEFINE BINDING:FINAL ()
61         <EMIT <INSTRUCTION PUSH TP* [0]>>
62         <EMIT <INSTRUCTION PUSH TP* [0]>>
63         <EMIT <INSTRUCTION PUSHJ P* SPECBIND>>>
64
65 <DEFINE LABEL (TAG) <EMIT .TAG>>
66
67 <DEFINE EMIT (INSTR)
68         <PUTREST .CODE:PTR (.INSTR)>
69         <SET CODE:PTR <REST .CODE:PTR>>>
70
71 <DEFINE TEST:ARG (NUMBER TAG)
72         <EMIT <INSTRUCTION HLRE C* AB>>
73         <EMIT <INSTRUCTION MOVMS C>>
74         <EMIT <INSTRUCTION CAIGE C* <* 2 .NUMBER>>>
75         <EMIT <INSTRUCTION JRST .TAG>>>
76
77 <DEFINE REFERENCE (OBJECT "EXTRA" TTYPE)
78         <COND (<AND!-  <==? <PRIMTYPE .OBJECT> WORD>
79                        <SET TTYPE
80                             <LOOKUP <STRING !"T <PNAME <TYPE .OBJECT>>>
81                                     <GET OP!-PACKAGE OBLIST>>>>
82                <EMIT <INSTRUCTION MOVSI A* .TTYPE>>
83                <EMIT <INSTRUCTION MOVE B* [.OBJECT]>>)
84               (ELSE
85                <SET OBJECT <FORM QUOTE .OBJECT>>
86                <EMIT <INSTRUCTION MOVE A* <FORM MQUOTE .OBJECT> -1>>
87                <EMIT <INSTRUCTION MOVE B* <FORM MQUOTE .OBJECT>>>)>>
88
89 <DEFINE FUNCTION:FINAL (PRINFLG)
90         <EMIT <INSTRUCTION JRST FINIS>>
91         <ASSEMBLE!-CODING <REST .CODE:TOP> .PRINFLG <MOBLIST INITIAL>>>
92
93 <DEFINE BINDING:VALUE () <STACK:ARGUMENT>>
94
95 <DEFINE BINDING:UNBOUND ()
96         <EMIT <INSTRUCTION MOVSI A* TUNBOUND>>
97         <EMIT <INSTRUCTION SETO B*>>
98         <STACK:ARGUMENT>>
99
100 <DEFINE BINDING:ARG (NUMBER)
101         <EMIT <INSTRUCTION PUSH TP* (AB) <- <* .NUMBER 2> 2>>>
102         <EMIT <INSTRUCTION PUSH TP* (AB) <- <* .NUMBER 2> 1>>>>
103
104 <DEFINE TEST:FALSE (TAG)
105         <EMIT <INSTRUCTION HLRZ O* A>>
106         <EMIT <INSTRUCTION CAIN O* TFALSE>>
107         <EMIT <INSTRUCTION JRST .TAG>>>
108
109 <SETG TAG:COUNT 0>
110
111 <DEFINE FUNCTION:INITIAL (NAME) <EMIT <FORM TITLE .NAME>>>
112
113 <DEFINE BLOCK:FINAL () 0>
114
115 <FINISHUP <SETG INSTRUCTION ,FORM> <SETG TAG:COUNT 0>>
116
117 <END>
118
119 <INTERNAL COMPL>
120 \f
121
122 <DEFINE <ENTRY COMPILE> (NAME "OPTIONAL" (PFLG <>) "NAME" COMPILER)
123         <COND (<NOT <==? <TYPE .NAME> ATOM>>
124                <MESSAGE ERROR "ARGUMENT NOT ATOMIC">)
125               (<NOT <GASSIGNED? .NAME>>
126                <MESSAGE ERROR "GLOBALLY UNASSIGNED" .NAME>)
127               (<NOT <==? <TYPE ,.NAME> FUNCTION>>
128                <MESSAGE ERROR "IMPROPERLY VALUED" .NAME>)>
129         <PUT .NAME APPLY:OBJECT <GET RSUBR APPLY:TYPE>>         ;"Recursive calls"
130         <SETG .NAME <COMPILE-FUNCTION ,.NAME .NAME>>
131         <PUT .NAME APPLY:OBJECT>                                ;"Remove"
132         <EXIT .COMPILER "DONE">>
133
134 <DEFINE COPY (OBJ)
135         <SUBR:CALL!-SETUP <PRIMTYPE .OBJ>
136                           <REPEAT ((I 0))
137                              <IF <EMPTY? .OBJ> <RETURN .I>>
138                              <COMP <1 .OBJ>>
139                              <STACK:ARGUMENT!-SETUP>
140                              <CHOP OBJ>
141                              <INC I>>>>
142
143
144 <DEFINE BINDINGS (ARGS "OPTIONAL" (MODE INITIAL) "NAME" BINDER)
145         <IF-NOT <==? <TYPE .ARGS> LIST> <MESSAGE ERROR "ILLEGAL ARGUMENT LIST" .ARGS>>
146         <IF <EMPTY? .ARGS> <EXIT .BINDER 0>>
147         <BINDINGS:INITIAL!-SETUP>
148         <REPEAT (ITEM DEFAULT:TAG GIVEN:TAG (ARG-NUMBER 1))
149            <SET ITEM <1 .ARGS>>
150            <COND (<==? <TYPE .ITEM> ATOM>
151                   <COND (<==? .MODE INITIAL>
152                          <BINDING:INITIAL!-SETUP>
153                          <BINDING:ATOM!-SETUP .ITEM>
154                          <BINDING:ARG!-SETUP .ARG-NUMBER>
155                          <BINDING:FINAL!-SETUP>
156                          <INC ARG-NUMBER>)
157                         (<==? .MODE EXTRA>
158                          <BINDING:INITIAL!-SETUP>
159                          <BINDING:ATOM!-SETUP .ITEM>
160                          <BINDING:UNBOUND!-SETUP>
161                          <BINDING:FINAL!-SETUP>)
162                         (<==? .MODE OPTIONAL>
163                          <SET DEFAULT:TAG <TAGMAK!-SETUP>>
164                          <SET GIVEN:TAG <TAGMAK!-SETUP>>
165                          <BINDING:INITIAL!-SETUP>
166                          <BINDING:ATOM!-SETUP .ITEM>
167                          <TEST:ARG!-SETUP .ARG-NUMBER .DEFAULT:TAG>
168                          <BINDING:ARG!-SETUP .ARG-NUMBER>
169                          <BRANCH!-SETUP .GIVEN:TAG>
170                          <LABEL!-SETUP .DEFAULT:TAG>
171                          <BINDING:UNBOUND!-SETUP>
172                          <LABEL!-SETUP .GIVEN:TAG>
173                          <BINDING:FINAL!-SETUP>
174                          <INC ARG-NUMBER>)
175                         (ELSE <MESSAGE WARNING "BINDING ATTEMPTED FOR" .ITEM .MODE>)>)
176                  (<AND <==? <TYPE .ITEM> LIST> <==? <LENGTH .ITEM> 2>>
177                   <COND (<==? .MODE EXTRA>
178                          <BINDING:INITIAL!-SETUP>
179                          <BINDING:ATOM!-SETUP <1 .ITEM>>
180                          <COMP <2 .ITEM>>
181                          <BINDING:VALUE!-SETUP>
182                          <BINDING:FINAL!-SETUP>)
183                         (<==? .MODE OPTIONAL>
184                          <SET DEFAULT:TAG <TAGMAK!-SETUP>>
185                          <SET GIVEN:TAG <TAGMAK!-SETUP>>
186                          <BINDING:INITIAL!-SETUP>
187                          <BINDING:ATOM!-SETUP <1 .ITEM>>
188                          <TEST:ARG!-SETUP .ARG-NUMBER .DEFAULT:TAG>
189                          <BINDING:ARG!-SETUP .ARG-NUMBER>
190                          <BRANCH!-SETUP .GIVEN:TAG>
191                          <LABEL!-SETUP .DEFAULT:TAG>
192                          <COMP <2 .ITEM>>
193                          <BINDING:VALUE!-SETUP>
194                          <LABEL!-SETUP .GIVEN:TAG>
195                          <BINDING:FINAL!-SETUP>
196                          <INC ARG-NUMBER>)
197                         (ELSE
198                          <MESSAGE ERROR "BINDING ATTEMPTED FOR" .ITEM>)>)
199                  (<==? <TYPE .ITEM> STRING>
200                   <COND (<=? .ITEM "OPTIONAL"> <SET MODE OPTIONAL>)
201                         (<OR <=? .ITEM "EXTRA"> <=? .ITEM "AUX">>
202                          <SET MODE EXTRA>)
203                         (ELSE
204                          <MESSAGE UNIMPLEMENTED "BINDINGS FOR" .ITEM>
205                          <CHOP ARGS>)>)
206                  (ELSE <MESSAGE UNIMPLEMENTED "BINDINGS FOR" .ITEM>)>
207            <IF <EMPTY? <CHOP ARGS>> <RETURN 0>>>
208         <BINDINGS:FINAL!-SETUP>>
209
210 <DEFINE COMPILE-FUNCTION (FUNCTN
211                           "OPTIONAL" (NAME NOT-NAMED)
212                           "EXTRA" (CODE:TOP!-SETUP (()))
213                                   (CODE:PTR!-SETUP .CODE:TOP!-SETUP)
214                                   (INFO!-SETUP ()))
215         <FUNCTION:INITIAL!-SETUP .NAME>
216         <IF <EMPTY? .FUNCTN> <MESSAGE ERROR "EMPTY FUNCTION">>
217         <IF <==? <TYPE <1 .FUNCTN>> ATOM>                   ;"Activation name ?"
218             <MESSAGE UNIMPLEMENTED "ACTIVATION NAMES">
219             <CHOP FUNCTN>>
220         <IF <EMPTY? .FUNCTN> <MESSAGE ERROR "NO ARGUMENT LIST">>
221         <BINDINGS <1 .FUNCTN>>
222         <IF <EMPTY? <CHOP FUNCTN>> <MESSAGE ERROR "EMPTY FUNCTION BODY">>
223         <REPEAT ()
224            <COMP <1 .FUNCTN>>      ;"Go do the real compilation for this object"
225            <CHOP FUNCTN>                              ;"Next object in the body"
226            <IF <EMPTY? .FUNCTN> <RETURN 0>>>
227         <FUNCTION:FINAL!-SETUP .PFLG>>
228
229 <DEFINE PROG-REPEAT (OB "EXTRA" (NAME <1 .OB>) AGAIN:TAG EXIT:TAG)
230         <BLOCK:INITIAL!-SETUP>
231         <IF <EMPTY? <CHOP OB>> <MESSAGE ERROR "EMPTY" .NAME>>
232         <IF <==? <TYPE <1 .OB>> ATOM>
233             <MESSAGE UNIMPLEMENTED "ACTIVATION TAGS">
234             <CHOP OB>>
235         <IF <EMPTY? .OB> <MESSAGE ERROR "NO VARIABLE LIST" .NAME>>
236         <BINDINGS <1 .OB> EXTRA>
237         <IF <EMPTY? <CHOP OB>> <MESSAGE ERROR "NO BODY FOR" .NAME>>
238         <LABEL!-SETUP <SET AGAIN:TAG <TAGMAK!-SETUP "AGAIN">>>
239         <SET EXIT:TAG <TAGMAK!-SETUP "EXIT">>
240         <REPEAT ()
241            <IF <==? <TYPE <1 .OB>> ATOM> <LABEL!-SETUP <1 .OB>>>
242            <COMP <1 .OB>>
243            <IF <EMPTY? <CHOP OB>> <RETURN 0>>>
244         <IF <==? .NAME REPEAT> <BRANCH!-SETUP .AGAIN:TAG>>
245         <LABEL!-SETUP .EXIT:TAG>
246         <BLOCK:FINAL!-SETUP>>
247
248 <DEFINE BOOL (PREDS TEST RESULT "EXTRA" (BOOL:TAG <TAGMAK!-SETUP "BOOL">))
249         <COND (<EMPTY? .PREDS> <COMP .RESULT>)
250               (ELSE
251                <REPEAT ()
252                   <SET RESULT <1 .PREDS>>
253                   <IF <EMPTY? <CHOP PREDS>> <RETURN BOOL>>
254                   <COMP .RESULT>
255                   <TEST .BOOL:TAG>>
256                <COMP .RESULT>
257                <LABEL!-SETUP .BOOL:TAG>)>>
258 \f
259 <DEFINE COMP (OBJECT)
260         <<OR <GET .OBJECT THIS:OBJECT>
261                               ;"Is there some function to compile this object ?"
262              <GET <TYPE .OBJECT> THIS:TYPE>
263                                        ;"Is there some function for this type ?"
264              ,REFERENCE!-SETUP>
265          .OBJECT>>
266
267 <FINISHUP <PUT VECTOR THIS:TYPE ,COPY>
268          <PUT UVECTOR THIS:TYPE ,COPY>
269          <PUT LIST THIS:TYPE ,COPY>
270          <PUT SEGMENT THIS:TYPE <FUNCTION (OBJ) <MESSAGE UNIMPLEMENTED "SEGMENT" .OBJ>>>
271          <PUT '<> THIS:OBJECT <FUNCTION (OBJ) <REFERENCE!-SETUP #FALSE ()>>>
272          <PUT FORM
273               THIS:TYPE                          ;"FORMs are compiled specially"
274               <FUNCTION (OBJ)
275                       <PROG APPLICATION
276                             ((APPLY <1 .OBJ>))
277                             <<OR <GET .APPLY APPLY:OBJECT>
278                                                ;"Do we know how to apply this ?"
279                                  <GET <TYPE .APPLY> APPLY:TYPE>
280                                                             ;"Apply this type ?"
281                                  <GET <PRIMTYPE .APPLY> APPLY:PRIMTYPE>
282                                                               ;"This primtype ?"
283                                  <FUNCTION (OB)
284                                          <REFERENCE!-SETUP .OBJECT>
285                                                ;"Otherwise go to eval with form"
286                                          <STACK:ARGUMENT!-SETUP>
287                                          <SUBR:CALL!-SETUP EVAL 1>>>
288                              .OBJ>>>>
289          <PUT ATOM
290               APPLY:TYPE           ;"Apply an ATOM as you would apply its value"
291               <FUNCTION (OB)
292                       <COND (<GASSIGNED? .APPLY>
293                                   ;"Try again with the global value if possible"
294                              <SET APPLY ,.APPLY>
295                              <AGAIN .APPLICATION>)
296                             (<AND <BOUND? .APPLY> <ASSIGNED? .APPLY>>
297                                                         ;"Else with local value"
298                              <MESSAGE NOTE "LOCAL VALUE USED FOR" .APPLY>
299                              <SET APPLY ..APPLY>
300                              <AGAIN .COMPILE-APPLY>)
301                             (ELSE
302                              <MESSAGE NOTE "NO VALUE FOR" .APPLY>
303                              <REFERENCE!-SETUP .OB>
304                                            ;"Otherwise go to EVAL with the form"
305                              <STACK:ARGUMENT!-SETUP>
306                              <SUBR:CALL!-SETUP EVAL 1>)>>>
307          <PUT SUBR
308               APPLY:TYPE
309               <FUNCTION (OB)
310                       <SUBR:CALL!-SETUP <1 .OB>
311                                         <REPEAT ((I 0))
312                                            <IF <EMPTY? <CHOP OB>> <RETURN .I>>
313                                            <COMP <1 .OB>>
314                                            <STACK:ARGUMENT!-SETUP>
315                                            <INC I>>>>>
316          <PUT RSUBR
317               APPLY:TYPE
318               <FUNCTION (OB)
319                       <COMP <1 .OB>>                 ;"Get atomic name of RSUBR"
320                       <STACK:ARGUMENT!-SETUP>
321                       <SUBR:CALL!-SETUP GVAL 1>
322                       <STACK:ARGUMENT!-SETUP>
323                       <SUBR:CALL!-SETUP APPLY
324                                         <REPEAT ((I 1))
325                                            <IF <EMPTY? <CHOP OB>> <RETURN .I>>
326                                            <COMP <1 .OB>>
327                                            <STACK:ARGUMENT!-SETUP>
328                                            <INC I>>>>>
329          <PUT FIX
330               APPLY:TYPE       ;"Integer as function is a selector of component"
331               <FUNCTION (OB)
332                       <IF <NOT <==? <LENGTH .OB> 2>>
333                           <MESSAGE ERROR "IMPROPER SELECTOR" .OB>>
334                       <COMP <2 .OB>>                        ;"Get the structure"
335                       <STACK:ARGUMENT!-SETUP>
336                       <COMP .APPLY>                         ;"Get the indicator"
337                       <STACK:ARGUMENT!-SETUP>
338                       <SUBR:CALL!-SETUP NTH 2>>>
339          <PUT ,PROG APPLY:OBJECT ,PROG-REPEAT>
340          <PUT ,REPEAT APPLY:OBJECT ,PROG-REPEAT>
341          <PUT ,RETURN
342               APPLY:OBJECT
343               <FUNCTION (OB)
344                       <IF-NOT <==? <LENGTH .OB> 2>
345                               <MESSAGE ERROR "WRONG NUMBER OF ARGUMENTS TO RETURN">>
346                       <COMP <2 .OB>>
347                       <BRANCH!-SETUP .EXIT:TAG>>>
348          <PUT ,AGAIN
349               APPLY:OBJECT
350               <FUNCTION (OB)
351                       <COND (<EMPTY? <CHOP OB>> <BRANCH!-SETUP .AGAIN:TAG>)
352                             (<==? <LENGTH .OB> 1>
353                              <COMP <1 .OB>>
354                              <STACK:ARGUMENT!-SETUP>
355                              <SUBR:CALL!-SETUP AGAIN 1>)
356                             (ELSE <MESSAGE ERROR "TOO MANY ARGUMENTS TO AGAIN">)>>>
357          <PUT ,GO
358               APPLY:OBJECT
359               <FUNCTION (OB)
360                       <IF <NOT <==? <LENGTH .OB> 2>>
361                           <MESSAGE ERROR "NO TAG IN GO">>
362                       <BRANCH!-SETUP <2 .OB>>>>
363          <PUT ,COND
364               APPLY:OBJECT
365               <FUNCTION (OB "EXTRA" (COND:TAG <TAGMAK!-SETUP "COND">))
366                       <IF <EMPTY? <CHOP OB>> <MESSAGE ERROR "EMPTY COND">>
367                       <REPEAT (PHRASE PHRASE:TAG)
368                          <SET PHRASE:TAG <TAGMAK!-SETUP "PHRASE">>
369                          <IF <EMPTY? <SET PHRASE <1 .OB>>>
370                              <MESSAGE ERROR "MISSING PREDICATE IN COND">>
371                          <COMP <1 .PHRASE>>
372                          <TEST:FALSE!-SETUP .PHRASE:TAG>
373                          <REPEAT ()
374                             <IF <EMPTY? <CHOP PHRASE>> <RETURN 0>>
375                             <COMP <1 .PHRASE>>>
376                          <BRANCH!-SETUP .COND:TAG>
377                          <LABEL!-SETUP .PHRASE:TAG>
378                          <IF <EMPTY? <CHOP OB>> <RETURN 0>>>
379                       <LABEL!-SETUP .COND:TAG>>>
380          <PUT ,OR
381               APPLY:OBJECT
382               <FUNCTION (OB) <BOOL <REST .OB> ,TEST:TRUE!-SETUP T>>>
383          <PUT ,AND
384               APPLY:OBJECT
385               <FUNCTION (OB) <BOOL <REST .OB> ,TEST:FALSE!-SETUP #FALSE ()>>>>
386
387 <END>
388
389 <END>
390 \f\f\ 3\f\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f\ 3\ 3\ 3\ 3\f