Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2020-03

Pass open array to static array?

13 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ryan Joseph

Why doesn't it compile to pass an open array to a static array of the same size? That would nice if this worked since it makes assigning values so easy.

program test;
var
  data: array[0..2] of integer;
begin
  // Incompatible types: got "{Array Of Const/Constant Open} Array of ShortInt" expected "Array[0..2] Of LongInt"
  data := [1,2,3];
end.

Regards,
Ryan Joseph

Reply by email

Howard Page-Clark
to Ryan Joseph
Ryan Joseph wrote 7 lines
program test; var data: array[0..2] of integer; begin // Incompatible types: got "{Array Of Const/Constant Open} Array of ShortInt" expected "Array[0..2] Of LongInt" data := [1,2,3]; end.

With recent FPCs you can however do this:

program test;
var
   data: array[0..2] of Integer;
   tmp: array of Integer = Nil;
begin
   tmp := [1,2,3];
   Move(tmp[0], data[0], SizeOf(data));
end.

Reply by email

Ryan Joseph
to Howard Page-Clark
Show quoted text 13 lines
On Mar 15, 2020, at 8:53 PM, Howard Page-Clark via fpc-pascal wrote: With recent FPCs you can however do this: program test; var data: array[0..2] of Integer; tmp: array of Integer = Nil; begin tmp := [1,2,3]; Move(tmp[0], data[0], SizeOf(data)); end.

yeah I figured you can do something similar with generics:

generic procedure Move<T>(source: array of T; var dest);
var
  bytes: SizeInt;
begin
  bytes := length(source) * sizeof(T);
  Move(source, dest, bytes);
end;
begin
  specialize Move<GLfloat>([0.0, 0.5, 0.0,
    -0.5, -0.5, 0.0,
    0.5, -0.5, 0.0],
    data.verts);
end.

but why doesn't open arrays already do this? an open array is just a constant array so the compiler should know the arrays are compatible for assignments.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph via fpc-pascal schrieb am
So., 15. März 2020, 19:58:

Show quoted text 38 lines
> On Mar 15, 2020, at 8:53 PM, Howard Page-Clark via fpc-pascal < > wrote: > > > With recent FPCs you can however do this: > > program test; > var > data: array[0..2] of Integer; > tmp: array of Integer = Nil; > begin > tmp := [1,2,3]; > Move(tmp[0], data[0], SizeOf(data)); > end. yeah I figured you can do something similar with generics: generic procedure Move<T>(source: array of T; var dest); var bytes: SizeInt; begin bytes := length(source) * sizeof(T); Move(source, dest, bytes); end; begin specialize Move<GLfloat>([0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0], data.verts); end. but why doesn't open arrays already do this? an open array is just a constant array so the compiler should know the arrays are compatible for assignments.

The message of the compiler is a bit misleading. It's a *dynamic* array that is created there, not an *open* array. Open arrays only exist when being passed directly to a parameter.

But to answer why the compiler does not do it: because I simply have not had the time to implement it! The main point of dynamic array constructors was to have them Delphi compatible. Support for static arrays is something I have planned though (and you're not the first to ask for it).

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth

Ok, that makes sense now. Dynamic arrays can't be passed to static arrays. I remember when I tried to make aligned dynamic arrays I got to look around in the code and it seems plausible you could just make a memcpy call in the RTL for dynamic arrays being passed to static arrays. Seems deceptively easy. :)

Shouldn't it be a constant array though? I'm not sure how the compiler works but from the programers perspective I thought I was getting something without runtime allocation because the array contained only constant values.

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph via fpc-pascal schrieb am
Mo., 16. März 2020, 07:33:

Show quoted text 9 lines
Ok, that makes sense now. Dynamic arrays can't be passed to static arrays. I remember when I tried to make aligned dynamic arrays I got to look around in the code and it seems plausible you could just make a memcpy call in the RTL for dynamic arrays being passed to static arrays. Seems deceptively easy. :)

You forget managed types. You can't do a simple Move for them.

Show quoted text 6 lines
Shouldn't it be a constant array though? I'm not sure how the compiler works but from the programers perspective I thought I was getting something without runtime allocation because the array contained only constant values.

It's only a constant array if it's declared in the const section. Inside normal code it can also contain variables, function calls, just any expression really.

Though it would be a potential optimization if all entries are constant to treat it as a constant array. Again that is something that *could* be done, but is not right now.

Regards,
Sven

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph via fpc-pascal schrieb am
Fr., 3. Apr. 2020, 04:13:

Show quoted text 12 lines
> On Mar 16, 2020, at 5:40 AM, Sven Barth wrote: > > The message of the compiler is a bit misleading. It's a *dynamic* array that is created there, not an *open* array. Open arrays only exist when being passed directly to a parameter. I forgot to ask. Are open arrays constants, or are they essentially dynamic arrays also?

They are neither. They are simply a pointer to the first element and a hidden size argument. For the pointer it is not important where it comes from: a single element, a dynamic array, a static array.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Apr 3, 2020, at 3:43 PM, Sven Barth wrote: They are neither. They are simply a pointer to the first element and a hidden size argument. For the pointer it is not important where it comes from: a single element, a dynamic array, a static array.

Ah, I see. In the example below the open array is still a dynamic array right? As you said earlier dynamic arrays are never constant/static (for now at least) and therefore [1,2,3] is a dynamic.

procedure DoThis(a: array of integer);
...
DoThis([1,2,3]);

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph via fpc-pascal schrieb am
Fr., 3. Apr. 2020, 14:33:

Show quoted text 19 lines
> On Apr 3, 2020, at 3:43 PM, Sven Barth wrote: > > They are neither. They are simply a pointer to the first element and a hidden size argument. For the pointer it is not important where it comes from: a single element, a dynamic array, a static array. > Ah, I see. In the example below the open array is still a dynamic array right? As you said earlier dynamic arrays are never constant/static (for now at least) and therefore [1,2,3] is a dynamic. procedure DoThis(a: array of integer); ... DoThis([1,2,3]);

No. The "[...]" for an open array parameter means "open array constructer" *not* "dynamic array constructor". And this on-the-fly open array is in fact constructed on the stack.

If your DoThis would be declared with a dynamic array parameter (e.G. "specialize TArray<Integer>") then you'd in fact have a temporary dynamic array constructed on the heap.

Also I didn't say that dynamic arrays can't be constant, but that they only are so if declared in a const section.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Apr 3, 2020, at 10:09 PM, Sven Barth wrote: No. The "[...]" for an open array parameter means "open array constructer" *not* "dynamic array constructor". And this on-the-fly open array is in fact constructed on the stack.

Ok, I see now. Excellent. I thought this was another dynamic array being created and destroyed.

Show quoted text 5 lines
If your DoThis would be declared with a dynamic array parameter (e.G. "specialize TArray<Integer>") then you'd in fact have a temporary dynamic array constructed on the heap. Also I didn't say that dynamic arrays can't be constant, but that they only are so if declared in a const section.

can you post an example of a const dynamic array? I tried and it thinks it's a set so I can't assign to an open array.

Also that made me think, is it possible for an open array parameter to be written to if its source was a static array? You said it's a pointer so I wonder if it's possible to use them instead of passing a static array pointer with an additional parameter for the length.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Ryan Joseph via fpc-pascal schrieb am
Fr., 3. Apr. 2020, 21:03:

Show quoted text 16 lines
> On Apr 3, 2020, at 10:09 PM, Sven Barth wrote: > > If your DoThis would be declared with a dynamic array parameter (e.G. "specialize TArray<Integer>") then you'd in fact have a temporary dynamic array constructed on the heap. > > Also I didn't say that dynamic arrays can't be constant, but that they only are so if declared in a const section. > can you post an example of a const dynamic array? I tried and it thinks it's a set so I can't assign to an open array.

It needs to be a typed constant:

const
  MyArray: array of LongInt = (1, 2, 3);

If the writable constants switch is off then this dynamic array won't be writable either.

Show quoted text 5 lines
Also that made me think, is it possible for an open array parameter to be written to if its source was a static array? You said it's a pointer so I wonder if it's possible to use them instead of passing a static array pointer with an additional parameter for the length.

Yes that is indeed the case though you'll have to declare the parameter as var as otherwise the compiler will create a copy on the stack which will be lost afterwards.

Also open array *always* start at index 0. So if you pass a static array that's declared as 4..6 then your function will get an open array stsrting at 0 with length 3 with the element at 0 being the element at 4 of the static array.

And as a special functionality open arrays allow slicing. That is if you have an open array parameter you can pass along parts of it to another open array:

SomeFunc(MyArrayArg[3..High(MyArrayArg) - 3]);

This will also work correctly with var/out open array parameters.

Regards,
Sven

Reply by email