Namespaces
namespace Foo {
int x = 0;
int f() { return x; }
}
As in C++, namespaces are used to avoid name clashes in code. For example: declares an integer named Foo::x and a function named Foo::f. Note that within the namespace, you don’t need to use the qualified name. For instance, Foo::f refers to Foo::x as simply x. We could also simply write “namespace Foo;” (note the trailing semi-colon) and leave out the enclosing braces. Every declaration (variables, functions, types, typedefs) following this namespace declaration would be placed in the Foo namespace.
As noted before, you can refer to elements of a namespace using the “::” notation. Alternatively, you can open up a namespace with a “using” declaration. For example, we could follow the above code with:
namespace Bar {
using Foo {
int g() { return f(); }
}
int h() { return Foo::f(); }
}
Here, we opened the Foo namespace within the definition of Bar::g. One can also write “using Foo;” to open a namespace for the remaining definitions in the current block.
Namespaces can nest as in C++.
Currently, namespaces are only supported at the top-level and you can’t declare a qualified variable directly. Rather, you have to write a namespace declaration to encapsulate it. For example, you cannot write “int Foo::x = 3;.”
The following subtle issues and implementation bugs may leave you scratching your head:
The current implementation translates qualified Cyclone variables to C identifiers very naively: each :: is translated to _ (underscore). This translation is wrong because it can introduce clashes that are not clashes in Cyclone, such as in the following:
namespace Foo { int x = 7; } int Foo_x = 9;
So avoid prefixing your identifiers with namespaces in your program. We intend to fix this bug in a future release.
Because #include is defined as textual substitution, the following are usually very bad ideas: Having “namespace Foo;” or “using Foo;” at the top level of a header file. After all, you will be changing the identifiers produced or the identifiers available in every file that includes the header file. Having #include directives within the scope of namespace declarations. After all, you are changing the names of the identifiers in the header file by (further) qualifying them. Unfortunately, the current system uses the C pre-processor before looking at the code, so it cannot warn you of these probable errors.
In short, you are advised to not use the “semicolon syntax” in header files and you are advised to put all #include directives at the top of files, before any namespace or using declarations.
The translation of identifiers declared extern “C” is different. Given
namespace Foo { extern "C" int x; }
the Cyclone code refers to the global variable as Foo::x, but the translation to C will convert all uses to just x. The following code will therefore get compiled incorrectly (f will return 4):
namespace Foo { extern "C" int x; } int f() { int x = 2; return x + Foo::x; }