February 07, 2018
On Wednesday, 7 February 2018 at 01:06:42 UTC, Luís Marques wrote:
> On Wednesday, 7 February 2018 at 00:24:26 UTC, H. S. Teoh wrote:
>> I really like your .nx idea!  It neatly sidesteps the nonsensical mandatory casts and on top of that documents intent (the .nx being a telltale sign of truncation -- much better than arbitrary implicit rules).
[...]
> Yeah, it's just a thin wrapper. I implemented just enough to cover my use cases but just in case it's useful to you or someone else, here goes my implementation...

Very cool! Much better than implementing new types.
Just

>     auto opBinary(string op, U)(NX!U rhs)
>     {
>         static if(rhs.value.sizeof > value.sizeof)
>             return mixin("rhs " ~ op ~  " value");

That won't do anything good for operators that are NOT commutative
(like -, ^^, <<, >>, %, /, ...)
Seems you don't use other things than +, *, &, | and ^, do you?

February 07, 2018
On 2/6/18 8:06 PM, Luís Marques wrote:
> On Wednesday, 7 February 2018 at 00:24:26 UTC, H. S. Teoh wrote:
>> I really like your .nx idea!  It neatly sidesteps the nonsensical mandatory casts and on top of that documents intent (the .nx being a telltale sign of truncation -- much better than arbitrary implicit rules).  I think I'll adopt it in some form in my code, to make dealing with narrow ints saner.  I don't know what your .nx type does, but for my purposes I'll probably just have a thin wrapper around byte/ubyte/etc. with overloaded arithmetic operators that perform the requisite casts.
> 
> Yeah, it's just a thin wrapper. I implemented just enough to cover my use cases but just in case it's useful to you or someone else, here goes my implementation...
> 
> private struct NX(T)
> {
...


I think this would be a good Phobos addition. std.typecons?

-Steve
February 07, 2018
On Wednesday, 7 February 2018 at 11:30:02 UTC, Dominikus Dittes Scherkl wrote:
> Very cool! Much better than implementing new types.
> Just
>
>>     auto opBinary(string op, U)(NX!U rhs)
>>     {
>>         static if(rhs.value.sizeof > value.sizeof)
>>             return mixin("rhs " ~ op ~  " value");
>
> That won't do anything good for operators that are NOT commutative
> (like -, ^^, <<, >>, %, /, ...)
> Seems you don't use other things than +, *, &, | and ^, do you?

Ahah! That "fix" was only a temporary workaround for a unittest. In my actual code the rhs is always a T, not a NX!U, so it didn't matter. I forgot to remove that kludge before I copy pasted it here :-)
February 07, 2018
On Tuesday, 6 February 2018 at 20:23:02 UTC, Walter Bright wrote:
> [...] DFA is a complex thing. This is why DFA is done on the vastly simplified and canonicalized intermediate code, not the ASTs.
>
> Doing DFA for VRP means doing it on the ASTs.
>
> I know what you're asking for sounds simple enough. But it ain't.

What you're saying is true.
There is a way though to have the cake and eat it.
If IR keeps a backwards-transform to the AST, (whereby I mean the semantically-augmented tree closest to the actual AST).

It is possible to transfer insight gained further in the processing to earlier constructs.
Making it possible to extend VRP.

This might negativity impact compile-times, and it (maybe) won't be simple to implement.
February 07, 2018
On 02/06/2018 05:38 PM, Luís Marques wrote:
> 
> Yeah, it's annoying. For my MSP430 work (16-bit, lots of shorts and bytes) I created a generic type which works around this, so you would do:
> 
> byte c = a.nx + b;
> 
> where .nx means "non-extending" and converts/wraps the (u)byte/(u)short in my special type. The arithmetic operations are infectious, so you only need to apply it to one of the operands (and you can preserve it across statements by using "auto" instead of "byte").

Very cool. Would love to see this as a dub package.
February 17, 2018
On 5 February 2018 at 11:22, H. S. Teoh via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> Code:
>
>         struct S {
>                 byte[2] x;
>         }
>         void main() {
>                 S s, t;
>                 s.x = [ 1, -1 ];                // OK
>                 t.x = [ -s.x[0], -s.x[1] ];     // NG (line 7)
>         }
>
>
> Compiler says:
>         /tmp/test.d(7): Deprecation: integral promotion not done for
> `-s.x[0]`, use '-transition=intpromote' switch or `-cast(int)(s.x[0])`
>         /tmp/test.d(7): Deprecation: integral promotion not done for
> `-s.x[1]`, use '-transition=intpromote' switch or `-cast(int)(s.x[1])`
>
>
> Why should I need to explicitly cast to int only to reassign it back to byte?!  This is ridiculous.


Seriously, WTF is going on here?


February 18, 2018
On Sunday, 18 February 2018 at 01:09:57 UTC, Manu wrote:
> On 5 February 2018 at 11:22, H. S. Teoh via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>
>> Code:
>>
>>         struct S {
>>                 byte[2] x;
>>         }
>>         void main() {
>>                 S s, t;
>>                 s.x = [ 1, -1 ];                // OK
>>                 t.x = [ -s.x[0], -s.x[1] ];     // NG (line 7)
>>         }
>>
>>
>> Compiler says:
>>         /tmp/test.d(7): Deprecation: integral promotion not done for
>> `-s.x[0]`, use '-transition=intpromote' switch or `-cast(int)(s.x[0])`
>>         /tmp/test.d(7): Deprecation: integral promotion not done for
>> `-s.x[1]`, use '-transition=intpromote' switch or `-cast(int)(s.x[1])`
>>
>>
>> Why should I need to explicitly cast to int only to reassign it back to byte?!  This is ridiculous.
>
>
> Seriously, WTF is going on here?

C compilers did it for ages, but D doesn’t auto promote to int on unary ops. Hence the warning, the suggestion is kinda stupid thiugh.

C gets away by truncating results silently on assign of int to byte.


February 18, 2018
On Sunday, 18 February 2018 at 13:36:28 UTC, Dmitry Olshansky wrote:
> On Sunday, 18 February 2018 at 01:09:57 UTC, Manu wrote:
>> On 5 February 2018 at 11:22, H. S. Teoh via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>>
>>> Code:
>>>
>>>         struct S {
>>>                 byte[2] x;
>>>         }
>>>         void main() {
>>>                 S s, t;
>>>                 s.x = [ 1, -1 ];                // OK
>>>                 t.x = [ -s.x[0], -s.x[1] ];     // NG (line 7)
>>>         }
>>>
>>>
>>> Compiler says:
>>>         /tmp/test.d(7): Deprecation: integral promotion not done for
>>> `-s.x[0]`, use '-transition=intpromote' switch or `-cast(int)(s.x[0])`
>>>         /tmp/test.d(7): Deprecation: integral promotion not done for
>>> `-s.x[1]`, use '-transition=intpromote' switch or `-cast(int)(s.x[1])`
>>>
>>>
>>> Why should I need to explicitly cast to int only to reassign it back to byte?!  This is ridiculous.
>>
>>
>> Seriously, WTF is going on here?

D used to not promote integer like C in the case of -short, -byte, ~ubyte etc. Which is a strange discrepancy as all other integer arithmetic are the same.

I'm surprised by the number of complaints, what do you prefer:
- explain until the end of times that D has the same integer promotion that C, except for one edge case with unary ops and smaller integers? and have translated C code have subtle bugs.
- add a cast here and there for some years

February 18, 2018
On 18 February 2018 at 05:36, Dmitry Olshansky via Digitalmars-d < digitalmars-d@puremagic.com> wrote:

> On Sunday, 18 February 2018 at 01:09:57 UTC, Manu wrote:
>
>> On 5 February 2018 at 11:22, H. S. Teoh via Digitalmars-d < digitalmars-d@puremagic.com> wrote:
>>
>> Code:
>>>
>>>         struct S {
>>>                 byte[2] x;
>>>         }
>>>         void main() {
>>>                 S s, t;
>>>                 s.x = [ 1, -1 ];                // OK
>>>                 t.x = [ -s.x[0], -s.x[1] ];     // NG (line 7)
>>>         }
>>>
>>>
>>> Compiler says:
>>>         /tmp/test.d(7): Deprecation: integral promotion not done for
>>> `-s.x[0]`, use '-transition=intpromote' switch or `-cast(int)(s.x[0])`
>>>         /tmp/test.d(7): Deprecation: integral promotion not done for
>>> `-s.x[1]`, use '-transition=intpromote' switch or `-cast(int)(s.x[1])`
>>>
>>>
>>> Why should I need to explicitly cast to int only to reassign it back to byte?!  This is ridiculous.
>>>
>>
>>
>> Seriously, WTF is going on here?
>>
>
> C compilers did it for ages, but D doesn’t auto promote to int on unary ops. Hence the warning, the suggestion is kinda stupid thiugh.
>
> C gets away by truncating results silently on assign of int to byte


The 'solution' so add cast(int) and then cast back is not okay. I have code
that does a lot of work on bytes/shorts (colour components are small
integers that receive a lot of maths), and most lines get 3-4 times longer
because of these casts...
I can't accept that.

If change the behaviour (is done), then just let the code be broken! Emitting these terrible noises, and encouraging people to make their code even noisier than the compiler output is much worse than broken code. There are hundreds of lines I need to molest to make the compiler shut up. I won't type another line of code on my colour library until this noise is gone... I will not maintain it. I am emotionally incapable of assaulting my code with those casts.


February 18, 2018
On 2/18/2018 11:21 AM, Guillaume Piolat wrote:
> D used to not promote integer like C in the case of -short, -byte, ~ubyte etc. Which is a strange discrepancy as all other integer arithmetic are the same.

It was a bug, plain and simple. Whether it was always there, or was inadvertently introduced at some point, I don't know.