Description
While implementing semantic analysis I noticed a conceptual problem with the order-independence approach of cpp2. Consider this code here:
foo: (x : int = bar()) -> int = { return 3*x+1; }
bar: (x : int = 2) -> int = { return x/2; }
main: () -> int = { return foo(); }
cppfront happily accept that code, but it then fails in C++ because the order of forward declarations is wrong. Swapping the order of foo and bar fixes that problem. (Modulo another bug that the default argument is repeated at the declaration site, which also makes the C++ compiler unhappy).
One question is, what should the intended semantic be? Can default arguments reference functions that are further down in the translation unit? Intuitive, if we fully bet on order-independence, the answer should be yes. On the other hand implementing that is actually quite subtle. Note that it is not always possible find a topological order, for example here:
foo: (x : int = bar()) -> int = { return 3*x+1; }
bar: (x : int = foo()) -> int = { return x/2; }
main: () -> int = { return foo(); }
Clearly that must trigger an error. We could detect this cyclic dependency, but it increases the complexity of the compiler. Another question is, is the compiler required to analyze default arguments if they are never evaluated? If not, we could simply translate them lazily on demand and check for cycles during expansion. (Though lowering that to C++ will be nightmare, this approach will only work of default arguments are expanded by cppfront itself and not by the underlying C++1 compiler).
Note that we will have exactly the same problem with auto
return types. These also require analyzing the function itself, which might depend on other functions further down.
I see basically two options. Either we forbid this, requiring that functions are defined before they are used as default arguments or with auto return types. Or we make function analysis lazy, which requires the compiler to topological order functions according to their dependencies, producing an error if that is not possible.