Older versions of C had the restriction that variables could only be declared at the start of a block. Supposedly this was due to the original C compiler being one-pass. It's easier to keep track of the size of the stack frame if you see all declarations in one place. Though I think with a frame pointer you could make it work anyway. You have essentially the same complications if you allow programmers to open a block anywhere and declare variables there. I don't know if the very first versions of C allowed this.
Maybe more exotically, here is a legal Haskell program:
compute = f x y
x = 3
y = 4
f = (+)
Using typed identifiers before they are declared would not be possible in a single-pass compiler. You wouldn't know what code to emit for compute since you wouldn't even know its type until you have seen the definitions of x, y, and f.
Interestingly, this restriction does not apply to goto labels, which you can use first and define later: The compiler can just emit the label as written into the assembly code and let the assembler worry about patching up the jump target.
> Interestingly, this restriction does not apply to goto labels, which you can use first and define later: The compiler can just emit the label as written into the assembly code and let the assembler worry about patching up the jump target.
A one-pass compiler can manage this by maintaining a mapping of undefined labels to a list of goto statements that refer to them. Once the definition is located, unwind the list and fill in the jump values. Types are trickier because the size is unknown.
There is no way to "fill in the jump values" if you have already emitted the goto to a place you can't modify later. Like the featured article does, emitting its code with printf. I agree that you could emit code to an intermediate buffer, fix it up later, and still call this (a slightly more relaxed version of) one-pass compilation.
>Older versions of C had the restriction that variables could only be declared at the start of a block.
Pascal also has that restriction
Although Delphi does not have it anymore. But FreePascal still has it, even in Delphi compatible mode. The FreePascal developers have also said, they will keep that restriction to improve readability. The code could not be read anymore if variables were placed willy-nilly everywhere
I’ve heard the readability justification for C restriction, but it doesn’t make sense: this prevent ´constification’ of variables (make the variable contains only one value)..
Maybe more exotically, here is a legal Haskell program:
Using typed identifiers before they are declared would not be possible in a single-pass compiler. You wouldn't know what code to emit for compute since you wouldn't even know its type until you have seen the definitions of x, y, and f.Interestingly, this restriction does not apply to goto labels, which you can use first and define later: The compiler can just emit the label as written into the assembly code and let the assembler worry about patching up the jump target.