(Note: This is something of a companion to my question about closures over goto labels. I believe that the answer to this question will be useful in solving the other problem.)
In C, it is perfectly legal for a goto statement to transcend scopes, as demonstrated in this question:
int cond(void);
void use(int);
void foo()
{
{
int y;
label:
y = 2;
use(y);
}
{
int z = 3;
use(z);
/* jump to sibling scope: */ if(cond()) goto label;
}
/* jump to inner scope: */ if(cond()) goto label;
}
In contrast, code like that is not permitted in Algol 60 or Algol 68, and probably in other languages. (Algol 60 allows jumps into compound statements, but not into blocks.)
How should such jumps be implemented? In my language, entry into a block creates a new stack frame; it is convenient to treat block activation and procedure calls identically, since blocks also return a value, like closed-clauses in Algol 68 or Common Lisp's progn. Thus a transfer into a block requires creating frames for any levels between the current one and the target of the transfer. On the other hand, a transfer to an outer scope is simple, requiring only that the stack be unwound to a certain level. (And a transfer within the same scope is, of course, trivial.)
Suppose that we are generating byte code for a traditional stack-based virtual machine.
Here is an example:
begin
integer x, p;
p := 10;
x := 20;
go to label;
begin
integer y;
y := begin
integer q;
label:
q := x + 2;
p + q;
end;
end;
end;
This should assign p + q (i.e., 32) to x.