Conditional Compilation
Note: Feature is as of yet TBD.
Syntax isn’t finalized, but there are a few main options.
The first is to have the lexer handle it, in a syntax (but not semantics) similar to the C preprocessor. Note that this is not a preprocessor, and especially not a C one. For example, conditional compilation is based on actual variables, and is not an arbitrary text/token replacement system. Likewise, function macros will not be supported, allowing a single pass over the entire source. I believe C# uses a similar system?
#if OS.Windows >= v`6.0` // 6.0 is Vista
import windows.foo;
#else
import posix.bar;
#endif
// note that unlike a C preprocessor, this does *not* affect the rest of the code:
var x = OS; // ERROR: variable `OS` does not exist
var y = debug.defines["OS"]; // if we really want it (e.g. for debugging), we can access it (exact module TBD)
A second approach is to instead do it in the parser. Note that this implies that even the “non-compiled” path must parse successfully — which removes the possibility of using this approach for syntactic extensions (not the worst downside ever, though).
// note: does not create a new scope (unlike e.g. `if`)
version(OS.Windows >= v`6.0`)
import windows.foo;
else
import posix.bar;
A third option, which is also the most powerful one, would be a system that allowed arbitrary compile-time execution. It does, however, create a chicken-and-egg problem with imports (needing separate imports for compile-time) and further complicates matters. In the example, compile-time statements are prefixed with #
(but could use some different syntax):
#import platform.os;
#if(OS == "Windows" && OS.version >= v`6.0`)
module.imports.add("windows.foo");
#else
module.imports.add("posix.bar");
// using compile-time execution to generate a lookup table
ubyte[] CRCLookupTable = #generateCRC8Lookup();