Page 1 of 4

Math syntax parsing issue

Posted: 07 Sep 2023, 10:39
by TheArkive
Not sure if this is a bug or not:

Code: Select all

d := 1
msgbox ((d) * (++d) * (++d))

; ---------------------------
; Test5.ahk
; ---------------------------
; 12
; ---------------------------
; OK   
; ---------------------------
I would think it would return 6 (1 x 2 x 3). Or is this not the right way to use that operator?

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 11:03
by WarlordAkamu67
Reproduced output of "12" even though the string version of the message box reports "1 * 2 * 3".

Code: Select all

#Requires AutoHotkey v2.0+

d := 1
msgbox ((d) " * " (++d) " * " (++d))

d := 1
msgbox ((d) * (++d) * (++d))

; ---------------------------
; Test5.ahk
; ---------------------------
; 12
; ---------------------------
; OK
; ---------------------------
stringnumbers.png
stringnumbers.png (17.48 KiB) Viewed 1939 times
multipliednumbers.png
multipliednumbers.png (16.69 KiB) Viewed 1939 times

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 11:07
by thqby
1. Variable d is pushed onto the stack instead of a value
2. ++d, then d = 2
3. Variable d is pushed onto the stack
4. d * d = 4
5. ++d, then d = 3
...
return 12

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 11:18
by andymbody
TheArkive wrote:
07 Sep 2023, 10:39
Not sure if this is a bug or not:
Sure looks like a bug.
e := d * ++d * ++d produces same issue.


Didn't see the explanation above.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 11:42
by TheArkive
Doesn't matter to me either way. I can of course write the expression differently. I'm just trying to figure out what's supposed to happen.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 11:50
by mikeyww
It isn't a bug, as explained by thqby.

Use if needed: (d + 1).

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 14:14
by teadrinker
IMO, a bug. Compare:

Code: Select all

n := 1
MsgBox( 'AHK: '        .                          n * ++n * ++n   . '`n'
        'Javascript: ' . GetJS().eval('var n = 1; n * ++n * ++n') )

GetJS() {
    static document := '', JS
    if !document {
        document := ComObject('HTMLFILE')
        document.write('<meta http-equiv="X-UA-Compatible" content="IE=9">')
        JS := document.parentWindow
        (document.documentMode < 9 && JS.execScript())
    }
    return JS
}

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 14:54
by teadrinker
Same in Java:

Code: Select all

public class Main {
    public static void main(String[] args) {
        int n = 1;
        System.out.println(n * ++n * ++n); // 6
    }
}

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 17:56
by andymbody
teadrinker wrote:
07 Sep 2023, 14:14
IMO, a bug. Compare:
Thx for the comparisons. I know very little about the low level operations between memory and registers, so could not argue in either direction, based on the explanation above. I think your comparison is stronger evidence towards a bug also. This specific instruction set is fairly uncommon so hopefully we don't see this issue very often or at all. But you have to wonder if it can creep in undetected in some circumstances. Maybe I can take advantage of it to double my bank account.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 18:34
by mikeyww

Code: Select all

#Requires AutoHotkey v2.0
d := 1
MsgBox d * (++d)         ;     2 * 2 = 4
d := 1
MsgBox (++d) * (++d) * d ; (3 * 3) * 3 = 27  ???
d := 1
MsgBox d * (++d) * (++d) ; (2 * 2) * 3 = 12
d := 1
MsgBox (++d) * d * (++d) ; (2 * 2) * 3 = 12
There is actually a pattern here.
1. Look at first two operands: increment both according to total number of increments.
2. Third operand is either this value (for d) or another increment (for ++d).

I admit that this differs from JavaScript! I'm not sure whether this was the author's intent (probably not).

At the least, it doesn't seem to fit exactly with the following description for ++.
The operation is performed and its result is used by the next operation.
The second example, adding to 27, surprised me the most.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 19:11
by andymbody
The pattern below shows clearly that the first ++d is being duplicated a second time by mistake (++d ++d). I also plugged in different values for d (1, 2, 3, 4, etc) and get the same pattern. Clearly a bug.

Code: Select all

d := 1
multiply := ++d * ++d	; 2 * 3 := 6
MsgBox % Multiply		; 9 -> (3*3)
d := 1
division := ++d / ++d	; 2 / 3 := .667
MsgBox % division		; 1.0 -> (3/3)
d := 1
subtract := ++d - ++d	; 2 - 3 := -1
MsgBox % subtract		; 0	-> (3-3)
d := 1
addition := ++d + ++d	; 2 + 3 := 5
MsgBox % addition		; 6	-> (3+3)
Which of the AHK modules might the ++x operator be located to see why this is happening? I don't have v2 installed, but this thread is v2, so it looks like this shows up in both versions. I guess @lexikos could take a look?

Andy

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 19:46
by teadrinker
Basically, the problem lies here:

Code: Select all

d := 1
MsgBox d * ++d ; expected 2, shows 4
The third operand in the examples above behaves as expected. @thqby's explanation is probably correct, but that doesn't mean it must be.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 19:49
by mikeyww
I didn't actually have trouble with that part, as I assumed that ++d executed first, d became 2, and then the computation was 2*2. Assuming that order would not matter for the first two operands, it would come out like this.

Code: Select all

#Requires AutoHotkey v2.0
d := 1
MsgBox (d := d + 1) * d
The evaluation with := would have to occur first. At that point, d=2, and the rest of the math is computed with that value. This actually matches the description in the documentation.

I was unable to follow what happened with (++d) * (++d). A plain description would seem to be that the two sums were processed in sequence (1 => 2 => 3), but then the final value was actually used in both operands. When a third operand was added, this pattern seemed to hold only for the first two operands, rather than all three. Thus, the result was unexpected when three operands were present.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 20:08
by andymbody
mikeyww wrote:
07 Sep 2023, 19:49
I was unable to follow what happened with (++d) * (++d)
Does my post above not cover this? Is there more going on? As you pointed out (d := d + 1), this is happening behind the scenes by mistake just before the first ++d is encountered (but only when the ++d is in the first or second position, as far as I can tell)

Andy

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 20:16
by teadrinker
Let's wait for what @lexikos has to say then :)

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 20:16
by mikeyww
Andy, sorry I had not seen your post. Agree.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 20:24
by andymbody
mikeyww wrote:
07 Sep 2023, 20:16
Andy, sorry I had not seen your post. Agree.
Oh... ok... I thought maybe I missed some other clues that invalidated the example. I have not found any other clues to indicate there is more going on, but there might be with further investigation. @lexikos can probably identify the cause in about 10 seconds.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 20:56
by teadrinker
I did some googling and it turns out that there is a classic example of ++i + ++i. It turns out that this is an example of so-called undefined behavior, and it gives different results on different compilers.

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 21:28
by andymbody
I find this one very interesting...

++d / ++d ; returns 1.0 rather than a flat integer of 1 (3/3)

It is interesting because... the returned "float" value seems to indicate that the internal operation allocated a float type for what we assume was an integer operation of 3/3. 2/3 would require a float, but 3/3 would not, correct? Or are all division operations assigned floats just in case in C++ or other lower level languages? So the theory of a double ++d operation or d=d+1 might not be completely accurate after all? Thoughts?

Andy

Re: Math syntax parsing issue

Posted: 07 Sep 2023, 21:34
by teadrinker
@andymbody

Code: Select all

MsgBox 1 / 1