Mixin C

Steven Schveighoffer schveiguy at gmail.com
Thu Mar 28 02:24:34 UTC 2024


On Saturday, 23 March 2024 at 19:02:52 UTC, Paul Backus wrote:
> On Saturday, 23 March 2024 at 02:51:31 UTC, Steven 
> Schveighoffer wrote:
>>
>> So the entirety of `stdio.h` is included in the body of the D 
>> main function? Is that wise?
>
> In this specific example, it's overkill.
>
> In general...is there a better alternative? The C preprocessor 
> is a blunt instrument, and if we want to have full support for 
> it, we are going to have to live with the consequences of that 
> bluntness.

My objection is to the *requirement* that you include it in the 
main function. It's very different from D nested imports, as it 
redefines everything inside the function.

Having to re-import *everything* everywhere you need to use a 
macro is really bad.

>
> You can use a lambda:
>
> ```d
> enum PI = () {
>     mixin(C) {
>         #include "pidef.h"
>         return PI;
>     }
> }();
> ```

Ugh, still having to include the entirety of a C header inside a 
function context.

>> What I'd like to see is:
>>
>> a) the C preprocessor is run on *all the mixin(C) islands of 
>> the file* regardless of where they appear, whether they are in 
>> templates, etc. Basically, take all the mixin(C) things and 
>> concatenate them, run the result through the preprocessor, and 
>> put the results back where they were. THEN run the importC 
>> compiler on them. This allows a more cohesive C-like 
>> experience, without having to import/define things over and 
>> over.
>
> Some downsides to this approach:
>
> 1. Concatenating all of the `mixin(C)` blocks in a module for 
> preprocessing violates D's scoping rules and creates a lot of 
> opportunities for "spooky action at a distance."

But that's what you get with C. For instance, you can #define a 
macro inside a function, and use it inside another function, as 
long as it comes later in the file. It's not spooky to C 
programmers. You can even #undef things or re #define them.

> 2. This would allow sharing macro definitions across `mixin(C)` 
> blocks, but would *not* allow sharing declarations. You'd still 
> have to `#include <stdio.h>` twice if you wanted to call 
> `printf` in two different blocks, for example.

but you wouldn't have to include them inside the functions. You 
get the function definitions and macros in the right place (at 
module level).

> 3. In order to "put the results back where they were" the D 
> compiler would have to parse the preprocessor's output for line 
> markers. Since the format of these is not specified by the C 
> standard, this means the D compiler would have to have separate 
> parsers for each C preprocessor implementation (or, at least, 
> one for gcc/clang and one for MSVC).

I came up with an approach for this, I detailed it in my dconf 
talk last year. All preprocessors have a flag which preserves 
comments.

But yes, you are right this is a big hacky problem to solve.

-Steve


More information about the dip.ideas mailing list