Part 5 of 10 of the COMTRAN Language Definition.
5. Control-flow statements
COMTRAN control flow is built from four elements: the default sequential execution of sentences; the conditional sentence (IF ... THEN ... OTHERWISE); the three control commands GO TO, DO, and STOP (F p. 48); and the sectioning apparatus (BEGIN SECTION / END) that creates the named units to which control can be transferred (F pp. 56–57). This section covers all of these, together with the conditional expressions (relations, condition-names, AND/OR/NOT, truth functions) that drive the conditional constructs, and the J-processor's comparison semantics, restrictions, and limits.
Throughout: F = F28-8043 (June 1960 General Information Manual, the language vision); J = J28-6169-1 (Jan 1962 709/7090 Processor manual, authoritative for the implemented language).
5.1 Default sequential flow and sentence boundaries
- "During the execution of the object program the procedure is normally executed in the order in which it appears in the source program. The control commands are used primarily to specify a departure from this sequence" (F p. 48).
- The basic complete unit of meaning is the sentence; sentences are composed of clauses, of which there are two kinds: imperative and conditional (F p. 24).
- An imperative clause "always begins with a verb and may contain one or more operands"; operands may include data-names, procedure-names, condition-names, literals, figurative constants, and arithmetic expressions (F p. 25).
- A sentence "must contain at least one imperative clause and may contain, in addition, one conditional clause and one or more additional imperative clauses. It is terminated by a period, which must be followed by a blank ... Imperative clauses within the same sentence must be separated by commas" (F p. 25). Blanks may be used in addition to the comma but are ignored (F p. 27, rule 5).
- Period-blank termination: "Each sentence must be terminated by a period, followed by a blank. Should the blank be omitted, the period will be treated as an 'imbedded period,' except where the period is found in Column 72 of the procedure description form" (F p. 27, rule 3). A blank is assumed to follow column 72 of the procedure form (F p. 28, rule 14).
- J commentary rule: "Procedure statements are terminated by the first period (.) followed by a blank. Any information following this period blank is considered to be commentary" (J 02.03.01). Also: "A period (.) followed by a blank in a procedure statement terminates analysis of the statement except when they appear within an alphabetic literal; any information in the same card which follows the period is assumed to be commentary. No diagnostic comment is made" (J 90.01.03). Procedure.names not followed by a period and blank "are handled properly; no diagnostic message is given" (J 90.01.03).
- Each clause has exactly one verb: the compiler deletes a "STATEMENT WITHOUT PROPER VERB" and a "STATEMENT WITH MORE THAN ONE VERB" from the text (J 90.04.01, messages 125,00 and 126,00).
- The compiler assigns statement numbers of the form
xxxxx,yy: the digits before the comma identify the line (sentence), the two after the comma identify the clause within it (J 02.02.01). Statement number 9999,99 references errors not confined to a single statement (J 02.02.01). - Per-sentence capacity limits (J): "NUMBER OF OPERATORS IN THIS SENTENCE EXCEEDS MAXIMUM OF 60. SENTENCE DELETED FROM TEXT." (message 171,00); "THIS SENTENCE EXCEEDS INTERNAL TABLE CAPACITY. SENTENCE DELETED FROM TEXT." (177,00); "CONDITIONAL EXPRESSION TEST CAPACITY EXCEEDED. REWRITE AS TWO OR MORE SEPARATE EXPRESSIONS..." (187,00) (all J 90.04.01).
- Continuity checks (J): the compiler diagnoses program flow that runs off the end of a division or into non-executable material: "PROBABLE PROGRAM CONTINUITY ERROR. PROGRAM FLOWS INTO *DATA." (87,00); "... PROGRAM FLOWS INTO GENERATED CONSTANTS." (169,00); "... PROGRAM FLOWS INTO STATEMENT OR SECTION 'NAME.1' ADDRESSED BY A -DO-." (99,00) (J 90.04.01). The last is the compiled form of the closed-subroutine rule (§5.5.5).
- Program entry point (J): error messages reveal a reserved name -PROGRAM.START-: "MORE THAN ONE -PROGRAM.START-. FIRST USED." (141,00); "-PROGRAM.START- MUST BE A STATEMENT OR SECTION NAME." (142,00); "-PROGRAM.START- CANNOT BE A STATEMENT OR SECTION NAME ADDRESSED BY A -DO-." (143,00) (J 90.04.01); Appendix 90.02 refers in passing to "the first word of the object program (not necessarily PROGRAM.START)" (J 90.02.01). Nowhere in either manual is PROGRAM.START formally defined; the Loader "will normally use the starting point of the first program of combined segments as the starting point for the combined deck", modifiable by a *START card (J 03.02.08). See the ambiguities register.
- Physical placement of procedure text (needed because control transfers target names written in the name margin): procedure-names go in columns 7–12 ("name margin"), text in columns 13–72; a named sentence follows its name on the same line; an unnamed sentence must begin on a separate line to the right of the name margin; succeeding lines of a sentence begin right of the name margin; only BEGIN SECTION may appear on the same line as a section name; "END section.name" is written as a sentence on a separate line (F p. 37). Procedure-names may contain up to thirty characters and "must be followed by a period and a blank" (F p. 37). Serial numbers in columns 1–6 are not sequence checked by the J compiler (J 02.03.01); F said they would be sequence-checked (F p. 37); F/J divergence.
5.2 The conditional statement (IF ... THEN ... OTHERWISE)
Neither manual gives a boxed "general form" for the conditional statement (it is not a verb command); its shape is defined by prose rules in F Chapter 2:
- A conditional clause "consists of a conditional expression introduced by the word IF and terminated by the word THEN. The conditional expression may be simple or compound. The word IF is an operator ... The word THEN defines the limit of the conditional expression to be tested; it will always be followed by an imperative clause" (F p. 25).
IF OUT.OF.ZONE THEN
IF AMOUNT GT 200 THEN
IF MARRIED AND OVER.21 THEN
IF A = B OR A = C AND A GT D THEN
(F p. 25 — examples of conditional clauses)
- Placement and scope: "When a conditional clause is used in a sentence, it must begin the sentence, and it must be followed by one or more imperative clauses to be executed if the prescribed condition is met. If the programmer wishes to prescribe alternative action to be taken if the conditional expression proves false, he may specify it by writing next (without intervening punctuation) the word OTHERWISE, followed by one or more imperative clauses. If the conditional expression should prove false, and if the sentence does not contain the word OTHERWISE, the conditional sentence will cause no action and the system will proceed to the next sentence in the program" (F p. 25). Likewise: "if OTHERWISE is absent the program continues with the succeeding sentence" (F p. 7).
IF MARRIED THEN MOVE NAME TO MAILING.LIST.M,
ADD 1 TO COUNTER.
IF GROSS.PAY LT NET.PAY THEN GO TO ERROR.ROUTINE.
IF OUT.OF.ZONE THEN DO BILLING.ROUTINE.A OTHERWISE
DO BILLING.ROUTINE.B.
(F p. 25 — example sentences)
Consequences a compiler writer must observe:
- At most one conditional clause per sentence and it must be the first clause (F p. 25). There is no nested IF, no ELSE-IF chain, and no multi-sentence conditional scope: both the THEN arm (all comma-separated imperative clauses up to OTHERWISE or the terminating period) and the OTHERWISE arm (all clauses from OTHERWISE to the period) end at the sentence period, and both arms rejoin at the next sentence (F pp. 7, 25).
- OTHERWISE may not begin a sentence: "SENTENCE CANNOT START WITH -OTHERWISE-" (J 90.04.01, message 208,00).
- Sentence-structure violations are diagnosed and the statement dropped: "ILLEGAL SENTENCE STRUCTURE NOTHING DONE." (196,00); "SENTENCE STRUCTURE ERROR. POSSIBLE ILLEGAL USE OF A KEY WORD." (192,00); and the recovery message "-WHEN- SUBSTITUTED FOR -IF- BECAUSE OF IMPROPER USE." (170,00) (all J 90.04.01). The last implies the compiler repairs an IF written where the conditional-GO TO's WHEN belongs (see ambiguities).
- Multi-clause arms in real code (J sample program):
IF MASTER FICA GT 144.00 THEN SET WORKING FICA = WORKING FICA - (MASTER FICA - 144.00), SET MASTER FICA = 144.00.andIF M.EMP.NO = HIGH.VALUE THEN GO TO END.OF.RUN OTHERWISE SET D.EMP.NO = HIGH.VALUE, GO TO HIGH.DETAIL.(J 90.05, listing PDF p. 196). - Program commands and processor commands cannot be intermixed in a sentence; e.g.
IF A = B THEN GO TO C OTHERWISE OVERLAP SECTION.1, SECTION.2.is meaningless (F p. 60). Processor commands (except BEGIN SECTION and END) should be written as unnamed sentences, which "makes it impossible for a program command to transfer control to a processor command" (F p. 60). - Testing vs. setting: "Testing the value provides a basis for a decision but does not change the value; the testing is accomplished by using a conditional clause, IF . . . THEN. Setting a value of a conditional variable ... is effected by means of the SET command" (F p. 46); see §5.4.4.
5.3 Conditional expressions
A conditional expression "may be either true or false, depending on conditions existing when the expression is examined"; it may contain data-names, condition-names, arithmetic expressions, and relational expressions, and expressions may be joined by AND and OR into compound conditional expressions (F p. 21). The two principal types are (1) relations and (2) condition-names (F p. 21).
Conditional expressions appear in exactly these control contexts: the IF clause (F p. 25), the WHEN clauses of the conditional GO TO (F p. 48), and inside truth functions TR( ) in arithmetic expressions (F pp. 20, 24; see §5.3.5). SET's ON OVERFLOW and GET's AT END phrases are not conditional expressions but appended event clauses (F pp. 40, 44; see the SET/arithmetic and Input/Output sections).
5.3.1 Relations
"Six basic relational expressions may be used in conditional expressions, each of which may be written in a full form or in an abbreviated form" (F p. 21):
| Relational expression | Abbreviated form |
|---|---|
| IS GREATER THAN | GT |
| IS NOT GREATER THAN | NOT GT |
| IS EQUAL TO | = |
| IS NOT EQUAL TO | NOT = |
| IS LESS THAN | LT |
| IS NOT LESS THAN | NOT LT |
(F p. 21)
- Relations "may be used to connect data-names, literals, and arithmetic expressions" (F p. 21). Examples (F p. 21):
BEGINNING.ON.HAND + RECEIPTS - SHIPMENTS IS LESS THAN REORDER.POINT,AGE GT 21,A * (B + C) - (D / E) = 500,DEPENDENTS NOT = 0,A GT B OR A = C. - There is no "greater than or equal" / "less than or equal" spelling; those are expressed as NOT LT / NOT GT (F p. 21). Note F p. 2's admonition on precision: "We must not say 'less than 30' if we mean 'less than or equal to 30.'"
- Each relational expression must be completely stated:
HOURLY.RATE IS GREATER THAN 3.50 AND LESS THAN 5.00is not accepted; both operands must be repeated (F p. 23, rule 3). - Reserved-word inventory relevant to relations: F Appendix 2 lists IS, GREATER, LESS, THAN, EQUAL, GT, LT, NOT (F p. 110). J's key-word list additionally reserves EQUALS (J 02.03.02) although no manual documents an "EQUALS" relational form; see open questions. The sample program uses
IS NOT EQUAL TO,NOT GT,GT,LT, and=(J 90.05, listing PDF pp. 195–197).
5.3.2 Comparison semantics (J 02.04.C — authoritative)
J 02.04.06–02.04.07, "C. Conditional Statements", gives the implemented comparison rules:
- "Comparisons may not be made between numeric and alphameric fields." Given ABC alphameric (AAA) and DEF numeric (999),
IF ABC = DEF THEN ---is an invalid comparison; "The implied or explicit specification of DEF as an external decimal field does not affect the validity of the comparison" (J 02.04.06). - Fields of unequal length (J 02.04.07):
- a) "Numeric fields are compared arithmetically without regard to length."
- b) Alphameric fields of unequal length are treated on the basis of the operator:
- i. "In tests for an = or NOT = condition the fields will always be found to be unequal." For unequal-length alphameric A and B, given
IF A = B THEN GO TO C OTHERWISE GO TO D."the only code generated will be a transfer to D"; forIF A NOT = B THEN GO TO D OTHERWISE GO TO C.likewise (J 02.04.07). I.e. the compiler folds the comparison at compile time. - ii. "In tests for NOT greater or less conditions the lengths are made equal by right truncation of the longer field" (J 02.04.07). (On the reading of this phrase see the ambiguities register; the plausible sense is: for the relative-magnitude operators (GT, LT, NOT GT, NOT LT) as opposed to =/NOT =.)
- i. "In tests for an = or NOT = condition the fields will always be found to be unequal." For unequal-length alphameric A and B, given
- "For purposes of comparison edited fields (see 02.05 for definition) are converted to pure numeric fields. They may not be compared to alphameric fields" (J 02.04.07).
- "All non-format fields (see 02.05 for definition) are compared alphamerically, subject to rules stated in 2b above" (J 02.04.07). (A field with no pictorial is treated as alphameric with length equal to its subfields, J 02.05.06; group items in a MOVE/ADD CORRESPONDING are likewise assumed alphameric, J 02.04.05.)
- "Variable length fields may not be compared. (A variable length field is a field which uses the QUANTITY IN option)" (J 02.04.07); enforced by "CANNOT USE VARIABLE LENGTH ITEMS FOR COMPARISON." (J 90.04.01, message 123,00).
- "For comparison purposes zero is considered an unsigned number, even though computational sequences generated by the compiler may produce negative or positive zeros" (J 02.04.07).
- Structural errors are reported as "ILLEGAL COMPARISON STRUCTURE." (J 90.04.01, message 107,00).
Figurative constants in comparisons (J 02.04.01): "ZERO may be compared to either numeric or alphameric fields. HIGH.VALUE, LOW.VALUE and BLANK may be compared to alphameric fields only."
Collating sequence. The compiler "normally generates comparison type instructions based on the 709/7090 collating sequence"; the Environment OPTION card COLLATE COM selects the Commercial (705) collating sequence instead, optionally limited to one section by IN section.name (reverting to normal at the end of that section; the modes may be altered any number of times) (J 02.06.16–02.06.17). The OPTION card general form:
Name Type Description
OPTION [COLLATE COM] [IN section.name]
[, CONSERVE {SPACE}] [IN section.name]
{TIME }
The 709/7090 sequence runs (lowest to highest) 0 through 9 = ' + A–I ⟨+0⟩ . ) − J–R ⟨−0⟩ $ * blank / S–Z ⟨rm⟩ , ( (digits lowest, ( highest) and the Commercial (705) sequence runs from Blank (lowest) through the specials and letters to 0 through 9 (highest) (J 02.06.16; scan-resolved reading — full displays and glyph legend in §1.1). Note the operational consequence: under the native 709/7090 sequence digits collate low and letters high; under COM, blank collates lowest and digits highest.
Consistently, the figurative-constant extremes depend on the sequence chosen: "HIGH.VALUE will be considered to be the left parenthesis, (, and LOW.VALUE the zero, 0, unless the Commercial collating sequence (COM) is specified in the Environment Description. The Commercial HIGH.VALUE is 9 and the LOW.VALUE is blank" (J 02.04.01). F defines LOW.VALUE/HIGH.VALUE only abstractly as "the lowest and highest characters in the collating sequence of the system for which the program is written" (F p. 20).
Object code: alphabetic comparison of two fields is performed by generated subroutine SYS)162, using conversion table SYS)161; "OP is a CVR or NOP depending of the need to adjust the collating sequence before the comparison" (J 90.02.12 — "depending of" is the original's typo).
F/J divergence: F never restricts comparisons by type or length (F pp. 21–24 are silent); all of the above type/length/collating machinery is J's implemented tightening and must be treated as the language definition.
5.3.3 Condition-name tests
- A condition-name "defines a condition which can be used to control an operation" (F p. 14) and "actually serves as an abbreviation of a relational expression": MARRIED defined for the conditional variable MARITAL.STATUS with value 'M' is "exactly equivalent to MARITAL.STATUS = 'M' and it may be substituted for it wherever the programmer wishes" (F p. 22);
IF MARRIED THEN DO TABULATION.ROUTINE.A≡IF MARITAL.STATUS = 'M' THEN DO TABULATION.ROUTINE.A(F p. 22). "The condition-name itself is a conditional expression in the full meaning of that term" (F p. 22). - Condition-names are declared in the Data Description with type code COND, immediately following the conditional variable's entry, at a lower level (higher level number), one entry per value (F pp. 71–72; see §3, Data description and storage model). If the programmer confines himself to full relational forms he need not declare condition-names at all (F p. 72).
- J test semantics: "Data Description condition.names are tested ... for absolute equivalence to the specified value" (J 02.06.17). The COND type entries "must be preceded by a higher level entry defining the format of the fields and must all have the same level number and include the COND type code" (J 02.05.02). A conditional variable has format restrictions ("FORMAT ERROR FOR CONDITIONAL VARIABLE", J 90.04.01 message 37,00) and "CONDITIONAL VARIABLE CANNOT HAVE -QUANTITY-." (38,00).
- Subscripting: "Neither a data item (literal) nor a condition.name may be subscripted. However, a conditional variable may be subscripted" (J 90.01.03). Condition-names may not be used in subscripts (F p. 31).
- Console-key conditions (J only): an Environment COND card defines a condition-name over the 36 console entry keys:
Name Type Description
condition.name COND KEYS 'nn'
'nn' is 12 octal digits giving "on" settings; "When the condition.name is tested in a procedure statement only the keys specified in 'nn' are tested for 'on' setting. The specified console keys must all be 'on' for the condition to be true. No 'off' or 'on' test is made for the non-specified keys" (J 02.06.17). This gives the object program an operator-controlled switch testable by IF, a facility absent from F. F/J divergence.
5.3.4 AND, OR, and NOT — combination rules and precedence
Compound conditions are formed with AND and OR, with parentheses where needed; "The negative form of a conditional expression may also be used; this is obtained by placing the word NOT before the expression" (F p. 23). The four interpretation rules (F p. 23):
- OR is inclusive: "either or both".
- AND means "both"; both conditions must be true.
- Each conditional expression must be completely stated (no elliptical second operand).
- "When a compound conditional expression contains both the word OR and the word AND, it will be interpreted as if the terms connected by AND were enclosed in parentheses. ... If a contrary sense is intended, parentheses must be used to show it."
Thus AND binds tighter than OR: "The conditional expression 'C1 OR C2 AND C3' is identical with 'C1 OR (C2 AND C3)' but is not the same as '(C1 OR C2) AND C3.' ... conditional expressions are grouped first according to AND and subsequently by OR. However, the programmer's use of parentheses will affect the order of grouping" (F p. 105, rule 3).
Truth-table statement of the operators (F p. 105, rule 1):
| The Conditional Expression | Is True If |
|---|---|
| C1 | C1 is true |
| NOT C1 | C1 is false |
| C1 AND C2 | Both C1 and C2 are true |
| C1 OR C2 | Either C1 is true, C2 is true, or both are true |
| NOT (C1 AND C2) | C1 is false, C2 is false, or both are false |
| NOT (C1 OR C2) | C1 and C2 are both false |
Closure rule: if C1, C2 are conditional expressions then so are "C1 AND C2", "C1 OR C2" and NOT-forms, reducible by successive substitution, e.g. C1 AND (C2 OR NOT (C3 OR C4)) (F p. 105, rule 2).
Legal symbol pairs (1 = permissible, 0 = not) (F p. 106, rule 4):
| First Symbol \ Second | C | OR | AND | NOT | ( | ) |
|---|---|---|---|---|---|---|
| C | 0 | 1 | 1 | 0 | 0 | 1 |
| OR | 1 | 0 | 0 | 1 | 1 | 0 |
| AND | 1 | 0 | 0 | 1 | 1 | 0 |
| NOT | 1 | 0 | 0 | 0 | 1 | 0 |
| ( | 1 | 0 | 0 | 1 | 1 | 0 |
| ) | 0 | 1 | 1 | 0 | 0 | 1 |
"Thus, the pair 'OR NOT' is permissible, while 'NOT OR' is not permissible" (F p. 106). Note in particular: NOT NOT is not permissible; NOT may be followed by a condition or by "(" but not by another NOT. NOT before a relation is built into the relation spellings themselves (NOT GT, NOT =, NOT LT) (F p. 21), and NOT before a condition-name or parenthesized compound negates it (F pp. 23, 105). Parentheses "may be used wherever needed ... in compound conditional expressions for the sake of clarity; where ambiguity would result from their omission, they must be used" (F p. 28, rule 11).
Worked interpretations of mixed AND/OR expressions are tabulated at F pp. 23–24 (e.g. MARRIED OR OVER.21 AND HOURLY.RATE IS GREATER THAN 3.50 = MARRIED, or the AND-pair, or both; the parenthesized variant regroups it).
J adds no separate AND/OR/NOT rules; its only related capacity note is message 187,00 (conditional expression test capacity; rewrite as two or more expressions) and the 60-operator sentence limit (171,00) (J 90.04.01).
5.3.5 Truth functions (TR)
- "A conditional expression enclosed in parentheses preceded by the truth operator TR is known as a truth function. A truth function always has one of two values, 1 or 0, depending on whether the conditional expression is true or false" (F p. 45); it "can be manipulated arithmetically in the same manner as any other quantity" (F pp. 45–46).
- The conditional expression is placed in parentheses with TR immediately in front (F p. 24). Example (F p. 24):
SET DISCOUNT = ORDER.AMOUNT * .05 * TR
(ORDER.AMOUNT IS GREATER THAN 1000).
- "The truth operator may be used with relational expressions ... or with condition-names" (F p. 24). TR is a unary arithmetic operator alongside ABS and negation; a unary operator's expression operand must be parenthesized (F p. 45). Two successive arithmetic operators are illegal unless the second is TR or ABS (F p. 27, rule 6).
- Alphameric variables and constants may appear in arithmetic expressions only within truth functions (F p. 45); i.e. TR( ) is the one bridge from alphameric comparison into arithmetic.
- Precedence (J): in the absence of parentheses, operators are honored in the order
TR or ABS or - (Negation), then**, then* or /, then+ or -; equal-precedence operators associate left to right (J 02.04.05.01). This makes TR bind most tightly, but since its operand is always parenthesized the practical effect is on the product/power context around it. - Object-time example in the field-test compiler:
SET WORKING WHT = WORKING WHT * TR(WORKING WHT GT 0)(J 90.05, listing PDF p. 196), a max(x, 0) idiom. - F also lists TR among "arithmetic operators" with meaning "Truth Value" (F p. 21) and demonstrates conditional expressions used inside arithmetic expressions solely via TR (F p. 20).
5.4 The GO TO command
"The GO TO command is used to specify transfer-type operations. It has three forms" (F p. 48).
Legal targets, all three forms: "The 'procedure.name' may be the name of either a sentence or a section in the procedural part of the source program" (F p. 48). J enforces this: "TRANSFER BYPASSED BECAUSE 'NAME.1' IS NOT A STATEMENT OR SECTION NAME." (127,00); "OPERATION IGNORED BECAUSE 'NAME.1' IS ILLEGAL TRANSFER ADDRESS." (26,00); and transfers into DO-addressed procedures are rejected: "TRANSFER BYPASSED BECAUSE 'NAME.1' IS A STATEMENT OR SECTION NAME ADDRESSED BY A -DO-." (128,00) (all J 90.04.01). Since processor commands (other than BEGIN SECTION/END) are unnamed, control cannot be transferred to them (F p. 60).
5.4.1 Unconditional GO TO
GO TO procedure.name
(F p. 48)
"It provides a transfer of control, or branching, to the item of procedure named in the command" (F p. 48). Examples: GO TO MAIN.ROUTINE., GO TO CALC.ORDER.POINT. (F p. 48). An unconditional GO TO placed immediately after a STOP yields a "dead-end" halt (F p. 54; §5.6). All overlapped procedures should end with an unconditional GO TO (F p. 56 — LOAD/OVERLAP deferred in J, see §5.7).
5.4.2 Conditional GO TO (WHEN)
"essentially a multiple branch or switching point" (F p. 48):
GO TO procedure.name.1 WHEN conditional expression 1,
procedure.name.2 WHEN conditional expression 2, ...
procedure.name.n WHEN conditional expression n
(F p. 48)
Semantics: "each conditional expression is evaluated in turn until one is found to be true. Thereupon, control is transferred to the 'procedure.name' associated with that conditional expression. Any remaining conditional expressions are left unevaluated. If none of the conditional expressions in the command is found to be true, control passes to the next clause or sentence in sequence" (F p. 48). I.e. first-match wins, evaluation is short-circuited, and no-match falls through.
GO TO ERROR.RTN WHEN DETAIL IS LESS THAN MASTER,
PROCESSING WHEN DETAIL IS EQUAL TO MASTER,
NO.ACTIVITY WHEN DETAIL IS GREATER THAN MASTER.
(F p. 48)
WHEN is one of the words "always interpreted as Key words" and may never be a programmer name (J 02.03.02). Real usage with fall-through (J 90.05, listing PDF p. 195):
COMPARE.EMPLOYEE.NUMBERS. GO TO CHECK.NEW.DEPT WHEN D.EMP.NO =
M.EMP.NO, LOW.DETAIL WHEN D.EMP.NO LT M.EMP.NO.
HIGH.DETAIL. ...
When neither WHEN condition holds, control falls into the next sentence (HIGH.DETAIL).
5.4.3 Assigned GO TO (ON index)
"also serves as a multiple branch point ... the transfer of control depends upon the prior setting of an index rather than on the truth or falsity of conditional expressions. The setting of the index may have occurred in one of two ways: 1. Through bringing the index into storage as a constant or file variable. 2. As a result of computation involving the index" (F pp. 48–49).
GO TO ( procedure.1, procedure.2, ... procedure.n ) ON index.name
(F p. 49)
- "A transfer of control will be made according to the value of the index at the time the GO TO is executed. If the value of the index is 1, control will pass to the first sentence or section of procedure named in the command; if 2, the second item named; and so on" (F p. 49).
- Range rule: "The functioning of the assigned GO TO command assumes that the value of the index will always be an integer in the range 1 to n. If the index has any other value, no transfer will occur; instead, control will pass to the next clause or sentence in sequence" (F p. 49).
- "Note that the parentheses shown in both the general form and the example are a fixed part of the command and must always be included" (F p. 49). ON is an always-reserved key word (J 02.03.02).
GO TO (PIECE.WORK, INCENTIVE, HOURLY.RATE, SALARY) ON
PAY.TYPE.
(F p. 49 — PAY.TYPE is a field in each employee record containing 1, 2, 3, or 4)
- How the "switch" is set: there is no special assign-verb; the index is an ordinary integer data field set by input data, by MOVE, or by SET arithmetic (F pp. 48–49). (SET condition.name (§5.4.4) changes a conditional variable, which is the switch mechanism for IF-type tests, not for the assigned GO TO.)
- J diagnostics for the index: "FORMAT ERROR FOR TRANSFER INDEX. NOTHING DONE." (129,00) and "TRANSFER INDEX NOT AN INTEGER. INTEGRAL PART TAKEN AS VALUE." (130,00) (J 90.04.01). J is silent on whether an object-time range check (the F fall-through rule) is actually generated; see open questions.
5.4.4 SET condition.name (switch setting for conditional tests)
For completeness of the "switch" picture (full SET coverage belongs with arithmetic/assignment):
SET condition.name
(F p. 46)
"the variable with which 'condition.name' is associated (in the data description) is assigned the status, or value, of the specified condition" (F p. 46). SET MARRIED. ≡ SET MARITAL.STATUS = 'M'. (F p. 46). J's SET discussion (J 02.04.05, "6. SET") covers only the arithmetic form and never re-states the condition-name form; nothing in J 90.01 defers it, and conditional variables remain fully supported (J 02.05.02; J 90.04.01 messages 37,00/38,00). Presume it implemented as per F (flagged in the ambiguities register).
5.5 The DO command
"The DO command provides a means of departing from the normal sequence of program steps in order to execute some procedure ... and then return to the original sequence. In other words, the DO is used to execute subroutines which, in the Commercial Translator system, are either named sentences or sections" (F p. 49). "The DO command may take one of several forms. In the simplest form ... the procedure is executed once each time the DO is encountered. Expanded forms of the command permit repetitive execution, or 'looping,' of the subroutine and control of subscripts. Data substitution, which is an optional feature, is also provided" (F p. 49).
Consolidated general forms (F p. 108, Appendix 2 — brackets denote optional phrases):
DO procedure.name [EXACTLY n TIMES] [USING data.name.1, data.name.2, ..
data.name.n] [GIVING result.name.1, result.name.2, ... result.name.n]
DO procedure.name FOR index.name.1 = p.1(q.1)r.1 [, index.name.2 =
p.2(q.2)r.2, index.name.3 = p.3(q.3)r.3] [USING data.name.1, data.name.2,
... data.name.n] [GIVING result.name.1, result.name.2, ... result.name.n]
5.5.1 Simple DO and DO ... EXACTLY n TIMES
DO procedure.name
DO procedure.name EXACTLY n TIMES
(F p. 49)
- "where 'procedure.name' represents the name of a sentence or section. (If a procedure consists of more than one sentence, it must be defined as a section in order to be named ...)" (F p. 49).
- First form: "the 'procedure.name' subroutine is executed only once and control passes to the sentence or clause following the DO" (F p. 50).
- Second form: "the 'procedure.name' procedure is executed the specified number of times. The number of repetitions, n, may be stated as a literal or as a data-name, but in either case the value of n must be a positive integer" (F p. 50). Example:
DO BOND.ORDER.RTN EXACTLY NO.OF.BONDS TIMES.(F p. 50). - J at-least-once rule: "A DO section will always be performed at least once regardless of the values of the loop control variables" (J 90.01.02). This applies to all repetitive forms (presumably even EXACTLY 0 TIMES (itself an invalid value per F p. 50, which requires n to be a positive integer) would execute once; not stated). F/J divergence in the sense that F never states it.
- EXACTLY and TIMES are reserved (J 02.03.02; F p. 110).
5.5.2 DO with indexing (FOR index = p(q)r)
DO procedure.name FOR index.name = p(q)r
(F p. 50)
- "'index.name' represents a field which has been defined in the data description as an integer" (F p. 50).
- Semantics, quoted in full because they are the precise loop contract (F p. 50): "The effect of this DO command (in the object program) is to set the index to the initial value p and transfer control to the first sentence of the named procedure. After the last sentence of the procedure has been reached and executed, control is returned to the DO command which increments the index by the quantity q and causes control to return to the 'loop.' This process is repeated until the value of the index equals r; at this point, control is no longer returned to the loop but instead passes to the sentence or clause which follows the DO."
- F gives the exact equivalence; the loop is test-after-body with an equality test:
SET i = p.
START. DO rtn.
IF i = r THEN GO TO NEXT.
ADD q TO i.
GO TO START.
NEXT. .
.
.
(F p. 51 — "the command, 'DO rtn FOR i = p(q)r' is the equivalent of" this expansion)
Consequences: the body executes with i = p first and executes for i = r (termination is checked after the body); the index equals r on exit; the body always runs at least once (consistent with J 90.01.02); if the step never makes i exactly equal r the expansion never terminates (see ambiguities).
- "Each of the loop control parameters p, q and r may be either of the following: 1. A literal having an integer value. 2. The name of a field defined as an integer" (F p. 51).
- Example and subscript interaction (F p. 51):
DO RATE.UPDATE.CALC FOR STATE = 1(1)50.with bodyRATE.UPDATE.CALC. SET RATE (STATE) = RATE (STATE) * ADJUST.FACTOR + FLAT.AMT.: "the variable RATE is said to be subscripted by the index STATE". Field-test example:DO SEARCH FOR INDEX = 1(1)12.(J 90.05, listing PDF p. 196). - Two indices (F p. 51): "'index.name.1' and 'index.name.2' are initially set to p.1 and p.2 respectively. Each time the inner loop is executed, index.name.2 is incremented by q.2 until it equals r.2; thereupon, index.name.2 is reset to p.2 and index.name.1 is set to p.1 + q.1. Control is returned to the inner loop and the process is repeated. When index.name.1 is equal to r.1, control passes to the clause or sentence which follows the DO." (On the literal "set to p.1 + q.1" wording see the ambiguities register.)
DO procedure.name FOR index.name.1 = p.1(q.1)r.1, index.name.2 = p.2(q.2)r.2
(F p. 51)
- Three indices maximum: "A maximum of three indices may be controlled with the DO command. Again, the rightmost index is the one which varies most rapidly" (F p. 51). Example
DO COMPUTATION FOR HOURS = 1(1)12, MINUTES = 1(1)60, SECONDS = 1(1)60.executes the subroutine 60x60x12 times (F p. 51). - J diagnostics: "FORMAT ERROR FOR LOOP CONTROL VARIABLE 'NAME.1'." (76,00); "FORMAT ERROR FOR PARAMETER 'NAME.1' OF LOOP CONTROL VARIABLE." (77,00); "FORMAT ERROR FOR LITERAL PARAMETER OF LOOP CONTROL VARIABLE 'NAME.1'." (78,00); "INVALID FORM OF -DO- STATEMENT." (83,00) (all J 90.04.01).
- J indexing interactions (see also §on subscripting): each unique subscripted name gets a compiler-generated positional indicator locating the element; "In general, positional indicators are evaluated when their subscripts change value" (J 02.04.07–02.04.07.01); "The initial value of an array is A(1) and not A(0)" (J 02.04.07.01). Restrictions bearing on loops (J 90.01.02): repeated use of the same subscript name for multiple purposes causes unnecessary recalculation ("it will not be incorrect"); "The dimensions of an array must be set before calculation of subscript values associated with the array is performed. Presently, failure to observe this restriction causes invalid object code"; "No object time check is made to insure that subscript references conform to the limits specified by the array dimensions in the Data Description." A DO index used as a subscript must be an integer (J 90.04.01, message 31,00) and numeric (79,00); inefficient formats are flagged (206,00).
5.5.3 DO with data substitution (USING ... GIVING ...)
Procedures to be used with data substitution "are always defined by the two processor commands 'BEGIN SECTION USING . . . GIVING . . .' and 'END'" (F p. 52). The simplest substituting DO:
DO procedure.name USING data.name.1, data.name.2, ...
data.name.n GIVING result.name.1, result.name.2 ...
result.name.n
(F p. 52)
"if data substitution is desired in the other forms of the DO command, the 'USING . . . GIVING . . .' option is simply appended to the command" (F p. 52). The matching section header:
BEGIN SECTION USING parameter.1, parameter.2, ...
parameter.n GIVING function.1, function.2, ... function.n
(F p. 57)
Semantics (F pp. 32–33, 52–53): at object time, data named in the DO's USING phrase is moved positionally into the parameter fields named in the BEGIN SECTION's USING phrase ("items of data named in a DO command will be placed in the parameter fields named in the BEGIN SECTION command in the order in which they are named", F p. 33); the procedure executes; then results are moved from the function fields (BEGIN SECTION GIVING) to the fields named in the DO's GIVING phrase (F p. 33). DO MIN.ROUT USING R.RATE, E.RATE, M.RATE GIVING MIN.RATE. is equivalent to three MOVEs in, DO MIN.ROUT., and one MOVE out (F pp. 52–53). Literals may be substituted: DO MIN.ROUT USING INSURED.AGE, BENEFIC.AGE, 70 GIVING LOW.AGE. (F p. 53), as may figurative constants such as HIGH.VALUES (F pp. 33–34).
- USING and GIVING are each optional on the DO; omitting USING reuses whatever values are in the parameter fields, omitting GIVING leaves results in the function fields for direct reference (F p. 33).
- A function-name may also be invoked directly in an expression, without a DO, by writing the function-name followed by its argument names in double parentheses, comma-separated, e.g.
SET APPROX = 2 * SQUARE.ROOT ((X)) TRUNCATED.(F p. 44);MOVE MINIMUM ((CALCULATED.PRICE, MARKET.PRICE. HIGH.VALUES)) TO PRICE.LIST.(F p. 34 — the period after MARKET.PRICE is an original printing inconsistency preserved by the conversion); rules at F pp. 33–34, 46, 58, and F p. 28 rule 15. When this technique is used the result can be obtained only from the function field (F p. 34). - Data substitution (object time) must not be confused with name substitution (INCLUDE, processing time) (F p. 52), and INCLUDE is deferred in J (J 90.01.02), so no library facilities exist.
- F/J divergence (PARAM/FUNCT): F requires every parameter-name and function-name to be declared in the data description with type codes PARAM and FUNCT (F pp. 34, 73). J: "These two type codes described in the General Information Manual are no longer in the language" (J 02.05.03). The USING/GIVING mechanism itself survives in J; the compiler checks argument counts: "TOO MANY -USING- PARAMETERS IN -DO- STATEMENT." (72,00), "TOO FEW -USING- ..." (73,00), "TOO MANY -GIVING- ..." (74,00), "TOO FEW -GIVING- ..." (75,00); and functions: "FUNCTION 'NAME.1' LACKS EXPLICIT SPECIFICATION OF ALL ARGUMENTS." (30,00), "EVALUATION IGNORED FOR FUNCTION 'NAME.1'. TOO MANY ARGUMENTS SPECIFIED." (68,00) (all J 90.04.01). In J, parameters and functions are therefore described as ordinary data items.
5.5.4 DO with named END (early exit from an iteration)
"When a DO command is compiled, the processor places appropriate instructions in the object program to effect transfer of control between the DO and the associated procedure and to perform any indexing operations specified in the DO. For correct functioning of the DO, these control instructions must be executed each time an iteration of the associated procedure is executed. The control instructions are performed following the last program command specified in the procedure." When the logic requires a conditional exit before the last command, "The solution ... is to name the 'END procedure.name' sentence which terminates the procedure and to use this name as an exit point. (Normally the END sentence is not named; this is the only exception to the rule.) This provides the necessary linkage with the control instructions" (F p. 53). Illustration (F p. 53):
DO REORDER.RTN FOR PART.NO = 1001(1)1499.
.
.
.
REORDER.RTN. BEGIN SECTION.
IF QTY.ON.HAND(PART.NO) IS GREATER THAN ORDER.POINT
(PART.NO) THEN GO TO EXIT.
SET REORDER.AMT(PART.NO) = ORDER.AMT(PART.NO) -
QTY.ON.HAND(PART.NO).
EXIT. END REORDER.RTN.
I.e. GO TO the named END sentence terminates the current iteration while preserving the loop/return linkage. The same pattern appears in the field-test sample program: BOND.ROUTINE contains ... GO TO BOND.END. with BOND.END. END BOND.ROUTINE., and SEARCH has SEARCH.END. END SEARCH. as the target of its in-loop GO TO (J 90.05, listing PDF pp. 196–197).
5.5.5 The closed-subroutine rule, entry, and exits
- "Any procedure ... that is referred to by a DO command must be what is known technically as a 'closed' or 'linked' subroutine. That is, it must be entered only through the use of a DO command, and not by any other means such as transfer of control to a sentence within the procedure or through the normal passage of control to the first sentence of the procedure. It should be noted, however, that this rule permits the addressing of a procedure by more than one DO command" (F p. 50). Also: "a section of procedure that is addressed by a DO becomes a closed subroutine; it can be entered only through the use of one or more DO commands" (F p. 57).
- J enforces the entry half of this rule diagnostically: flowing into a DO-addressed name is a "PROBABLE PROGRAM CONTINUITY ERROR" (99,00); a GO TO to a DO-addressed name is bypassed (128,00); PROGRAM.START may not be DO-addressed (143,00); and the DO target must exist: "'NAME.1', ADDRESSED BY A -DO-, IS NEITHER A STATEMENT NOR A SECTION NAME." (188,00) (all J 90.04.01).
- Exits out of a DO'd procedure: neither manual states a rule against a GO TO that leaves a DO'd procedure for a target outside it, and the J sample program does exactly that: inside DO-addressed SEARCH,
... GO TO NET.transfers permanently out of the section (and out of the activeDO SEARCH FOR INDEX = 1(1)12loop) into the main body (J 90.05, listing PDF pp. 196–197); the DO'd sentence END.OF.MASTERS likewise executesGO TO END.OF.RUNout of its DO (J 90.05, listing PDF p. 196). The pending return linkage is simply abandoned. See the ambiguities register. - The normal completion of a DO'd sentence, or execution of the END sentence of a DO'd section, returns control "to the command following the DO instruction" (F p. 33) / "to the sentence or clause following the DO" (F p. 50).
- A DO may appear as one clause among others in a sentence, including inside IF arms:
IF CURRENT.DEPT IS NOT EQUAL TO D.DEPT THEN DO DEPARTMENT.END OTHERWISE GO TO COMPUTE.PAY.andEND.OF.RUN. DO DEPARTMENT.END, MOVE CORRESPONDING ... , CLOSE ALL FILES, STOP RUN.(J 90.05, listing PDF pp. 195–196). GET's AT END phrase may also invoke DO:GET MASTER, AT END DO END.OF.MASTERS.(J 90.05, listing PDF p. 195), but note the J restriction that "The AT END clause ... may consist of a single imperative statement only" (J 02.07.05) and message 106,00 "STATEMENT OR SECTION NAME MUST FOLLOW -AT END-." (J 90.04.01); see the Input/Output section. - Manuals are silent on DO-from-within-a-DO'd-procedure (nested calls) and on recursion; the sample program only issues DOs from the main body. See open questions.
5.6 The STOP command; STOP RUN
F form:
STOP n
(F p. 54): "where n is an integer. The number n will be displayed when the command is executed, i.e., when the machine halts. Restarting the machine causes execution of the object program to be resumed beginning with the next command in sequence. For a 'dead-end' halt, an unconditional GO TO command placed immediately following the STOP can be used to effect a transfer back to the STOP command" (F p. 54). (F p. 25 also shows the bare example sentence STOP. with no operand, and the F payroll example uses STOP 1234. (F pp. 92, 101, Appendix 1); see ambiguities.)
J forms and semantics: the STOP display subroutine SYS)178 records "the Statement Number of the Stop (in BCD), and the type of STOP (STOP NNN or STOP RUN)" (J 90.02.14). At execution (J 05.06.04):
- "STOP nnnnnn where nnnnnn is any number 6 digits or less. The computer will stop, and hitting the START key will cause the object program to continue in execution. (It is hoped that the programmer uses this instruction sparingly, if at all)."
- "STOP RUN — This message means that object-time processing of the job is completed and control has returned to the CTM supervisor."
- "The STOP messages will be accompanied by the source language statement number at which the STOP occurred, i.e. AT xxxxx,yy STOP nnnnnn where xxxxx,yy is the statement number" (J 05.06.04). The field-test processor prints DISPLAY/STOP messages on the on-line printer (J 05.06.04).
STOP RUN is mandatory in J: "A STOP RUN instruction must be included in each program to provide for transfer of control to the CT Supervisor at conclusion of execution of the object program. All open files are closed prior to this transfer of control as if a CLOSE ALL FILES had been supplied" (J 02.04.06, "9. STOP RUN"). Diagnostic: "NO -STOP RUN- IN PROGRAM." (J 90.04.01, message 175,00). Files closed by CLOSE ALL FILES (hence by STOP RUN) "may not be subsequently reopened by the program" (J 02.04.06, "8. CLOSE ALL FILES"). Sample usage: CLOSE ALL FILES, STOP RUN. (J 90.05, listing PDF p. 196).
F/J divergence: F has only STOP n (halt-and-resume); STOP RUN (normal program termination returning control to the supervisor) is a J addition (RUN is reserved in J: key-word list J 02.03.02; message 2,00 "-RUN- DELETED. ITS USE IS RESTRICTED TO PROCESSOR."). J bounds n at 6 digits (J 05.06.04); F gives no bound.
5.7 Sections, procedure-names, and structural constraints on transfer targets
Control transfers are defined in terms of named sentences and sections, so the sectioning rules are part of control flow:
- "A section consists of one sentence, or a group of successive sentences, which has been given a name ... Sectioning, in the Commercial Translator, is used for the purpose of naming portions of procedure" (F p. 26). "Unless BEGIN SECTION and END are used, a procedure-name applies only to the sentence which follows it" (F p. 56).
procedure.name. BEGIN SECTION.
any sentence.
.
.
.
any sentence.
END procedure.name.
(F p. 57)
- "The beginning of a section must be identified by a procedure-name, followed by a period. The name must then be followed by the words BEGIN SECTION ... Following the last sentence in the routine, the programmer must write the word END, followed by the procedure-name used originally" (F p. 26).
- Nesting: "Sections may be 'nested,' that is, one or more sections may be contained within a larger section, but each such section must be wholly contained—it cannot overlap another section" (F p. 26; nesting diagram F p. 57). J enforces proper nesting: "CANNOT -END- SECTION WHEN NONE ARE OPEN." (64,00); "CANNOT -END- SECTION 'NAME.1' BEFORE SECTION 'NAME.2'." (65,00); "ONE OR MORE SECTIONS NOT CLOSED." (66,00); "-END- SECTION MUST BE THE ONLY CLAUSE IN THE SENTENCE." (179,00) (all J 90.04.01).
- The END sentence is normally unnamed; the single exception is the named END of a DO'd procedure (F p. 57; §5.5.4).
- "Where necessary, the names of sections can be used as parts of compound names" (F p. 26). J qualifies name uniqueness by section: "'NAME.1' IS NOT UNIQUE IN THIS SECTION." (J 90.04.01, message 166,00); but a record defined within a section may not use the section.name as qualifier (J 90.01.03). Sections may contain data as well as procedure: "A record is a data hierarchy which may not be part of any data organization except a file or a section" (J 02.05.01); see §3 (Data description and storage model).
- The commands that "take advantage of" sections are DO, LOAD and OVERLAP (F p. 57). LOAD and OVERLAP are deferred in J: "Implementation of these verbs has been deferred" (J 90.01.03) and "programs may not be segmented into separate memory loads at this time" (J 90.01.05, Loader item B.2), so their control-flow behavior (F pp. 54–56: initial loading includes all non-overlapped parts plus the first procedure of each OVERLAP; loading does not execute — a GO TO or DO must transfer control; a LOAD must not appear within the procedure it obliterates; overlapped procedures should end in an unconditional GO TO) is F-only, unimplemented language.
- Sections in generated code: section numbers begin with 0 for the main body and increase by 1 for each BEGIN SECTION; result-storage cells are section-qualified (J 90.02.03).
- CONTRL areas (multiple-deck combination; mechanization deferred, J 90.01.04): "Indices inside a CONTRL area must not be referenced or modified outside of that area in any of the programs to be merged" (J 02.06.16).
- Control-flow-relevant reserved words: always-key words include BEGIN, FOR, IN, ON, WHEN (J 02.03.02, list 1); never usable as data/procedure names include DO, GO, IF, THEN, OTHERWISE, STOP, RUN, SECTION, END, EXACTLY, TIMES, USING, GIVING, NOT, AND, OR, GT, LT, IS, GREATER, LESS, THAN, EQUAL, EQUALS, TR (J 02.03.02, list 2; F p. 110). F's full word list is at F p. 110.
5.8 Numeric limits and restrictions bearing on control flow (J)
| Item | Limit / rule | Citation |
|---|---|---|
| Operators per sentence | max 60, sentence deleted if exceeded | J 90.04.01 (171,00) |
| Conditional expression tests per expression | internal capacity; "rewrite as two or more separate expressions" | J 90.04.01 (187,00) |
| Number of SECTIONS | approx. max 35 | J 90.01.05 |
| Depth of nested sections | approx. max 18 | J 90.01.05 |
| Number of index expressions (a * VARIABLE ± b) | approx. max 50 | J 90.01.05 |
| Number of positional indicators (unique array+subscript combinations) | approx. max 90 | J 90.01.05 |
| Internal dictionary (all names, programmer + generated) | approx. max 3500 | J 90.01.05 |
| Generated constants in constant pool | approx. max 500 | J 90.01.05 |
| DO loop body executions | always at least once, regardless of loop-control values | J 90.01.02 |
| DO indices per command | max 3; rightmost varies fastest | F p. 51 |
| Assigned GO TO index | integer 1..n, else fall through | F p. 49 |
| Subscript range at object time | no object-time check against array dimensions | J 90.01.02 |
| Array origin | A(1), not A(0) | J 02.04.07.01 |
| STOP operand | ≤ 6 digits | J 05.06.04 |
| STOP RUN | required once per program; implies CLOSE ALL FILES | J 02.04.06; 90.04.01 (175,00) |
| Procedure-name length | 1–30 characters, followed by period + blank | F p. 37 |
| Statement numbering | xxxxx,yy: line , clause | J 02.02.01 |
| Severity codes | 1 = still runnable; >1 no compile-and-go; 5 stops compilation, no deck | J 90.04.02; J 02.01.01 |
| INCLUDE (library procedures) | deferred; no library facilities | J 90.01.02 |
| LOAD / OVERLAP (segmentation) | deferred | J 90.01.03; 90.01.05 (B.2) |
| PARAM / FUNCT type codes | "no longer in the language" (USING/GIVING remain) | J 02.05.03 |
| AT END clause | single imperative statement only; must name a statement/section | J 02.07.05; 90.04.01 (106,00) |
5.9 Flagged ambiguities (summary)
The following points, developed above, are recorded in full in the ambiguities register accompanying this document: (1) the DO ... FOR equality-termination test and non-reaching step values; (2) the "index.name.1 is set to p.1 + q.1" wording in the two-index DO; (3) the phrase "tests for NOT greater or less conditions" in the unequal-length comparison rule; (4) legality/semantics of GO TO out of a DO'd procedure; (5) bare STOP. vs STOP n; (6) whether an object-time range check is generated for the assigned GO TO; (7) the undocumented PROGRAM.START facility; (8) the reserved word EQUALS; (9) SET condition.name in J; (10) nested/recursive DO.