February 08, 2018
On Thursday, 8 February 2018 at 01:53:43 UTC, Walter Bright wrote:
> On 2/7/2018 11:29 AM, Ralph Doncaster wrote:
>> I just did a quick check, and with DMD v2.078.1, the hexString template increases code size by ~300 bytes vs the hex literal. So yet one more reason to prefer the hex literals.
>
> Indeed it does, and that is the result of a poor implementation of hexString. I've figured out how to fix that, and hope to make a PR for it shortly.
>
>   https://issues.dlang.org/show_bug.cgi?id=18397

While the fix is a huge improvement, it doesn't match the code generated by the hex literals.  hexString!"deadbeef" stores the null-terminated string in the data section of the object file, while x"deadbeef" only stores 4 bytes in the data section.
February 07, 2018
On 2/7/2018 9:45 PM, Ralph Doncaster wrote:
> While the fix is a huge improvement, it doesn't match the code generated by the hex literals.  hexString!"deadbeef" stores the null-terminated string in the data section of the object file, while x"deadbeef" only stores 4 bytes in the data section.

  string s = x"deadbeef";

stores a null terminated string, too.

If you want only 4 bytes,

  __gshared immutable char[4] = hexString!"deadbeef";

just as you'd do for any string literal.
February 08, 2018
On Wednesday, 7 February 2018 at 17:01:54 UTC, Adam D. Ruppe wrote:
> http://dpldocs.info/experimental-docs/source/core.sys.posix.fcntl.d.html#L123
>
>    version (X86)
>     {
>         enum O_CREAT        = 0x40;     // octal     0100
>         enum O_EXCL         = 0x80;     // octal     0200
>         enum O_NOCTTY       = 0x100;    // octal     0400
>         enum O_TRUNC        = 0x200;    // octal    01000

Dunno, hex reads better here. Octal is only good for unix permissions which are grouped by 3 bits, which is not the case for io constants - these are usual ungrouped flags that are always done with hex and are easier to understand in hex. If you're desperate, octal can be also written as (1<<6)|(2<<3)|(4).
February 08, 2018
Or have a function specifically for unix permissions, like
int unix(int r, int w, int x, int gr, int gw, int gx, int ur, int uw, int ux);
It might be even more readable.
February 08, 2018
On 2/7/18 3:24 PM, Adam D. Ruppe wrote:
> On Wednesday, 7 February 2018 at 18:59:38 UTC, Steven Schveighoffer wrote:
>> Not even close. Octal literals are a disaster, because putting a leading 0 should never change the base of a number.
> 
> I agree the leading 0 is terrible. But that's not the real question here: it is 0o100 vs import std.conv. Note it isn't the syntax - octal!100 is quite nice to me - but rather the requirement to import.
> 
> That is why it isn't used in druntime... and low level code interfacing with external OS or hardware APIs are the most common place for octal, and also where we can't use it. I fear hex will fall into the same pit.

So you think it should go into druntime? I don't see why it wasn't in there in the first place to be honest.

But there is no "decision" on whether to import or not, it's not possible in druntime to import from phobos. So saying the lack of use of octal in druntime is somehow a detraction on the import is incorrect. If you could have imported std.conv in druntime, it would have been done.

>> This has its own problems (e.g. 0O)
> 
> That's why I specifically wrote `0o`. I wouldn't allow `0O`, just like D doesn't allow `1l`: "Error: lower case integer suffix 'l' is not allowed. Please use 'L' instead"

I'm still not in love with the little-o syntax, but this definitely would be necessary.

>> The difference for me isn't how the problem is solved, but that there was a problem for octals (error prone sinister errors) but there isn't/wasn't one for hex strings.
> 
> You and I are on the same side :) I also think they should stay (I just want to see them retyped as immutable(ubyte)[] instead of immutable(char)[], we always cast anyway).

To me, it is a shortcut for specifying hex for every character. The cast isn't that horrible, and probably can be abstracted away into a function if you want.

-Steve
February 08, 2018
On 2/8/18 1:10 AM, Walter Bright wrote:
> On 2/7/2018 9:45 PM, Ralph Doncaster wrote:
>  > While the fix is a huge improvement, it doesn't match the code generated by the hex literals.  hexString!"deadbeef" stores the null-terminated string in the data section of the object file, while x"deadbeef" only stores 4 bytes in the data section.
> 
>    string s = x"deadbeef";
> 
> stores a null terminated string, too.
> 
> If you want only 4 bytes,
> 
>    __gshared immutable char[4] = hexString!"deadbeef";
> 
> just as you'd do for any string literal.

The extra data in the object file comes from the inclusion of the hexStringImpl function, and from the template parameter (the symbol _D3std4conv__T9hexStringVAyaa8_6465616462656566ZQBiyAa is in there as well, which will always be larger than the actual string passed to hexString).

I also see the data in there twice for some reason.

-Steve
February 08, 2018
On Thursday, 8 February 2018 at 10:52:35 UTC, Kagamin wrote:
> Or have a function specifically for unix permissions, like
> int unix(int r, int w, int x, int gr, int gw, int gx, int ur, int uw, int ux);
> It might be even more readable.

I actually personally prefer binary: 0b_1_111_101_000 which visually corresponds with ls's output: drwxr-xr-x.

But octal is the way they are usually done in C. The comments in druntime are because that had to be translated from the common convention.
February 08, 2018
On Thursday, 8 February 2018 at 13:06:44 UTC, Steven Schveighoffer wrote:
> So you think it should go into druntime? I don't see why it wasn't in there in the first place to be honest.

Yeah, probably. I might even publically import it when you import the posix header so it just works in the most common place.

Of course, it is important then that the compile-time thing doesn't cause a link time error when you just import and don't compile it in.... but that should be the case anyway (and the other posts in this thread show Walter is working on that so yay)

> If you could have imported std.conv in druntime, it would have been done.

That's my point. We keep clashing despite being on the same side!

When I say the import is the problem, I don't mean the syntax or literal line of code. I mean the whole concept of depending on the Phobos module and all the stuff that brings. druntime can't have that dependency. Neither can a few other specialized low-level cases. And specialized low-level cases are where you find 95% of octal literals. (well ok 50% of octal literals, where the other 50% are bugs cuz someone wrote 010 to line up leading zeros... )
February 08, 2018
On 2/8/18 9:44 AM, Adam D. Ruppe wrote:
> On Thursday, 8 February 2018 at 13:06:44 UTC, Steven Schveighoffer wrote:
>> So you think it should go into druntime? I don't see why it wasn't in there in the first place to be honest.
> 
> Yeah, probably. I might even publically import it when you import the posix header so it just works in the most common place.
> 
> Of course, it is important then that the compile-time thing doesn't cause a link time error when you just import and don't compile it in.... but that should be the case anyway (and the other posts in this thread show Walter is working on that so yay)
> 
>> If you could have imported std.conv in druntime, it would have been done.
> 
> That's my point. We keep clashing despite being on the same side!

Your statement before: "it is 0o100 vs import std.conv" and "That is why it isn't used in druntime" I thought it meant there was some sort of decision made to not use the import because it would be too costly. But really, there was no decision to be made.

Sorry about the misunderstanding!

> When I say the import is the problem, I don't mean the syntax or literal line of code. I mean the whole concept of depending on the Phobos module and all the stuff that brings. druntime can't have that dependency. Neither can a few other specialized low-level cases. And specialized low-level cases are where you find 95% of octal literals. (well ok 50% of octal literals, where the other 50% are bugs cuz someone wrote 010 to line up leading zeros... )

I agree, you could implement the octal template in druntime without too much issue. The octal!"100" would have been easy-to-parse, the octal!100 version would be more difficult, but nothing impossible that requires the whole of phobos to do so.

My concern in the hexString case is the sheer requirement of CTFE for something that is so easy to do in the compiler, already *done* in the compiler, and has another form specifically for hex strings (the "\xde\xad\xbe\xef" form) that isn't going away. It makes me laugh actually that Walter is now replacing the implementation with a mixin of that other form, incurring all the cost of CTFE so you can transform the string, while breaking existing code in the process: https://github.com/dlang/phobos/pull/6138

-Steve
February 08, 2018
On Thu, Feb 08, 2018 at 08:26:03AM -0500, Steven Schveighoffer via Digitalmars-d wrote: [...]
> The extra data in the object file comes from the inclusion of the hexStringImpl function, and from the template parameter (the symbol _D3std4conv__T9hexStringVAyaa8_6465616462656566ZQBiyAa is in there as well, which will always be larger than the actual string passed to hexString).
[...]

This is one area that really should be improved.  Is there some easy way in the compiler to mark a template function as "only used in CTFE", and not emit it into the object file if there are no other runtime references to it?  I'm thinking of some kind of boolean attribute that defaults to false, and gets set if the function is referenced by runtime code.  During codegen, any function that doesn't have this attribute set will be skipped over.

My speculation is that this would lead to a good amount of reduction in template bloat, given how pervasively CTFE is used in Phobos (and idiomatic D in general).


T

-- 
He who does not appreciate the beauty of language is not worthy to bemoan its flaws.