Input needed on FoxPro array support

This forum is meant for questions about the Visual FoxPro Language support in X#.

User avatar
robert
Posts: 4558
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Input needed on FoxPro array support

Post by robert »

We are working on the implementation of the FoxPro array support.
From what we have seen the FoxPro arrays are one dimensional arrays that also support a 2 dimensional indexes.
You can declare an array like this

Code: Select all

Dimension myArray(2,2)
myArray(1,1) = 1
myArray(1,2) = 2
myArray(2,1) = 3
myArray(2,2) = 4
and then access
myArray(4) and see the value 4.

or
Redimension the array to

Code: Select all

Dimension myArray(4)
and see that the contents has been saved and the elements have the values 1 through 4.

We have this working.

However this works quite different from the array support that we already have in the system, which is based on the Clipper array support (sometimes also called Ragged Arrays) where each array is in fact a single dimensional array, but the elements of the array can also be arrays, which allows unlimited nested arrays. This array support is also available in Visual Objects, Vulcan and Xbase++.

The questions that we have are:
1) In the FoxPro dialect should there be both the FoxPro compatible arrays (for example declared with the Dimension keyword) and Clipper compatible (Ragged) arrays ? Or should we map the ARRAY keyword in the FoxPro dialect to the special FoxPro array type?
2) There are many functions in the FoxPro runtime that take an not declared, unitialized array and fill the array. See for example this code from the VFP helpfile:

Code: Select all

Set PATH TO (HOME(2) + 'data')     && Sets path to database
Open Database testdata && Opens the database
? ADatabases(gaDatabase)     && Creates an array of open databases
As you can see gaDatabase is not declared and not initialized. The runtime magically creates the array inside the ADatabases() function and adds it as private to the function that called it.

In most other XBase dialects you would write it like this

Code: Select all

LOCAL gaDatabase           && declare the array (could also be PRIVATE gaDatabase)
? ADatabases(@gaDatabase)     && pass the array by reference so ADatabases() can create it 
or

Code: Select all

LOCAL gaDatabase           && declare the array (could also be PRIVATE gaDatabase)
gaDatabase = ADatabases()      && then the array gets returned, but we loose the numeric return value
How common is this kind of code (like the example from the help file) in your code? Would it be a problem to require people to declare the private first. We can add the @ character automatically in the compiler. We already have support for that.

If it is a problem to require people to declare the variable first then it would also be possible to mark functions such as ADatabase() with a special attribute in the runtime, so the compiler "knows" that this is a function that may create a new local and then it can automatically generate a private (or local) declaration at compile time.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
atlopes
Posts: 83
Joined: Sat Sep 07, 2019 11:43 am
Location: Portugal

Input needed on FoxPro array support

Post by atlopes »

Robert,

I'll try to refer to as many points as possible and number them in the process to facilitate further references.

[*]
[*]DIMENSION an array not previously declared creates a PRIVATE array.
[*]DIMENSION an array that was previously declared respects the current scope of the array (PUBLIC, PRIVATE, or LOCAL).
[*]All elements of a DIMENSIONed or LOCAL ARRAY are initialized to FALSE.
[*]All the Axxxx() functions that populate an array with some content start by creating a PRIVATE array if it does not exists. Otherwise, they operate as the DIMENSION command.
[*]The first parameter of the Axxxx() functions is passed by reference.
[*]Elements of a bidimensional array can be addressed as if the array is unidimensional (the contrary is not supported).
[*]The array can be used as a simple variable (if Qry is the name of an array, ? Qry is possible and refers to the first element of the array).
[*]All elements of the array can be assigned at once with a single statement (Qry = "x" stores the value "x" to all elements, no matter if the array is bi or unidimensional).
[*]Arrays can be a property of a class, declared as DIMENSION propertyName(initialDimension) in the property section of the class definition.
[*]An array property can also be added to an object in run time using the ADDPROPERTY() function or the AddProperty() method of containers.
[*]Imposing the need for variable declaration - arrays or not - will break lots of VFP code. Is it possible for a pre-processor to look for undeclared variables and make the necessary amends (at least for arrays)?


Other aspects may come to mind with further discussion. I hope this covers most of the behavior that will require your attention.
User avatar
robert
Posts: 4558
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Input needed on FoxPro array support

Post by robert »

Antonio,
Thanks for your input.
What about question 1:
In the FoxPro dialect should there be both the FoxPro compatible arrays (for example declared with the Dimension keyword) and Clipper compatible (Ragged) arrays ? Or should we map the ARRAY keyword in the FoxPro dialect to the special FoxPro array type?

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
atlopes
Posts: 83
Joined: Sat Sep 07, 2019 11:43 am
Location: Portugal

Input needed on FoxPro array support

Post by atlopes »

Robert,

As a rule of thumb, I would prefer a combination of retro compatibility support with additional features. Of course, I cannot fathom the dimension (sorry for the pun...) of the task.
User avatar
robert
Posts: 4558
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Input needed on FoxPro array support

Post by robert »

Antonio,
So would it be OK with you if the Dimension and Declare statements produce a FoxPro compatible array (as well as functions like ADatabases).
And a declaration like

Code: Select all

LOCAL myArray AS ARRAY
or

Code: Select all

VAR myArray := {1,2,3}
would then produce a Clipper compatible array, that can grow with functions such as AAdd()

Robert

PS Is there a syntax for a "literal array" in FoxPro? I have not found it.
XSharp Development Team
The Netherlands
robert@xsharp.eu
atlopes
Posts: 83
Joined: Sat Sep 07, 2019 11:43 am
Location: Portugal

Input needed on FoxPro array support

Post by atlopes »

Robert,

Yes, I think that the way you're proposing would be great. Just a note I would like to add: the syntax

Code: Select all

PUBLIC ARRAY x(1)
LOCAL ARRAY y(1)
should also produce FoxPro like arrays (scoped as the declaration suggests).

I can confirm that there is no way to create literal arrays in FoxPro.
User avatar
robert
Posts: 4558
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Input needed on FoxPro array support

Post by robert »

Antonio,
Thanks.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
mainhatten
Posts: 200
Joined: Wed Oct 09, 2019 6:51 pm

Input needed on FoxPro array support

Post by mainhatten »

Hi Robert,
Antonio already ticked off most of the things to watch out for. Only a few things left unsaid after on 27. adding local [ARRAY] la(arraydim):
Numbering to his first answer:
4 ) vfp will check whether the first parameter exists or not - but if it exists it is also checked if it really is a vfp Array, otherwise error.
8 ) the ability to set all array elements with a single line without referring array element like
laMyArray = luForWholeArray
this encompasses only simple data types like strings, dates or numbers - you cannot assign an object to all array elements at once, those must be assigned to individual array elements.
9 and 10: for me one of the more illogical syntax parts in vfp, in prg code class code you use Dimension again, whereas in object.addproperty("aMyNewArrayProperty[3]" [, ValueforAllNewElements)
method plus the addproperty function with the object as first parameter.indicating dimensionality inside property name string is enough.
Here I wonder if it is enough to have a Clipper ragged array as last parameter on a undimensioned property name, but see no obstacles, as
obj.addproperty("PropertyName", createobject("MyWishedforClass")) adds complex property, which could be the ragged type
robert wrote: So would it be OK with you if the Dimension and Declare statements produce a FoxPro compatible array (as well as functions like ADatabases).
And a declaration like

Code: Select all

LOCAL myArray AS ARRAY
or

Code: Select all

VAR myArray := {1,2,3}
would then produce a Clipper compatible array, that can grow with functions such as AAdd()
gets also strong yes, perhaps with new keyword RAGGEDARRAY to register when speedreading code - as long as previously written vfp code works as expected, having more code options is a benefit. Would the vartype(RaggedArray)/type("RaggedArray") be "O" with further checking the object or a new return value like "R" ? Checking Alen() probably could not differentiate between vfp and RAGGEDARRAY ?
How common is this kind of code (like the example from the help file) in your code? Would it be a problem to require people to declare the private first. We can add the @ character automatically in the compiler. We already have support for that.

If it is a problem to require people to declare the variable first then it would also be possible to mark functions such as ADatabase() with a special attribute in the runtime, so the compiler "knows" that this is a function that may create a new local and then it can automatically generate a private (or local) declaration at compile time.
On 11) I think I wrote a simple Try Catch when topic was raised a few months back which will handle creation of non-existing variable without heavy lifting, can en passant check that any existing variable really is a vfp array and otherwise throw error - Adding automatic @ / ref parameter after parse as not in vfp code for first parameter should be easy.in same step.
If every vfp Array function is automatically wrapped with that Try Catch no real speed or other problems should crop up...

edit: rethinking a bit, as 1. parameter is a reference, perhaps not even try-catch is needed if the macrocompiler works without failure if encountering lines along

Code: Select all

lnLines  =  ALINES(&tcMak, "1,2,3,5",5,",")
where tcMak might be a string parameter the compiler cannot parse in advance, as checking only is done on globals, privates and locals in that scope defined by function or method.
/edit

regards
thomas
jpmoschi
Posts: 77
Joined: Thu May 21, 2020 3:45 pm

Input needed on FoxPro array support

Post by jpmoschi »

I found this nice thread about foxpro arrays.
It is clear that all of you catch the real situation.
I even gave you examples to help to understand the case without lost the macrosubsitution.
I understand the problem between brackets and parenthesis and accept the brackets like a good solution.

When do you think I'm going to be able to jump to the latest version? And when do you think the vectors are going to be reasonably contemplated?

Best regards
Juan
User avatar
robert
Posts: 4558
Joined: Fri Aug 21, 2015 10:57 am
Location: Netherlands

Input needed on FoxPro array support

Post by robert »

Juan,

We plan to release a new version (2.8 ) of the product 2-3 weeks from now. This will include the new FoxPro array support, but will NOT support the Parenthesized array operators. So it will work with square brackets only. The only place where parentheses will be allowed is in the DIMENSION statement and in the LOCAL ARRAY statement.
It also includes improved support for exposing locals in your code to the X# runtime. In fact you will no longer have to use the ./fox2 compiler option to tell the compiler that your code wants to expose locals.
We have added a special attribute to the runtime and we have marked functions that need to read and/or write to local variables with this attribute. The compiler now checks for this attribute and will automatically add code to make locals visible to the runtime.
Examples of runtime functions that are marked with this attribute are SqlExec(), the Redim functions for foxpro arrays, Evaluate(), Type() etc.

The Dimension statement should also work and it should also allow you to re-dimension arrays without loosing the contents of the array.
The only thing that I am not sure about if we can include in the next build is the construct where you pass the name of the variable in a macro to the dimension statement like in
DIMENSION &varName.(10).
This may or may nor be easy I need to have a look.
Your test code to test various array functions is part of our test suite now (see https://github.com/X-Sharp/XSharpDev/bl ... g/C771.prg) We will use this to fix and test the array support.

Robert
XSharp Development Team
The Netherlands
robert@xsharp.eu
Post Reply