I thought GPC handled array splices, but this:
program peter109;
type MyArray(count: Integer) = array[1..count] of Integer; var p: ^MyArray; begin New(p,10); p^[1..5] := p^[2..6]; end.
Gives a compiler error:
peter109.pas:9: error: type mismatch in array assignment
It works for strings, but I guess strings have all that packed array of char type checking extra baggage.
Should I just go back to BlockMoveData, or is there a way for array splice assignments to work, and if so, are they safe for overlapping moves?
While I'm at it, is there any better way to zero part of such an array than:
FillChar( p^[3], 4 * SizeOf(p^[3]), 0 );
And further while I'm at it, I looked at the docs for MoveLeft et al, and they are all under construction. Would it be worth while setting up a wiki for the docs? The docs already have an organizational layout, which is very helpful for starting a wiki and letting others add information. I've never set up a wiki before, but I'd be happy to set it up and look at transferring the existing documentation over if people thought it was a good idea. I know the docs are all tied in with the make system, and there might be some loss with regard to automation of that, but on the other hand it might mean more people participate in improving the docs so it might be an overall win. Anyway, just a thought, if there is no interest, I'll go back to reading move.pas to figure out what the RTS does ;).
Thanks, Peter.
Peter N Lewis wrote:
I thought GPC handled array splices, but this:
program peter109;
type MyArray(count: Integer) = array[1..count] of Integer; var p: ^MyArray; begin New(p,10); p^[1..5] := p^[2..6]; end.
Gives a compiler error:
peter109.pas:9: error: type mismatch in array assignment
It works for strings, but I guess strings have all that packed array of char type checking extra baggage.
Yes. More precisely, EP defines slices only for strings. Other array slices are a GPC extension, so these rules are actually nowhere defined, so in principle we could change them. I agree that what you want to do would be nice to have.
However, this might be difficult to implement, because which type should an array slice have? For string slices, we have the generic string-type which is always compatible. For other arrays, there are no generic types, and two arrays [1 .. 5] and [2 .. 6] are normally not compatible. I suppose the Borland solution would be to shift slices (if they had them) to base 0, as they do with arrays in several other contexts, but I don't really like this (as it can be very confusing and a trap to the unknowing, as are their "open arrays"). So if we can find a more elegant solution, without doing away with type-checking at all, of course, it could be worth changing it in GPC ...
While I'm at it, is there any better way to zero part of such an array than:
FillChar( p^[3], 4 * SizeOf(p^[3]), 0 );
I suppose a simple for-loop is not acceptable for some reason?
And further while I'm at it, I looked at the docs for MoveLeft et al, and they are all under construction. Would it be worth while setting up a wiki for the docs?
I doubt it. You know, we've had so many efforts to plan and organize writing, improving, translating documentation etc. It always went like this: Longish, often heated debates, finally someone (often me) setting something up, one or two people writing one or two paragraphs, and then everyone forgetting about it.
I think the problem is really whether there's people willing to write something. If they write something substantial, I'd even be willing to include it in the manual manually (but I think the last time this happened was some 4 years ago) ...
The docs already have an organizational layout, which is very helpful for starting a wiki and letting others add information. I've never set up a wiki before, but I'd be happy to set it up and look at transferring the existing documentation over if people thought it was a good idea.
I won't stop you if you like. (Only I won't do any serious setup effort anymore ...)
I know the docs are all tied in with the make system, and there might be some loss with regard to automation of that,
In the end the results should be transferred back to Texinfo format, so we can produce the different output formats. (It's not so much about the make system, but just so we can generate different formats such as Info, HTML or PDF.) So you might want to plan for this in your setup. E.g., if you do it for the reference chapter, the most lacking bit, you might want to predetermine the structure (Synopsis, Description, ...), and your wiki software should allow for automated extraction as formatted text. Converting the formatting then should be a simple matter of scripting ...
Frank
type MyArray(count: Integer) = array[1..count] of Integer; var p: ^MyArray; begin New(p,10); p^[1..5] := p^[2..6]; end.
However, this might be difficult to implement, because which type should an array slice have? For string slices, we have the generic string-type which is always compatible. For other arrays, there are no generic types, and two arrays [1 .. 5] and [2 .. 6] are normally not compatible. I suppose the Borland solution would be to shift slices (if they had them) to base 0, as they do with arrays in several other contexts, but I don't really like this (as it can be very confusing and a trap to the unknowing, as are their "open arrays"). So if we can find a more elegant solution, without doing away with type-checking at all, of course, it could be worth changing it in GPC ...
I guess the most elegant solution would be to say that p[1..5] is a subarray of MyArray, and that such a type is assignment compatible with MyArray and other subarrays, and that you then need a runtime check to test that the length of the subarrays match (or the subarray matches the total length of MyArray) (unless the values are all compile time constants and the check can be done at runtime, which is not guaranteed).
But it would introduce a bunch of new things (the concept of a subarray type, and runtime checks for assignment compatibility), and whether that is worth the advantage of doing
p^[1..5] := p^[2..6];
instead of
Assert( 6-2+1 = 5-1+1 ); Move( p^[2], p^[1], (5-1+1) * SizeOf(p^[2]) );
I don't know.
While I'm at it, is there any better way to zero part of such an
array than:
FillChar( p^[3], 4 * SizeOf(p^[3]), 0 );
I suppose a simple for-loop is not acceptable for some reason?
No particular reason, except for the extra lines, extra index variable and definition, and the I find the for loop is less clearly an array assignment that a Move/Zero. Conceptually to me, the for loop is indexing over the elements of the array, where really I want to reset the array - its a subtle distinction that probably doesn't concern others).
And further while I'm at it, I looked at the docs for MoveLeft et al, and they are all under construction. Would it be worth while setting up a wiki for the docs?
I doubt it.
I won't stop you if you like. (Only I won't do any serious setup effort anymore ...)
I know the docs are all tied in with the make system, and there might be some loss with regard to automation of that,
Ok, I guess then the next question is whether any folks think they would contribute to the docs if they were available in a wiki form. If so, speak up, otherwise I agree with Frank that there is little reason to make the effort.
Enjoy, Peter.
Peter N Lewis wrote:
type MyArray(count: Integer) = array[1..count] of Integer; var p: ^MyArray; begin New(p,10); p^[1..5] := p^[2..6]; end.
However, this might be difficult to implement, because which type should an array slice have? For string slices, we have the generic string-type which is always compatible. For other arrays, there are no generic types, and two arrays [1 .. 5] and [2 .. 6] are normally not compatible. I suppose the Borland solution would be to shift slices (if they had them) to base 0, as they do with arrays in several other contexts, but I don't really like this (as it can be very confusing and a trap to the unknowing, as are their "open arrays"). So if we can find a more elegant solution, without doing away with type-checking at all, of course, it could be worth changing it in GPC ...
I guess the most elegant solution would be to say that p[1..5] is a subarray of MyArray, and that such a type is assignment compatible with MyArray and other subarrays, and that you then need a runtime check to test that the length of the subarrays match (or the subarray matches the total length of MyArray) (unless the values are all compile time constants and the check can be done at runtime, which is not guaranteed).
OK, this check would be much the same as is necessary for schema discriminants (e.g., when either or both of the formal and actual parameters of a schematic type have non compile time constant discriminants). I've implemented this in GPC (20050312 ;-), so we could probably reuse it.
What's more effort is probably the introduction of a new class of type "subarray of something". I'd really have to see how difficult this would be to implement (if we really want that) ...
While I'm at it, is there any better way to zero part of such an
array than:
FillChar( p^[3], 4 * SizeOf(p^[3]), 0 );
I suppose a simple for-loop is not acceptable for some reason?
No particular reason, except for the extra lines, extra index variable and definition, and the I find the for loop is less clearly an array assignment that a Move/Zero. Conceptually to me, the for loop is indexing over the elements of the array, where really I want to reset the array - its a subtle distinction that probably doesn't concern others).
As a mathematician, I can understand the difference, and insofar I tend to agree with you. On the other hand, I have to point out that Move/FillChar are low-level, non-standard, sometimes dangerous (think of strings or schemata in the array) constructs, in comparison to a for-loop, and to me this disadvantage weighs heavier.
If we had a way to do the same thing cleanly, say by assigning an array constructor, this might be more interesting. However, GPC currently doesn't accept it, and I think it's not correct EP either (arrays not compatible, even if structurally equivalent), is it?
program Bar; type MyArray(count: Integer) = array[1..count] of Integer; Foo = array [3 .. 6] of Integer; var p: ^MyArray; begin New(p,10); p^[3 .. 6] := Foo[otherwise 0]; end.
Perhaps we could allow for an extension here to make this work (with much the same issues as above). But I'm still usure how much effort it will be and whether it will be worth it ...
Frank
At 13:06 +0200 8/9/05, Frank Heckenbach wrote:
Peter N Lewis wrote:
type MyArray(count: Integer) = array[1..count] of Integer; var p: ^MyArray; begin New(p,10); p^[1..5] := p^[2..6]; end.
However, this might be difficult to implement, because which type should an array slice have?
I guess the most elegant solution would be to say that p[1..5] is a subarray of MyArray, and that such a type is assignment compatible with MyArray and other subarrays, and that you then need a runtime check to test that the length of the subarrays match (or the subarray matches the total length of MyArray) (unless the values are all compile time constants and the check can be done at runtime, which is not guaranteed).
What's more effort is probably the introduction of a new class of type "subarray of something". I'd really have to see how difficult this would be to implement (if we really want that) ...
I'm not certain it is absolutely required, but it's another way we can get to a nice high level construct that avoids doing low level memory tricks. I think that's worth something, but I'm not the one who will have to implement it.
While I'm at it, is there any better way to zero part of such an
array than:
FillChar( p^[3], 4 * SizeOf(p^[3]), 0 );
I suppose a simple for-loop is not acceptable for some reason?
As a mathematician, I can understand the difference, and insofar I tend to agree with you. On the other hand, I have to point out that Move/FillChar are low-level, non-standard, sometimes dangerous (think of strings or schemata in the array) constructs, in comparison to a for-loop, and to me this disadvantage weighs heavier.
I certainly agree with your negatives, that's why I'd like to know a better way.
If we had a way to do the same thing cleanly, say by assigning an array constructor, this might be more interesting. However, GPC currently doesn't accept it, and I think it's not correct EP either (arrays not compatible, even if structurally equivalent), is it?
program Bar; type MyArray(count: Integer) = array[1..count] of Integer; Foo = array [3 .. 6] of Integer; var p: ^MyArray; begin New(p,10); p^[3 .. 6] := Foo[otherwise 0]; end.
Perhaps we could allow for an extension here to make this work (with much the same issues as above). But I'm still usure how much effort it will be and whether it will be worth it ...
Having to define a matching type would be impractical as well, especially for the case where 3 and 6 are run time calculations and the assignment might be in the middle of the procedure when the values had been calculated.
I wonder if the case of assigning a single value to an array[x..y] of scalar is sufficiently common that it would be worth a specific solution? That is, we could potentially define some construct (I have no particular suggestion for syntax perhaps array(5)?) which would repesent an arbitrary array of a signle scalar. It would be type compatible with a one dimensional array of any size of scalar which is assignment compatible with the value?
Then p^[3..6] := array(0);
I don't know if this is hard or easy, or worth doing as a GPC only feature or not. The big plus is it is one more way to avoid low level junk like FillChar, especially for the case of zeroing scalars.
Just a thought, Peter.
(As this is related to the other thread, I finally answer this one now ...)
Peter N Lewis wrote:
If we had a way to do the same thing cleanly, say by assigning an array constructor, this might be more interesting. However, GPC currently doesn't accept it, and I think it's not correct EP either (arrays not compatible, even if structurally equivalent), is it?
program Bar; type MyArray(count: Integer) = array[1..count] of Integer; Foo = array [3 .. 6] of Integer; var p: ^MyArray; begin New(p,10); p^[3 .. 6] := Foo[otherwise 0]; end.
Perhaps we could allow for an extension here to make this work (with much the same issues as above). But I'm still usure how much effort it will be and whether it will be worth it ...
Having to define a matching type would be impractical as well, especially for the case where 3 and 6 are run time calculations and the assignment might be in the middle of the procedure when the values had been calculated.
Yes. Perhaps one solution would be like:
type Foo = array [1 .. MaxVal] of Integer;
const Foo0 = Foo[otherwise 0];
begin p^[a .. b] := Foo0[a .. b]; end;
Now, this wouldn't be EP (EP allows slices only of string variables), and GPC currently doesn't allow it because of strict type-checking (cf. other thread). And if it did, I don't know how efficient code it would generate -- basically we'd need rather good constant folding for slices with possibly non-constant bounds, of constructors. (Waldek, does this sound like horrors to implement? ;-)
I wonder if the case of assigning a single value to an array[x..y] of scalar is sufficiently common that it would be worth a specific solution? That is, we could potentially define some construct (I have no particular suggestion for syntax perhaps array(5)?) which would repesent an arbitrary array of a signle scalar. It would be type compatible with a one dimensional array of any size of scalar which is assignment compatible with the value?
Sorry, I don't really like this, for several reasons:
- Introduces a new syntax, quite different from everything existing. What's more like regular syntax would be:
p^[3..6] := [otherwise 5];
I.e., like a structured value, but without a type specifier -- as in: type adjusting to the LHS. But that's exactly what probably would make it hard to implement.
- doesn't specify the bounds,
- loose typing WRT the component type,
- wouldn't solve the problem if the array contents are not scalar.
Frank