Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-30 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/30/19 10:03 PM, Nicholas Wilson wrote:

On Thursday, 31 January 2019 at 02:29:47 UTC, Steven Schveighoffer wrote:

I came up with this idea based on tempCString, but it doesn't work:

So I don't get why it doesn't work. But if that was fixed, could be a 
potential workaround without requiring a DIP.


Thats nice! But it doesn't fix the problem that in generic code you 
don't know without checking if you need to do that. Also the template 
bloat.


Yeah, it could do this too:

auto ref rv(T)(auto ref T t)
{
   static if(__traits(isRef, t)) return t;
   else /* do the other stuff */
}

But yes, template bloat. Plus having to put rv on everything... would 
suck. The DIP to me seems like it should be good with the clarification 
of not applying to lvalue -> rvalue auto translations.


-Steve


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-30 Thread Nicholas Wilson via Digitalmars-d-announce
On Thursday, 31 January 2019 at 02:29:47 UTC, Steven 
Schveighoffer wrote:
I came up with this idea based on tempCString, but it doesn't 
work:


So I don't get why it doesn't work. But if that was fixed, 
could be a potential workaround without requiring a DIP.


Thats nice! But it doesn't fix the problem that in generic code 
you don't know without checking if you need to do that. Also the 
template bloat.


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-30 Thread Steven Schveighoffer via Digitalmars-d-announce

On 1/29/19 6:52 AM, Andrei Alexandrescu wrote:

While writing this example:

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
if (alloc.reallocate(a, 200 * int.sizeof))
{
     assert(a.length == 200);
}

=>

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
void[] __temp0 = a;
if (alloc.reallocate(__temp0, 200 * int.sizeof)
{
     assert(a.length == 200);
}

I noticed a problem - the lowering as informally described in DIP 1016 
makes it difficult to figure how function calls present in control 
statements like if, while, etc. should behave. Where should the 
temporary go? An expression-based lowering clarifies everything. A 
statement-based lowering would need to work on a case basis for all 
statements involving expressions.


I don't think it's very difficult or confusing. Any rvalue in any 
expression that requires ref should be implicitly declared before the 
statement that contains the expression, and include a new scope:




>

{
   auto _tmpr1 = r1;
   auto _tmpr2 = r2;
   auto _tmpr3 = r3;
   ...
   auto _tmprN = rN;
   
}

Essentially, nothing is different from existing semantics today, when 
rvalues are used and provides reference semantics (yes, it's possible, 
see tempCString). They live until the end of the statement. It's how 
this has to be. It can't be expression based.


-Steve


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-30 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/30/19 3:34 AM, Kagamin wrote:

On Tuesday, 29 January 2019 at 11:52:40 UTC, Andrei Alexandrescu wrote:

Where should the temporary go?


Doesn't D already specify allocation and lifetime of temporaries? AIU 
the DIP doesn't invent the notion of a temporary.


My bad, I overloaded the term "temporary". I meant the variable inserted 
by the lowering.


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-30 Thread Kagamin via Digitalmars-d-announce
On Tuesday, 29 January 2019 at 11:52:40 UTC, Andrei Alexandrescu 
wrote:

Where should the temporary go?


Doesn't D already specify allocation and lifetime of temporaries? 
AIU the DIP doesn't invent the notion of a temporary.


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-29 Thread Rubn via Digitalmars-d-announce
On Tuesday, 29 January 2019 at 15:44:02 UTC, Nicholas Wilson 
wrote:
On Tuesday, 29 January 2019 at 11:52:40 UTC, Andrei 
Alexandrescu wrote:

While writing this example:

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
if (alloc.reallocate(a, 200 * int.sizeof))
{
assert(a.length == 200);
}

=>

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
void[] __temp0 = a;
if (alloc.reallocate(__temp0, 200 * int.sizeof)
{
assert(a.length == 200);
}

I noticed a problem - the lowering as informally described in 
DIP 1016 makes it difficult to figure how function calls 
present in control statements like if, while, etc. should 
behave. Where should the temporary go? An expression-based 
lowering clarifies everything. A statement-based lowering 
would need to work on a case basis for all statements 
involving expressions.


On the contrary, an expression lowering cannot inject temporary 
declarations and is impossible.


The correct lowering in the case for `if` & friends follows the 
form of C++ initialiser conditions(?) i.e:


 if (auto val = expr(); val) { ... },

 or the slightly more ugly valid D:

 if ((){return expr(); }()) { ... }

this lambdification will work for just about anything: if, 
while, assert...


If it a condition then you can do the following in C++:

if(int* val = expr()) {
   // use val, not nullptr
}

Where it is useful is in the following case:

if(int val = expr(); val != -1) {

}

D follows C++'s construct for initializing a variable in control 
blocks. The only exception I think is for switch.


switch(int val = expr()) // ok in C++, not ok in D
{
}


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-29 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/29/19 10:57 AM, Adam D. Ruppe wrote:

On Tuesday, 29 January 2019 at 15:48:23 UTC, Andrei Alexandrescu wrote:

On 1/29/19 10:44 AM, Nicholas Wilson wrote:

  if (auto val = expr(); val) { ... },


Since we don't have these constructs, lowering would need to explain 
what happens here.



Nitpick, but D has something very similar to that:

if(auto val = expr()) { ... }

it just depends on val implicitly casting to bool.


It's okay if the resulting code is ugly, it won't be user-visible.


We do have to be careful about this - error messages sometimes leak that 
ugly code out.


Yah, it did happen in the past that implementations have been switched 
from lowering to a dedicated case. Lowerings do remain a terrific tool 
for conveying semantics and DIP authors should not worry about 
implementation details.


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-29 Thread Adam D. Ruppe via Digitalmars-d-announce
On Tuesday, 29 January 2019 at 15:48:23 UTC, Andrei Alexandrescu 
wrote:

On 1/29/19 10:44 AM, Nicholas Wilson wrote:

  if (auto val = expr(); val) { ... },


Since we don't have these constructs, lowering would need to 
explain what happens here.



Nitpick, but D has something very similar to that:

if(auto val = expr()) { ... }

it just depends on val implicitly casting to bool.

It's okay if the resulting code is ugly, it won't be 
user-visible.


We do have to be careful about this - error messages sometimes 
leak that ugly code out.


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-29 Thread Andrei Alexandrescu via Digitalmars-d-announce

On 1/29/19 10:44 AM, Nicholas Wilson wrote:

On Tuesday, 29 January 2019 at 11:52:40 UTC, Andrei Alexandrescu wrote:

While writing this example:

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
if (alloc.reallocate(a, 200 * int.sizeof))
{
    assert(a.length == 200);
}

=>

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
void[] __temp0 = a;
if (alloc.reallocate(__temp0, 200 * int.sizeof)
{
    assert(a.length == 200);
}

I noticed a problem - the lowering as informally described in DIP 1016 
makes it difficult to figure how function calls present in control 
statements like if, while, etc. should behave. Where should the 
temporary go? An expression-based lowering clarifies everything. A 
statement-based lowering would need to work on a case basis for all 
statements involving expressions.


On the contrary, an expression lowering cannot inject temporary 
declarations and is impossible.


The correct lowering in the case for `if` & friends follows the form of 
C++ initialiser conditions(?) i.e:


  if (auto val = expr(); val) { ... },


Since we don't have these constructs, lowering would need to explain 
what happens here. Not difficult, but would be nice if we could avoid.



  or the slightly more ugly valid D:

  if ((){return expr(); }()) { ... }

this lambdification will work for just about anything: if, while, assert...


Yes, converting to lambdas is nice and easy and requires no statement 
enumeration - just lower expressions to lambdas and be done with it. 
It's okay if the resulting code is ugly, it won't be user-visible.


Re: DIP 1016 should use expression lowering, not statement lowering

2019-01-29 Thread Nicholas Wilson via Digitalmars-d-announce
On Tuesday, 29 January 2019 at 11:52:40 UTC, Andrei Alexandrescu 
wrote:

While writing this example:

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
if (alloc.reallocate(a, 200 * int.sizeof))
{
assert(a.length == 200);
}

=>

int[] a = cast(int[]) alloc.allocate(100 * int.sizeof);
void[] __temp0 = a;
if (alloc.reallocate(__temp0, 200 * int.sizeof)
{
assert(a.length == 200);
}

I noticed a problem - the lowering as informally described in 
DIP 1016 makes it difficult to figure how function calls 
present in control statements like if, while, etc. should 
behave. Where should the temporary go? An expression-based 
lowering clarifies everything. A statement-based lowering would 
need to work on a case basis for all statements involving 
expressions.


On the contrary, an expression lowering cannot inject temporary 
declarations and is impossible.


The correct lowering in the case for `if` & friends follows the 
form of C++ initialiser conditions(?) i.e:


 if (auto val = expr(); val) { ... },

 or the slightly more ugly valid D:

 if ((){return expr(); }()) { ... }

this lambdification will work for just about anything: if, while, 
assert...