May 10, 2021
On Monday, 10 May 2021 at 01:45:22 UTC, Walter Bright wrote:
> 11. C++ can compile C code, which is a ginormous advantage for C++. Can we afford not to do that?

You want to fully compile the C code, not just extract bindings to link to it?

There's a lot of convenience to that - I've translated many lines of code from C to D by hand (a pretty easy process btw, just tedious, but if you sit down for a few hours and just do it, it is a result you can use for years to come) to take advantage of the convenience; being able to dmd -i is nice.

But I think the binding aspect is a lot more important and without the preprocessor part you just can't do that. It is an absolute must for this to be useful.

If you can get some of that #define stuff to just work, then maybe we can merge this and iterate on it from there.

But I'm against merging something that's only maybe 20% done. Get up to 50% - integrated cpp with those #defines actually being available to D... and maybe we have something usable and a solid basis to estimate how much work is left (by the time you get to the point where you can do this, the work is about 1/3 done. There'd still the all the little details that need to be done and the inevitable flurry of bugs. I'd be surprised if this is legitimately usable by the end of the year. But it would prove it is realistically possible once importing a module with some defined constants works from the D side.)
May 10, 2021

On Monday, 10 May 2021 at 01:50:40 UTC, Brian wrote:

>

On Monday, 10 May 2021 at 01:13:25 UTC, Max Haughton wrote:

>

[...]

Whether or not your code links in C depends on a number of factors. It is not as simple as you make it out to be.

Consider on my OpenBSD machine:

/home/brian/c $ gcc --version
gcc (GCC) 12.0.0 20210421 (experimental)
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

/home/brian/c $ gcc -o square square.c
ld: error: undefined symbol: square
>>>               [...]
collect2: error: ld returned 1 exit status
/home/brian/c $ gcc -O2 -o square square.c
/home/brian/c $ ./square
9

~Brian

That particular case is fairly simple if you look at the outputted code. The function square is never emitted, but with the optimization flag it is never used (by name).

May 10, 2021
Hi Walter --

Though still new to D, I really like this idea. Some rather trivial meta comments below.

On Monday, 10 May 2021 at 01:45:22 UTC, Walter Bright wrote:
> 5. We will have complete control over it. We can adjust it so it works best for us. We don't need to fork or get anyone's buy-in. We control the user experience.
>
> 8. There are a lot of wacky C extensions out there. We only need to implement currently used ones (not the 16 bit stuff), and only the stuff that appears in C headers.
>
> 9. Without a C compiler, we're stuck with, wedded to, and beholden to libclang. I wouldn't be surprised that the eventual cost of adapting ourselves to libclang will exceed the cost of doing our own C compiler.
>

Completely agree with these 3 related points. The only thing I would add is that ANSI C11 is a start but it might be worthwhile to think sooner rather than later about what if any extensions are to be accepted and what the process would like like to incorporate those extensions. GNU C is a de facto standard. Even if that was relaxed to LLVM C, that is still a number of extensions. But I think this can be overall a tomorrow problem, so long as the initial considerations aren't too many tomorrows from now.

> 11. C++ can compile C code, which is a ginormous advantage for C++. Can we afford not to do that?
>

As a new user to D, I was legitimately surprised that D didn't already compile C with the very explicit writings about DasBetterC, going so far as to having a -betterC flag. Perhaps that was my mistake in understanding the language. I wonder how many other newcomers also experience that confusion.

~Brian
May 09, 2021
On 5/9/2021 7:22 PM, Brian wrote:
> As a new user to D, I was legitimately surprised that D didn't already compile C with the very explicit writings about DasBetterC, going so far as to having a -betterC flag. Perhaps that was my mistake in understanding the language. I wonder how many other newcomers also experience that confusion.

Having both ImportC and DasBetterC is definitely a messaging issue.
May 09, 2021
On 5/9/2021 7:12 PM, Adam D. Ruppe wrote:
> On Monday, 10 May 2021 at 01:45:22 UTC, Walter Bright wrote:
>> 11. C++ can compile C code, which is a ginormous advantage for C++. Can we afford not to do that?
> 
> You want to fully compile the C code, not just extract bindings to link to it?

Yes. Frankly, there's no reason not to once you've done nearly all the work anyway. (For example, to evaluate static array dimensions, an expression parser is needed.)


> There's a lot of convenience to that - I've translated many lines of code from C to D by hand (a pretty easy process btw, just tedious, but if you sit down for a few hours and just do it, it is a result you can use for years to come) to take advantage of the convenience; being able to dmd -i is nice.

Yeah, I did the backend conversion from C to D. It took a couple hours per file, most of the tedium came from it being terribly written code.


> But I think the binding aspect is a lot more important and without the preprocessor part you just can't do that. It is an absolute must for this to be useful.

I do have a forlorn hope that some C users will find it useful to replace many of their macros with enum, const, and inline function declarations.


> If you can get some of that #define stuff to just work, then maybe we can merge this and iterate on it from there.
> 
> But I'm against merging something that's only maybe 20% done. Get up to 50% - integrated cpp with those #defines actually being available to D... and maybe we have something usable and a solid basis to estimate how much work is left (by the time you get to the point where you can do this, the work is about 1/3 done. There'd still the all the little details that need to be done and the inevitable flurry of bugs. I'd be surprised if this is legitimately usable by the end of the year. But it would prove it is realistically possible once importing a module with some defined constants works from the D side.)

The trouble is making it fully functional will require tweaks all over the D semantic code. Constantly needing to rebase this large code base for a year is an unpleasant prospect.

Besides, ImportC is simply not going to break any existing functionality, so people can just ignore it successfully.

May 10, 2021
On Monday, 10 May 2021 at 01:45:22 UTC, Walter Bright wrote:
> [A meta comment in reply to Adam]
>
> The end goal is to be able to import a C file and it will "just work". The following problems need to be solved to make this happen:
>
> [...]

+1
May 10, 2021

On Monday, 10 May 2021 at 03:13:51 UTC, Walter Bright wrote:

>

On 5/9/2021 7:12 PM, Adam D. Ruppe wrote:

>

On Monday, 10 May 2021 at 01:45:22 UTC, Walter Bright wrote:

>
  1. C++ can compile C code, which is a ginormous advantage for C++. Can we afford not to do that?

You want to fully compile the C code, not just extract bindings to link to it?

Yes. Frankly, there's no reason not to once you've done nearly all the work anyway. (For example, to evaluate static array dimensions, an expression parser is needed.)

>

There's a lot of convenience to that - I've translated many lines of code from C to D by hand (a pretty easy process btw, just tedious, but if you sit down for a few hours and just do it, it is a result you can use for years to come) to take advantage of the convenience; being able to dmd -i is nice.

Yeah, I did the backend conversion from C to D. It took a couple hours per file, most of the tedium came from it being terribly written code.

>

But I think the binding aspect is a lot more important and without the preprocessor part you just can't do that. It is an absolute must for this to be useful.

I do have a forlorn hope that some C users will find it useful to replace many of their macros with enum, const, and inline function declarations.

As a C programmer I do use already a lot of enums and inlines, but the C semantic makes it quite tricky to use.
To use inlines in big C projects you have to guarantee that you emit the non inlined version of the function in exactly one module as some linkers do not like to have multiple object files with the same functions in them. You also want to have always at least one uninlined version of the fucnton so that it can
be linked with modules that were compiled with -O0 or -fno-inline. Not difficult, but requires some pre-processor acrobatics that can be problematic.

The issue I see is that the preprocessor is not bound by the language syntax and is sometimes used in things that cannot be translated easily to a D construct. I have, for example, a lot of functions that take a string and its length. For string literals it is annoying to count the number of characters so I have a macro to do it:

#define SnL(array) (array),LENGTH(array)

one will note that this fits two parameters

The LENGTH macro is also interesting it is define as

#define LENGTH(arr) (NUM_ELEMS(arr)-1) ok, so far it's easy, but here comes
NUM_ELEMS, that I have lifted from the Linux kernel

```
#ifdef __GNUC__
/** Array size macro. Copied the Linux Kernel version which is not portable but
    which checks that it's a real array (not a pointer) and evaluates to a
    constant expression. This allows to use it to declare other array sizes. */
  #define NUM_ELEMS(arr) (sizeof(struct {int :-!!(__builtin_types_compatible_p(typeof (arr), typeof (&0[arr])));})+sizeof (arr)/sizeof 0[arr])
#else
/** A portable variant, but which doesn't check for array or pointer. */
  #define NUM_ELEMS(arr) (sizeof (arr)/sizeof 0[arr])
#endif
```

This is the kind of macros that are all over the place in real C code.

May 10, 2021
On 5/9/2021 11:21 PM, Patrick Schluter wrote:
> As a C programmer I do use already a lot of enums and inlines, but the C semantic makes it quite tricky to use.
> To use inlines in big C projects you have to guarantee that you emit the non inlined version of the function in exactly one module as some linkers do not like to have multiple object files with the same functions in them.

Those linkers were obsoleted in 1990 with the advent of C++ (C++ forced the introduction of COMDAT sections to handle that). D relies on COMDATs, too, so if you're stuck on such an obsolete platform, and I know C wishes to still support them, D won't work on it anyway.


> You also want to have always at least one uninlined version of the fucnton so that it can
> be linked with modules that were compiled with -O0 or -fno-inline. Not difficult, but requires some pre-processor acrobatics that can be problematic.

With COMDATs, this is not a problem.


> The issue I see is that the preprocessor is not bound by the language syntax and is sometimes used in things that cannot be translated easily to a D construct.

Yup.

> I have, for example, a lot of functions that take a string and its length. For string literals it is annoying to count the number of characters so I have a macro to do it:
> 
> `#define SnL(array) (array),LENGTH(array)`
> 
> one will note that this fits two parameters
> 
> The LENGTH macro is also interesting it is define as
> 
> `#define LENGTH(arr)  (NUM_ELEMS(arr)-1)` ok, so far it's easy, but here comes
> NUM_ELEMS, that I have lifted from the Linux kernel
> 
>      ```
>      #ifdef __GNUC__
>      /** Array size macro. Copied the Linux Kernel version which is not portable but
>          which checks that it's a real array (not a pointer) and evaluates to a
>          constant expression. This allows to use it to declare other array sizes. */
>        #define NUM_ELEMS(arr) (sizeof(struct {int :-!!(__builtin_types_compatible_p(typeof (arr), typeof (&0[arr])));})+sizeof (arr)/sizeof 0[arr])
>      #else
>      /** A portable variant, but which doesn't check for array or pointer. */
>        #define NUM_ELEMS(arr) (sizeof (arr)/sizeof 0[arr])
>      #endif
>      ```
> 
> This is the kind of macros that are all over the place in real C code.

I know. I used to revel in this stuff. Macros that piece together syntax are a horror show, and a big part of why D doesn't have macros. (I eventually removed all this stuff from my C code and it was much nicer as a result.)

There's no way to mechanically translate this stuff to D.

However, the preprocessed code can be compiled just fine by ImportC. You just won't be able to use those macros in the D code. But I'm pretty sure an equivalent can be made by hand.

P.S. that unnamed bit field is, well, sheesh. It could be replaced with a template.

May 10, 2021

On Monday, 10 May 2021 at 07:21:31 UTC, Walter Bright wrote:

>

On 5/9/2021 11:21 PM, Patrick Schluter wrote:

>

[...]

Those linkers were obsoleted in 1990 with the advent of C++ (C++ forced the introduction of COMDAT sections to handle that). D relies on COMDATs, too, so if you're stuck on such an obsolete platform, and I know C wishes to still support them, D won't work on it anyway.

>

[...]

With COMDATs, this is not a problem.

>

[...]

Yup.

>

[...]

I know. I used to revel in this stuff. Macros that piece together syntax are a horror show, and a big part of why D doesn't have macros. (I eventually removed all this stuff from my C code and it was much nicer as a result.)

There's no way to mechanically translate this stuff to D.

However, the preprocessed code can be compiled just fine by ImportC. You just won't be able to use those macros in the D code. But I'm pretty sure an equivalent can be made by hand.

P.S. that unnamed bit field is, well, sheesh. It could be replaced with a template.

Yes, I just read the comment on your PR and the way chosen is indeed the only viable way to proceed.
The only thing that bothers me as it is now is the fact that it doesn't support intializer list { intializers }, which I suppose means that designated initializers { .field = ..., [3]=... }and compound statements (type){ initializers } are not working either. This would be a real real problem for modern C code (C99 and superior).

May 10, 2021
On Monday, 10 May 2021 at 02:12:02 UTC, Adam D. Ruppe wrote:
> If you can get some of that #define stuff to just work, then maybe we can merge this and iterate on it from there.

You could add a syntax for embedding C function defs or even C expressions in D code and run only that through cpp. Then make D declarations available to C by making a C extension.

However... If it takes years to fix D issues, then this whole project is likely to not be used in serious projects as it will be viewed as less reliable than just manually creating wrappers.

It makes more sense to reuse clang and emit llvm IR.