Mixin C
Paul Backus
snarwin at gmail.com
Thu Mar 28 03:47:26 UTC 2024
On Thursday, 28 March 2024 at 02:24:34 UTC, Steven Schveighoffer
wrote:
> On Saturday, 23 March 2024 at 19:02:52 UTC, Paul Backus wrote:
>> 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.
I think most C programmers would regard this as a horrifying
abuse of the preprocessor--the kind of thing they switch to D
(and other languages) to get away from.
>> 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).
It sounds like the usage pattern you're envisioning is something
like this:
```d
/// Bindings for libfoo
module foo;
mixin(C) {
#include "libfoo.h"
}
/// Wraps foo_do_stuff
void doStuff(int x)
{
mixin(C) {
// reuses top-level #include
foo_do_stuff(x, FOO_SOME_MACRO);
}
}
/// Wraps foo_do_other_stuff
void doOtherStuff(const(char)* s)
{
mixin(C) {
// reuses top-level #include
foo_do_other_stuff(s, FOO_SOME_OTHER_MACRO);
}
}
```
I agree that supporting this usage pattern would be desirable,
but I'm not sure concatenating every `mixin(C)` block in a module
is the best way to do so. Perhaps instead we can have a dedicated
"`mixin(C)` header" block that can appear at module scope, whose
content is prepended to each `mixin(C)` block?
E.g.,
```d
/// Bindings for libfoo
module foo;
mixinC_header {
#include "foo.h"
}
void doStuff(int x)
{
mixin(C) {
// #include "foo.h" inserted here
foo_do_stuff(x, FOO_SOME_MACRO);
}
}
// etc.
```
Granted, this only solves the UX problems of the original
proposal, not the performance problems--under the hood you are
still doing a bunch of separate preprocessor calls, and including
the same file over and over. But, again, you are not *forced* to
use Mixin C like this, and programmers who want to optimize their
build times will still have alternatives to turn to that do not
require opening the door to total macro madness.
More information about the dip.ideas
mailing list