May 24, 2019
On Friday, 24 May 2019 at 07:09:56 UTC, Radu wrote:
> On Friday, 24 May 2019 at 04:49:22 UTC, bpr wrote:
>> On Thursday, 23 May 2019 at 19:33:15 UTC, Walter Bright wrote:
>>> string formatString(string f, string[] A ...)
>>> {
>>>     string r;
>>>     size_t i;
>>>     size_t ai;
>>>     while (i < f.length)
>>>     {
>>> 	if (f[i] != '%' || i + 1 == f.length)
>>> 	{
>>> 	    r ~= f[i];
>>
>>
>> Are you sure this works for betterC? It's been a while for me, but I think it won't, the string appends will stop it.
>>
>> Good job at getting unit tests and final switch in!
>>
>>> ----- End Of Das Code ----------
>
> Indeed it doesn't work with -betterC flag. Easily testable on run.dlang.io
>
> This probably would work if CTFE was supported when compiling with betterC.


In cases like this, one needs to use the enum lambda trick:

// Before:
string foo(string arg1) { /* .. */ }

// After:
enum foo(string arg1) = () { /* .. */ };


(Replace `string arg1` with all compile-time and run-time parameters that `foo` may take.)

That way, `foo` won't reach the code-generator and hence you won't get errors with `-betterC`.
May 24, 2019
On Friday, 24 May 2019 at 08:00:31 UTC, Petar Kirov [ZombineDev] wrote:
> In cases like this, one needs to use the enum lambda trick:
>
> // Before:
> string foo(string arg1) { /* .. */ }
>
> // After:
> enum foo(string arg1) = () { /* .. */ };
>
>
> (Replace `string arg1` with all compile-time and run-time parameters that `foo` may take.)
>
> That way, `foo` won't reach the code-generator and hence you won't get errors with `-betterC`.

Ohh, that is nice one. Thanks!
May 24, 2019
On Friday, 24 May 2019 at 08:00:31 UTC, Petar Kirov [ZombineDev] wrote:
> On Friday, 24 May 2019 at 07:09:56 UTC, Radu wrote:
>> On Friday, 24 May 2019 at 04:49:22 UTC, bpr wrote:
>>>> [...]
>>
>> Indeed it doesn't work with -betterC flag. Easily testable on run.dlang.io
>>
>> This probably would work if CTFE was supported when compiling with betterC.
>
>
> In cases like this, one needs to use the enum lambda trick:
>
> // Before:
> string foo(string arg1) { /* .. */ }
>
> // After:
> enum foo(string arg1) = () { /* .. */ };
>
>
> (Replace `string arg1` with all compile-time and run-time parameters that `foo` may take.)
>
> That way, `foo` won't reach the code-generator and hence you won't get errors with `-betterC`.

Yes, good point! I forgot about this trick.
May 24, 2019
On Friday, 24 May 2019 at 09:52:58 UTC, Radu wrote:
>
> Yes, good point! I forgot about this trick.

Best verified on d.godbolt.org. Compare:

* https://d.godbolt.org/z/E8aoBg - compiles without -betterC, generates a ton of bloat

* https://d.godbolt.org/z/GGh9c1 - same, but doesn't compile with -betterC

* https://d.godbolt.org/z/mPQMcc - compiles with -betterC

* https://run.dlang.io/gist/run-dlang/1caf15c8c7dded16ba812353361feda9 - what I would like to write, but currently produces too much bloat and doesn't work with -betterC

The examples above, were inspired by https://twitter.com/Cor3ntin/status/1127210941718962177. I wanted to check how D with -betterC would compare to C++23+ w.r.t code gen (bloat).

May 24, 2019
On Friday, 24 May 2019 at 12:14:09 UTC, Petar Kirov [ZombineDev] wrote:
> On Friday, 24 May 2019 at 09:52:58 UTC, Radu wrote:
>>
>> Yes, good point! I forgot about this trick.
>
> Best verified on d.godbolt.org. Compare:
>
> * https://d.godbolt.org/z/E8aoBg - compiles without -betterC, generates a ton of bloat
>
> * https://d.godbolt.org/z/GGh9c1 - same, but doesn't compile with -betterC
>
> * https://d.godbolt.org/z/mPQMcc - compiles with -betterC
>
> * https://run.dlang.io/gist/run-dlang/1caf15c8c7dded16ba812353361feda9 - what I would like to write, but currently produces too much bloat and doesn't work with -betterC
>
> The examples above, were inspired by https://twitter.com/Cor3ntin/status/1127210941718962177. I wanted to check how D with -betterC would compare to C++23+ w.r.t code gen (bloat).

I used the same method to generate C header files for a betterC library, I know it works and doesn't produce runtime bloat.

To bad it is something you forget, i.e. it is not obvious :)
May 24, 2019
On 5/24/19 8:14 AM, Petar Kirov [ZombineDev] wrote:
> On Friday, 24 May 2019 at 09:52:58 UTC, Radu wrote:
>>
>> Yes, good point! I forgot about this trick.
> 
> Best verified on d.godbolt.org. Compare:
> 
> * https://d.godbolt.org/z/E8aoBg - compiles without -betterC, generates a ton of bloat
> 
> * https://d.godbolt.org/z/GGh9c1 - same, but doesn't compile with -betterC
> 
> * https://d.godbolt.org/z/mPQMcc - compiles with -betterC
> 
> * https://run.dlang.io/gist/run-dlang/1caf15c8c7dded16ba812353361feda9 - what I would like to write, but currently produces too much bloat and doesn't work with -betterC
> 
> The examples above, were inspired by https://twitter.com/Cor3ntin/status/1127210941718962177. I wanted to check how D with -betterC would compare to C++23+ w.r.t code gen (bloat).

Interesting. These problems seem to be implementation-specific, not fundamental.

May 24, 2019
On 2019-05-23 21:33, Walter Bright wrote:
> While up at night with jetlag at DConf, I started toying about solving a small problem. In order to use printf(), the format specifiers in the printf format string have to match the types of the rest of the parameters. This is well known to be brittle and error-prone, especially when refactoring the types of the arguments.
> 
> (Of course, this is not a problem with writefln() and friends, but that isn't available in the dmd front end, nor when using betterC. Making printf better would mesh nicely with betterC. Note that many C compilers have extensions to tell you if there's a mismatch, but they won't fix it for you.)
> 
> I thought why not use D's metaprogramming to fix it. Some ground rules:
> 
> 1. No extra overhead
> 2. Completely self-contained
> 3. Only %s specifiers are rewritten
> 4. %% is handled
> 5. diagnose mismatch between number of specifiers and number of arguments
> 
> Here's my solution:
> 
>      int i;
>      dprintf!"hello %s %s %s %s betty\n"(3, 4.0, &i, "abc".ptr);
> 
> gets rewritten to:
> 
>      printf("hello %d %g %p %s betty\n", 3, 4.0, &i, "abc".ptr);
> 

This is kind of nice, but I would prefer to have a complete implementation written in D (of sprintf) that is @nogc @safe nothrow and pure. To avoid having to add various hacks to apply these attributes.

Would be nice if it recognizes objects and calls `toString` or `toChars` as well.

I can also add that there was this guy at DConf that said that if a D string should be passed to a C library it should manually pass the pointer and length separately without any magic ;)

-- 
/Jacob Carlborg
May 24, 2019
On 5/24/2019 8:35 AM, Jacob Carlborg wrote:
> This is kind of nice, but I would prefer to have a complete implementation written in D (of sprintf) that is @nogc @safe nothrow and pure. To avoid having to add various hacks to apply these attributes.

C's sprintf is already @nogc nothrow and pure. Doing our own is not that easy, in particular, the floating point formatting is a fair amount of tricky work.

Besides, this is a few lines of code, and would fit in fine with betterC.


> I can also add that there was this guy at DConf that said that if a D string should be passed to a C library it should manually pass the pointer and length separately without any magic ;)

That wouldn't work with %.*s because the .length argument must be cast to int.

May 24, 2019
On 2019-05-24 20:39, Walter Bright wrote:

> C's sprintf is already @nogc nothrow and pure.

Technically it's not pure because it access `errno`, that's what I meant with "various hacks".

> Doing our own is not that easy, in particular, the floating point formatting is a fair amount of tricky work.

Stefan Koch has an implementation for that [3], even works at CTFE. Not sure if it's compatible with the C implementation though.

> That wouldn't work with %.*s because the .length argument must be cast to int.

Of course it works. The DMD code base is littered with calls to printf with D strings the manually way of passing the pointer and length separately, including the casting.

[3] https://github.com/UplinkCoder/fpconv/blob/master/src/fpconv_ctfe.d

-- 
/Jacob Carlborg
May 24, 2019
On 5/24/19 2:39 PM, Walter Bright wrote:
> On 5/24/2019 8:35 AM, Jacob Carlborg wrote:
>> This is kind of nice, but I would prefer to have a complete implementation written in D (of sprintf) that is @nogc @safe nothrow and pure. To avoid having to add various hacks to apply these attributes.
> 
> C's sprintf is already @nogc nothrow and pure. Doing our own is not that easy, in particular, the floating point formatting is a fair amount of tricky work.

This 100x. Once C++ variadics were out, everybody and their cat had an article about "safely replacing the printf family". Invariably the implementations ditched printf and as a consequence were bulky and they did awfully with floating point numbers. The right approach in 10% of the code is to check the arguments during compilation and then forward to the C function. The only remaining slightly tricky part (for printing to a string) is figuring out the maximum buffer size needed.