May 16, 2022
```d
void main() {
    import std.stdio;
    writeln("Starting application");

    mixinc(qc{
        #include <stdio.h>
        #include <string.h>
        #include <lua.h>
        #include <lauxlib.h>
        #include <lualib.h>

          char buff[256];
          int error;
          lua_State *L = lua_open();   /* opens Lua */
          luaopen_base(L);             /* opens the basic library */
          luaopen_table(L);            /* opens the table library */
          luaopen_io(L);               /* opens the I/O library */
          luaopen_string(L);           /* opens the string lib. */
          luaopen_math(L);             /* opens the math lib. */

          while (fgets(buff, sizeof(buff), stdin) != NULL) {
            error = luaL_loadbuffer(L, buff, strlen(buff), "line") ||
                    lua_pcall(L, 0, 0, 0);
            if (error) {
              fprintf(stderr, "%s", lua_tostring(L, -1));
              lua_pop(L, 1);  /* pop error message from the stack */
            }
          }

          lua_close(L);
    });

    writeln("Program end");
}
```

Copied the function body from[0].

Now imagine some awful macros that exist. It allows you to bridge C into D without creating new or modifying any C files.

This is the ultimate tool for porting C to D.

[0] https://www.lua.org/pil/24.1.html
May 16, 2022
On Monday, 16 May 2022 at 03:12:47 UTC, Walter Bright wrote:
> But I still don't understand - why mixin this stuff? Why would someone want to type C code into a D source file?

dpp and dstep are not always able to divine the meaning of a given macro, so having an escape hatch is either necessary or the most direct way of doing certain things.

If you use them you can see that they're just looking for relatively simple patterns, not magic. You can approximate magic a little by looking at how a macro is used within a source file (if you're lucky), but extracting this info programmatically would use a lot of niche infrastructure and thinking that is probably beyond reachh.

ImportC does not (currently) emit a D equivalent to a header file, which means that documenting what it actually does for some non-trivial preprocessor metaprogramming uglyvomityuck is going to be irritating.

You have a C API, dstep might turn that into a template, which might be initially confusing but you can just grep (or use an IDE) for the symbol (or lack thereof if it couldn't do it). With ImportC this is now much murkier for obvious reasons (although I'll note that adding a palatable header-output mode is something I've played around with and honestly wouldn't be particularly hard as long as we kept a little bit more info around in the compiler).

So you're in a hurry and you can't seem to get a macro working? mixinC the bit you need. It's either that or doing it in your head anyway.
May 16, 2022

On Monday, 16 May 2022 at 03:12:47 UTC, Walter Bright wrote:

>

I'm not going to pretend this can ever be a complete 100% solution, after all:

#define BEGIN {
#define END }

What can one do with that? Phooey.

Just do the right thing. Build macro expansion into the lexer and tag tokens from macros. Then sort it out in the parser an remaining ambiguities in semantic analysis.

>

I've talked with Atila about how dpp handles it. dpp looks for general patterns, and replaces those with generic D

Sounds like a hack. Think instead in terms of C grammar productions and how they match with D.

>

But I still don't understand - why mixin this stuff? Why would someone want to type C code into a D source file?

The problem isnt why, but that it will make code less readable and only be understood by the inner hardcore.

You really need to set up a list of requirements for what is needed in terms of usability for regular D users otherwise forkit’s concerns will materialize...

May 15, 2022
On 5/15/2022 9:39 PM, max haughton wrote:
> So you're in a hurry and you can't seem to get a macro working? mixinC the bit you need. It's either that or doing it in your head anyway.

Ok, I see what you're talking about.

But what I'd do is put that use of the macro in a .c file and import it.
May 15, 2022
Interesting. I note that this is inserting C expressions and statements into D functions. ImportC works at the declaration level - i.e. inserting C symbols. I expect there may be impedance mismatch problems by putting it at a lower level. In fact I'm certain that a redo of how the C semantics are handled in the compiler would be necessary.
May 15, 2022
On 5/15/2022 8:59 PM, max haughton wrote:
> One thing I'd also like to note is that once the C has been turned into the D AST you actually can almost get it to emit D code that represents the C

"almost" is the operative word, here :-/

One of the motivations for ImportC (as opposed to C=>D translations that htod, dstep, and dpp do) is that the semantics can be an exact match to C.
May 16, 2022
On Monday, 16 May 2022 at 05:11:42 UTC, Walter Bright wrote:
> On 5/15/2022 8:59 PM, max haughton wrote:
>> One thing I'd also like to note is that once the C has been turned into the D AST you actually can almost get it to emit D code that represents the C
>
> "almost" is the operative word, here :-/
>
> One of the motivations for ImportC (as opposed to C=>D translations that htod, dstep, and dpp do) is that the semantics can be an exact match to C.

The semantics will be an exact match because I'm talking about merely making the dmd AST dumping feature better versus a new tool. It basically already works it's just that you have to make it not emit `import object` and also fix a bug in the dmd parser because extern(C) doesn't work inside a function parameter or something to that effect.
May 16, 2022
On Monday, 16 May 2022 at 05:08:58 UTC, Walter Bright wrote:
> Interesting. I note that this is inserting C expressions and statements into D functions. ImportC works at the declaration level - i.e. inserting C symbols. I expect there may be impedance mismatch problems by putting it at a lower level. In fact I'm certain that a redo of how the C semantics are handled in the compiler would be necessary.

The PoC for mixinC (the syntax is actually mixin[C] because it was easier to parse) that I did doesn't blow up (note: this does not mean it works) many things I tried.

As long as the semantic analysis can happen in a new Scope (a dmd one not a lexical one) then the normal semantic routines should work and it'll be the same as any other mixin (I.e. mixin is not free of bugs).
May 16, 2022
On Monday, 16 May 2022 at 05:13:52 UTC, max haughton wrote:
> On Monday, 16 May 2022 at 05:11:42 UTC, Walter Bright wrote:
>> On 5/15/2022 8:59 PM, max haughton wrote:
>>> [...]
>>
>> "almost" is the operative word, here :-/
>>
>> One of the motivations for ImportC (as opposed to C=>D translations that htod, dstep, and dpp do) is that the semantics can be an exact match to C.
>
> The semantics will be an exact match because I'm talking about merely making the dmd AST dumping feature better versus a new tool. It basically already works it's just that you have to make it not emit `import object` and also fix a bug in the dmd parser because extern(C) doesn't work inside a function parameter or something to that effect.

Further note that I don't really care about the bodies of functions, so 99% of the usefulness is 30% of the problem.
May 16, 2022
On 16/05/2022 5:16 PM, max haughton wrote:
> As long as the semantic analysis can happen in a new Scope (a dmd one not a lexical one) then the normal semantic routines should work and it'll be the same as any other mixin (I.e. mixin is not free of bugs).

Indeed, we already have scope awareness of C vs D. As long as we can mix them (within each other) than shouldn't need things to be redone.

It shouldn't be any different than:

void main() {
	writeln;

	{
		... c ...
	}

	writeln;
}