On Wed, Sep 2, 2009 at 3:29 PM, Don<[email protected]> wrote: > Michiel Helvensteijn wrote: >> >> Rainer Deyke wrote: >> >>>> I still find it silly that it was built that way. Seems to me you should >>>> be able to forward-reference *any* symbol that has a value that can't >>>> change over its lifetime. Functions, const/immutable vars, typedefs, >>>> classes, etc. >>> >>> That can lead to subtle problems in the case of functions: >>> >>> int i = f(); >>> int f() { return i; } >> >> You're right, I forgot about that. You can conservatively statically >> forbid >> this. But I admit it makes the 'constant data should obviously be >> forward-referenceable' thing less convincing. :-) >> > I can't see how it can be done in the general case, other than by > constructing a dependency tree of top-level symbols. > Pass over the tree, evaluating everything which is a leaf of the tree. > If you have a pass where you don't succeed in removing any leaf nodes, you > have a circular dependency. > DMD sort of does this, I think, but it only does two passes, and it's not > very good at backing out when it discovers something is not a leaf. > It'd be hard to make that efficient when there are potentially infinite > passes.
It wouldn't even be that difficult. Basically if you treat forward-referenced nested functions as a sort of goto, the same rules should apply: a call to a nested function may not skip the initialization of any variables it depends on. When i's initializer is evaluated, it has not been declared yet, so the call to f is illegal. It also prevents other invalid use.
