In computer programming, COMEFROM is an obscure control flow structure used in some programming languages, originally as a joke. COMEFROM is the inverse of GOTO in that it can take the execution state from any arbitrary point in code to a COMEFROM statement. The point in code where the state transfer happens is usually given as a parameter to COMEFROM. Whether the transfer happens before or after the instruction at the specified transfer point depends on the language used. Depending on the language used, multiple COMEFROMs referencing the same departure point may be invalid, be non-deterministic, be executed in some sort of defined priority, or even induce parallel or otherwise concurrent execution as seen in Threaded Intercal. A simple example of a "COMEFROM x" statement is a labelx that acts as a "trap door". When code execution reaches the label, control gets passed to the statement following the COMEFROM. This may also be conditional, passing control only if a condition is satisfied, analogous to a GOTO within an IF statement. The primary difference from GOTO is that GOTO only depends on the local structure of the code, while COMEFROM depends on the global structure – a GOTO transfers control when it reaches a line with a GOTO statement, while COMEFROM requires scanning the entire program or scope to see if any COMEFROM statements are in scope for the line, and then verifying if a condition is hit. The effect of this is primarily to make debugging extremely difficult, since there is no indication near the line or label in question that control will mysteriously jump to another point of the program – one must study the entire program to see if any COMEFROM statements reference that line or label. Debugger hooks can be used to implement a COMEFROM statement, as in the humorous Python goto module; see below. This also can be implemented with the gcc feature "asm goto" as used by the Linux kernel configuration option CONFIG_JUMP_LABEL. A no-op has its location stored, to be replaced by a jump to an executable fragment that at its end returns to the instruction after the no-op.
The following is an example of a program in a hypothetical BASIC dialect with "COMEFROM" instead of "GOTO". 10 COMEFROM 40 20 INPUT "WHAT IS YOUR NAME? "; A$ 30 PRINT "HELLO, "; A$ 40 REM
This program works by asking the user for their name, greeting them with the same name, and continuing all over again. The instruction "REM" on line 40 is simply a NOP — the "COMEFROM" statement on line 10 causes a branch back to that line when execution reaches line 40, regardless of its contents. A fully runnable example in Python with the joke goto module installed looks like this: from goto import comefrom, label comefrom.repeat name = raw_input if name: print label.repeat print
This is an implementation in Ruby of the Intercal COME FROM statement. $come_from_labels = def label if $come_from_labels $come_from_labels.call end end def come_from callcc do |block| $come_from_labels = block end end
OS/360 Fortran G
The OS/360 Fortran G compiler has a debug packet feature. Its "AT" statement is similar to COMEFROM in that it hands the control flow over to the debug block. Breakpoints in general are similar.
Example 1: the values of SOLON, GFAR, and EWELL are examined as they were at the completion of statement 10. The AT statement indicates statement 11.
INTEGER SOLON, GFAR, EWELL . . . 10 SOLON = GFAR * SQRT 11 IF 40, 50, 60 . . . DEBUG UNIT AT 11 DISPLAY GFAR, SOLON, EWELL END
Example 2: all the values of STOCK are displayed when statement 35 is encountered.
DIMENSION STOCK,OUT . . . DO 30 I=1, 1000 25 STOCK=STOCK - OUT 30 CONTINUE 35 A = B + C . . . DEBUG UNIT AT 35 DISPLAY STOCK END
Example 3: tracing begins at statement 10, at statement 20, tracing stops while the loop is executed, and resumes after the loop. Tracing stops just before statement 30 is executed.
10 A = 1.5 12 L = 1 15 B = A + 1.5 20 DO 22 I = 1,5 . . . 22 CONTINUE 25 C = B + 3.16 30 D = C/2 STOP . . . DEBUG UNIT, TRACE C DEBUG PACKET NUMBER 1 AT 10 TRACE ON C DEBUG PACKET NUMBER 2 AT 20 TRACE OFF DO 35 I = 1,3 . . . 35 CONTINUE TRACE ON C DEBUG PACKET NUMBER 3 AT 30 TRACE OFF END