Welcome, Guest
Username: Password: Remember me
This public forum is meant for questions and discussions about Visual FoxPro
  • Page:
  • 1
  • 2

TOPIC:

Implementing missing VFP functions 17 Mar 2021 19:45 #17797

  • Chris
  • Chris's Avatar
  • Topic Author


  • Posts: 3843
  • Hello all!

    One of the remaining tasks for properly supporting VFP in X#, is to implement the missing FoxPro-specific functions. We will soon start working on that, but we need your help in order to prioritize what gets done first. You can see a list of those already implemented and many missing in the runtime source code here: github.com/X-Sharp/XSharpPublic/tree/fea...e/Runtime/XSharp.VFP

    The .prg files with filenames Todo* contain those that are not implemented in the X# runtime yet (they have an empty body) and I am sure there exist others that are still missing and have not been included in the list yet. So can you please let us know which missing functions are being used more often in VFP applications or are most important, so should be implemented with higher priority? And of course, if you'd like to further contribute by impementing some of those yourselves, that would be most welcome!
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 17 Mar 2021 19:54 #17798

    • Eric Selje
    • Eric Selje's Avatar


  • Posts: 31
  • I'm trying to think if there's a tool that VFP devs can run on their codebase that counts up function call into a nice report. Anybody know of such a thing. A profiler of sorts.

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 18 Mar 2021 02:55 #17799

    • FoxProMatt
    • FoxProMatt's Avatar



    Let me give a reminder that most (non-dbf related) FoxPro functions were implemented in a C# library way back in June of 2020 a long time ago and the source code is on my GitHub account. It is called "Visual FoxPro Toolkit for .NET". Of course we probably wouldn't want to use these DLLs or the C# code directly, but the code could be helpful in seeing how the VFP functions were implemented in C#.

    The source code and documentation can be found here:
    github.com/mattslay/Visual-FoxPro-Toolki...Pro-Toolkit-for-.NET

    Please Log in or Create an account to join the conversation.

    Last edit: by FoxProMatt.

    Implementing missing VFP functions 18 Mar 2021 12:14 #17806

    • Chris
    • Chris's Avatar
    • Topic Author


  • Posts: 3843
  • Hi Matt,

    Thank you, this is helpful indeed! But I am not sure how thoroughly those functions have been designed and tested to be compatible with VFP. I made a quick test, the very first implemented function I tried was GetWordCount() and tested the following:

    ? GetWordCount("abc" + Chr(13) + "def")

    VFP returns 1. Also the X# implementation of the function returns 1. But the GetWordCount() as implemented in the toolkit returns 2.

    This was just the very first test I did, I am sure there will be many incompatibilities with other functions as well. So unfortunately we can't just go ahead and use those functions "as is", but can certainly serve as a starting point!
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Last edit: by Chris.

    Implementing missing VFP functions 18 Mar 2021 12:19 #17807

    • Karl-Heinz
    • Karl-Heinz's Avatar


  • Posts: 774
  • Hi Matt

    The toolkit doesn´t help that much. I looked e.g. at the BitOr() function which has a signature for 2 params
    public static int BitOr(int tnExpression1, int tnExpression2)
    
    {	
    return tnExpression1 | tnExpression2;
    }

    X# has the pseudo (compiler) function _or(), where it´s possible to pass more than two values. A similar BitOr() runtime function might look like
    FUNCTION BitOr ( a PARAMS OBJECT[] ) AS INT 
    LOCAL nRet AS INT
    LOCAL nCount := a:Length AS INT
    
    	IF nCount < 2
    
    		// Throw a exception like 'Arguments missing'	
    		
    	ELSE 	
    	    FOR VAR i := 1 UPTO nCount
    
        		nRet |= (INT) a[i]
    
    		// same as:
        		// nRet := _OR ( nRet , (INT) a[i] ) 
    
    
    	    NEXT		
    	    
    	ENDIF 	    
        
    	RETURN nRet 
    
    ? BitOr ( 234 , 6 , 8 )	
    ? BitOr ( 3456 , 5 , 8 , 9 , 10) 
    
    ? _or ( 234 , 6 , 8 )	
    ? _or ( 3456 , 5 , 8 , 9 , 10)	
    

    But, it would IMO make sense to look at the c# functions that open standard dialogs. I don't have VFP to see how such dialogs behave in detail, but it should be no big deal to translate the sources to X# and compare / change the behaviour.

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 18 Mar 2021 16:53 #17809

    • kevclark64
    • kevclark64's Avatar


  • Posts: 123
  • Chris, at the github link you give there is a document called "functionsToImplement.txt". Is that up to date?

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 18 Mar 2021 19:52 #17812

    • Chris
    • Chris's Avatar
    • Topic Author


  • Posts: 3843
  • Kevin, yes, I checked and it should be up to date, at least almost all. Not sure if the list is complete though or there exist more other functions that we might have missed.
    XSharp Development Team
    chris(at)xsharp.eu

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 20 Mar 2021 18:40 #17820

    • mainhatten
    • mainhatten's Avatar


  • Posts: 199
  • FoxProMatt wrote: Let me give a reminder that most (non-dbf related) FoxPro functions were implemented in a C# library way back in June of 2020 a long time ago and the source code is on my GitHub account. It is called "Visual FoxPro Toolkit for .NET". Of course we probably wouldn't want to use these DLLs or the C# code directly, but the code could be helpful in seeing how the VFP functions were implemented in C#.


    Chris already pointed out that the implementation of vfp Toolkit is not free of errors.
    As he used "my" function pair as example, let me add how I approached implementation:
    first I spent about an H behind car steering wheel of a drive back from Munich to get a first idea on problems involved and probably needed additional effort (mostly nodding on unicode and possible string/char/array issues at first to the speedometer).

    Only then I looked at the code in the toolkit, but just from reading the code it was clear that it was not free of issues ;-)
    Still, it verified my basic idea on how to resolve implementation and made me aware of the System:Char:IsWhiteSpace(tc2Check) method, for which I added one of the additional implementation branches. Getting speed of X# near ol' vfp on long test strings involved quite a few tweaks and optimizations, already ballooning code size to a multiple of toolkit size plus solidifying the need to offer a special approach for speed junkies when used in SQL or table usage. Also possible parallel or asynch issues - all of which did not faze vfp, as the option of paralellization, while existing in vfp, is offered only at a much higher level (think COM threads most of the time).

    Further benchmarking showed that x# .dbf handling speed back then was not really comparable to vfp speeds, so I did not implement that part back then - might resume if my time permits and x# .dbf handling is in the same ballpark.

    So yes, look at that code AFTER thinking on the problems involved, but with distrust, a few basic tests and an eye for runtime optimization.

    Please Log in or Create an account to join the conversation.

    Last edit: by mainhatten.

    Implementing missing VFP functions 24 Mar 2021 18:37 #17839

    • Karl-Heinz
    • Karl-Heinz's Avatar


  • Posts: 774
  • Guys,

    i´m looking at the BitTest(),BitSet() and BitClear() functions, and try - according to the VFP help - to implement at least the *numeric* behaviour. But i can´t compare the results because my old FP doesn´t know Bitwise operators. Could someone run this code with VFP and report back the results ?
    PRIVATE n
    	
    ? BitSet ( 3400 , 0 , 3 )	&& 3407 
    ? BitSet ( 3400 , 0 , 2 )	&& 3403 
    ? BitSet ( 3400 , 0 , 1 )  	&& 3401
    ? BitSet ( 3400 , 0 )  		&& 3401
    ? BitSet ( 3400)  		&& 2147483647  - sets the int32.maxvalue bits 
    ? BitTest ( 3400 , 12 ) 	&& .f.
    ? BitTest ( 3400 , 13 ) 	&& .f.
    n = BitSet ( 3400 , 12 , 2 ) 
    ? n 				&& 15688 
    ? BitTest ( n , 12 ) 		&& .t.
    ? BitTest ( n , 13 ) 		&& .t.
    n = BitClear ( n , 12 , 2 )  
    ? n  				&& 3400 
    ? BitTest ( n , 12 ) 		&& .f.
    ? BitTest ( n , 13 ) 		&& .f.
    ? BitClear ( n )			&& 0 - clears all bits 
    
    If it works as i´m thinking that it should work ;-) i´ll upload the sources as a starting point. So someone who has VFP installed might add the missing varbinary/Blob support.

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 24 Mar 2021 19:21 #17840

    • Eric Selje
    • Eric Selje's Avatar


  • Posts: 31
  • It looks like in VFP the first parameter needs to be explicitly in binary to allow all three parameters like you have, so I tweaked your code a little bit.
    LOCAL bTest AS varbinary, n
    bTest = 0h110101001000
    ? BitSet( bTest, 0 , 3 )	&& 3407 
    ? BitSet( bTest, 0 , 2 )	&& 3403 
    ? BitSet( bTest, 0 , 1 )  	&& 3401
    ? BITSET(bTest, 0 )  		&& 3401
    ? BitSet( bTest)  		&& 2147483647  - sets the int32.maxvalue bits 
    ? BITTEST(bTest, 12 ) 	&& .f.
    ? BitTest (bTest, 13 ) 	&& .f.
    n = BitSet (bTest , 12 , 2 ) 
    ? n 				&& 15688 
    ? BitTest ( n , 12 ) 		&& .t.
    ? BitTest ( n , 13 ) 		&& .t.
    n = BitClear ( n , 12 , 2 )  
    ? n  				&& 3400 
    ? BitTest ( n , 12 ) 		&& .f.
    ? BitTest ( n , 13 ) 		&& .f.
    ? BitClear ( n )

    Here's the result:

    0h170101001000
    0h130101001000
    0h110101001000
    0h110101001000
    0hFFFFFFFFFFFF
    .F.
    .F.
    0h113101001000
    .T.
    .T.
    0h110101001000
    .F.
    .F.
    0h000000000000

    Here's the syntax in the help file:

    BITSET(nNumericExpression1, nNumericExpression2)
    BITSET(BinaryExpression [, nStartBit [, nBitCount]])

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 24 Mar 2021 19:28 #17841

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Karl-Heinz,

    I think that the declaration for the VFP Bit* operations should be something like this:
    FUNCTION BitAnd (Num AS Integer, Num2 PARAMS Integer[]) AS Integer
    FUNCTION BitAnd (BinString AS Binary, BinString2 PARAMS Binary[]) AS Binary
    
    FUNCTION BitOr (Num AS Integer, Num2 PARAMS Integer[]) AS Integer
    FUNCTION BitOr (BinString AS Binary, BinString2 PARAMS Binary[]) AS Binary
    
    FUNCTION BitXOr (Num AS Integer, Num2 PARAMS Integer[]) AS Integer
    FUNCTION BitXOr (BinString AS Binary, BinString2 PARAMS Binary[]) AS Binary
    
    FUNCTION BitNot (Num AS Integer) AS Integer
    FUNCTION BitNot (BinString AS Binary) AS Binary
    FUNCTION BitNot (BinString AS Binary, StartBit AS Integer, BitCount := 1 AS Integer) AS Binary
    
    FUNCTION BitSet (Num AS Integer, Bit AS Integer) AS Integer
    FUNCTION BitSet (BinString AS Binary, StartBit AS Integer, BitCount := 1 AS Integer) AS Binary
    
    FUNCTION BitClear (Num AS Integer, Bit AS Integer) AS Integer
    FUNCTION BitClear (BinString AS Binary, StartBit AS Integer, BitCount := 1 AS Integer) AS Binary
    
    FUNCTION BitTest (Num AS Integer, Bit AS Integer) AS Logical
    FUNCTION BitTest (BinString AS Binary, Bit AS Integer) AS Logical
    
    FUNCTION BitLShift (Num AS Integer, BitShift AS Integer) AS Integer
    FUNCTION BitRShift (Num AS Integer, BitShift AS Integer) AS Integer

    I believe this covers all the expected variations of the functions. As you can see, some of your examples won't match against any of these declarations.

    Please Log in or Create an account to join the conversation.

    Last edit: by atlopes.

    Implementing missing VFP functions 24 Mar 2021 20:22 #17842

    • robert
    • robert's Avatar


  • Posts: 3446
  • Antonio,

    The problem with this approach is that in VFP almost everything is un-typed. So the parameters will often be of type USUAL.
    The compiler will have no idea which of these functions to call.

    I think the best solution is to create "top level" functions with USUAL parameter types. And then in these functions we can inspect the parameter types of the arguments and delegate the work to the right "worker function". And throw an error if an unexpected parameter type is passed.

    For some functions we can add overloads:
    FUNCTION BitNot (Num AS USUAL) AS USUAL
    SWITCH UsualType(Num)
    CASE __UsualType.Long
        RETURN _BitNot( (LONG) Num)
    CASE __UsualType.Int64 // should we allow this too ?
        RETURN _BitNot( (INT64) Num)
    CASE __UsualType.Binary
       RETURN _BitNot( (BINARY) Num)
    OTHERWISE
       THROW Exception{"Unexpected type" }
    END SWITCH
    FUNCTION BitNot (BinString AS USUAL, StartBit AS Integer, BitCount := 1 AS Integer) AS USUAL
    // more work to do
    
    And since the version with an integer should return an integer and the version with a Binary should return a binary the only solution is to set the return type to USUAL

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 24 Mar 2021 23:50 #17843

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Robert,

    It's a decision you'll have to make. These set of functions either work with numeric parameters to return numeric results or work with binary parameters to return binary results. If you want to accept USUAL types then it will be USUAL at both sides, parameters and results. This was what was done with STRCONV() that returns a USUAL result (String or Binary).

    The BITNOT implementation (USUAL not taken into consideration):
    FUNCTION BITNOT (Num AS Int) AS Int
       
        RETURN ~Num
    
    ENDFUNC
    
    FUNCTION BITNOT (BinString AS Binary) AS Binary
    
        RETURN BITNOT(BinString, 0, BinString.Length * 8)
    
    ENDFUNC
    
    FUNCTION BITNOT (BinString AS Binary, StartBit AS Int, BitCount := 1 AS Int) AS Binary
    
        LOCAL Result := BinString AS Byte[]
        LOCAL ByteIndex AS Int
        LOCAL BitIndex := StartBit AS Int
        LOCAL BitCounter AS Int
    
        FOR BitCounter := 1 TO BitCount
            
            ByteIndex := BitIndex / 8 + 1
            Result[ByteIndex] := _Xor(Result[ByteIndex], 1 << BitIndex % 8)
            BitIndex++
    
        NEXT
    
        RETURN (Binary)Result
    
    ENDFUNC

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 25 Mar 2021 13:23 #17849

    • Karl-Heinz
    • Karl-Heinz's Avatar


  • Posts: 774
  • Hi Eric,

    thanks for your input ! I´ve tried some of your '0h' prefixed values, and indeed it compiles with X#, but the X# results are:
    ? 0h170101001000  // output is a string and the value is "0h170101001000"  ?
    ? 0h170101001000 + "addSomeText" // -> output is a string and the value is "0h170101001000616464536F6D6554657874" ?
    
    ? 0h110101001000 + "addSomeText" // -> output is a string and the value is "0h110101001000616464536F6D6554657874" ?

    With X# a hex value is declared this way:
    ?  0xFFFFFFFFFFFF  // -> 281474976710655

    and a bin presentation looks like
    ? 0b110101001000 // -> 3400 

    note: the prefix is either '0x' or '0b'. For better readability you can add a underscore
    ? 0xFFFF_FFFFF_FFFF  // -> 281474976710655 
    ? 0b1101_0100_1000  // -> 3400 

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 25 Mar 2021 13:58 #17850

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Robert,

    I ran the following code against the exact implementation of the BITNOT() functions above.
    LOCAL N
    LOCAL B
    
    N := 10
    B := 0hFFB0
    
    ? BITNOT(N)
    ? BITNOT(B)

    The first display statement executes properly and calls the BITNOT(Int) AS Int, the second raises an error: 'XSharp.Error: 'Conversion.Error from USUAL(UNKNOWN) to LONGINT'.

    My question is: why is X# trying to convert a USUAL to LONGINT in the first place? If X# knows the type of the underlying value in the second statement ("Q"), and if it's going to convert before calling the function, why not convert to Binary instead?

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 25 Mar 2021 16:46 #17852

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Karl-Heinz,

    The literals prefixed with 0h are type Binary, which basically is a binary string (Byte[]). It's a VFP data type that X# implemented since version 2.7.

    The Bit* functions work on this data type differently from how they work with numeric values. For instance, a BitOr operation in a Binary string may extend the length of the string. In some cases, the meaning of the parameters is not even the same in both implementations.

    Hex literals are represented in VFP in the same way as in X#, except for the underscore, while there is no provision for 2-base literals.

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 25 Mar 2021 17:15 #17853

    • Karl-Heinz
    • Karl-Heinz's Avatar


  • Posts: 774
  • Hi Antonio,

    thanks for the "0h" clarificaton !

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 25 Mar 2021 17:16 #17854

    • robert
    • robert's Avatar


  • Posts: 3446
  • Karl-Heinz ,

    The ? operator is not the best way to look at a value like a binary value.
    It calls the AsString() function on its parameters, and there may be additional logic in AsString() that may change "what you see".
    For example if you display a floating point number it will use either the internal precision and decimals (for floats) or it may use the SetDecimals() and SetFixed() settings to format the number. That may result in a value like "******" if the number does not fit in the preset width or it may hide decimals that are stored in a number. You may see 1.234 for a number that actually has the value 1.2336

    AsString() is here:
    github.com/X-Sharp/XSharpPublic/blob/mai...Conversions.prg#L238

    For binaries it calls the Binary:ToString() method that you can find here:
    github.com/X-Sharp/XSharpPublic/blob/mai...ypes/Binary.prg#L228

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    Implementing missing VFP functions 26 Mar 2021 12:01 #17865

    • Karl-Heinz
    • Karl-Heinz's Avatar


  • Posts: 774
  • Hi Antonio,

    it seems there´s something missing in the USUAL support ? I can detect the correct type of the 'B' var:
    LOCAL B 
    
    B := 0hFFB0
    
    ? UsualType ( b ) //  29 , ok

    when i declare the 'B' var as Binary, or cast the var it works and the return value is 0h004F.
    LOCAL B AS Binary
    // or  
    BITNOT( (BINARY) B )  

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    Last edit: by Karl-Heinz.

    Implementing missing VFP functions 26 Mar 2021 18:41 #17875

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Thank you, Karl-Heinz.

    I hope that Robert and the X# team will clarify the difference in behavior between the two data types (numeric and binary string). It will help to compose the implementation of other VFP functions.

    Please Log in or Create an account to join the conversation.

    • Page:
    • 1
    • 2