Re: opIndexUnary post in-/decrement how to ?

2021-07-16 Thread wjoe via Digitalmars-d-learn

On Thursday, 15 July 2021 at 15:39:59 UTC, Tejas wrote:

On Thursday, 15 July 2021 at 13:28:19 UTC, wjoe wrote:

On Thursday, 15 July 2021 at 12:09:20 UTC, Tejas wrote:

[...]


The only way, for me, to explain the error message ```opIndex 
isn't an lvalue and can't be modified.``` for ```i[1]++``` is 
that the compiler rewrites to

```D
(auto e = i.opIndex(1), i.opIndex(1).opUnary!"++"()/*1) note: 
not opIndexUnary*/, return e;)

```
If it were using ```opIndexUnary``` at 1) it would work.

[...]


Sucks :(

I really can't spend more time on this, hope things work out 
for you somehow.

Best of luck

Regards
Tejas


No worries. Your time is very much appreciated.


Re: opIndexUnary post in-/decrement how to ?

2021-07-15 Thread Tejas via Digitalmars-d-learn

On Thursday, 15 July 2021 at 13:28:19 UTC, wjoe wrote:

On Thursday, 15 July 2021 at 12:09:20 UTC, Tejas wrote:

[...]


The only way, for me, to explain the error message ```opIndex 
isn't an lvalue and can't be modified.``` for ```i[1]++``` is 
that the compiler rewrites to

```D
(auto e = i.opIndex(1), i.opIndex(1).opUnary!"++"()/*1) note: 
not opIndexUnary*/, return e;)

```
If it were using ```opIndexUnary``` at 1) it would work.

[...]


Sucks :(

I really can't spend more time on this, hope things work out for 
you somehow.

Best of luck

Regards
Tejas



Re: opIndexUnary post in-/decrement how to ?

2021-07-15 Thread wjoe via Digitalmars-d-learn

On Thursday, 15 July 2021 at 12:09:20 UTC, Tejas wrote:

[...]

Oh yes, that is what happens. I was trying to be a little 
concise.
You are correct, this is what the code will look in the gory 
details (I believe) :

```d
auto x = (auto e = i.opIndex(1), i.opIndexUnary("++")(1)/*this 
may or may not expand to what you wrote, not sure what the 
compiler does, although what you say does sound like the 
obvious thing to do*/, return e);

```
I did indeed override opIndex() but since i need to apply a 
bit mask and do some shifting I can't return anything by ref.


As I mentioned, maybe the bit manipulation library could 
help(although they don't seem to be overloading the operators 
in the first place, thus sidestepping the problem you 
encountered).


The only way, for me, to explain the error message ```opIndex 
isn't an lvalue and can't be modified.``` for ```i[1]++``` is 
that the compiler rewrites to

```D
(auto e = i.opIndex(1), i.opIndex(1).opUnary!"++"()/*1) note: not 
opIndexUnary*/, return e;)

```
If it were using ```opIndexUnary``` at 1) it would work.

The gist of it
```D
part_int_t!("alpha", 1, "beta", 4, "gamma", 16) a;

struct part_int_t(ARGS...)
{
   int _int;
   mixin(generatePartInt!ARGS);
}

// auto-generated from ARGS
alias typeof_alpha = bool;
enum ulong offset_alpha = 0;
enum ulong mask_alpha = 0x;
// etc.

//getter
@property const pure nothrow @nogc typeof_alpha alpha() {
   if (_int & signmask_alpha)
  return cast(typeof(return))(((_int & mask_alpha) >> 
offset_alpha) | signpad_alpha);

   else
  return cast(typeof(return))((_int & mask_alpha) >> 
offset_alpha);

}

// setter
// ...

const pure nothrow @nogc auto opIndex(size_t _i) {
  switch (_i) {
default:
  assert (0, "Out of bounds.");

 // cases are auto generated from ARGS and mixed in like this
 case 0:
return alpha;

case 1:
 return beta;

case 2:
 return gamma;
}}

// OpIndexAssign, etc.

pure nothrow @nogc auto opIndexUnary(string op)(size_t _i) {
  switch (_i) {
default:
  assert (0, "Out of bounds.");

 // cases are auto generated from ARGS and mixed in like this
 case 0:
typeof_alpha result;
auto tmp = prepare_for_op!(op, "alpha");
mixin(op ~ "tmp");
result = finalize!(op, "alpha")(tmp);
return result;

// ...

}}

// repeat for beta and gamma

```

I'll revisit the bitfields in std.bitmanip but there were 
shortcomings which prompted me to start ```part_int_t```.




Re: opIndexUnary post in-/decrement how to ?

2021-07-15 Thread Tejas via Digitalmars-d-learn

On Thursday, 15 July 2021 at 11:02:17 UTC, wjoe wrote:

On Thursday, 15 July 2021 at 04:07:49 UTC, Tejas wrote:

Your code
```d
auto x = i[1]++;
```
Expands to:
```d
auto x = (auto e = i[1]/*notice opIndex*/, ++i[1]/* notice 
opIndexUnary*/, return e;);

```

This doesn't happen with pre increment. No compiler 
shenanigans.


Interesting to see it spelt out like this (your remarks are 
very enlightening) so I just went one step further and rewrote 
this line like so:

```D
i[1] = 3;
auto x = (){auto e = i[1]; ++i[1]; return e;}();
assert (i[1] == 4 && x == 3);
```
This just works. But I don't think this is what happens. What I 
think happens is that the compiler rewrites ```i[1]++`` to 
something like this:

```D
i.opIndex(1).opUnary!"++"();
```
plus all the other shenanigans.




Oh yes, that is what happens. I was trying to be a little concise.
You are correct, this is what the code will look in the gory 
details (I believe) :

```d
auto x = (auto e = i.opIndex(1), i.opIndexUnary("++")(1)/*this 
may or may not expand to what you wrote, not sure what the 
compiler does, although what you say does sound like the obvious 
thing to do*/, return e);

```
I did indeed override opIndex() but since i need to apply a bit 
mask and do some shifting I can't return anything by ref.


As I mentioned, maybe the bit manipulation library could 
help(although they don't seem to be overloading the operators in 
the first place, thus sidestepping the problem you encountered).


Re: opIndexUnary post in-/decrement how to ?

2021-07-15 Thread wjoe via Digitalmars-d-learn

On Thursday, 15 July 2021 at 04:07:49 UTC, Tejas wrote:

Your code
```d
auto x = i[1]++;
```
Expands to:
```d
auto x = (auto e = i[1]/*notice opIndex*/, ++i[1]/* notice 
opIndexUnary*/, return e;);

```

This doesn't happen with pre increment. No compiler shenanigans.


Interesting to see it spelt out like this (your remarks are very 
enlightening) so I just went one step further and rewrote this 
line like so:

```D
i[1] = 3;
auto x = (){auto e = i[1]; ++i[1]; return e;}();
assert (i[1] == 4 && x == 3);
```
This just works. But I don't think this is what happens. What I 
think happens is that the compiler rewrites ```i[1]++`` to 
something like this:

```D
i.opIndex(1).opUnary!"++"();
```
plus all the other shenanigans.

I did indeed override opIndex() but since i need to apply a bit 
mask and do some shifting I can't return anything by ref.


Re: opIndexUnary post in-/decrement how to ?

2021-07-15 Thread wjoe via Digitalmars-d-learn

On Thursday, 15 July 2021 at 04:01:15 UTC, Tejas wrote:

I'm so sorry all this was basically useless for you.

I can't spend more time on this, so as a last resort I leave 
you this:


https://dlang.org/phobos/std_bitmanip.html

This is the official bit manipulation standard library, maybe 
it will help you in some way; the ```bitfield``` struct looked 
mighty familiar to your ```part_int``` struct, but maybe that's 
my cognitive bias,  you should verify it.


Best of luck!


Oh no it wasn't useless at all. The time and effort you put into 
this is very much appreciated and that of everyone else, too.




Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 20:55:32 UTC, wjoe wrote:

In my particular case the compiler can rule out ```opIndex``` 
so why does it abort instead of trying ```opIndexUnary``` ? Or 
was it trying and it didn't work ? If that's the case I'd like 
to know the reason why it discarded ```opIndexUnary```.


Anyways all the answers so far are much appreciated!


Your code
```d
auto x = i[1]++;
```
Expands to:
```d
auto x = (auto e = i[1]/*notice opIndex*/, ++i[1]/* notice 
opIndexUnary*/, return e;);

```

This doesn't happen with pre increment. No compiler shenanigans.

Hence your problems.

Please take a look at the library I mentioned previously, it may 
help.





Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 20:55:32 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 16:13:35 UTC, Tejas wrote:

[...]


Congratulations:) Unfortunately I haven't got anything I could 
return by ref so I can't take advantage of a low hanging fruit.
In my book overloading operators is no fun - at all - and 
always a last resort because it requires so much time and 
testing and causes so many headaches.


Workarounds exist like ```i[n] += 1``` or direct call via 
```i.opIndexUnary!"++"(n)``` or simply ```++i[n]```.
But that's beside the point. There's nothing in the spec that 
says something about something needs to be returned by ref.
Rewriting manually compiles and works as intended. So clearly 
something else is going on which makes the compiler select 
```opIndex``` over ```opIndexUnary``` rewriting it post to pre.
In my particular case the compiler can rule out ```opIndex``` 
so why does it abort instead of trying ```opIndexUnary``` ? Or 
was it trying and it didn't work ? If that's the case I'd like 
to know the reason why it discarded ```opIndexUnary```.


Anyways all the answers so far are much appreciated!


I'm so sorry all this was basically useless for you.

I can't spend more time on this, so as a last resort I leave you 
this:


https://dlang.org/phobos/std_bitmanip.html

This is the official bit manipulation standard library, maybe it 
will help you in some way; the ```bitfield``` struct looked 
mighty familiar to your ```part_int``` struct, but maybe that's 
my cognitive bias,  you should verify it.


Best of luck!


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread wjoe via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 16:13:35 UTC, Tejas wrote:

On Wednesday, 14 July 2021 at 15:08:56 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote:

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

[...]


It's how the contract of post-inc/dec work---pre-inc/dec 
return the modified value, post-inc/dec return the original 
value.


[...]


That makes a lot of sense now, thank you!


**IT WORKS NOW**

Thanks vit for the ```ref``` idea!

```d
import   std.stdio;

struct abc{
int[100] a;
static int temp;
ref/*notice this ref*/ int opIndex(int index)return/*NOTICE 
THE RETURN*/ {

return a[index];
}
int opIndexUnary(string s)(int index)
if(s == "++"){
return ++a[index];
}
int[] opUnary(string s)() if (s == "++"){
return a[] += 1;
}
}

void main (){
abc s;

writeln(s[0]++);// doesn't work for some reason EDIT: IT 
NOW WORKS


writeln(s[0]);
writeln(++s[0]);

   // writeln(s++);//but this works!!

   // writeln(s);
}

```


Congratulations:) Unfortunately I haven't got anything I could 
return by ref so I can't take advantage of a low hanging fruit.
In my book overloading operators is no fun - at all - and always 
a last resort because it requires so much time and testing and 
causes so many headaches.


Workarounds exist like ```i[n] += 1``` or direct call via 
```i.opIndexUnary!"++"(n)``` or simply ```++i[n]```.
But that's beside the point. There's nothing in the spec that 
says something about something needs to be returned by ref.
Rewriting manually compiles and works as intended. So clearly 
something else is going on which makes the compiler select 
```opIndex``` over ```opIndexUnary``` rewriting it post to pre.
In my particular case the compiler can rule out ```opIndex``` so 
why does it abort instead of trying ```opIndexUnary``` ? Or was 
it trying and it didn't work ? If that's the case I'd like to 
know the reason why it discarded ```opIndexUnary```.


Anyways all the answers so far are much appreciated!


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Ali Çehreli via Digitalmars-d-learn

On 7/14/21 11:27 AM, Tejas wrote:

> the compiler error should have been a dead giveaway
> that opIndex was returning a _constant_ value

I know you mean "rvalue" but if I may be unnecessarily pedantic, an 
rvalue can indeed be mutated:


struct A {
  int i;
  void mutate() {
i = 42;
import std.stdio;
writeln("I am not constant. :)");
  }
}

struct B {
  auto opUnary(string op)() {
return A();
  }
}

void main() {
  auto b = B();
  (++b).mutate();  // <-- Mutating an rvalue
}

Ali



Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 17:42:03 UTC, Ali Çehreli wrote:

On 7/14/21 9:13 AM, Tejas wrote:

>  ref/*notice this ref*/ int opIndex(int
index)return/*NOTICE THE
> RETURN*/ {

Indeed... I cover that 'ref' here:


http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.return%20type,%20operator

Two quotes from that section:

1) "it is advisable to observe the return type of the same 
operator on fundamental types."


NOTE: I agree that for that to make sense, one needs to know 
the "return type" of fundamental type operations. It may not be 
clear that ++i is a reference to 'i' ("i itself"):


void main() {
  int i;
  ++i = 42;
  assert(i == 42);
}

2) "With the exception of opAssign, it is recommended that the 
operators that modify the object return the object itself. 
[...] The return type is the type of the struct, marked by the 
ref keyword to mean reference."


Ali


To be honest even the compiler error should have been a dead 
giveaway that opIndex was returning a _constant_ value and the 
```++``` operator can't operate on that... I should've taken the 
diagnostic to heart and not just tried to brute force my way 
through the problem.



Obviously, I retract my statement that this might be a compiler 
bug.


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Ali Çehreli via Digitalmars-d-learn

On 7/14/21 9:13 AM, Tejas wrote:

>  ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE
> RETURN*/ {

Indeed... I cover that 'ref' here:


http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.return%20type,%20operator

Two quotes from that section:

1) "it is advisable to observe the return type of the same operator on 
fundamental types."


NOTE: I agree that for that to make sense, one needs to know the "return 
type" of fundamental type operations. It may not be clear that ++i is a 
reference to 'i' ("i itself"):


void main() {
  int i;
  ++i = 42;
  assert(i == 42);
}

2) "With the exception of opAssign, it is recommended that the operators 
that modify the object return the object itself. [...] The return type 
is the type of the struct, marked by the ref keyword to mean reference."


Ali



Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 15:08:56 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote:

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

[...]


It's how the contract of post-inc/dec work---pre-inc/dec 
return the modified value, post-inc/dec return the original 
value.


[...]


That makes a lot of sense now, thank you!


**IT WORKS NOW**

Thanks vit for the ```ref``` idea!

```d
import   std.stdio;

struct abc{
int[100] a;
static int temp;
ref/*notice this ref*/ int opIndex(int index)return/*NOTICE 
THE RETURN*/ {

return a[index];
}
int opIndexUnary(string s)(int index)
if(s == "++"){
return ++a[index];
}
int[] opUnary(string s)() if (s == "++"){
return a[] += 1;
}
}

void main (){
abc s;

writeln(s[0]++);// doesn't work for some reason EDIT: IT NOW 
WORKS


writeln(s[0]);
writeln(++s[0]);

   // writeln(s++);//but this works!!

   // writeln(s);
}

```


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 15:23:05 UTC, vit wrote:

On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote:


```d
import   std.stdio;

struct abc{
int[100] a;

struct Proxy{
abc* ptr;
const int index;

int opUnary(string op : "++")(){
return ++ptr.a[index]; //add missing ++
}
}

Proxy opIndex(int index)return{
return Proxy(, index);
}
}

void main (){
abc s;
s[0]++;
++s[0];
}


```


I tried changing ```s[0]++``` to ``` s[0] += 1```

the same lvalue problem arose :(

```

Error: `s.opIndex(0)` is not an lvalue and cannot be modified

```



Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 15:23:05 UTC, vit wrote:

On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote:


```d
import   std.stdio;

struct abc{
int[100] a;

struct Proxy{
abc* ptr;
const int index;

int opUnary(string op : "++")(){
return ++ptr.a[index]; //add missing ++
}
}

Proxy opIndex(int index)return{
return Proxy(, index);
}
}

void main (){
abc s;
s[0]++;
++s[0];
}


```


The ```post increment``` still doesn't work :(

this is the output for your code:
```
Proxy(7FFC7ACB3E60, 0)
2
```
And if the add the following statements:
```d

writeln(s[0]++);
writeln(s[0]);
writeln(s[0]++);
writeln(s[0]);
writeln(++s[0]);
```

Output:
```
Proxy(7FFCBE3CAF20, 0)
Proxy(7FFCBE3CAF20, 0)
Proxy(7FFCBE3CAF20, 0)
Proxy(7FFCBE3CAF20, 0)
3

```



Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread vit via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote:


```d
import   std.stdio;

struct abc{
int[100] a;

struct Proxy{
abc* ptr;
const int index;

int opUnary(string op : "++")(){
return ++ptr.a[index]; //add missing ++
}
}

Proxy opIndex(int index)return{
return Proxy(, index);
}
}

void main (){
abc s;
s[0]++;
++s[0];
}


```


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote:

On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote:

On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote:

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:

[...]


From doc: https://dlang.org/spec/operatoroverloading.html
Postincrement e++ and Postdecrement e-- Operators
These are not directly overloadable, but instead are 
rewritten in terms of the ++e and --e prefix operators:


Postfix Operator Rewrites
op  rewrite
e-- (auto t = e, --e, t)
e++ (auto t = e, ++e, t)


Rewriting part doesn't work with operator overloading.


If the rewriting part doesn't work with over

This work:

```d
import   std.stdio;

struct abc{
int[100] a;

ref int opIndex(int index)return{
return a[index];
}
}

void main (){
abc s;
s[0]++;
++s[0];
}

```


Oh... since it was asking for an lvalue, you just passed it by 
reference... seems so obvious in hindsight...


Nice.

Pity it doesn't seem to solve OP's problem.


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread vit via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 15:01:45 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote:

On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote:

[...]



This work:

```d
import   std.stdio;

struct abc{
int[100] a;

ref int opIndex(int index)return{
return a[index];
}
}

void main (){
abc s;
s[0]++;
++s[0];
}

```


This does work for that example but I can't return by reference 
because what I'm operating on is a part of an int.

Some context:
```D
struct part_int_t(ARGS...)
{
   int _int;
   mixin(generate_parts!ARGS);
}

alias handle_t = part_int_t!("isAllocated", 1, "gen", 8, 
"index", 23);


handle_t handle;

static assert (is(handle.typeof_isAllocated): bool));
static assert (is(handle.typeof_gen): ubyte));
static assert (is(handle.typeof_index): uint));

handle[2] = true;
handle.gen = 1;
handle.index = 1234;

assert (handle.isAllocated);
assert (handle.gen = 1);
assert (handle[0] = 1234);

handle++;
assert (handle.index == 1235);

handle.gen++;
assert (handle.gen == 2);

handle.reset();
assert (!handle.isAllocated);
assert (handle.gen = 3);
assert (handle.index = 0);

```

generate_parts!ARGS produces bit masks, getters, setters, 
opIndex/OpAssign/Unary, etc. and it's impossible to return bits 
0-26 of _int by ref.


Try something like this:

```d
import   std.stdio;

struct abc{
int[100] a;

struct Proxy{
abc* ptr;
const int index;

int opUnary(string op : "++")(){
return ptr.a[index];
}
}

Proxy opIndex(int index)return{
return Proxy(, index);
}
}

void main (){
abc s;
s[0]++;
++s[0];
}
```


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread wjoe via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote:

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

[...]


It's how the contract of post-inc/dec work---pre-inc/dec return 
the modified value, post-inc/dec return the original value.


[...]


That makes a lot of sense now, thank you!


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread wjoe via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote:

On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote:

On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote:

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:

[...]


From doc: https://dlang.org/spec/operatoroverloading.html
Postincrement e++ and Postdecrement e-- Operators
These are not directly overloadable, but instead are 
rewritten in terms of the ++e and --e prefix operators:


Postfix Operator Rewrites
op  rewrite
e-- (auto t = e, --e, t)
e++ (auto t = e, ++e, t)


Rewriting part doesn't work with operator overloading.


If the rewriting part doesn't work with overloading then why 
aren't we allowed to explicitly overload 
```post-increment/decrement``` operators?


How else will the OP solve their problem?

It must rewrite,  otherwise it's impossible (I think).



This work:

```d
import   std.stdio;

struct abc{
int[100] a;

ref int opIndex(int index)return{
return a[index];
}
}

void main (){
abc s;
s[0]++;
++s[0];
}

```


This does work for that example but I can't return by reference 
because what I'm operating on is a part of an int.

Some context:
```D
struct part_int_t(ARGS...)
{
   int _int;
   mixin(generate_parts!ARGS);
}

alias handle_t = part_int_t!("isAllocated", 1, "gen", 8, "index", 
23);


handle_t handle;

static assert (is(handle.typeof_isAllocated): bool));
static assert (is(handle.typeof_gen): ubyte));
static assert (is(handle.typeof_index): uint));

handle[2] = true;
handle.gen = 1;
handle.index = 1234;

assert (handle.isAllocated);
assert (handle.gen = 1);
assert (handle[0] = 1234);

handle++;
assert (handle.index == 1235);

handle.gen++;
assert (handle.gen == 2);

handle.reset();
assert (!handle.isAllocated);
assert (handle.gen = 3);
assert (handle.index = 0);

```

generate_parts!ARGS produces bit masks, getters, setters, 
opIndex/OpAssign/Unary, etc. and it's impossible to return bits 
0-26 of _int by ref.




Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Mike Parker via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote:


``` {auto a = i[1] , ++i[1] , a} //note the , not the ;```

Sorry I can't provide something even more concrete.


Yes I saw that, and I suppose it would work just fine if it 
were rewritten to just  ```++i[1]```.
What I'm struggling to understand is the ```{auto a = i[1], ... 
,a}``` part. I can't parse that. What's up with the assignment 
and the comma stuff ?


It's how the contract of post-inc/dec work---pre-inc/dec return 
the modified value, post-inc/dec return the original value.


```d
int i = 1;
assert(++i == 2);
int j = 1;
assert(j++ == 1);
```
The rewrite of the compiler is done in such a way that the result 
of the expression is the original value. That's what the commas 
are for.


```
So you can parse that rewrite example as it if were a function, 
with each expression separated by a comma, and the final 
expression the result:


```d
int postInc(ref int j)
{
auto a = j;
++j;
return a;
}
```

It doesn't actually create a function, but this demonstrates the 
effect.


So that's why you don't have to worry about postfix/prefix for 
these. The compiler handles that behind the scenes. All you need 
to worry about is returning the incremented value.


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread wjoe via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:


I think it's a bug, because the following works:

```d

import   std.stdio;

struct abc{
int[100] a;
int opIndex(int index){
return a[index];
}
int opIndexUnary(string s)(int index)
if(s == "++"){
return ++a[index];
}
int[] opUnary(string s)() if (s == "++"){
return a[] += 1;
}
}

void main (){
abc s;
int[100] a;
int temp;
writeln (a[20]++);

writeln(a[20]);

writeln(++s[20]);

writeln(s[20]);

//writeln(s[0]++);// doesn't work for some reason

writeln(s[0]);

writeln(s++);//but this works!!

writeln(s);
}

```


```D
writeln(++s[0]); // should work
writeln(s++); // this calls opUnary if I'm not mistaken
```


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread vit via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote:

On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote:

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:

[...]


From doc: https://dlang.org/spec/operatoroverloading.html
Postincrement e++ and Postdecrement e-- Operators
These are not directly overloadable, but instead are rewritten 
in terms of the ++e and --e prefix operators:


Postfix Operator Rewrites
op  rewrite
e-- (auto t = e, --e, t)
e++ (auto t = e, ++e, t)


Rewriting part doesn't work with operator overloading.


If the rewriting part doesn't work with overloading then why 
aren't we allowed to explicitly overload 
```post-increment/decrement``` operators?


How else will the OP solve their problem?

It must rewrite,  otherwise it's impossible (I think).



This work:

```d
import   std.stdio;

struct abc{
int[100] a;

ref int opIndex(int index)return{
return a[index];
}
}

void main (){
abc s;
s[0]++;
++s[0];
}

```


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote:

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote:


``` {auto a = i[1] , ++i[1] , a} //note the , not the ;```

Sorry I can't provide something even more concrete.


Yes I saw that, and I suppose it would work just fine if it 
were rewritten to just  ```++i[1]```.
What I'm struggling to understand is the ```{auto a = i[1], 
... ,a}``` part. I can't parse that. What's up with the 
assignment and the comma stuff ?


I think it's a bug, because the following works:

```d

import   std.stdio;

struct abc{
int[100] a;
int opIndex(int index){
return a[index];
}
int opIndexUnary(string s)(int index)
if(s == "++"){
return ++a[index];
}
int[] opUnary(string s)() if (s == "++"){
return a[] += 1;
}
}

void main (){
abc s;
int[100] a;
int temp;
writeln (a[20]++);

writeln(a[20]);

writeln(++s[20]);

writeln(s[20]);

//writeln(s[0]++);// doesn't work for some reason

writeln(s[0]);

writeln(s++);//but this works!!

writeln(s);
}

```


From doc: https://dlang.org/spec/operatoroverloading.html
Postincrement e++ and Postdecrement e-- Operators
These are not directly overloadable, but instead are rewritten 
in terms of the ++e and --e prefix operators:


Postfix Operator Rewrites
op  rewrite
e-- (auto t = e, --e, t)
e++ (auto t = e, ++e, t)


Rewriting part doesn't work with operator overloading.


If the rewriting part doesn't work with overloading then why 
aren't we allowed to explicitly overload 
```post-increment/decrement``` operators?


How else will the OP solve their problem?

It must rewrite,  otherwise it's impossible (I think).


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread vit via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote:

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote:


``` {auto a = i[1] , ++i[1] , a} //note the , not the ;```

Sorry I can't provide something even more concrete.


Yes I saw that, and I suppose it would work just fine if it 
were rewritten to just  ```++i[1]```.
What I'm struggling to understand is the ```{auto a = i[1], 
... ,a}``` part. I can't parse that. What's up with the 
assignment and the comma stuff ?


I think it's a bug, because the following works:

```d

import   std.stdio;

struct abc{
int[100] a;
int opIndex(int index){
return a[index];
}
int opIndexUnary(string s)(int index)
if(s == "++"){
return ++a[index];
}
int[] opUnary(string s)() if (s == "++"){
return a[] += 1;
}
}

void main (){
abc s;
int[100] a;
int temp;
writeln (a[20]++);

writeln(a[20]);

writeln(++s[20]);

writeln(s[20]);

//writeln(s[0]++);// doesn't work for some reason

writeln(s[0]);

writeln(s++);//but this works!!

writeln(s);
}

```


From doc: https://dlang.org/spec/operatoroverloading.html
Postincrement e++ and Postdecrement e-- Operators
These are not directly overloadable, but instead are rewritten in 
terms of the ++e and --e prefix operators:


Postfix Operator Rewrites
op  rewrite
e-- (auto t = e, --e, t)
e++ (auto t = e, ++e, t)


Rewriting part doesn't work with operator overloading.




Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote:

On Wednesday, 14 July 2021 at 10:07:38 UTC, wjoe wrote:

I'm want to do something like this
```D
part_int_t!(1,2,3) i;

auto x = -i[0];
--i[1]; // 1
i[1]++; // 2

```
I think the operator I need to overload would be opIndexUnary 
which I did.

(1) compiles.
(2) doesn't - the compiler complains that i.opIndex isn't an 
lvalue and can't be modified.
The language spec says that Post in- and decrement are 
rewritten but something's fishy.

What's going on behind the scene and how can I make it work?


Please check the language spec here:

https://dlang.org/spec/operatoroverloading.html#postincrement_postdecrement_operators

You can't directly overload the postincrement operator.

You need to rewrite it like:

``` {auto a = i[1] , ++i[1] , a} //note the , not the ;```

Sorry I can't provide something even more concrete.


Ignore this, I wanted to say that this is what the _compiler_ 
rewrites it to when _you_ write ```i[1]++```


There is no way to explicitly overload the ```post increment``` 
operator because of this.


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote:

On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote:


``` {auto a = i[1] , ++i[1] , a} //note the , not the ;```

Sorry I can't provide something even more concrete.


Yes I saw that, and I suppose it would work just fine if it 
were rewritten to just  ```++i[1]```.
What I'm struggling to understand is the ```{auto a = i[1], ... 
,a}``` part. I can't parse that. What's up with the assignment 
and the comma stuff ?


I think it's a bug, because the following works:

```d

import   std.stdio;

struct abc{
int[100] a;
int opIndex(int index){
return a[index];
}
int opIndexUnary(string s)(int index)
if(s == "++"){
return ++a[index];
}
int[] opUnary(string s)() if (s == "++"){
return a[] += 1;
}
}

void main (){
abc s;
int[100] a;
int temp;
writeln (a[20]++);

writeln(a[20]);

writeln(++s[20]);

writeln(s[20]);

//writeln(s[0]++);// doesn't work for some reason

writeln(s[0]);

writeln(s++);//but this works!!

writeln(s);
}

```


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread wjoe via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote:


``` {auto a = i[1] , ++i[1] , a} //note the , not the ;```

Sorry I can't provide something even more concrete.


Yes I saw that, and I suppose it would work just fine if it were 
rewritten to just  ```++i[1]```.
What I'm struggling to understand is the ```{auto a = i[1], ... 
,a}``` part. I can't parse that. What's up with the assignment 
and the comma stuff ?


Re: opIndexUnary post in-/decrement how to ?

2021-07-14 Thread Tejas via Digitalmars-d-learn

On Wednesday, 14 July 2021 at 10:07:38 UTC, wjoe wrote:

I'm want to do something like this
```D
part_int_t!(1,2,3) i;

auto x = -i[0];
--i[1]; // 1
i[1]++; // 2

```
I think the operator I need to overload would be opIndexUnary 
which I did.

(1) compiles.
(2) doesn't - the compiler complains that i.opIndex isn't an 
lvalue and can't be modified.
The language spec says that Post in- and decrement are 
rewritten but something's fishy.

What's going on behind the scene and how can I make it work?


Please check the language spec here:

https://dlang.org/spec/operatoroverloading.html#postincrement_postdecrement_operators

You can't directly overload the postincrement operator.

You need to rewrite it like:

``` {auto a = i[1] , ++i[1] , a} //note the , not the ;```

Sorry I can't provide something even more concrete.


opIndexUnary post in-/decrement how to ?

2021-07-14 Thread wjoe via Digitalmars-d-learn

I'm want to do something like this
```D
part_int_t!(1,2,3) i;

auto x = -i[0];
--i[1]; // 1
i[1]++; // 2

```
I think the operator I need to overload would be opIndexUnary 
which I did.

(1) compiles.
(2) doesn't - the compiler complains that i.opIndex isn't an 
lvalue and can't be modified.
The language spec says that Post in- and decrement are rewritten 
but something's fishy.

What's going on behind the scene and how can I make it work?