1: include "std"; 2: val top = 1; 3: module A { 4: val a = top + 1; 5: module B { 6: val b = a + 1; 7: } 8: } 9: 10: print top; endl; 11: print root::top; endl; 12: print A::a; endl; 13: print A::B::b; endl;
You can put anything except export declarations in modules that you can put at the top level, and for a very simple reason: the top level is, in fact, a module itself.
When a qualified name is used, the qualifier specifies the module in which the next name must be found. Qualification inhibits upscope overloading.
Note the name 'root' is used to name the top-level module, in lieu of the actual module name, which is derived from the basename of the filename.
Finally, it is vital to understand that Felix scopes act like sets of names. Names are always defined in parallel, and visible to all definitions in the scope, so that all definitions are mutually recursive. For this reason, forward declarations are never needed. The following example is quite legal:
x = 1; y = x; var y:int; var x:int;This is much like the 'rewriting rule' for C++ class member functions. Note, however, that executable code is still sequential! Thus, the order of value and variable definition does matter: initialisations are executed in order of writing.