# Goto and Compile

Clear[sum];
sum = Compile[{{n0, _Integer}, {s0, _Integer}},
Block[{n = n0, s = s0},
Label["t"];
If[n > 0, s += n; n--; Goto["t"]];
s
]
];

sum[10, 0]


It seems that the Label is not found. How to make it works?

• The issue appears to relate to compile as the non-compiled function works without problem: sumnc[n0_, s0_] := Block[{n = n0, s = s0}, Label[t]; If[n > 0, s += n; n--; Goto[t], s]]; sumnc[10, 0] The last line yields 55 I look forward to clarification from the experts. – ubpdqn Nov 3 '13 at 11:51
• possible duplicate of Using Goto and Label in compiled function? – Sjoerd C. de Vries Nov 3 '13 at 12:00
• I retract my close as duplicate vote as the linked question is strongly related, but the issue is slightly different in this case (see my answer). – Sjoerd C. de Vries Nov 3 '13 at 12:21

It looks like the compiler has troubles when Goto appears as a compound statement in If. It causes a call to MainEvaluate for this part of the code which, as shown here, means calling a labelled Goto where the compiler already removed the Label.

Needs["CompiledFunctionTools"]

CompilePrint[sum]

2 arguments
1 Boolean register
9 Integer registers
Underflow checking off
Overflow checking off
Integer overflow checking on
RuntimeAttributes -> {}

I0 = A1
I1 = A2
I7 = 1
I5 = 0
Result = I4

1   I2 = I0
2   I4 = I1
3
4   B0 = I5 < I2
5   if[ !B0] goto 8
6   V17I2I4 = MainEvaluate[ Function[{n0, s0, nCompile$22, sCompile$23},
Block[{n = nCompile$22, s = sCompile$23},
{s += n; n--; Goto[t], n, s}]][ I0, I1, I2, I4]]
7   goto 8
8   Return


If you rewrite it to move the compound statement out of the If:

Clear[sum];
sum = Compile[{{n0, _Integer}, {s0, _Integer}},
Block[{n = n0, s = s0},
Label["t"];
If[n <= 0, Goto["end"]];
s += n; n--; Goto["t"];
Label["end"];
s]];

sum[10, 0]


55

it works as intended.

• I just noted that @LeonidShifrin's deleted answer in the question I referred to seems to say something to the same extent. In short, anything that causes the part of the code that contains Goto to generate an MEvaluate call will fail. That could be a non-compilable Print as in the other question, but also apparently CompundExpression with Goto as is the case here. – Sjoerd C. de Vries Nov 3 '13 at 12:27

Sjoerd's answer already gives the solution. Let me try to dig a bit deeper. In the Details section of the Goto documentation one finds

Goto first scans any compound expression in which it appears directly, then scans compound expressions that enclose this one.

This suggests to me that Goto only works iff the Label is in the same CompoundExpression or in an enclosed one. If we look at a simplified version of the OP's code we see

Hold[(Label[t];
If[True,
Goto[t];
];
s)] // TreeForm


that CompoundExpression containing the Goto is not enclosed by another one. It is enclosed by an If expression. Sjoerds solution circumvents this by eliminating the CompoundExpression inside the If thus leaving outer CompoundExpression as first reachable one.

Hold[(
Label["t"];
If[True, Goto["end"]];
Goto["t"];
Label["end"])] // TreeForm


Unfortunately, this is not the end of the story. It seems that with Compile exactly this "scan for the next enclosed CompoundExpression" does not work correctly. Let's take one very simple example

Hold[(1; Goto["end"]; 2; Label["end"]; 3)] // TreeForm


If one compiles this code, it will work as expected: no MainEvaluate. Although, if you nest the CompoundExpression by simply using some parenthesis

Hold[((1; Goto["end"]); 2; Label["end"]; 3)] // TreeForm


The code will not compile. This leaves only one conclusion: Be careful when you work with Goto and Compile`, it might not work as expected.