Commit | Line | Data |
---|---|---|
8340f87c BJ |
1 | .NH |
2 | LANGUAGE DESCRIPTION | |
3 | .SH | |
4 | Design | |
5 | .PP | |
6 | Ratfor | |
7 | attempts to retain the merits of Fortran | |
8 | (universality, portability, efficiency) | |
9 | while hiding the worst Fortran inadequacies. | |
10 | The language | |
11 | .ul | |
12 | is | |
13 | Fortran except for two aspects. | |
14 | First, | |
15 | since control flow is central to any program, | |
16 | regardless of the specific application, | |
17 | the primary task of | |
18 | Ratfor | |
19 | is to conceal this part of Fortran from the user, | |
20 | by providing decent control flow structures. | |
21 | These structures are sufficient and comfortable | |
22 | for structured programming in the narrow sense of programming without | |
23 | .UC GOTO 's. | |
24 | Second, since the preprocessor must examine an entire program | |
25 | to translate the control structure, | |
26 | it is possible at the same time to clean up many of the | |
27 | ``cosmetic'' deficiencies of Fortran, | |
28 | and thus provide a language which is easier | |
29 | and more pleasant to read and write. | |
30 | .PP | |
31 | Beyond these two aspects _ control flow and cosmetics _ | |
32 | Ratfor | |
33 | does nothing about the host of other weaknesses of Fortran. | |
34 | Although it would be straightforward to extend | |
35 | it | |
36 | to provide | |
37 | character strings, | |
38 | for example, | |
39 | they are not needed by everyone, | |
40 | and of course | |
41 | the preprocessor would be harder to implement. | |
42 | Throughout, the design principle which has determined | |
43 | what should be in | |
44 | Ratfor | |
45 | and what should not has | |
46 | been | |
47 | .ul | |
48 | Ratfor | |
49 | .ul | |
50 | doesn't know any Fortran. | |
51 | Any language feature which would require that | |
52 | Ratfor | |
53 | really understand Fortran has been omitted. | |
54 | We will return to this point in the section | |
55 | on implementation. | |
56 | .PP | |
57 | Even within the confines of control flow and cosmetics, | |
58 | we have attempted to be selective | |
59 | in what features to provide. | |
60 | The intent has been to provide a small set of the most useful | |
61 | constructs, | |
62 | rather than to throw in everything that has ever been thought useful | |
63 | by someone. | |
64 | .PP | |
65 | The rest of this section contains an informal description | |
66 | of the | |
67 | Ratfor | |
68 | language. | |
69 | The control flow aspects will be | |
70 | quite familiar to readers used to languages like | |
71 | Algol, PL/I, Pascal, etc., | |
72 | and the cosmetic changes are equally straightforward. | |
73 | We shall concentrate on | |
74 | showing what the language looks like. | |
75 | .SH | |
76 | Statement Grouping | |
77 | .PP | |
78 | Fortran provides no way to group statements together, | |
79 | short of making them into a subroutine. | |
80 | The standard construction | |
81 | ``if a condition is true, | |
82 | do this group of things,'' | |
83 | for example, | |
84 | .P1 | |
85 | if (x > 100) | |
86 | { call error("x>100"); err = 1; return } | |
87 | .P2 | |
88 | cannot be written directly in Fortran. | |
89 | Instead | |
90 | a programmer is forced to translate this relatively | |
91 | clear thought into murky Fortran, | |
92 | by stating the negative condition | |
93 | and branching around the group of statements: | |
94 | .P1 | |
95 | if (x .le. 100) goto 10 | |
96 | call error(5hx>100) | |
97 | err = 1 | |
98 | return | |
99 | 10 ... | |
100 | .P2 | |
101 | When the program doesn't work, | |
102 | or when it must be modified, | |
103 | this must be translated back into | |
104 | a clearer form before one can be sure what it does. | |
105 | .PP | |
106 | Ratfor | |
107 | eliminates this error-prone and confusing back-and-forth translation; | |
108 | the first form | |
109 | .ul | |
110 | is | |
111 | the way the computation is written in | |
112 | Ratfor. | |
113 | A group of statements can be treated as a unit | |
114 | by enclosing them in the braces { and }. | |
115 | This is true throughout the language: | |
116 | wherever a single | |
117 | Ratfor | |
118 | statement can be used, | |
119 | there can be several enclosed in braces. | |
120 | (Braces seem clearer and less obtrusive than | |
121 | .UL begin | |
122 | and | |
123 | .UL end | |
124 | or | |
125 | .UL do | |
126 | and | |
127 | .UL end , | |
128 | and of course | |
129 | .UL do | |
130 | and | |
131 | .UL end | |
132 | already have Fortran meanings.) | |
133 | .PP | |
134 | Cosmetics | |
135 | contribute to the readability of code, | |
136 | and thus to its understandability. | |
137 | The character ``>'' is clearer than | |
138 | .UC ``.GT.'' , | |
139 | so | |
140 | Ratfor | |
141 | translates it appropriately, | |
142 | along with several other similar shorthands. | |
143 | Although many Fortran compilers permit character strings in quotes | |
144 | (like | |
145 | .UL """x>100""" ), | |
146 | quotes are | |
147 | not allowed in | |
148 | .UC ANSI | |
149 | Fortran, | |
150 | so | |
151 | Ratfor | |
152 | converts it into the right number of | |
153 | .UL H 's: | |
154 | computers count better than people do. | |
155 | .PP | |
156 | Ratfor | |
157 | is a free-form language: | |
158 | statements may appear anywhere on a line, | |
159 | and several may appear on one line | |
160 | if they are separated by semicolons. | |
161 | The example above could also be written as | |
162 | .P1 | |
163 | if (x > 100) { | |
164 | call error("x>100") | |
165 | err = 1 | |
166 | return | |
167 | } | |
168 | .P2 | |
169 | In this case, no semicolon is needed at the end of each line because | |
170 | Ratfor | |
171 | assumes there is one statement per line | |
172 | unless told otherwise. | |
173 | .PP | |
174 | Of course, | |
175 | if the statement that follows the | |
176 | .UL if | |
177 | is a single statement | |
178 | (Ratfor | |
179 | or otherwise), | |
180 | no braces are needed: | |
181 | .P1 | |
182 | if (y <= 0.0 & z <= 0.0) | |
183 | write(6, 20) y, z | |
184 | .P2 | |
185 | No continuation need be indicated | |
186 | because the statement is clearly not finished on the first line. | |
187 | In general | |
188 | Ratfor | |
189 | continues lines when it seems obvious that they are not yet done. | |
190 | (The continuation convention is discussed in detail later.) | |
191 | .PP | |
192 | Although a free-form language permits wide latitude in formatting styles, | |
193 | it is wise to pick one that is readable, then stick to it. | |
194 | In particular, proper indentation is vital, | |
195 | to make the logical structure of the program obvious to the reader. | |
196 | .sp | |
197 | .SH | |
198 | The ``else'' Clause | |
199 | .PP | |
200 | Ratfor | |
201 | provides an | |
202 | .UL "else" | |
203 | statement to handle the construction | |
204 | ``if a condition is true, | |
205 | do | |
206 | this | |
207 | thing, | |
208 | .ul | |
209 | otherwise | |
210 | do that thing.'' | |
211 | .P1 | |
212 | if (a <= b) | |
213 | { sw = 0; write(6, 1) a, b } | |
214 | else | |
215 | { sw = 1; write(6, 1) b, a } | |
216 | .P2 | |
217 | This writes out the smaller of | |
218 | .UL a | |
219 | and | |
220 | .UL b , | |
221 | then the larger, and sets | |
222 | .UL sw | |
223 | appropriately. | |
224 | .PP | |
225 | The Fortran equivalent of this code is circuitous indeed: | |
226 | .P1 | |
227 | if (a .gt. b) goto 10 | |
228 | sw = 0 | |
229 | write(6, 1) a, b | |
230 | goto 20 | |
231 | 10 sw = 1 | |
232 | write(6, 1) b, a | |
233 | 20 ... | |
234 | .P2 | |
235 | This is a mechanical translation; | |
236 | shorter forms exist, | |
237 | as they do for many similar situations. | |
238 | But all translations suffer from the same problem: | |
239 | since they are translations, | |
240 | they are less clear and understandable than code | |
241 | that is not a translation. | |
242 | To understand the Fortran version, | |
243 | one must scan the entire program to make | |
244 | sure that no other statement branches | |
245 | to statements 10 or 20 | |
246 | before one knows that indeed this is an | |
247 | .UL if-else | |
248 | construction. | |
249 | With the | |
250 | Ratfor | |
251 | version, | |
252 | there is no question about how one gets to the parts of the statement. | |
253 | The | |
254 | .UL if-else | |
255 | is a single unit, | |
256 | which can be read, understood, and ignored if not relevant. | |
257 | The program says what it means. | |
258 | .PP | |
259 | As before, if the statement following an | |
260 | .UL if | |
261 | or an | |
262 | .UL else | |
263 | is a single statement, no braces are needed: | |
264 | .P1 | |
265 | if (a <= b) | |
266 | sw = 0 | |
267 | else | |
268 | sw = 1 | |
269 | .P2 | |
270 | .PP | |
271 | The syntax of the | |
272 | .UL if | |
273 | statement is | |
274 | .P1 | |
275 | if (\fIlegal Fortran condition\fP) | |
276 | \fIRatfor statement\fP | |
277 | else | |
278 | \fIRatfor statement\fP | |
279 | .P2 | |
280 | where the | |
281 | .UL else | |
282 | part is optional. | |
283 | The | |
284 | .ul | |
285 | legal Fortran condition | |
286 | is | |
287 | anything that can legally go into a Fortran Logical | |
288 | .UC IF . | |
289 | Ratfor | |
290 | does not check this clause, | |
291 | since it does not know enough Fortran | |
292 | to know what is permitted. | |
293 | The | |
294 | .ul | |
295 | Ratfor | |
296 | .ul | |
297 | statement | |
298 | is any Ratfor or Fortran statement, or any collection of them | |
299 | in braces. | |
300 | .SH | |
301 | Nested if's | |
302 | .PP | |
303 | Since the statement that follows an | |
304 | .UL if | |
305 | or | |
306 | an | |
307 | .UL else | |
308 | can be any Ratfor statement, this leads immediately | |
309 | to the possibility of another | |
310 | .UL if | |
311 | or | |
312 | .UL else . | |
313 | As a useful example, consider this problem: | |
314 | the variable | |
315 | .UL f | |
316 | is to be set to | |
317 | \-1 if | |
318 | .UL x | |
319 | is less than zero, | |
320 | to | |
321 | +1 | |
322 | if | |
323 | .UL x | |
324 | is greater than 100, | |
325 | and to 0 otherwise. | |
326 | Then in Ratfor, we write | |
327 | .P1 | |
328 | if (x < 0) | |
329 | f = -1 | |
330 | else if (x > 100) | |
331 | f = +1 | |
332 | else | |
333 | f = 0 | |
334 | .P2 | |
335 | Here the statement after the first | |
336 | .UL else | |
337 | is another | |
338 | .UL if-else . | |
339 | Logically it is just a single statement, | |
340 | although it is rather complicated. | |
341 | .PP | |
342 | This code says what it means. | |
343 | Any version written in straight Fortran | |
344 | will necessarily be indirect | |
345 | because Fortran does not let you say what you mean. | |
346 | And as always, clever shortcuts may turn out | |
347 | to be too clever to understand a year from now. | |
348 | .PP | |
349 | Following an | |
350 | .UL else | |
351 | with an | |
352 | .UL if | |
353 | is one way to write a multi-way branch in Ratfor. | |
354 | In general the structure | |
355 | .P1 | |
356 | if (...) | |
357 | - - - | |
358 | else if (...) | |
359 | - - - | |
360 | else if (...) | |
361 | - - - | |
362 | ... | |
363 | else | |
364 | - - - | |
365 | .P2 | |
366 | provides a way to specify the choice of exactly one of several alternatives. | |
367 | (Ratfor also provides a | |
368 | .UL switch | |
369 | statement which does the same job | |
370 | in certain special cases; | |
371 | in more general situations, we have to make do | |
372 | with spare parts.) | |
373 | The tests are laid out in sequence, and each one | |
374 | is followed by the code associated with it. | |
375 | Read down the list | |
376 | of decisions until one is found that is satisfied. | |
377 | The code associated with this condition is executed, | |
378 | and then the entire structure is finished. | |
379 | The trailing | |
380 | .UL else | |
381 | part handles the ``default'' case, | |
382 | where none of the other conditions apply. | |
383 | If there is no default action, this final | |
384 | .UL else | |
385 | part | |
386 | is omitted: | |
387 | .P1 | |
388 | if (x < 0) | |
389 | x = 0 | |
390 | else if (x > 100) | |
391 | x = 100 | |
392 | .P2 | |
393 | .SH | |
394 | if-else ambiguity | |
395 | .PP | |
396 | There is one thing to notice about complicated structures | |
397 | involving nested | |
398 | .UL if 's | |
399 | and | |
400 | .UL else 's. | |
401 | Consider | |
402 | .P1 | |
403 | if (x > 0) | |
404 | if (y > 0) | |
405 | write(6, 1) x, y | |
406 | else | |
407 | write(6, 2) y | |
408 | .P2 | |
409 | There are two | |
410 | .UL if 's | |
411 | and | |
412 | only one | |
413 | .UL else . | |
414 | Which | |
415 | .UL if | |
416 | does the | |
417 | .UL else | |
418 | go with? | |
419 | .PP | |
420 | This is a genuine ambiguity in Ratfor, as it is in many other programming | |
421 | languages. | |
422 | The ambiguity is resolved in Ratfor | |
423 | (as elsewhere) by saying that in such cases the | |
424 | .UL else | |
425 | goes with the closest previous | |
426 | .UL else 'ed un- | |
427 | .UL if . | |
428 | Thus in this case, the | |
429 | .UL else | |
430 | goes with the inner | |
431 | .UL if , | |
432 | as we have indicated by the indentation. | |
433 | .PP | |
434 | It is a wise practice to resolve such cases by explicit braces, | |
435 | just to make your intent clear. | |
436 | In the case above, we would write | |
437 | .P1 | |
438 | if (x > 0) { | |
439 | if (y > 0) | |
440 | write(6, 1) x, y | |
441 | else | |
442 | write(6, 2) y | |
443 | } | |
444 | .P2 | |
445 | which does not change the meaning, but leaves | |
446 | no doubt in the reader's mind. | |
447 | If we want the other association, we | |
448 | .ul | |
449 | must | |
450 | write | |
451 | .P1 | |
452 | if (x > 0) { | |
453 | if (y > 0) | |
454 | write(6, 1) x, y | |
455 | } | |
456 | else | |
457 | write(6, 2) y | |
458 | .P2 | |
459 | .SH | |
460 | The ``switch'' Statement | |
461 | .PP | |
462 | The | |
463 | .UL switch | |
464 | statement | |
465 | provides a clean way to express multi-way branches | |
466 | which branch on the value of some integer-valued expression. | |
467 | The syntax is | |
468 | .P1 | |
469 | \f3switch (\fIexpression\|\f3) { | |
470 | ||
471 | case \fIexpr1\f3 : | |
472 | \f2statements\f3 | |
473 | case \fIexpr2, expr3\f3 : | |
474 | \f2statements\f3 | |
475 | ... | |
476 | default: | |
477 | \f2statements\f3 | |
478 | } | |
479 | .P2 | |
480 | .PP | |
481 | Each | |
482 | .UL case | |
483 | is followed by a | |
484 | list of comma-separated integer expressions. | |
485 | The | |
486 | .ul | |
487 | expression | |
488 | inside | |
489 | .UL switch | |
490 | is compared against the case expressions | |
491 | .ul | |
492 | expr1, | |
493 | .ul | |
494 | expr2, | |
495 | and so on in turn | |
496 | until one matches, | |
497 | at which time the statements following that | |
498 | .UL case | |
499 | are executed. | |
500 | If no cases match | |
501 | .ul | |
502 | expression, | |
503 | and there is a | |
504 | .UL default | |
505 | section, | |
506 | the statements with it are done; | |
507 | if there is no | |
508 | .UL default, | |
509 | nothing is done. | |
510 | In all situations, | |
511 | as soon as some block of statements is executed, | |
512 | the entire | |
513 | .UL switch | |
514 | is exited immediately. | |
515 | (Readers familiar with C[4] should beware that this | |
516 | behavior is not the same as the C | |
517 | .UL switch .) | |
518 | .SH | |
519 | The ``do'' Statement | |
520 | .PP | |
521 | The | |
522 | .UL do | |
523 | statement in | |
524 | Ratfor | |
525 | is quite similar to the | |
526 | .UC DO | |
527 | statement in Fortran, | |
528 | except that it uses no statement number. | |
529 | The statement number, after all, serves only to mark the end | |
530 | of the | |
531 | .UC DO , | |
532 | and this can be done just as easily with braces. | |
533 | Thus | |
534 | .P1 | |
535 | do i = 1, n { | |
536 | x(i) = 0.0 | |
537 | y(i) = 0.0 | |
538 | z(i) = 0.0 | |
539 | } | |
540 | .P2 | |
541 | is the same as | |
542 | .P1 | |
543 | do 10 i = 1, n | |
544 | x(i) = 0.0 | |
545 | y(i) = 0.0 | |
546 | z(i) = 0.0 | |
547 | 10 continue | |
548 | .P2 | |
549 | The syntax is: | |
550 | .P1 | |
551 | do \fIlegal\(hyFortran\(hyDO\(hytext\fP | |
552 | \fIRatfor statement\fP | |
553 | .P2 | |
554 | The part that follows | |
555 | the keyword | |
556 | .UL do | |
557 | has to be something that can legally go into a Fortran | |
558 | .UC DO | |
559 | statement. | |
560 | Thus if a local version of Fortran allows | |
561 | .UC DO | |
562 | limits to be expressions | |
563 | (which is not currently permitted in | |
564 | .UC ANSI | |
565 | Fortran), | |
566 | they can be used in a | |
567 | Ratfor | |
568 | .UL do. | |
569 | .PP | |
570 | The | |
571 | .ul | |
572 | Ratfor statement | |
573 | part will often be enclosed in braces, but | |
574 | as with the | |
575 | .UL if , | |
576 | a single statement need not have braces around it. | |
577 | This code sets an array to zero: | |
578 | .P1 | |
579 | do i = 1, n | |
580 | x(i) = 0.0 | |
581 | .P2 | |
582 | Slightly more complicated, | |
583 | .P1 | |
584 | do i = 1, n | |
585 | do j = 1, n | |
586 | m(i, j) = 0 | |
587 | .P2 | |
588 | sets the entire array | |
589 | .UL m | |
590 | to zero, and | |
591 | .P1 | |
592 | do i = 1, n | |
593 | do j = 1, n | |
594 | if (i < j) | |
595 | m(i, j) = -1 | |
596 | else if (i == j) | |
597 | m(i, j) = 0 | |
598 | else | |
599 | m(i, j) = +1 | |
600 | .P2 | |
601 | sets the upper triangle of | |
602 | .UL m | |
603 | to \-1, the diagonal to zero, and the lower triangle to +1. | |
604 | (The operator == is ``equals'', that is, ``.EQ.''.) | |
605 | In each case, the statement that follows the | |
606 | .UL do | |
607 | is logically a | |
608 | .ul | |
609 | single | |
610 | statement, even though complicated, | |
611 | and thus needs no braces. | |
612 | .sp | |
613 | .SH | |
614 | ``break'' and ``next'' | |
615 | .PP | |
616 | Ratfor | |
617 | provides a statement for leaving a loop early, | |
618 | and one for beginning the next iteration. | |
619 | .UL "break" | |
620 | causes an immediate exit from the | |
621 | .UL do ; | |
622 | in effect it is a branch to the statement | |
623 | .ul | |
624 | after | |
625 | the | |
626 | .UL do . | |
627 | .UL next | |
628 | is a branch to the bottom of the loop, | |
629 | so it causes the next iteration to be done. | |
630 | For example, this code skips over negative values in an array: | |
631 | .P1 | |
632 | do i = 1, n { | |
633 | if (x(i) < 0.0) | |
634 | next | |
635 | \fIprocess positive element\fP | |
636 | } | |
637 | .P2 | |
638 | .UL break | |
639 | and | |
640 | .UL next | |
641 | also work in the other Ratfor looping constructions | |
642 | that we will talk about in the next few sections. | |
643 | .PP | |
644 | .UL break | |
645 | and | |
646 | .UL next | |
647 | can be followed by an integer to indicate breaking or iterating | |
648 | that level of enclosing loop; thus | |
649 | .P1 | |
650 | break 2 | |
651 | .P2 | |
652 | exits from two levels of enclosing loops, | |
653 | and | |
654 | .UL break\ 1 | |
655 | is equivalent to | |
656 | .UL break . | |
657 | .UL next\ 2 | |
658 | iterates the second enclosing loop. | |
659 | (Realistically, | |
660 | multi-level | |
661 | .UL break 's | |
662 | and | |
663 | .UL next 's | |
664 | are | |
665 | not likely to be much used | |
666 | because they lead to code that is hard to understand | |
667 | and somewhat risky to change.) | |
668 | .sp | |
669 | .SH | |
670 | The ``while'' Statement | |
671 | .PP | |
672 | One of the problems with the Fortran | |
673 | .UC DO | |
674 | statement | |
675 | is that it generally insists upon being done once, | |
676 | regardless of its limits. | |
677 | If a loop begins | |
678 | .P1 | |
679 | DO I = 2, 1 | |
680 | .P2 | |
681 | this will typically be done once with | |
682 | .UL I | |
683 | set to 2, | |
684 | even though common sense would suggest that perhaps it shouldn't be. | |
685 | Of course a | |
686 | Ratfor | |
687 | .UL do | |
688 | can easily be preceded by a test | |
689 | .P1 | |
690 | if (j <= k) | |
691 | do i = j, k { | |
692 | _ _ _ | |
693 | } | |
694 | .P2 | |
695 | but this has to be a conscious act, | |
696 | and is often overlooked by programmers. | |
697 | .PP | |
698 | A more serious problem with the | |
699 | .UC DO | |
700 | statement | |
701 | is that it encourages that a program be written | |
702 | in terms of an arithmetic progression | |
703 | with small positive steps, | |
704 | even though that may not be the best way to write it. | |
705 | If code has to be contorted to fit the requirements | |
706 | imposed by the Fortran | |
707 | .UC DO , | |
708 | it is that much harder to write and understand. | |
709 | .PP | |
710 | To overcome these difficulties, | |
711 | Ratfor | |
712 | provides a | |
713 | .UL while | |
714 | statement, | |
715 | which is simply a loop: | |
716 | ``while some condition is true, | |
717 | repeat this group of statements''. | |
718 | It has | |
719 | no preconceptions about why one is looping. | |
720 | For example, this routine to compute sin(x) | |
721 | by the Maclaurin series | |
722 | combines two termination criteria. | |
723 | .P1 1 | |
724 | .ta .3i .6i .9i 1.2i 1.5i 1.8i | |
725 | real function sin(x, e) | |
726 | # returns sin(x) to accuracy e, by | |
727 | # sin(x) = x - x**3/3! + x**5/5! - ... | |
728 | ||
729 | sin = x | |
730 | term = x | |
731 | ||
732 | i = 3 | |
733 | while (abs(term)>e & i<100) { | |
734 | term = -term * x**2 / float(i*(i-1)) | |
735 | sin = sin + term | |
736 | i = i + 2 | |
737 | } | |
738 | ||
739 | return | |
740 | end | |
741 | .P2 | |
742 | .PP | |
743 | Notice that | |
744 | if the routine is entered with | |
745 | .UL term | |
746 | already smaller than | |
747 | .UL e , | |
748 | the | |
749 | loop will be done | |
750 | .ul | |
751 | zero times, | |
752 | that is, no attempt will be made to compute | |
753 | .UL x**3 | |
754 | and thus a potential underflow is avoided. | |
755 | Since the test is made at the top of a | |
756 | .UL while | |
757 | loop | |
758 | instead of the bottom, | |
759 | a special case disappears _ | |
760 | the code works at one of its boundaries. | |
761 | (The test | |
762 | .UL i<100 | |
763 | is the other boundary _ | |
764 | making sure the routine stops after | |
765 | some maximum number of iterations.) | |
766 | .PP | |
767 | As an aside, a sharp character ``#'' in a line | |
768 | marks the beginning of a comment; | |
769 | the rest of the line is comment. | |
770 | Comments and code can co-exist on the same line _ | |
771 | one can make marginal remarks, | |
772 | which is not possible with Fortran's ``C in column 1'' convention. | |
773 | Blank lines are also permitted anywhere | |
774 | (they are not in Fortran); | |
775 | they should be used to emphasize the natural divisions | |
776 | of a program. | |
777 | .PP | |
778 | The syntax of the | |
779 | .UL while | |
780 | statement is | |
781 | .P1 | |
782 | while (\fIlegal Fortran condition\fP) | |
783 | \fIRatfor statement\fP | |
784 | .P2 | |
785 | As with the | |
786 | .UL if , | |
787 | .ul | |
788 | legal Fortran condition | |
789 | is something that can go into | |
790 | a Fortran Logical | |
791 | .UC IF , | |
792 | and | |
793 | .ul | |
794 | Ratfor statement | |
795 | is a single statement, | |
796 | which may be multiple statements in braces. | |
797 | .PP | |
798 | The | |
799 | .UL while | |
800 | encourages a style of coding not normally | |
801 | practiced by Fortran programmers. | |
802 | For example, suppose | |
803 | .UL nextch | |
804 | is a function which returns the next input character | |
805 | both as a function value and in its argument. | |
806 | Then a loop to find the first non-blank character is just | |
807 | .P1 | |
808 | while (nextch(ich) == iblank) | |
809 | ; | |
810 | .P2 | |
811 | A semicolon by itself is a null statement, | |
812 | which is necessary here to mark the end of the | |
813 | .UL while ; | |
814 | if it were not present, the | |
815 | .UL while | |
816 | would control the next statement. | |
817 | When the loop is broken, | |
818 | .UL ich | |
819 | contains the first non-blank. | |
820 | Of course the same code can be written in Fortran as | |
821 | .P1 1 | |
822 | 100 if (nextch(ich) .eq. iblank) goto 100 | |
823 | .P2 | |
824 | but many Fortran programmers (and a few compilers) believe this line is illegal. | |
825 | The language at one's disposal | |
826 | strongly influences how one thinks about a problem. | |
827 | .sp | |
828 | .SH | |
829 | The ``for'' Statement | |
830 | .PP | |
831 | The | |
832 | .UL for | |
833 | statement | |
834 | is another Ratfor loop, which | |
835 | attempts to carry the separation of | |
836 | loop-body from reason-for-looping | |
837 | a step further | |
838 | than the | |
839 | .UL while. | |
840 | A | |
841 | .UL for | |
842 | statement allows explicit initialization | |
843 | and increment steps as part of the statement. | |
844 | For example, | |
845 | a | |
846 | .UC DO | |
847 | loop is just | |
848 | .P1 | |
849 | for (i = 1; i <= n; i = i + 1) ... | |
850 | .P2 | |
851 | This is equivalent to | |
852 | .P1 | |
853 | i = 1 | |
854 | while (i <= n) { | |
855 | ... | |
856 | i = i + 1 | |
857 | } | |
858 | .P2 | |
859 | The initialization and increment of | |
860 | .UL i | |
861 | have been moved into the | |
862 | .UL for | |
863 | statement, | |
864 | making it easier to see at a glance | |
865 | what controls the loop. | |
866 | .PP | |
867 | The | |
868 | .UL for | |
869 | and | |
870 | .UL while | |
871 | versions have the advantage that they will be done zero times | |
872 | if | |
873 | .UL n | |
874 | is less than 1; this is not true of the | |
875 | .UL do . | |
876 | .PP | |
877 | The loop of the sine routine in the previous section | |
878 | can be re-written | |
879 | with a | |
880 | .UL for | |
881 | as | |
882 | .P1 3 | |
883 | for (i=3; abs(term) > e & i < 100; i=i+2) { | |
884 | term = -term * x**2 / float(i*(i-1)) | |
885 | sin = sin + term | |
886 | } | |
887 | .P2 | |
888 | .PP | |
889 | The syntax of the | |
890 | .UL for | |
891 | statement is | |
892 | .P1 | |
893 | for ( \fIinit\fP ; \fIcondition\fP ; \fIincrement\fP ) | |
894 | \fIRatfor statement\fP | |
895 | .P2 | |
896 | .ul | |
897 | init | |
898 | is any single Fortran statement, which gets done once | |
899 | before the loop begins. | |
900 | .ul | |
901 | increment | |
902 | is any single Fortran statement, | |
903 | which gets done at the end of each pass through the loop, | |
904 | before the test. | |
905 | .ul | |
906 | condition | |
907 | is again anything that is legal in a logical | |
908 | .UC IF. | |
909 | Any of | |
910 | .ul | |
911 | init, | |
912 | .ul | |
913 | condition, | |
914 | and | |
915 | .ul | |
916 | increment | |
917 | may be omitted, | |
918 | although the semicolons | |
919 | .ul | |
920 | must | |
921 | always be present. | |
922 | A non-existent | |
923 | .ul | |
924 | condition | |
925 | is treated as always true, | |
926 | so | |
927 | .UL "for(;;)" | |
928 | is an indefinite repeat. | |
929 | (But see the | |
930 | .UL repeat-until | |
931 | in the next section.) | |
932 | .PP | |
933 | The | |
934 | .UL for | |
935 | statement is particularly | |
936 | useful for | |
937 | backward loops, chaining along lists, | |
938 | loops that might be done zero times, | |
939 | and similar things which are hard to express with a | |
940 | .UC DO | |
941 | statement, | |
942 | and obscure to write out | |
943 | with | |
944 | .UC IF 's | |
945 | and | |
946 | .UC GOTO 's. | |
947 | For example, | |
948 | here is a | |
949 | backwards | |
950 | .UC DO | |
951 | loop | |
952 | to find the last non-blank character on a card: | |
953 | .P1 | |
954 | for (i = 80; i > 0; i = i - 1) | |
955 | if (card(i) != blank) | |
956 | break | |
957 | .P2 | |
958 | (``!='' is the same as | |
959 | .UC ``.NE.'' ). | |
960 | The code scans the columns from 80 through to 1. | |
961 | If a non-blank is found, the loop | |
962 | is immediately broken. | |
963 | .UL break \& ( | |
964 | and | |
965 | .UL next | |
966 | work in | |
967 | .UL for 's | |
968 | and | |
969 | .UL while 's | |
970 | just as in | |
971 | .UL do 's). | |
972 | If | |
973 | .UL i | |
974 | reaches zero, | |
975 | the card is all blank. | |
976 | .PP | |
977 | This code is rather nasty to write with a regular Fortran | |
978 | .UC DO , | |
979 | since the loop must go forward, | |
980 | and we must explicitly set up proper conditions | |
981 | when we fall out of the loop. | |
982 | (Forgetting this is a common error.) | |
983 | Thus: | |
984 | .P1 1 | |
985 | .ta .3i .6i .9i 1.2i 1.5i 1.8i | |
986 | DO 10 J = 1, 80 | |
987 | I = 81 - J | |
988 | IF (CARD(I) .NE. BLANK) GO TO 11 | |
989 | 10 CONTINUE | |
990 | I = 0 | |
991 | 11 ... | |
992 | .P2 | |
993 | The version that uses the | |
994 | .UL for | |
995 | handles the termination condition properly for free; | |
996 | .UL i | |
997 | .ul | |
998 | is | |
999 | zero when we fall out of the | |
1000 | .UL for | |
1001 | loop. | |
1002 | .PP | |
1003 | The increment | |
1004 | in a | |
1005 | .UL for | |
1006 | need not be an arithmetic progression; | |
1007 | the following program walks along a list | |
1008 | (stored in an integer array | |
1009 | .UL ptr ) | |
1010 | until a zero pointer is found, | |
1011 | adding up elements from a parallel array of values: | |
1012 | .P1 | |
1013 | sum = 0.0 | |
1014 | for (i = first; i > 0; i = ptr(i)) | |
1015 | sum = sum + value(i) | |
1016 | .P2 | |
1017 | Notice that the code works correctly if the list is empty. | |
1018 | Again, placing the test at the top of a loop | |
1019 | instead of the bottom eliminates a potential boundary error. | |
1020 | .SH | |
1021 | The ``repeat-until'' statement | |
1022 | .PP | |
1023 | In spite of the dire warnings, | |
1024 | there are times when one really needs a loop that tests at the bottom | |
1025 | after one pass through. | |
1026 | This service is provided by the | |
1027 | .UL repeat-until : | |
1028 | .P1 | |
1029 | repeat | |
1030 | \fIRatfor statement\fP | |
1031 | until (\fIlegal Fortran condition\fP) | |
1032 | .P2 | |
1033 | The | |
1034 | .ul | |
1035 | Ratfor statement | |
1036 | part is done once, | |
1037 | then the condition is evaluated. | |
1038 | If it is true, the loop is exited; | |
1039 | if it is false, another pass is made. | |
1040 | .PP | |
1041 | The | |
1042 | .UL until | |
1043 | part is optional, so a bare | |
1044 | .UL repeat | |
1045 | is the cleanest way to specify an infinite loop. | |
1046 | Of course such a loop must ultimately be broken by some | |
1047 | transfer of control such as | |
1048 | .UL stop , | |
1049 | .UL return , | |
1050 | or | |
1051 | .UL break , | |
1052 | or an implicit stop such as running out of input with | |
1053 | a | |
1054 | .UC READ | |
1055 | statement. | |
1056 | .PP | |
1057 | As a matter of observed fact[8], the | |
1058 | .UL repeat-until | |
1059 | statement is | |
1060 | .ul | |
1061 | much | |
1062 | less used than the other looping constructions; | |
1063 | in particular, it is typically outnumbered ten to one by | |
1064 | .UL for | |
1065 | and | |
1066 | .UL while . | |
1067 | Be cautious about using it, for loops that test only at the | |
1068 | bottom often don't handle null cases well. | |
1069 | .SH | |
1070 | More on break and next | |
1071 | .PP | |
1072 | .UL break | |
1073 | exits immediately from | |
1074 | .UL do , | |
1075 | .UL while , | |
1076 | .UL for , | |
1077 | and | |
1078 | .UL repeat-until . | |
1079 | .UL next | |
1080 | goes to the test part of | |
1081 | .UL do , | |
1082 | .UL while | |
1083 | and | |
1084 | .UL repeat-until , | |
1085 | and to the increment step of a | |
1086 | .UL for . | |
1087 | .SH | |
1088 | ``return'' Statement | |
1089 | .PP | |
1090 | The standard Fortran mechanism for returning a value from a function uses the name of the function as a variable which can be assigned to; | |
1091 | the last value stored in it | |
1092 | is the function value upon return. | |
1093 | For example, here is a routine | |
1094 | .UL equal | |
1095 | which returns 1 if two arrays are identical, | |
1096 | and zero if they differ. | |
1097 | The array ends are marked by the special value \-1. | |
1098 | .P1 1 | |
1099 | .ta .3i .6i .9i 1.2i 1.5i 1.8i | |
1100 | # equal _ compare str1 to str2; | |
1101 | # return 1 if equal, 0 if not | |
1102 | integer function equal(str1, str2) | |
1103 | integer str1(100), str2(100) | |
1104 | integer i | |
1105 | ||
1106 | for (i = 1; str1(i) == str2(i); i = i + 1) | |
1107 | if (str1(i) == -1) { | |
1108 | equal = 1 | |
1109 | return | |
1110 | } | |
1111 | equal = 0 | |
1112 | return | |
1113 | end | |
1114 | .P2 | |
1115 | .PP | |
1116 | In many languages (e.g., PL/I) | |
1117 | one instead says | |
1118 | .P1 | |
1119 | return (\fIexpression\fP) | |
1120 | .P2 | |
1121 | to return a value from a function. | |
1122 | Since this is often clearer, Ratfor provides such a | |
1123 | .UL return | |
1124 | statement _ | |
1125 | in a function | |
1126 | .UL F , | |
1127 | .UL return (expression) | |
1128 | is equivalent to | |
1129 | .P1 | |
1130 | { F = expression; return } | |
1131 | .P2 | |
1132 | For example, here is | |
1133 | .UL equal | |
1134 | again: | |
1135 | .P1 1 | |
1136 | .ta .3i .6i .9i 1.2i 1.5i 1.8i | |
1137 | # equal _ compare str1 to str2; | |
1138 | # return 1 if equal, 0 if not | |
1139 | integer function equal(str1, str2) | |
1140 | integer str1(100), str2(100) | |
1141 | integer i | |
1142 | ||
1143 | for (i = 1; str1(i) == str2(i); i = i + 1) | |
1144 | if (str1(i) == -1) | |
1145 | return(1) | |
1146 | return(0) | |
1147 | end | |
1148 | .P2 | |
1149 | If there is no parenthesized expression after | |
1150 | .UL return , | |
1151 | a normal | |
1152 | .UC RETURN | |
1153 | is made. | |
1154 | (Another version of | |
1155 | .UL equal | |
1156 | is presented shortly.) | |
1157 | .sp | |
1158 | .SH | |
1159 | Cosmetics | |
1160 | .PP | |
1161 | As we said above, | |
1162 | the visual appearance of a language | |
1163 | has a substantial effect | |
1164 | on how easy it is to read and understand | |
1165 | programs. | |
1166 | Accordingly, Ratfor provides a number of cosmetic facilities | |
1167 | which may be used to make programs more readable. | |
1168 | .SH | |
1169 | Free-form Input | |
1170 | .PP | |
1171 | Statements can be placed anywhere on a line; | |
1172 | long statements are continued automatically, | |
1173 | as are long conditions in | |
1174 | .UL if , | |
1175 | .UL while , | |
1176 | .UL for , | |
1177 | and | |
1178 | .UL until . | |
1179 | Blank lines are ignored. | |
1180 | Multiple statements may appear on one line, | |
1181 | if they are separated by semicolons. | |
1182 | No semicolon is needed at the end of a line, | |
1183 | if | |
1184 | Ratfor | |
1185 | can make some reasonable guess about whether the statement | |
1186 | ends there. | |
1187 | Lines ending with any of the characters | |
1188 | .P1 | |
1189 | = + - * , | & ( \(ru | |
1190 | .P2 | |
1191 | are assumed to be continued on the next line. | |
1192 | Underscores are discarded wherever they occur; | |
1193 | all others remain as part of the statement. | |
1194 | .PP | |
1195 | Any statement that begins with an all-numeric field is | |
1196 | assumed to be a Fortran label, | |
1197 | and placed in columns 1-5 upon output. | |
1198 | Thus | |
1199 | .P1 | |
1200 | write(6, 100); 100 format("hello") | |
1201 | .P2 | |
1202 | is converted into | |
1203 | .P1 | |
1204 | write(6, 100) | |
1205 | 100 format(5hhello) | |
1206 | .P2 | |
1207 | .SH | |
1208 | Translation Services | |
1209 | .PP | |
1210 | Text enclosed in matching single or double quotes | |
1211 | is converted to | |
1212 | .UL nH... | |
1213 | but is otherwise unaltered | |
1214 | (except for formatting _ it may get split across card boundaries | |
1215 | during the reformatting process). | |
1216 | Within quoted strings, the backslash `\e' serves as an escape character: | |
1217 | the next character is taken literally. | |
1218 | This provides a way to get quotes (and of course the backslash itself) into | |
1219 | quoted strings: | |
1220 | .P1 | |
1221 | "\e\e\e\(fm" | |
1222 | .P2 | |
1223 | is a string containing a backslash and an apostrophe. | |
1224 | (This is | |
1225 | .ul | |
1226 | not | |
1227 | the standard convention of doubled quotes, | |
1228 | but it is easier to use and more general.) | |
1229 | .PP | |
1230 | Any line that begins with the character `%' | |
1231 | is left absolutely unaltered | |
1232 | except for stripping off the `%' | |
1233 | and moving the line one position to the left. | |
1234 | This is useful for inserting control cards, | |
1235 | and other things that should not be transmogrified | |
1236 | (like an existing Fortran program). | |
1237 | Use `%' only for ordinary statements, | |
1238 | not for the condition parts of | |
1239 | .UL if , | |
1240 | .UL while , | |
1241 | etc., or the output may come out in an unexpected place. | |
1242 | .PP | |
1243 | The following character translations are made, | |
1244 | except within single or double quotes | |
1245 | or on a line beginning with a `%'. | |
1246 | .P1 | |
1247 | .ta .5i 1.5i 2i | |
1248 | == .eq. != .ne. | |
1249 | > .gt. >= .ge. | |
1250 | < .lt. <= .le. | |
1251 | & .and. | .or. | |
1252 | ! .not. ^ .not. | |
1253 | .P2 | |
1254 | In addition, the following translations are provided | |
1255 | for input devices with restricted character sets. | |
1256 | .P1 | |
1257 | .ta .5i 1.5i 2i | |
1258 | [ { ] } | |
1259 | $( { $) } | |
1260 | .P2 | |
1261 | .SH | |
1262 | ``define'' Statement | |
1263 | .PP | |
1264 | Any string of alphanumeric characters can be defined as a name; | |
1265 | thereafter, whenever that name occurs in the input | |
1266 | (delimited by non-alphanumerics) | |
1267 | it is replaced by the rest of the definition line. | |
1268 | (Comments and trailing white spaces are stripped off). | |
1269 | A defined name can be arbitrarily long, | |
1270 | and must begin with a letter. | |
1271 | .PP | |
1272 | .UL define | |
1273 | is typically used to create symbolic parameters: | |
1274 | .P1 | |
1275 | define ROWS 100 | |
1276 | define COLS 50 | |
1277 | .if t .sp 5p | |
1278 | dimension a(ROWS), b(ROWS, COLS) | |
1279 | .if t .sp 5p | |
1280 | if (i > ROWS \(or j > COLS) ... | |
1281 | .P2 | |
1282 | Alternately, definitions may be written as | |
1283 | .P1 | |
1284 | define(ROWS, 100) | |
1285 | .P2 | |
1286 | In this case, the defining text is everything after the comma up to the balancing | |
1287 | right parenthesis; | |
1288 | this allows multi-line definitions. | |
1289 | .PP | |
1290 | It is generally a wise practice to use symbolic parameters | |
1291 | for most constants, to help make clear the function of what | |
1292 | would otherwise be mysterious numbers. | |
1293 | As an example, here is the routine | |
1294 | .UL equal | |
1295 | again, this time with symbolic constants. | |
1296 | .P1 3 | |
1297 | .ta .3i .6i .9i 1.2i 1.5i 1.8i | |
1298 | define YES 1 | |
1299 | define NO 0 | |
1300 | define EOS -1 | |
1301 | define ARB 100 | |
1302 | ||
1303 | # equal _ compare str1 to str2; | |
1304 | # return YES if equal, NO if not | |
1305 | integer function equal(str1, str2) | |
1306 | integer str1(ARB), str2(ARB) | |
1307 | integer i | |
1308 | ||
1309 | for (i = 1; str1(i) == str2(i); i = i + 1) | |
1310 | if (str1(i) == EOS) | |
1311 | return(YES) | |
1312 | return(NO) | |
1313 | end | |
1314 | .P2 | |
1315 | .SH | |
1316 | ``include'' Statement | |
1317 | .PP | |
1318 | The statement | |
1319 | .P1 | |
1320 | include file | |
1321 | .P2 | |
1322 | inserts the file | |
1323 | found on input stream | |
1324 | .ul | |
1325 | file | |
1326 | into the | |
1327 | Ratfor | |
1328 | input in place of the | |
1329 | .UL include | |
1330 | statement. | |
1331 | The standard usage is to place | |
1332 | .UC COMMON | |
1333 | blocks on a file, | |
1334 | and | |
1335 | .UL include | |
1336 | that file whenever a copy is needed: | |
1337 | .P1 | |
1338 | subroutine x | |
1339 | include commonblocks | |
1340 | ... | |
1341 | end | |
1342 | ||
1343 | suroutine y | |
1344 | include commonblocks | |
1345 | ... | |
1346 | end | |
1347 | .P2 | |
1348 | This ensures that all copies of the | |
1349 | .UC COMMON | |
1350 | blocks are identical | |
1351 | .SH | |
1352 | Pitfalls, Botches, Blemishes and other Failings | |
1353 | .PP | |
1354 | Ratfor catches certain syntax errors, such as missing braces, | |
1355 | .UL else | |
1356 | clauses without an | |
1357 | .UL if , | |
1358 | and most errors involving missing parentheses in statements. | |
1359 | Beyond that, since Ratfor knows no Fortran, | |
1360 | any errors you make will be reported by the Fortran compiler, | |
1361 | so you will from time to time have to relate a Fortran diagnostic back | |
1362 | to the Ratfor source. | |
1363 | .PP | |
1364 | Keywords are reserved _ | |
1365 | using | |
1366 | .UL if , | |
1367 | .UL else , | |
1368 | etc., as variable names will typically wreak havoc. | |
1369 | Don't leave spaces in keywords. | |
1370 | Don't use the Arithmetic | |
1371 | .UC IF . | |
1372 | .PP | |
1373 | The Fortran | |
1374 | .UL nH | |
1375 | convention is not recognized anywhere by Ratfor; | |
1376 | use quotes instead. |