No, you emit all the code in one go, then after you've done that you have some residual pieces of data left one the side: the symbol table, and the list of all the calls of (hopefully)-forward-declared functions. At this point you could run the check on that list against the symbol table, no additional codegen or re-reading the source text needed.
Granted, you can call that a second pass although that's not that different from emitting a function's epilogue IMHO.
There is no need for the second phase. You can record the implicit declaration when you encounter it, and if there is a subsequent declaration, you can check that it's consistent or error out immediately.
This is what C compilers already do, in fact, to produce warnings when an implicit declaration doesn't match a later explicit declaration. But this is a best-effort warning only; it doesn't work if there is no declaration because the function is defined in a different translation unit, as I pointed out above.
Usually, the second pass in a compiler does not re-parse source files. Rather, it operates on another data structure, like an AST, intermediate representation, or the list mentioned in the original comment. At least, that’s my understanding of multi-pass compilation.
Well, this "list mentioned in the original comment" is not an AST or an immediate representation of the program in any reasonable sense just as a symbol table is not. Otherwise, setting the exact values of the text/data/bss size fields in the executable file header's at the end of the compilation would count as the second pass as well which IMO it should not.
The difference is that you need to make a complete second iteration (or pass) over the entire list to correctly check all of the callsites after all function type information is collected. The same is not true for symbol table usage in a single-pass C compiler.
What's fascinating to me is that index cards are a kind of spiritual predecessor to modern database systems and computers - perhaps even more closely related than counting devices like the abacus. Richard Feynman touches on this in one of his lectures [1] that's been linked many times on HN.
The theory of information and computing seems pretty fundamental, and not necessarily tied to what we typically think of as a computer, with CPUs, RAM, SSDs, etc. In a way, a card catalog full of index cards and run by a bunch of people is a computer too. Maybe this isn't an incredible revelation, but it's still interesting to think about.
Using the delta between frames directly isn't quite right either, but it's better than writing framerate-dependent code. I think an even better way is to use an accumulator with a fixed time step, as described here: http://gafferongames.com/game-physics/fix-your-timestep/
I created http://jogolang.org, mostly because I was interested in learning how compilers worked. I was also motivated by the lack of simple, type-safe, ahead-of-time-compiled programming languages for writing video games. Now the project is kind of dead, but I certainly learned a lot about parsers, code generation, optimizations, SSA, and register allocation!
I think Frodo's failure to destroy the ring is a good example of how Tolkien's books do not have a simple good vs. evil dichotomy. Other good examples are the wrath/pride of Feanor's sons, and the tale of Turin, both from the Silmarillion.
Tolkien has a very Christian good / evil dichotomy. And Frodo at the cracks of doom fits right in.
In this scheme, we mortals are not able to save ourselves, only God can do that. In Frodo's case, Gollum turned out to be Gods instrument. But first Frodo had climb the mountain before that could happen.
> I think Frodo's failure to destroy the ring is a good example of how Tolkien's books do not have a simple good vs. evil dichotomy.
I think its an example of how the focal characters are imperfect, but I don't think it shows that there isn't a simple good v. evil dichotomy in the books; I mean, there's no ambiguity that destroying the ring was the one correct course of action and that Frodo was falling short of it.
I like 'xIs' for mutators, because it reads more like English, and the important part of the name ('x') is first. I find that convention makes it easier to scan code by name and sort.