Page 1 of 2
Question: Compatibility ?
Posted: Tue Aug 15, 2017 7:06 am
by robert
When fixing the issue that Leonid reported (when accessing a PSZ with an array syntax) I discovered that Vulcan is not compatible with VO in this area. X# was following the Vulcan logic and assumed indexed access into the PSZ type was 0 based and not 1 based which is apparently not what Leonid expected.
The reason is that the array syntax for the PSZ type is resolved through an indexed property and not through an array operator. The Vulcan code for the PSZ type contains something like this:
Code: Select all
PROPERTY Item(nPos as INT) AS BYTE
GET
RETURN SELF:bytes[nPos]
END GET
SET
SELF:bytes[nPos] := VALUE
END SET
END PROPERTY
And the Vulcan compiler only applies the "ArrayZero" logic to "true" arrays and indexed pointer access only. So NOT to Indexed properties.
I solved the problem from Leonid by coding an exception in the compiler. So for the PSZ type in the VO dialect the behavior is now different than for the same type in Vulcan.
The question is now:
What do you want: Should the X# compiler in the VO dialect by default assume that indexed properties starts with 1 and not with 0?
Of course using the /AZ (ArrayZero) compiler option will treat all array and indexed access as Zero based.
To be absolutely clear: I do not intend to change the behavior in the Core or Vulcan dialect.
Robert
Question: Compatibility ?
Posted: Tue Aug 15, 2017 7:34 am
by wriedmann
Hi Robert,
The VO dialect should be most compatible to VO as possible.
So the start should be 1 and not 0.
Of course, to write compatible code, the __ARRAYBASE__ macro can be used.
Wolfgang
Question: Compatibility ?
Posted: Wed Aug 16, 2017 5:49 am
by Chris
Robert,
This would be very nice, but the problem with doing that is that for collections it would be perfect, but for other kind of classes that have a numeric indexer, this will be a problem if the index value does not represent a zero-based counter, but something else. For example in something like
CLASS XSharpReleaseNames
PROPERTY SELF[nYear AS INT] AS STRING
GET
DO CASE
CASE nYear == 2017
RETURN "Anjou"
CASE nYear == 2018
RETURN "<secret>"
END CASE
RETURN "Unknown"
END GET
END PROPERTY
END CLASS
FUNCTION Start() AS VOID
VAR x := XSharpReleaseNames{}
? x[2017]
RETURN
if now the compiler subtracts one from the index, then x[2017] will not return the expected value any more.
Would it be an option doing that only for collection classes, so maybe classes with a namespace that starts with "System.Collections"?
Also either way I think it's better to have a separate compiler option for that, maybe an /cz (Zero based collections), which people can set on/off at will, for any dialect.
Chris
Question: Compatibility ?
Posted: Wed Aug 16, 2017 2:33 pm
by robert
Chris,
Well what can I say. Although this is valid code, this is not what most people would use for indexed properties.
In almost all cases that I have seen the indexed properties were used to access an element in an (ordered) list.
Maybe we can add a check to see if a type supports IList or IEnumerable. If it does then I think we can safely assume that it will have 0 based indexes and that the index should be corrected with 1.
IList itself is not enough I think. Many COM collections, such as Excel's WorkSheets and Ranges collections only support IEnum and not IList.
And the /cz option is not a bad idea at all.
The default would be then to use 1 based collection indexes ?
Robert
Question: Compatibility ?
Posted: Wed Aug 16, 2017 3:04 pm
by Chris
Robert,
I remember that Don, you and I were discussing this matter many years ago in the vulcan dev forum and at the end we had decided to leave collections untouched in the vulcan implementation. I keep a copy of all my posts, will check to see if I can find this discussion and remember exactly why we decided this way.
But anyway in any case with a separate /cs option it will be safe, I was just thinking that the default should be zero-based collections, since people using vulcan are used to that now. Making the vulcan/VO dialects have different default settings could be confusing I think.
Chris
Question: Compatibility ?
Posted: Wed Aug 16, 2017 3:10 pm
by Chris
Just figured a better code sample:
VAR oSorted := SortedList<INT,STRING>{}
oSorted:Add(30 , "a")
oSorted:Add(10 , "small")
oSorted:Add(20 , "test")
? oSorted[20]
that's a common code scenario, in which if the compiler subtracts one from the index expression in the indexer, it will cause unwanted behavior.
So maybe we can create a list of classes on which this should be applied? But in any case I think this needs to be optional and not the default option, because of reasons like the above.
Chris
Question: Compatibility ?
Posted: Wed Aug 16, 2017 5:12 pm
by wriedmann
Hi Chris, hi Robert,
I'm not more sure what the best option is.
Ok, compatibility is the fist and most important issue when moving code over from VO.
But VO code will never contain collections, so maybe the 0-based index is not an issue.
And more and more people will have code in both VO and Core dialects (as I do), and having different rules will make more confusion than other. If someone copies code that works, from a VO dialect application to a Code dialect application, code that worked before, it will not work anymore, and this may led to undesired side effects.
IMHO there should be a simple rule without exceptions at the base, indifferent from dialects.
Wolfgang
P.S. I'm trying to write all my array iterations where I cannot use the foreach statement with the __ARRAYBASE__ macro, and I would recommend this to anyone. Maybe you could introduce some language construct that could simplify this
Question: Compatibility ?
Posted: Wed Aug 16, 2017 6:24 pm
by Chris
Hi Wolfgang,
Can you please explain a bit more why you use the __ARRAYBASE__ macro?
I guess it's so that if at the future you decide to use zero based arrays in the future, instead of 1-based arrays, then you will not need to change your code. But why would you ever change to 0-based arrays? In my opinion the 1-based option is the most intuitive one and there's no need to change it at any point (well, for high level apps at least).
In case you plan to convert your arrays to collections in the future, then yeah I agree if you use such a macro now, it will be easier to later convert the code. But maybe the /cz option that we're discussing will help more on this, too.
Chris
Question: Compatibility ?
Posted: Wed Aug 16, 2017 8:09 pm
by wriedmann
Hi Chris,
I try only to write code that works independently from any compiler options.
What if sometimes someone changes this switch, maybe without thinking? The code will compile, but give runtime errors and nobody will understand this.
Wolfgang
Question: Compatibility ?
Posted: Thu Aug 17, 2017 10:16 am
by leon-ts
Hello,
Between the VODialect and ZeroBasedIndexing parameters there is a contradiction. If we port from VO in XSharp the big project in which the indexing of arrays always begins with 1, then I very much doubt that someone will read all code and to change in it an indexing with 1 on 0. Especially in a code where the indexing of an array goes through variables, and you need to look very carefully, which values are taken by this variable: it is already reduced by 1 or it needs to be reduced at the moment of direct access to the array. As a result, the inclusion of this parameter will result in the VO program not working.
I suggest to leave the ZeroBasedIndexing parameter only for Core dialect. And in dialects VO and Vulcan turn it off to avoid confusing users. In case of a Dialect choice the compiler shall inherit the appropriate behavior. In my opinion indexing of arrays also belongs to such behavior, without any additional settings.
Best regards,
Leonid