Are Preprocessor Directives Indentation Sensitive in F#? - f#

FSI version: 11.0.50727.1
So I was working on an F# shell script and I ran across something that sort of surprised me.
When I did this:
#if INTERACTIVE
#r "System.Data.dll"
#r "FSharp.Data.TypeProviders.dll"
#r "System.Data.Linq.dll"
#endif
open System
I got an FS0010 error when I pasted the block into the FSI. But if I did not indent the #r lines, no FS0010 error. I'm just sort of surprised that preprocessor lines would be indentation sensitive. Is this a compiler issue or is there something else at work here?

I think the specification and documentation are quite unclear on this topic, but the specification makes a notable distinction between lexical preprocessor directives and compiler directives (see §12.4):
Compiler directives are declarations in non-nested modules or namespace declaration groups in the following form:
# id string ... string
The lexical preprocessor directives #if, #else, #endif and #indent "off" are similar to compiler directives. For details on #if, #else, #endif, see §3.3. The #indent "off" directive is described in §18.4.
My interpretation is that lexical preprocessor directives are actually hanled by some pre-processor before running the main compilation and so the indentation does not matter for these.
On the other hand, directives like #r, #load, #time etc. are processed later by the compiler and so they need to match the usual F# indentation guidelines.
As #unwind says, the documentation states "Indentation is not significant for preprocessor directives", but I think this applies only to the preprocessor directives listed on that documentation page (which are lexical preprocessor directives and not compiler directives).

According to the documentation, it must be something else at work:
Indentation is not significant for preprocessor directives.

Related

Clang libtooling: how to print compiler macro definitions

I have a LibTooling based utility and I would like to output a list of macro definitions for debug purposes. One can print compiler macro definitions with clang/gcc -dM -E -, but it does not seem to work if I pass -dM -E or -dD to ClangTool. Is it possible to do so with LibTooling API or CLI options in any way? It does not matter if it will include macros defined in a parsed source code or not.
I've looked at other similar questions, and as far as I can tell they all are about macros expanded in a parsed source code. That's not exactly what I need.
The answer is blindingly obvious—in retrospect. clang::Preprocessor::getPredefines() returns just that—a list of compiler predefines. The preprocessor object can be obtained e.g. from clang::CompilerInstance, as an argument in clang::DiagnosticConsumer::BeginSourceFile(), etc.
Just for the sake of completeness, this functionality is not available via libclang API, but I could do that using the fact that all predefines are present in the beginning of a translation unit. So after parsing I just listed all top-level cursors of CursorKind.MACRO_DEFINITION that are not in any real location (location.file is None using python bindings notation)

How to check if a Decl is inside a scope of #if directive?

i am building a clang libtool,
how can i get the preprocessor information that will tell me if a given Decl is inside a scope of #if #ifdef #ifndef ?
There's no easy answer for this unfortunately. Clang isn't fully aware at an AST level of any preprocessor directives.
The best you can do to the best of my knowledge is to implement a PPCallbacks class, register it with the compiler instance preprocessor and implement the functions for If, Elif, Endif.
Then you can use a ASTVisitor to find everything in between those Source locations.

Defining preprocessor symbols for CLion analyzer

In my project there's a file enclosed in an ifdef preprocessor directive
#ifdef SOME_SYMBOL
... entire file ...
#endif
SOME_SYMBOL is defined by another file that's compiled before this one, and the code works as expected, but the static analyzer isn't aware of this symbol and so it treats SOME_SYMBOL is undefined. The entire file has no syntax highlighting and some of the analysis is just skipped (e.g. syntax error highlighting).
Is there a way to tell the analyzer to treat this symbol as defined without defining it in CMakeLists.txt?
I don't have the option of defining SOME_SYMBOL in CMakeLists.txt since the project depends on it being undefined in some compilation paths (changing this would be near impossible).
Update:
Seems like this is currently an open issue with JetBrains. See Issue CPP-2286
Clion now has a macro which you can use to detect the IDE:
https://youtrack.jetbrains.com/issue/CPP-1296#comment=27-1846360
#ifdef __JETBRAINS_IDE__
// Stuff that only clion will see goes here
#endif
This allows you to put in defines to make clion render your code properly in cases where it can't be clever enough to figure it out.
The __JETBRAINS_IDE__ macro's value is a version string for the IDE. Specific versions of the macro exist for different Jetbrains IDEs: __CLION_IDE__, __STUDIO_IDE__ (for Android Studio), and __APPCODE_IDE__ (for AppCode).
Yay!
To get syntax highlighting:
Go to Settings ⇒ Editor ⇒ Colors&Fonts ⇒ C/C++ and remove all ticks for 'Conditionally non-compiled code'. This way all code will show up with the usual highlighting.
The task has no solution for common case.
But! You can find the target and related resolve context, where SOME_SYMBOL is defined.
...in the status bar you can find the Resolve Context chooser for switching between the Debug, Release, RelWithDebInfo and MinSizeRel contexts to resolve your code in the IDE with the desired definitions.

Can I undefine a conditional in the command line?

In the help of Delphi 7 command line compiler, I just see an option to define a conditional compiling directive:
-D<syms> = Define conditionals
Is it possible to undefine a conditional?
I have defined DEVELOPMENT in the IDE, and want to have define just PRODUCTION in the command line compiler. The problem is that the command line compiler keeps the IDE definitions. I'd like just to undef it as is possible in the C world.
If you don't come up with a command line option, you can always add additional conditionals in your units or include file like this:
{$DEFINE FOO}
// Allow us to undefine foo at the command line by defining UNDEFFOO
{$IFDEF UNDEFFOO}
{$UNDEF FOO}
{$ENDIF}
{$IFDEF FOO}
...
{$ENDIF}
Then use -D to set UNDEFFOO.
You can use {$UNDEF NAME} to undefine a symbol, equivalent to #undef in C and C++. The facility to undefine a conditional is only applicable at a unit level and cannot be applied project wide. In other words you cannot unset conditionals at the command line. This is no different from the facilities offered by C or C++ toolsets.
A very common approach is to locate all your conditional definitions in a shared .inc file which is then included at the head of every source file that relies on those definitions. If you arrange things this way then you have all the flexibility that you need.
I know it will be of little consolation, but more recent Delphi versions have much stronger support for configuration management. Modern Delphi versions make use of the msbuild system. They allow the same configuration options to be used in the IDE and on the command line. There is flexibility to define, for example, debug and release build options and switch between them easily. I know I find it a great reassurance to know, for sure, that I am using the same build in the IDE as on the command line. I did not feel anywhere near so secure in legacy Delphi versions.

Preprocessor directives supported by the RIM compiler

This isn't really clearly documented, but a shallow search reveals that RIM's RAPC compiler does support preprocessor statements (with some project file modification).
We've been using the simple #ifdef, #else, and #endif directives for quite some time now, as supporting platforms 4.1 through 4.7 with one code base is nearly impossible without them, but I began wondering recently if there are other supported directives which aren't quite as well documented; something akin to C's #elif for example, or even rudimentary equivalency directives?
Here's a complete listing of commands for the RAPC preprocessor. The preprocessor's not very robust, but that's on purpose.
//#preprocess - Used to specify that the file should be preprocessed. It must be the first line of the file.
//#implicit tag - This needs to be on the second line of the file. If tag is part of the command line, then the whole file should be compiled. If not, then it should be excluded.
Then there's the //#ifdef tag ... #else ... #endif and the //#ifndef tag ... #else ... #endif directives that you mentioned.
Also note, there is no nesting of preprocessed blocks and no macros.
RIM Help Center Doc:
http://docs.blackberry.com/en/developers/deliverables/21065/Specifying_preprocessor_directives_657636_11.jsp

Resources