xsharp.eu • Multiplying INT and USUAL
Page 1 of 1

Multiplying INT and USUAL

Posted: Wed Apr 21, 2021 6:15 pm
by boonnam
Forgive me if this was brought up before. I did some search on this forum and could not find any mention of it. We are testing our conversion application from VO to X#. I ran into an interesting issue. Here is our line of code:

Code: Select all

iNoMode := IIF(m=4,2,1) * IIF( iPmtType = PAYMENT_REVERSAL, -1, 1 )
iNoMode and m are both INT type. iPmtType is a parameter. PAYMENT_REVERSAL is a define.
m=1
iPmtType=3
PAYMENT_REVERSAL=3

In VO iNoMode result is -1, but in X# it is 255. If I cast the factors as such:

Code: Select all

iNoMode := (INT)IIF(m=4,2,1) * (INT)IIF( iPmtType = PAYMENT_REVERSAL, -1, 1 )
Then the result is what we expected, which is -1. I am able to re-create this issue using console application.

Code: Select all

FUNCTION Start() AS VOID STRICT
    local iMode, iCount as int
    local iPmtType, iReversal as usual
    
    iPmtType := 3
    iReversal := 3
    iCount := 1
    
    iMode := iif(iCount==4,2,1) * iif(iPmtType == iReversal,-1,1)
    ? "iMode " + iMode:ToString()
   
    wait
    
    RETURN


I know it would be better if we strong type our variables. Is there is a plan to address this situation?

Thanks,
Boonnam

Multiplying INT and USUAL

Posted: Wed Apr 21, 2021 6:32 pm
by robert
Boonnam,
This is a tricky area.
We translate the IIF() statement to a C# conditional expression. In C# both results in the conditional expression must be of the same type. What we do in the X# compiler is determine what the (smallest) type of each the expressions is:
2 => unsigned byte
1 => unsigned byte
So the first IIF returns a byte
-1 -> Signed byte
1 -> unsigned Byte
So the second IIF returns a signed byte

Then you are multiplying an unsigned byte with a signed byte, So 2 different types.
For binary operations such as these we assume that the result of the multiplication is the type of the first operand when they both have the same size. Apparently in this case that is wrong.

I am afraid that this is deep in the hard of the compiler and changing this will most likely cause side effects.
Nevertheless: if does not hurt to add a ticket for this: https://github.com/X-Sharp/XSharpPublic/issues

Robert

Multiplying INT and USUAL

Posted: Wed Apr 21, 2021 7:24 pm
by Chris
Robert,

Can't you make relatively easily INT the smallest type that the compiler will assume for iif() expressions? And only if it is larger than that, then it may use an INT64/float etc. I am sure this will fix several similar issues which are probably hidden now.

Multiplying INT and USUAL

Posted: Wed Apr 21, 2021 7:39 pm
by robert
Chris,
If I do that then assigning the result of an IIF() to a local of a type smaller than INT will cause problems, like in compiler test C652. Before I added the check for "smallest of the 2 operands" this was causing an error.

And the problem in this situation is not really the IIF() but the binary operation (multiplication) with 2 operands with different types that defaults to the type of the first operand

Robert

Multiplying INT and USUAL

Posted: Wed Apr 21, 2021 8:14 pm
by Chris
Robert,

I think it's better to make iif() return INTs and then require to enable /vo4 (implicit signed/unsigned conversions) for C652 to compile (in the VO/VFP etc dialects), instead of ever returning a byte form iif().

If you have existing VO code like:

LOCAL b AS BYTE
LOCAL n AS INT
b := n

then also in this case /vo4 is required, so I think this is the most natural way to workaround this.

Anyway, I will log this for now and include the info above.

Multiplying INT and USUAL

Posted: Thu Apr 22, 2021 4:13 pm
by ArneOrtlinghaus
In the past we had many problems with IIF-pattern, that could be resolved expanding to normal if conditions. Sometimes It is nice to have short code, but often it is difficult to verify and as in this case having possible conversion problems.