February 22, 2009
Hello Bill,
> I use this feature pretty frequently to break up long strings. I think
> I didn't use ~ for that because it makes me think an allocation might
> happen when it doesn't need to.
> 


yah, the WILL-happen-at-compiletime bit is nice

> But after seeing the discussion here I'd be happy to switch to using
> "a"~"b" as long as it's guaranteed by the language that such strings
> will be concatenated at compile time.   (I think the is the case now,
> right?)

same here.

> 
> --bb
> 


February 22, 2009
Hello Jarrett,

> On Sun, Feb 22, 2009 at 12:51 PM, Bill Baxter <wbaxter@gmail.com>
> wrote:
> 
>> I use this feature pretty frequently to break up long strings. I
>> think I didn't use ~ for that because it makes me think an allocation
>> might happen when it doesn't need to.
>> 
>> But after seeing the discussion here I'd be happy to switch to using
>> "a"~"b" as long as it's guaranteed by the language that such strings
>> will be concatenated at compile time.   (I think the is the case now,
>> right?)
>> 
> Of course, it does it as a matter of constant folding, just like 3 +
> 4.
> 

IIRC DMD doesn't always do the constant folding (Decent has a post processed view that shows this in some cases) For instance, IIRC it only does left most so this:

char[] foo = "foo";
char[] bar = foo ~ "bar" ~ "baz"

doesn't get folded. And even if DMD were to start doing that one, there is no requirement that another compiler also do it.


February 23, 2009
BCS:

> IIRC DMD doesn't always do the constant folding (Decent has a post processed
> view that shows this in some cases) For instance, IIRC it only does left
> most so this:
> char[] foo = "foo";
> char[] bar = foo ~ "bar" ~ "baz"
> doesn't get folded. And even if DMD were to start doing that one, there is
> no requirement that another compiler also do it.

If there are guarantees that "abc" "def" are folded at compile time, then the same guarantees can be specified for "abc" ~ "def". I can't see a problem.

I have also compiled this code with DMD:

void main() {
    string foo = "foo";
    string bar = foo ~ "bar" ~ "baz";
}

Resulting asm, no optimizations:

L0:		push	EBP
		mov	EBP,ESP
		mov	EDX,FLAT:_DATA[0Ch]
		mov	EAX,FLAT:_DATA[08h]
		push	dword ptr FLAT:_DATA[01Ch]
		push	dword ptr FLAT:_DATA[018h]
		push	dword ptr FLAT:_DATA[02Ch]
		push	dword ptr FLAT:_DATA[028h]
		push	EDX
		push	EAX
		push	3
		mov	ECX,offset FLAT:_D11TypeInfo_Aa6__initZ
		push	ECX
		call	near ptr __d_arraycatnT
		xor	EAX,EAX
		add	ESP,020h
		pop	EBP
		ret


Resulting asm, with optimizations:

L0:		sub	ESP,0Ch
		mov	EAX,offset FLAT:_D11TypeInfo_Aa6__initZ
		push	dword ptr FLAT:_DATA[01Ch]
		push	dword ptr FLAT:_DATA[018h]
		push	dword ptr FLAT:_DATA[02Ch]
		push	dword ptr FLAT:_DATA[028h]
		push	dword ptr FLAT:_DATA[0Ch]
		push	dword ptr FLAT:_DATA[08h]
		push	3
		push	EAX
		call	near ptr __d_arraycatnT
		add	ESP,020h
		add	ESP,0Ch
		xor	EAX,EAX
		ret

I can see just one arraycatn, so the two string literals are folded at compile time, I think.

Bye,
bearophile
February 23, 2009
On Mon, 23 Feb 2009 04:18:35 +0300, bearophile <bearophileHUGS@lycos.com> wrote:

> BCS:
>
>> IIRC DMD doesn't always do the constant folding (Decent has a post processed
>> view that shows this in some cases) For instance, IIRC it only does left
>> most so this:
>> char[] foo = "foo";
>> char[] bar = foo ~ "bar" ~ "baz"
>> doesn't get folded. And even if DMD were to start doing that one, there is
>> no requirement that another compiler also do it.
>
> If there are guarantees that "abc" "def" are folded at compile time, then the same guarantees can be specified for "abc" ~ "def". I can't see a problem.
>
> I have also compiled this code with DMD:
>
> void main() {
>     string foo = "foo";
>     string bar = foo ~ "bar" ~ "baz";
> }
>

Won't work. Imaging foo is a user-defined type with custom opCat:

auto bar = foo  ~  "123" ~  "456";

compare to:

     std::cout << "123" << "456";
February 23, 2009
Denis Koroskin:
> bearophile:
> > void main() {
> >     string foo = "foo";
> >     string bar = foo ~ "bar" ~ "baz";
> > }
> >
> 
> Won't work. Imaging foo is a user-defined type with custom opCat:
> auto bar = foo  ~  "123" ~  "456";
> compare to:
>       std::cout << "123" << "456";

In this thread I was talking about the concat of true strings, not of generic objects: auto bar = foo  ~ ("123" ~  "456");

Are you saying that the concat operation of
"123" ~  "456"
has a different (invisible) "operator" precedence of:
"123" "456" ?
If this is true, then the ~ isn't a fully drop-in replacement for the automatic concat of strings as done in C...

Bye,
bearophile
February 23, 2009
Hello bearophile,

> If there are guarantees that "abc" "def" are folded at compile time,
> then the same guarantees can be specified for "abc" ~ "def". I can't
> see a problem.

While it is not part of the spec, I do see a problem. If it were added....


> 
> I have also compiled this code with DMD:
> 
> void main() {
> string foo = "foo";
> string bar = foo ~ "bar" ~ "baz";
> }
> Resulting asm, no optimizations:
> 
> L0:		push	EBP
> mov	EBP,ESP
> mov	EDX,FLAT:_DATA[0Ch]
> mov	EAX,FLAT:_DATA[08h]
> push	dword ptr FLAT:_DATA[01Ch]
> push	dword ptr FLAT:_DATA[018h]
> push	dword ptr FLAT:_DATA[02Ch]
> push	dword ptr FLAT:_DATA[028h]

note 6 things

> push	EDX
> push	EAX
> push	3
> mov	ECX,offset FLAT:_D11TypeInfo_Aa6__initZ
> push	ECX
> call	near ptr __d_arraycatnT
> xor	EAX,EAX
> add	ESP,020h
> pop	EBP
> ret
> Resulting asm, with optimizations:
> 
> L0:		sub	ESP,0Ch
> mov	EAX,offset FLAT:_D11TypeInfo_Aa6__initZ
> push	dword ptr FLAT:_DATA[01Ch]
> push	dword ptr FLAT:_DATA[018h]
> push	dword ptr FLAT:_DATA[02Ch]
> push	dword ptr FLAT:_DATA[028h]
> push	dword ptr FLAT:_DATA[0Ch]
> push	dword ptr FLAT:_DATA[08h]


again 6 things


> push	3

I think that is a varargs call

> push	EAX
> call	near ptr __d_arraycatnT
> add	ESP,020h
> add	ESP,0Ch
> xor	EAX,EAX
> ret
> I can see just one arraycatn, so the two string literals are folded at
> compile time, I think.
> 
> Bye,
> bearophile


I think that DMD does some optimization for a~b~c etc. so that there is only one call for any number of chained ~ (array cat n). In this case I think it is doing that.


February 23, 2009
bearophile wrote:
> Denis Koroskin:
>> bearophile:
>>> void main() {
>>>     string foo = "foo";
>>>     string bar = foo ~ "bar" ~ "baz";
>>> }
>>>
>> Won't work. Imaging foo is a user-defined type with custom opCat:
>> auto bar = foo  ~  "123" ~  "456";
>> compare to:
>>       std::cout << "123" << "456";
> 
> In this thread I was talking about the concat of true strings, not of generic objects:
> auto bar = foo  ~ ("123" ~  "456");
> 
> Are you saying that the concat operation of
> "123" ~  "456"
> has a different (invisible) "operator" precedence of:
> "123" "456" ?
> If this is true, then the ~ isn't a fully drop-in replacement for the automatic concat of strings as done in C...
> 
> Bye,
> bearophile

"123" "456" has the higher precedence
February 23, 2009
On Sun, Feb 22, 2009 at 9:29 PM, bearophile <bearophileHUGS@lycos.com> wrote:

> Are you saying that the concat operation of
> "123" ~  "456"
> has a different (invisible) "operator" precedence of:
> "123" "456" ?
> If this is true, then the ~ isn't a fully drop-in replacement for the automatic concat of strings as done in C...

Currently that's the case.  But it's simply unspecified in the language specification, and there's no reason why the compiler can't turn:

a = foo ~ "bar" ~ "baz";

into:

a = foo ~ "barbaz";

FWIW the MiniD compiler does this already.  It's just that DMD currently does concatenation constant folding in a simple manner that makes this kind of folding "invisible" to it.

But when all the operands of the concatenations are strings - like when building up strings to be mixed-in, or in static/const variable initializers - then everything will obviously be folded at compile time.
February 24, 2009
bearophile Wrote:

> Months ago I have suggested to remove it

Didn't find it in bugzilla. Reported as bug 2685.
February 25, 2009
Frank Benoit wrote:
> Find the bug:
>     static string[] KEYWORDS = [ "abstract", "alias", "align", "asm",

Out of curiosity, are you trying to create a D parser? Because "private:", "protected:", "public:" and "~this" are not keywords.