Sign in Join

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

Mailing lists / fpc-devel / 2019-06

Thoughts on being able to declare "pointer-to-type" parameters directly in method signatures?

57 messages · 12 people · –

Reply by email Subscribe to this list Your subscription

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

Ben Grasset

For example, consider the following code, that implements a generic "memcpy"-style procedure using a static advanced-record method:

program Example;
{$mode Delphi}
type
  TMem<T> = record
  public type
    PT = ^T;
  public
    class procedure Copy(Dest: PT; Src: PT; Len: PtrUInt); static; inline;
  end;
  class procedure TMem<T>.Copy(Dest: PT; Src: PT; Len: PtrUInt);
  begin
    while Len > 0 do begin
      Dest^ := Src^;
      Inc(Dest);
      Inc(Src);
      Dec(Len);
    end;
  end;
type
  String4 = String[4];
var
  X: TArray<String4> = ['AAAA', 'BBBB', 'CCCC', 'DDDD', 'EEEE'];
  Y: TArray<String4> = ['', '', '', '', ''];
  S: String4;
begin
  TMem<String4>.Copy(@Y[0], @X[0], 5);
  for S in Y do WriteLn(S);
end.

The only reason the record is necessary at all is to be able to declare "PT" as a pointer type alias to the record's overall "T".

Personally, I'd much rather simply write the following, if it was possible:

procedure MemCopy<T>(Dest: ^T; Src: ^T; Len: PtrUInt);
begin
  while Len > 0 do begin
    Dest^ := Src^;
    Inc(Dest);
    Inc(Src);
    Dec(Len);
  end;
end;

Of course, currently that's not valid code. This kind of thing is useful for more than just generics, also: it would be just as applicable to non-generic records, primitive types, e.t.c.

Surely I can't be the only one who has ever wanted to use a "typed pointer" without first having to declare a named alias.

So I guess my questions are:

A) How feasible is this to implement?

B) Is there a specific reason is has *not* been implemented previously? (Seems unlikely)

Reply by email

Jonas Maebe
to Ben Grasset
Ben Grasset wrote
B) Is there a specific reason is has *not* been implemented previously? (Seems unlikely)

Pascal does not support declaring any new types inside parameter lists, apart from
a) local procvar types (in ISO/MacPas modes)
b) open arrays

In both cases, theses can in fact only be declared in parameter lists (at least in their original dialects). In case of a), the reason is that this prevents you from accidentally assigning a local procvar to a variable in an outer scope and then call it when it is no longer valid. In case of b), the reason is that they don't make sense outside the context of a parameter list.

It would be inconsistent to only allow such declaration for pointers, and not for other types (a programming language should strive to be as orthogonal as possible, with as few exceptions as possible). But then you get issues with a.o. open arrays vs dynamic arrays, and record compatibility (structurally equivalent records are not assignment-compatible in Pascal).

Additionally, when extending a language, the question should always be "does this greatly improve programmer efficiency, code safety, portability, performance, ...", rather than "is there a reason why this has not been added". The reason is that extending a language also always comes with inherent downsides: slower/more complex parser, more complex documentation, incompatibilities with other compilers, potential future conflicts with other compilers if they extend it in a conflicting way, ...

Jonas

Reply by email

Ben Grasset
to Jonas Maebe
PM Jonas Maebe wrote
It would be inconsistent to only allow such declaration for pointers, and not for other types (a programming language should strive to be as orthogonal as possible, with as few exceptions as possible).

I can't think of any particular variety of normal declaration *other* than pointer aliases that aren't allowed in parameter lists, though.

As you said, "array of type" is fine (in all modes, I think.) In fact, that's one of the reasons that the inability to use the "^" symbol in front of a type for a pointer alias has always seemed like "missing" functionality to me, as the fact that arrays can work like that makes me think it's not unrealistic to implement the same kind of thing for pointers.

The "local procvar" thing is probably less common, but again it exists (and only actually requires {$modeswitch NestedProcvars} I'm pretty sure.)

Apart from that, what else is there? Parameters can be records, classes, objects, interfaces, function types, primitives, e.t.c.

There's no other type of alias I'm aware of that would make any sense by itself (by which I mean, outside the context of an actual "type" block.)

Reply by email

Jonas Maebe
to Ben Grasset
Ben Grasset wrote 10 lines
On Fri, Jun 7, 2019 at 1:47 PM Jonas Maebe < > wrote: It would be inconsistent to only allow such declaration for pointers, and not for other types (a programming language should strive to be as orthogonal as possible, with as few exceptions as possible). I can't think of any particular variety of normal declaration *other* than pointer aliases that aren't allowed in parameter lists, though.

You mention them later:

Apart from that, what else is there? Parameters can be records, classes, objects, interfaces, function types, primitives, e.t.c.

None of these can be defined as a type in parameter lists. Keep in mind that "^Type" defines a new type. Semantically, it's at the same level as "0..5" and "record a, b: longint end;".

As you said, "array of type" is fine (in all modes, I think.) In fact, > that's one of the reasons that the inability to use the "^" symbol in front of a type for a pointer alias has always seemed like "missing" functionality to me, as the fact that arrays can work like that makes me think it's not unrealistic to implement the same kind of thing for pointers.

An open array has specific semantics that are completely different from any regular array type. Your "^Type" inline type definition would behave exactly the same as a regular pointer type definition.

Jonas

Reply by email

Ben Grasset
to Jonas Maebe
PM Jonas Maebe wrote
None of these can be defined as a type in parameter lists. Keep in mind that "^Type" defines a new type. Semantically, it's at the same level as "0..5" and "record a, b: longint end;".

Right, that's the point. There's nothing else that *would* make any syntactic sense in a parameter list besides "^Type" that isn't already allowed in them.

PM Jonas Maebe wrote
Your "^Type" inline type definition would behave exactly the same as a regular pointer type definition.

Of course. It would be strange if it didn't, I think. That's the whole point.

Here's another more simplistic example, in {$mode ObjFPC} this time:

program Example;
{$mode ObjFPC}
generic procedure GenProc<T>(Param: ^T); // <-- does not compile
var
  P: ^T; // <-- compiles just fine
begin
end;
procedure NonGenProc(Param: ^LongInt); // <-- does not compile
var
  P: ^LongInt; // <-- compiles just fine
begin
end;
begin
end.

To me it's always seemed illogical (in various different Pascal compilers over time, not just FPC) that the "parameter" declarations there don't work, whereas things like the "var" ones (which are just as "inline", I'd say) work just fine.

It comes across as the kind of thing that would happen if someone simply forgot to account for the "^" symbol in their code for parsing method signatures, not like any kind of intentional design choice.

Reply by email

Ryan Joseph
to Ben Grasset
On Jun 7, 2019, at 3:06 PM, Ben Grasset wrote: To me it's always seemed illogical (in various different Pascal compilers over time, not just FPC) that the "parameter" declarations there don't work, whereas things like the "var" ones (which are just as "inline", I'd say) work just fine.

I don’t get this either. It feels to me like ^ is a modifier more than an actual new type. That’s just me feeling though as a long time Pascal programmer.

Regards,
Ryan Joseph

Reply by email

Jonas Maebe
to Ben Grasset: Right, that's the point. There's nothing else that *would* make any syntactic sense in a…
Ben Grasset wrote 8 lines
On Fri, Jun 7, 2019 at 2:35 PM Jonas Maebe < > wrote: Your "^Type" inline type definition would behave  exactly the same as a regular pointer type definition.  Of course. It would be strange if it didn't, I think. That's the whole point.

My point is that a parameter type declaration is a completely different beast than a type definition. So if you add something in it that is in fact the same as a regular type definition, something is wrong.

Jonas

Reply by email

Sven Barth
to Ben Grasset: Right, that's the point. There's nothing else that *would* make any syntactic sense in a…
Ben Grasset wrote 13 lines
On Fri, Jun 7, 2019 at 2:35 PM Jonas Maebe < > wrote: None of these can be defined as a type in parameter lists. Keep in mind that "^Type" defines a new type. Semantically, it's at the same level as "0..5" and "record a, b: longint end;". Right, that's the point. There's nothing else that *would* make any syntactic sense in a parameter list besides "^Type" that isn't already allowed in them.

No, I think you *missed* the point. "^Type" defines a new type. "0..5" defines a new type. "set of (Alpha, Beta, Gamma)" defines a new type. "record a, b: longint end" defines a new types. All four of these can be used either to declare a named type or for an anonymous type in a variable declaration. However none of these can be used in a parameter declaration. Parameter declarations and variable declarations are different beasts, they have different rules (for example you can't declare open arrays outside of parameter declarations and no, dynamic arrays don't count, cause despite them sharing a syntax dynamic arrays and open arrays are different concepts).

Regards,
Sven

Reply by email

Sven Barth
to Ben Grasset: For example, consider the following code, that implements a generic "memcpy"-style…
Ben Grasset wrote 53 lines
For example, consider the following code, that implements a generic "memcpy"-style procedure using a static advanced-record method: program Example; {$mode Delphi} type   TMem<T> = record   public type     PT = ^T;   public     class procedure Copy(Dest: PT; Src: PT; Len: PtrUInt); static; inline;   end;   class procedure TMem<T>.Copy(Dest: PT; Src: PT; Len: PtrUInt);   begin     while Len > 0 do begin       Dest^ := Src^;       Inc(Dest);       Inc(Src);       Dec(Len);     end;   end; type   String4 = String[4]; var   X: TArray<String4> = ['AAAA', 'BBBB', 'CCCC', 'DDDD', 'EEEE'];   Y: TArray<String4> = ['', '', '', '', ''];   S: String4; begin   TMem<String4>.Copy(@Y[0], @X[0], 5);   for S in Y do WriteLn(S); end. The only reason the record is necessary at all is to be able to declare "PT" as a pointer type alias to the record's overall "T". Personally, I'd much rather simply write the following, if it was possible: procedure MemCopy<T>(Dest: ^T; Src: ^T; Len: PtrUInt); begin   while Len > 0 do begin     Dest^ := Src^;     Inc(Dest);     Inc(Src);     Dec(Len);   end; end;

You can do it like this (yes, works in mode Delphi as well):

=== code begin ===

{$mode objfpc}
{$modeswitch advancedrecords}
type
   generic TPointerType<T> = record
   public type
     PT = ^T;
   end;
   generic procedure MemCopy<T>(Dest, Src: specialize
TPointerType<T>.PT; Len: PtrUInt);
   begin
     while Len > 0 do begin
       Dest^ := Src^;
       Inc(Dest);
       Inc(Src);
       Dec(Len);
     end;
   end;
type
   String4 = String[4];
var
   X: specialize TArray<String4> = ('AAAA', 'BBBB', 'CCCC', 'DDDD', 'EEEE');
   Y: specialize TArray<String4> = ('', '', '', '', '');
   S: String4;
begin
   specialize MemCopy<String4>(@Y[0], @X[0], 5);
   for S in Y do WriteLn(S);
end.

=== code end ===

Regards,
Sven

Reply by email

denisgolovan
to Sven Barth

Hi Sven

Just my 50 cents.
Just stumbled upon the same problem today.
I mean typed pointer in generic function.

But "specialize TPointerType<T>.PT" is just too much noise. Personally, I consider this issue really annoying as for generics.

Regards, Denis Golovan

Reply by email

Ben Grasset
to Jonas Maebe: My point is that a parameter type declaration is a completely different beast than a type…
PM Jonas Maebe wrote
So if you add something in it that is in fact the same as a regular type definition, something is wrong.

What exactly is "wrong" there, though? In a world where they both worked, doing this, as we've discussed:

procedure Proc(Param: ^TSomeType);

would be no different than doing this in any sense that really mattered:

type PSomeType = ^TSomeType;
procedure Proc(Param:  PSomeType);

apart from being somewhat more convenient.

Reply by email

Ben Grasset
to Sven Barth: No, I think you *missed* the point. "^Type" defines a new type. "0..5" defines a new…

On Fri, Jun 7, 2019 at 3:44 PM Sven Barth via fpc-devel <

Show quoted text 12 lines
wrote: No, I think you *missed* the point. "^Type" defines a new type. "0..5" defines a new type. "set of (Alpha, Beta, Gamma)" defines a new type. "record a, b: longint end" defines a new types. All four of these can be used either to declare a named type or for an anonymous type in a variable declaration. However none of these can be used in a parameter declaration. Parameter declarations and variable declarations are different beasts, they have different rules (for example you can't declare open arrays outside of parameter declarations and no, dynamic arrays don't count, cause despite them sharing a syntax dynamic arrays and open arrays are different concepts)

You're just describing what is *currently* valid and not-valid syntax, which we all already know. No one has explained *why* exactly "^Type" would be somehow a negative thing in the context of method signatures, while at the same time being perfectly fine for things like both global and local variables, as well as constants. The following works, for example:

const X: LongInt = 12;
const Y: ^LongInt = @X;

I get what you mean about the range, set, and record declarations, however, I don't think it's the same issue in a practical sense. All of those *really* declare types that are *actually* new in a completely arbitrary way. "^Type" declares a new type in the sense of "it has its own RTTI name", but it's still ultimately just an alias that can never mean anything other than "a pointer to a specific type that already exists."

As far as your example, I'm well aware of that kind of thing, but it's a workaround, not a solution.

Reply by email

Ryan Joseph
to Sven Barth: You can do it like this (yes, works in mode Delphi as well): === code begin === {$mode…
Show quoted text 11 lines
On Jun 7, 2019, at 3:50 PM, Sven Barth via fpc-devel wrote: generic procedure MemCopy<T>(Dest, Src: specialize TPointerType<T>.PT; Len: PtrUInt); begin while Len > 0 do begin Dest^ := Src^; Inc(Dest); Inc(Src); Dec(Len); end; end;

May I ask where the syntax for “specialize” came from? Delphi doesn’t use it nor does any other language out there. Honestly it’s extremely verbose and makes me want to avoid generics sometimes. I just don’t get it. I will say that I like the “generic” addition to type declarations though because it makes it more clear what they are.

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Ben Grasset: On Fri, Jun 7, 2019 at 3:44 PM Sven Barth via fpc-devel < You're just describing what is…
On Jun 7, 2019, at 4:44 PM, Ben Grasset wrote: You're just describing what is *currently* valid and not-valid syntax, which we all already know. No one has explained *why* exactly "^Type" would be somehow a negative thing in the context of method signatures, while at the same time being perfectly fine for things like both global and local variables, as well as constants. The following works, for example:

Because it’s not valid syntax to declare types in parameter lists. I think your argument is that pointers should be an exception to the rule?

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph: May I ask where the syntax for “specialize” came from? Delphi doesn’t use it nor…
Ryan Joseph wrote 13 lines
> On Jun 7, 2019, at 3:50 PM, Sven Barth via fpc-devel wrote: > > generic procedure MemCopy<T>(Dest, Src: specialize TPointerType<T>.PT; Len: PtrUInt); > begin > while Len > 0 do begin > Dest^ := Src^; > Inc(Dest); > Inc(Src); > Dec(Len); > end; > end; May I ask where the syntax for “specialize” came from? Delphi doesn’t use it nor does any other language out there. Honestly it’s extremely verbose and makes me want to avoid generics sometimes. I just don’t get it. I will say that I like the “generic” addition to type declarations though because it makes it more clear what they are.

It has been part of FPC from the beginning of generics. It allows the parser to differentiate easier that a specialization is following. This was less important when only type declarations could contain specializations, but nowadays with support for inline specializations this is especially true as something with "<" in it is not always easy to differentiate between a specialization and an expression. Case in point: Delphi mode doesn't yet support all kinds of expressions containing specializations that mode ObjFPC supports.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Jun 7, 2019, at 4:51 PM, Sven Barth via fpc-devel wrote: It has been part of FPC from the beginning of generics. It allows the parser to differentiate easier that a specialization is following. This was less important when only type declarations could contain specializations, but nowadays with support for inline specializations this is especially true as something with "<" in it is not always easy to differentiate between a specialization and an expression. Case in point: Delphi mode doesn't yet support all kinds of expressions containing specializations that mode ObjFPC supports.

Then maybe it could be optional within type declarations? Delphi mode achieves this so I think ObjFPC could also. Yet another modeswitch like “autoderef”? :)

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 5 lines
> On Jun 7, 2019, at 4:51 PM, Sven Barth via fpc-devel wrote: > > It has been part of FPC from the beginning of generics. It allows the parser to differentiate easier that a specialization is following. This was less important when only type declarations could contain specializations, but nowadays with support for inline specializations this is especially true as something with "<" in it is not always easy to differentiate between a specialization and an expression. Case in point: Delphi mode doesn't yet support all kinds of expressions containing specializations that mode ObjFPC supports. Then maybe it could be optional within type declarations? Delphi mode achieves this so I think ObjFPC could also. Yet another modeswitch like “autoderef”? :)

No. The generic keywords are part of mode ObjFPC. The only thing I plan to do is to move the whole idea of generic keywords to a modeswitch, but that is neither here nor there currently.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Jun 7, 2019, at 5:06 PM, Sven Barth via fpc-devel wrote: No. The generic keywords are part of mode ObjFPC. The only thing I plan to do is to move the whole idea of generic keywords to a modeswitch, but that is neither here nor there currently.

Good idea to make generics a mode switch. That probably will improve compiler times.

Regards,
Ryan Joseph

Reply by email

Ben Grasset
to Sven Barth: No, I think you *missed* the point. "^Type" defines a new type. "0..5" defines a new…

On Fri, Jun 7, 2019 at 3:44 PM Sven Barth via fpc-devel <

Show quoted text 5 lines
wrote: "0..5" defines a new type. "set of (Alpha, Beta, Gamma)" defines a new type. "record a, b: longint end" defines a new types.

Building on my last reply, also, here's an example that shows what I see as the actual hypothetical ramifications of those in method signatures:

program Example;
{$mode ObjFPC}
type Letter = (A, B, C);
{ this *could* be valid code, because something like "TakesASet([A, C])" is
valid code }
procedure TakesASet(ASet: set of Letter);
begin
end;
{ this *could not* be valid code, because D, E and F do not exist outside
to actually call it with }
procedure ImpossibleTakesASet(ASet: set of (D, E, F));
begin
end;
{ this *could* be valid code, because something like "TakesARange(2)" is
valid code }
procedure TakesARange(ARange: 0..3);
begin
end;
{ this would be nonsensical IMO, because you could only call it with a
  variable of an existing named record type with identical fields, making
it pointless }
procedure TakesARecord(ARecord: record A, B: LongInt; end;);
begin
end;
begin
end.

Reply by email

Sven Barth
to Ryan Joseph: Good idea to make generics a mode switch. That probably will improve compiler times. Ryan…
Ryan Joseph wrote 5 lines
> On Jun 7, 2019, at 5:06 PM, Sven Barth via fpc-devel wrote: > > No. The generic keywords are part of mode ObjFPC. The only thing I plan to do is to move the whole idea of generic keywords to a modeswitch, but that is neither here nor there currently. Good idea to make generics a mode switch. That probably will improve compiler times.

Huh? Who said anything about generics themselves? I meant the generic keywords: "generic" and "specialize". So that those that want to use mode ObjFPC without the keywords can do so.
Also it makes no sense to disable specializations as more and more generics are becoming part of the RTL/FCL.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Jun 7, 2019, at 5:30 PM, Sven Barth via fpc-devel wrote: Huh? Who said anything about generics themselves? I meant the generic keywords: "generic" and "specialize". So that those that want to use mode ObjFPC without the keywords can do so.

Ah, I see now. That’s even better. :)

Regards,
Ryan Joseph

Reply by email

Ben Grasset

Two final things:

A) I didn't really make this thread with to imply I necessarily wanted *someone else* to implement this. What I ultimately was trying to figure out is basically would I be wasting my time if I was able to implement this on my own, probably under a new modeswitch (maybe {$modeswitch TypedPointerParams} or something.)

B) I was looking at some output from FPC's "-vp" flag today, and it's pretty clear that the compiler is already perfectly capable of knowing exactly what "^Type" means in all cases, because *all* pointer type aliases in that output are literally desugared to "^Type".

Reply by email

Florian Klämpfl
to Ben Grasset
Ben Grasset wrote
B) I was looking at some output from FPC's "-vp" flag today, and it's pretty clear that the compiler is already perfectly capable of knowing exactly what "^Type" means in all cases, because *all* pointer type aliases in that output are literally desugared to "^Type".

And? It is obvious that FPC has to know what's the base type of a pointer else it couldn't do type checking.

Reply by email

Ryan Joseph
to Florian Klämpfl
On Jun 9, 2019, at 9:45 AM, Florian Klämpfl wrote: And? It is obvious that FPC has to know what's the base type of a pointer else it couldn't do type checking.

I think all he means is this:

type
  TInt = ^integer;
procedure DoThis(i: TInt);
begin
end;
var
  a: ^integer;
begin
  DoThis(a0);

He just wants function parameters to declare the new pointer type inline.

procedure DoThis(i: ^integer);
begin
end;
var
  a: ^integer;
begin
  DoThis(a0);

Regards,
Ryan Joseph

Reply by email

Florian Klämpfl
to Ryan Joseph
Ryan Joseph wrote 21 lines
> On Jun 9, 2019, at 9:45 AM, Florian Klämpfl wrote: > > And? It is obvious that FPC has to know what's the base type of a pointer else it couldn't do type checking. I think all he means is this: type TInt = ^integer; procedure DoThis(i: TInt); begin end; var a: ^integer; begin DoThis(a0); He just wants function parameters to declare the new pointer type inline.

Yes, but this has *nothing* to do with the output of -vp. Nothing.

Reply by email

Ben Grasset
to Florian Klämpfl: Yes, but this has *nothing* to do with the output of -vp. Nothing.
AM Florian Klämpfl wrote
Yes, but this has *nothing* to do with the output of -vp. Nothing.

My point with that was more just getting at "clearly typed pointer aliases are not actually that big of a deal internally for FPC", as in it doesn't really matter if it *technically* declares a new type.

Again, literally nobody in this entire message chain has stated any actual reason why exactly they think it would be specifically *bad* to have `^Type` in method parameters.

Reply by email

John Doe

Personally I'd LOVE to see be possible. I'm pretty sure just about every Pascal developer out there has wanted to be able to do that kind of thing at some point.

It's not like there's any real downsides to it either that I can think of. It doesn't make code harder to read. It's not ambiguous (because like, everyone knows what ^ means.)

Reply by email

Dmitry Boyarintsev
to Ben Grasset: On Sun, Jun 9, 2019 at 11:26 AM Florian Klämpfl My point with that was more just getting…
PM Ben Grasset wrote
Again, literally nobody in this entire message chain has stated any actual reason why exactly they think it would be specifically *bad* to have `^Type` in method parameters.

Is it because parameter types are doesn't really match a type definition. One can't do

  function myFunc(var a: record a,b: integer; end): integer;

the record type has to be declared separately.
or
declaring

  function myFunc(var a: array of integer): integer;

is 100% not the same as

  TArrayType = array of Integer;
  function myFunc(var a:  TArrayType  ): integer;

so parameter type declaration is pretty much "reserved" for Embarcadero to change... and FPC will eventually follow :)

Ultimately the bad thing is changing Pascal ideology. Declare first, then use.
Specifying a parameter type is "use". Thus it has to be declared first.

Do you really want to change it? If yes, what's the **technical** benefit?

thanks,
Dmitry

Reply by email

Bernd Oppolzer
to Ben Grasset: On Sun, Jun 9, 2019 at 11:26 AM Florian Klämpfl My point with that was more just getting…
Ben Grasset wrote 13 lines
On Sun, Jun 9, 2019 at 11:26 AM Florian Klämpfl < > wrote: Yes, but this has *nothing* to do with the output of -vp. Nothing. My point with that was more just getting at "clearly typed pointer aliases are not actually that big of a deal internally for FPC", as in it doesn't really matter if it *technically* declares a new type. Again, literally nobody in this entire message chain has stated any actual reason why exactly they think it would be specifically *bad* to have `^Type` in method parameters.

A compiler writer's point of view:

I did something similar recently, when I added types with parameters to my New Stanford Pascal compiler (for example CHAR (15), STRING (25), DECIMAL (15, 2)).
I decided to allow this notation in procedure declarations, too.

This has the following impacts on the compiler:

- you have to parse "type with parameters" in procedure declarations, where you had only
type identifiers up to now

- you have to construct a new "artificial" type record with a name which is not a normal identifier
but which matches for identical notations used later and insert this record into the type list on
first occurence. In my case, the types CHAR (n) etc. are standard types, so they are inserted
into the type list of the top-level block, even if they occur at lower levels (there is one entry for
CHAR (n) for every different value of n, although the CHAR (n) types are compatible to each other
to a certain degree, same goes for STRING (n) - CHAR (n) is simply an abbreviation for
ARRAY [1..n] of CHAR; STRING (n) are varying length strings, involving a length field).

In the case of the pointer notation, things would be different:

- a pointer symbol should be accepted in front of the type identifier (or in my case, "type with parameters")

- the base type must have been declared already

- if there is no definition for this pointer type, also in this case a new "artificial" type record must be built,
but the type record should be inserted at the same level as the record of the base type. The generated
name should be unique, not a normal identifier, and dependent from the base type identifier.

But:

I am still not sure, if it is a good idea, because this would be an exception for pointer types;
other type constructors like arrays, records, enumerations etc. are still not supported ...
and it does not make sense IMO to support them.

Kind regards

Bernd

Reply by email

Ben Grasset
to Dmitry Boyarintsev: Is it because parameter types are doesn't really match a type definition. One can't do…
PM Dmitry Boyarintsev wrote
One can't do function myFunc(var a: record a,b: integer; end): integer; the record type has to be declared separately.

Of course not. That would be rather nonsensical, *for very obvious reasons*, that I've already gone out of my way to address in this comment chain. It is however utterly ridiculous to directly correlate that with `^Type` syntax, as they are only related in the most vague of ways.

PM Dmitry Boyarintsev wrote 6 lines
declaring function myFunc(var a: array of integer): integer; is 100% not the same as TArrayType = array of Integer; function myFunc(var a: TArrayType ): integer;

Trying to pretend like this
*completely-irrelevant-to-the-current-subject *point means anything at all in this context is frankly even more ridiculous, notwithstanding the fact that the whole "open array vs. dynamic array" thing is *only remotely applicable in any way whatsoever* to, well, *arrays *(and quite arguably a bizarre quirk of the language in the first place.)

If you're going to do this whole faux-academic "I care so very much about strictly traditional Pascal" thing, also, at least do it with features that *are
*themselves in any way "traditional". *Everything *about the entire existence of dynamic arrays is *non*-traditional, and dreamt up by some random combination of Borland employees in California at some point in the 1990s, none of whom we're likely to ever even know the specific names of.

Are we going to remove dynamic arrays, though? No, of course not, because they're *useful.*

PM Dmitry Boyarintsev wrote
so parameter type declaration is pretty much "reserved" for Embarcadero to change... and FPC will eventually follow :)

Embarcadero is a running joke of a company, firmly in the "it's surprising these guys are still in business at all" category, with a long history of decisions made
for reasons that had *absolutely nothing *to do with making Pascal better (such as outsourcing large aspects of recent Delphi development) and *absolutely
everything *to do with
pretty desperately trying to continue to make money in any way they possibly could.

I do not care in the slightest about them or anything they do, and I had frankly been under the impression that many people in the FPC community felt the same way.
If anything, FPC's development team has a *far* better track record of competence and is objectively more qualified to make decisions about the language in a general sense.

(Not that I think we even *need* that kind of overly formal "decision making". This is not C++, we do not have the ISO Pascal Committee, and as far as I'm concerned that's probably a good thing.)

That said, again, I think *all *of this is massively overblowing the issue. I find it quite surprising that there's really any controversy at all with regards to `^Type` in method declarations,
as the way I see it it's a highly non-intrusive bit of added syntax that almost certainly should have been there in the first place.

PM Dmitry Boyarintsev wrote
Do you really want to change it? If yes, what's the **technical** benefit?

Yes? Obviously? I clearly demonstrated the technical benefit in my original comment. *Yet again *though I do not understand why this is controversial. It would amount to a very tiny syntax addition, that does *nothing *other than make certain things *easier* to write.

Reply by email

Ryan Joseph
to Dmitry Boyarintsev: Is it because parameter types are doesn't really match a type definition. One can't do…
Show quoted text 13 lines
On Jun 9, 2019, at 8:11 PM, Dmitry Boyarintsev wrote: Is it because parameter types are doesn't really match a type definition. One can't do function myFunc(var a: record a,b: integer; end): integer; the record type has to be declared separately. or declaring function myFunc(var a: array of integer): integer; is 100% not the same as TArrayType = array of Integer; function myFunc(var a: TArrayType ): integer;

What if static array and record types were the exception? I agree it looks bad using anonymous records in parameters but pointers makes perfect sense to me. I think simply allowing pointers (and perhaps dynamic arrays) covers 99% percent of use cases.

Personally I’ve had to write dummy types more than once in order to get around this design problem. If I had to guess I’d say this is just a historical relict the didn’t stand up to the test of time.

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Ben Grasset
Show quoted text 10 lines
On Jun 9, 2019, at 9:17 PM, Ben Grasset wrote: On Sun, Jun 9, 2019 at 11:23 AM Ryan Joseph wrote: var a: ^integer; begin DoThis(a0); I'm assuming "a0" was just a typo there?...

typo.

Regards,
Ryan Joseph

Reply by email

Dmitry Boyarintsev
to Ben Grasset: On Sun, Jun 9, 2019 at 8:11 PM Dmitry Boyarintsev Of course not. That would be rather…
PM Ben Grasset wrote 12 lines
On Sun, Jun 9, 2019 at 8:11 PM Dmitry Boyarintsev < > wrote: > Do you really want to change it? If yes, what's the **technical** > benefit? > Yes? Obviously? I clearly demonstrated the technical benefit in my original comment. *Yet again *though I do not understand why this is controversial. It would amount to a very tiny syntax addition, that does *nothing *other than make certain things *easier* to write.

Ah... I found it now. It's all about generics. Well, there's nothing I can argue about here.

Maybe just to point out that usage of "var" and "const" might have been a more appropriate option, in the example.
And they don't require a pointer declaration either.

thanks,
Dmitry

Reply by email

Dmitry Boyarintsev
to Ryan Joseph: What if static array and record types were the exception? I agree it looks bad using…
PM Ryan Joseph wrote
What if static array and record types were the exception?

Avoiding making any exceptions in a design is typically a good thing.

Personally I’ve had to write dummy types more than once in order to get around this design problem. If I had to guess I’d say this is just a historical relict the didn’t stand up to the test of time.

I'm not so confident about dummy types.
I typically refer to C-based API's. For example WinAPI. WinAPI is actually providing a pointer-to-type type declaration, for all of it's type.
Even though they don't really have to do that, as C does allow inline reference declaration.
I'm wondering what were Microsoft's reasons to introduce a lot of "historical relic" in their apis

thanks,
Dmitry

Reply by email

Ben Grasset
to Bernd Oppolzer: A compiler writer's point of view: I did something similar recently, when I added types…
PM Bernd Oppolzer wrote
the base type must have been declared already

Well, not necessarily in FPC, because generics, but that would just follow the same way generic parameters are currently "filled in later" in all other areas.

PM Bernd Oppolzer wrote 7 lines
if there is no definition for this pointer type, also in this case a new "artificial" type record must be built, but the type record should be inserted at the same level as the record of the base type. The generated name should be unique, not a normal identifier, and dependent from the base type identifier.

Presumably the compiler (in the case of FPC) would handle it roughly the same way it currently handles stuff like:

var PI: ^LongInt

I do not believe it would be overly complicated to implement, in general.

PM Bernd Oppolzer wrote 6 lines
I am still not sure, if it is a good idea, because this would be an exception for pointer types; other type constructors like arrays, records, enumerations etc. are still not supported ... and it does not make sense IMO to support them.

People keep saying this as though the *entire concept *of adding even the smallest new thing syntactically to FPC is a completely new idea (which it obviously is not.)
Adding this would *not *be any kind of notable "exception" in any practical sense, unless you're holding FPC to a purely fictional standard for Pascal that it does not actually currently follow in reality.

Reply by email

Dmitry Boyarintsev
to Ben Grasset: On Sun, Jun 9, 2019 at 8:11 PM Dmitry Boyarintsev Of course not. That would be rather…
PM Ben Grasset wrote 5 lines
Of course not. That would be rather nonsensical, *for very obvious reasons*, that I've already gone out of my way to address in this comment chain. It is however utterly ridiculous to directly correlate that with `^Type` syntax, as they are only related in the most vague of ways.
If such declaration would be ok:
function DoSomething (a: ^Integer; b: Pointer): integer;
Should the flowing code (inside of DoSomething body) be ok as well?
  ((^Integer)(b))^ := a^;

(keep in mind that ^A ... ^Z is also a character escaping)

thanks,
Dmitry

Reply by email

Ben Grasset
to Dmitry Boyarintsev: Ah... I found it now. It's all about generics. Well, there's nothing I can argue about…
PM Dmitry Boyarintsev wrote
Ah... I found it now. It's all about generics. Well, there's nothing I can argue about here.

Well, not *really.* As I stated in the original message, it's just as useful for non-generic procedures or non-generic anything else.

PM Dmitry Boyarintsev wrote
Maybe just to point out that usage of "var" and "const" might have been a more appropriate option, in the example.

I had been under the impression that it was *exceedingly* obvious what the benefits of this sort of thing were.
Apparently I was wrong! I did use "var" and "const" examples in a later message though (not that I think that really should have been necessary as an explanation, again.)

Reply by email

Ben Grasset
to Dmitry Boyarintsev: If such declaration would be ok: function DoSomething (a: ^Integer; b: Pointer): integer;…

On Sun, Jun 9, 2019 at 10:00 PM Dmitry Boyarintsev <

Show quoted text 5 lines
wrote: Should the flowing code (inside of DoSomething body) be ok as well? ((^Integer)(b))^ := a^;

I mean, like *many, many, many *things, yes it is technically possible for that to be valid Pascal syntax. As far as *should*, well, I'm not personally a fan of that sort of too-many-parentheses typecasting, but I wouldn't specifically care one way or another if it was added as there's no reason for me to.

I fail to see how that is anything more than *distantly *related to what we're discussing in this thread, though.

In general I'm not really interested in playing this sort of FUD-ish *"if we add X, it's gonna lead down the road to Largely Unrelated Y!" * back-and-forth game, as I find it both childish and a waste of time as it's almost always highly unrealistic with regards to whatever is being talked about.

Reply by email

Dmitry Boyarintsev
to Ben Grasset
PM Ben Grasset wrote 9 lines
I mean, like *many, many, many *things, yes it is technically possible for that to be valid Pascal syntax. As far as *should*, well, I'm not personally a fan of that sort of too-many-parentheses typecasting, but I wouldn't specifically care one way or another if it was added as there's no reason for me to. I fail to see how that is anything more than *distantly *related to what we're discussing in this thread, though.

Distantly? you're proposing to introduce a reference-to-type declaration within a parameter. Without giving it any name.
Fine. But that would requires a type-casting within the code to the same type as has been declared within the parameter.
Otherwise you're creating some type, that cannot be casted-to. Which is odd.

So if you're fan of having ^Integer as a parameter type, then you pretty much self-declaring to be a fan of (^Integer)(varname) as well.

In general I'm not really interested in playing this sort of FUD-ish *"if

Show quoted text 5 lines
we add X, it's gonna lead down the road to Largely Unrelated Y!" * back-and-forth game, as I find it both childish and a waste of time as it's almost always highly unrealistic with regards to whatever is being talked about.

It's kinda what language designers HAVE to do.
It's nice just to throw out the "next-big-thing-cool-idea" out there and make yourself look smart.
But you actually HAVE to think everything through. If you don't then your idea might not be so cool after all.

thanks,
Dmitry

Reply by email

Ben Grasset
to Dmitry Boyarintsev

On Sun, Jun 9, 2019 at 10:28 PM Dmitry Boyarintsev <

Show quoted text 12 lines
wrote: Distantly? you're proposing to introduce a reference-to-type declaration within a parameter. Without giving it any name. Fine. But that would requires a type-casting within the code to the same type as has been declared within the parameter. Otherwise you're creating some type, that cannot be casted-to. Which is odd. So if you're fan of having ^Integer as a parameter type, then you pretty much self-declaring to be a fan of (^Integer)(varname) as well.

This is.... completely ludicrous, to say the very least. "PSomething: ^TSomeType" declared in a method signature would behave *completely identically in every way *to how "var PSomething: ^TSomeType" *already behaves right now*, as far as using it inside the scope of the method body is concerned. It introduces *nothing* that does not already exist.

On Sun, Jun 9, 2019 at 10:28 PM Dmitry Boyarintsev <

Show quoted text 8 lines
wrote: t's kinda what language designers HAVE to do. It's nice just to throw out the "next-big-thing-cool-idea" out there and make yourself look smart. But you actually HAVE to think everything through. If you don't then your idea might not be so cool after all.

I have been programming in Pascal for decades and decades. This has *absolutely nothing *to do with the stupid "oh look another person trying to add a fancy new feature" thing that people insist on whining about any time anyone suggests *anything at all* (despite the fact that the phenomenon itself only nominally exists in any capacity.

The functionality I'm suggesting is *utterly trivial. *If you don't think so, it's likely you don't really quite get what I'm actually talking about.

Reply by email

Ben Grasset
to Ben Grasset
Show quoted text 11 lines
On Sun, Jun 9, 2019 at 10:28 PM Dmitry Boyarintsev < > wrote: > t's kinda what language designers HAVE to do. > It's nice just to throw out the "next-big-thing-cool-idea" out there and > make yourself look smart. > But you actually HAVE to think everything through. > If you don't then your idea might not be so cool after all. >

Furthermore, all that this whole chain of posts has taught me generally is that if I come on here and simply ask extremely straightforward *questions*, I will get a whole lot of people skirting the issue and rambling on about semi-related things, but nobody will ever actually give me a simple, direct *answer
*for any of them*.* How is this helpful? I'm currently no better off than I was when I sent the initial message.

Reply by email

Dmitry Boyarintsev
to Ben Grasset: On Sun, Jun 9, 2019 at 10:28 PM Dmitry Boyarintsev < This is.... completely ludicrous, to…
PM Ben Grasset wrote 16 lines
On Sun, Jun 9, 2019 at 10:28 PM Dmitry Boyarintsev < > wrote: > So if you're fan of having ^Integer as a parameter type, then you pretty > much self-declaring to be a fan of (^Integer)(varname) as well. > This is.... completely ludicrous, to say the very least. "PSomething: ^TSomeType" declared in a method signature would behave *completely identically in every way *to how "var PSomething: ^TSomeType" *already behaves right now*, as far as using it inside the scope of the method body is concerned. It introduces *nothing* that does not already exist. The functionality I'm suggesting is *utterly trivial. *If you don't think so, it's likely you don't really quite get what I'm actually talking about.

You've been told before. Variable types are not the same as parameter types.

The "utterly trivial" is in fact a change to the language syntax. Where currently, a parameter is:
[modifier] parameter_name [ : [array of] {type_identifier, const}]] You're proposing to do it as:
[modifier] parameter_name [ : [array of] {[^]type_identifier, const}]]

treating "^" as a special rule to pass a reference to a type (because "^" cannot be a part of identifier).

Adding a new exception never hurts anyone.

thanks,
Dmitry

Reply by email

Ben Grasset
to Dmitry Boyarintsev

On Mon, Jun 10, 2019 at 12:15 AM Dmitry Boyarintsev <

Show quoted text 5 lines
wrote: You've been told before. Variable types are not the same as parameter types.

That *doesn't matter* in any *practical *sense. How you *used *something declared as "^Type" would always be the same no matter what context it appeared in, because it can only ever mean one very specific thing.

I certainly do not need to be "told" anything, by the way.

On Mon, Jun 10, 2019 at 12:15 AM Dmitry Boyarintsev <

Show quoted text 11 lines
wrote: The "utterly trivial" is in fact a change to the language syntax. Where currently, a parameter is: [modifier] parameter_name [ : [array of] {type_identifier, const}]] You're proposing to do it as: [modifier] parameter_name [ : [array of] {[^]type_identifier, const}]] treating "^" as a special rule to pass a reference to a type (because "^" cannot be a part of identifier).

So, you're going to keep pretending like you're actually concerned about maintaining the integrity of some (completely fictional) "traditional" Pascal (that FPC never has been and was presumably never intended to be), and implying that arbitrary *syntax diagrams* of all things are non-trivially relevant to real people writing real Pascal code in real life? Great, I guess we won't be getting anywhere productive then.

If you or anyone else *actually *cared about that sort of thing at all, FPC would not do or allow many things that it currently does. Unfortunately, that would have the nasty side effect of making it a significantly less useful compiler for an objectively less useful form of the language,

Reply by email

Dmitry Boyarintsev
to Ben Grasset
AM Ben Grasset wrote 7 lines
So, you're going to keep pretending like you're actually concerned about maintaining the integrity of some (completely fictional) "traditional" Pascal (that FPC never has been and was presumably never intended to be), and implying that arbitrary *syntax diagrams* of all things are non-trivially relevant to real people writing real Pascal code in real life? Great, I guess we won't be getting anywhere productive then.

Then be productive and say - "yes, there must be an exception". That's it. It's not about a Pascal purity, it's about a design purity.

Just like the same example you've had with dynamic and open arrays. They were pretty much added as an exception. And they stayed. So maybe there's an exception for a reference type as well. Yet they also can be considered as a "need for delphi" compatibility, in context of FPC.

So, if the exception proposed by you is to be accepted, maybe others should follow as well?

Show quoted text 6 lines
If you or anyone else *actually *cared about that sort of thing at all, FPC would not do or allow many things that it currently does. Unfortunately, that would have the nasty side effect of making it a significantly less useful compiler for an objectively less useful form of the language,

Exactly. Let's add more nastiness to one's favor. It's your turn now, so why not?! right?!

...or maybe you would like to do more of this FDU work?! And rather than making a big deal of reference type for a parameter, would come up with a better design in general?
So pascal rule would state something like:
paramName : type_descriptor
rather than
paramName : type_identifier

where type_description would be something more, than a language entity used in parameter declaration.
I don't know. Unlike you, I don't have decades and decades in Pascal development.

You could probably even create a patch for the compiler. Introduce is it as your own "modeswitch" and let others run it.
Being productive!

thanks,
Dmitry

Reply by email

denisgolovan
to Sven Barth: You can do it like this (yes, works in mode Delphi as well): === code begin === {$mode…
Show quoted text 41 lines
You can do it like this (yes, works in mode Delphi as well): === code begin === {$mode objfpc} {$modeswitch advancedrecords} type generic TPointerType<T> = record public type PT = ^T; end; generic procedure MemCopy<T>(Dest, Src: specialize TPointerType<T>.PT; Len: PtrUInt); begin while Len > 0 do begin Dest^ := Src^; Inc(Dest); Inc(Src); Dec(Len); end; end; type String4 = String[4]; var X: specialize TArray<String4> = ('AAAA', 'BBBB', 'CCCC', 'DDDD', 'EEEE'); Y: specialize TArray<String4> = ('', '', '', '', ''); S: String4; begin specialize MemCopy<String4>(@Y[0], @X[0], 5); for S in Y do WriteLn(S); end. === code end === Regards, Sven

Maybe we can get generic aliases instead?
I mean

type
  generic TPtr<T> = ^T;

... then put TPtr into some FPC system unit and at least provide one single common type instead of re-inventing it in each separate library?

It'll be at least something like:

  generic function Test<T>( ptr: TPtr<T>);

I mean we already have TArray<T>, right?

Regards, Denis Golovan

Reply by email

Michael Van Canneyt
to Ben Grasset: On Mon, Jun 10, 2019 at 12:15 AM Dmitry Boyarintsev < That *doesn't matter* in any…
Ben Grasset wrote 8 lines
> So, you're going to keep pretending like you're actually concerned about maintaining the integrity of some (completely fictional) "traditional" Pascal (that FPC never has been and was presumably never intended to be), and implying that arbitrary *syntax diagrams* of all things are non-trivially relevant to real people writing real Pascal code in real life? Great, I guess we won't be getting anywhere productive then.

After 50 years of language extensions, I think "productivity" arguments can go straight to where they belong: the trash can. If someone still needs extra features to be productive, he really needs to look for another language to program in (or worse, another job).

So let's dispense with those arguments, please.

To the actual proposal. A recap:

The reason why you cannot do

Procedure A(B : Type definition);

as opposed to

Procedure C(D : Type Identifier);

is that the type definition for B in A only exists within the scope of A. Whereas the type of D must exist outside of C.

So if a strict type compatibility is maintained, anything declared outside of A will not be assignment compatible to B. (in general)

Meaning, if you were to declare

Procedure A(B : (one,two,three));

you would never be able to call this routine.

So the "rule" of not allowing to introduce new types in a procedure header is a logical consequence of the pascal type safety.

This is a simple and easy to understand rule.

Now, there exists an exception to this rule, introduced by Borland: open array parameters.

In a sense, a pointer definition resembles an array definition: there is a base type. So one could make the case for allowing

procedure A(B : ^SomeType);

as an equivalent of open array parameters.

But:

We recently had a case where open array parameters and the 'ease of use' functionality introduced around it, lead to a bug in overload resolution:

https://bugs.freepascal.org/view.php?id=35580
https://bugs.freepascal.org/view.php?id=35576

As you can see in the second bugreport the only solution was to disable the 'ease of use' functionality.

So

1. Before embarking on implementing yet another 'ease of use' addition, better make sure we will not again lay the foundations of hard to understand bugs.

2. I really want to see more arguments than the worn-out 'increased productivity' before adding another exception to an otherwise easy to understand rule in declaring procedures/functions. Simplicity has its virtues.

Michael.

Reply by email

Florian Klämpfl
to Ben Grasset: On Sun, Jun 9, 2019 at 11:26 AM Florian Klämpfl My point with that was more just getting…
Ben Grasset wrote 7 lines
On Sun, Jun 9, 2019 at 11:26 AM Florian Klämpfl < > wrote: Yes, but this has *nothing* to do with the output of -vp. Nothing. My point with that was more just getting at "clearly typed pointer aliases are not actually that big of a deal internally for FPC", as in it doesn't really matter if it *technically* declares a new type.

A lot is not a big deal - even not supporting localized keywords - but we don't do it for good reasons.

Again, literally nobody in this entire message chain has stated any actual reason why exactly they think it would be specifically *bad* to have `^Type` in method parameters.

I am pretty sure (I do not read completely anymore those lengthy "I have a great idea how to improve productivity" threads) somebody did explain you that this is not orthogonal as other types cannot be declared this way.

Reply by email

Florian Klämpfl
to Michael Van Canneyt: After 50 years of language extensions, I think "productivity" arguments can go straight…
Michael Van Canneyt wrote
Now, there exists an exception to this rule, introduced by Borland: open array parameters.

Well, open strings and open arrays cannot be considered as real types imo (you cannot declare anything else than a parameter as open array/string) but more a parameter passing convention similar to call by reference parameters which could also be considered as a type definition then (C++ has reference types after all).

Reply by email

Michael Van Canneyt
to Florian Klämpfl
Florian Klämpfl wrote 7 lines
Am 10.06.2019 um 09:14 schrieb Michael Van Canneyt: > > Now, there exists an exception to this rule, introduced by Borland: open array parameters. Well, open strings and open arrays cannot be considered as real types imo (you cannot declare anything else than a parameter as open array/string) but more a parameter passing convention similar to call by reference parameters which could also be considered as a type definition then (C++ has reference types after all).

The main thing is that there is a solid reason for the current behaviour, and better arguments than 'productivity' must be provided.

I'm not a big fan of generics, anonymous functions and many other recent language additions, but at least those actually add new functionality to the language.

Michael.

Reply by email

Martin Frb
to Ben Grasset: On Sun, Jun 9, 2019 at 8:11 PM Dmitry Boyarintsev Of course not. That would be rather…
Ben Grasset wrote 5 lines
Yes? Obviously? I clearly demonstrated the technical benefit in my original comment. *Yet again *though I do not understand why this is controversial. It would amount to a very tiny syntax addition, that does *nothing *other than make certain things *easier* to write.

Well a few points from my side.

Your first post (if I have it right) was about generics:   procedure MemCopy<T>(Dest: ^T; Src: ^T; Len: PtrUInt); A case in which the type is determined later, and you cannot (easily) declare the pointer type in advance)

To start with, I can see the appeal for that case.

Problem 1: Overloading.

program Project1;
type
   Ta = type ^byte;
   Tb = type ^byte;
procedure P1(x: Ta); overload;
begin  writeln(1); end;
procedure P1(x: Tb); overload;
begin  writeln(2); end;
begin
   P1(Ta(1));
   P1(Tb(1));
end.

If you did have "procedure P1(x: ^Byte); overload;", how would you call it?

Problem 2:
pointer to pointer?
This is not allowed in type:
  type PPFoo = ^^Foo;
But what if you need it for a param?

Problem 3:
You stated (IIRC, somewhere in this thread), this was a special case for pointers only. All the other types that can be declared are not needing this.
Well, that may be true for inline record declarations, though you could call them with a constant:
   procedure P1(record a,b: Byte end); overload; and
    P1( (a:1; b:2) );

Yes it is more far fetched. But gets closer with each step.

The possible next step, if pointers would be agreed on, might be sets. They are identical to the pointer issue. (At specialization T must substituted by an existing enum)
  procedure Foo<T>(arg: set of T);
The enum values of T are known, so this can be called.

And to extend on this, if specialization can also take constants, then
ranges would be in the same category
   procedure Foo<A,B>(arg: A..B);
Actually
   type TBar = class
     const A=1; B=5;
   end
   procedure Foo<T>(arg: T.A..T.B);

So this is all, but limited to pointers.

Reply by email

Martin Frb
to Dmitry Boyarintsev: If such declaration would be ok: function DoSomething (a: ^Integer; b: Pointer): integer;…
Dmitry Boyarintsev wrote 8 lines
function DoSomething (a: ^Integer; b: Pointer): integer; Should the flowing code (inside of DoSomething body) be ok as well?   ((^Integer)(b))^ := a^; (keep in mind that ^A ... ^Z is also a character escaping)

Inside code / Outside declaration, this already has a meaning:

^I  is #9
So this is a char constant.

Reply by email

Luca Olivetti
to Michael Van Canneyt: After 50 years of language extensions, I think "productivity" arguments can go straight…

El 10/6/19 a les 9:14, Michael Van Canneyt ha escrit:

2. I really want to see more arguments than the worn-out 'increased productivity' before adding another exception to an otherwise easy to understand rule in declaring procedures/functions. Simplicity has its virtues.

I think that what really boosts productivity is lazarus being able to code complete correctly most of the code most of the time. With many exceptions I fear that would become more difficult. In fact I see more and more lazarus being confused and I have to restart it frequently just to be able to make it code complete again instead of reporting bogus errors (but that may be just another bug).

Bye

Luca

Reply by email

Bernd Oppolzer
to Ben Grasset: On Sun, Jun 9, 2019 at 8:37 PM Bernd Oppolzer Well, not necessarily in FPC, because…

FYI:

I thought a little bit more about your answer and decided to try it with my Stanford compiler;
in fact, your pointer parameter is a VALUE parameter, and because it is copied into the procedure's
local stack, it should be treated much like a local variable IMO, and there it is indeed possible to use
the  ^basetype notation and all the other type notations, too. Therefore IMO it should also be possible
to define new types with value parameters, be it useful or not. The normal Pascal assignment
rules apply (parameter passing to value parameters is much like normal assignment, with some
tolerance regarding types).

So I decided to allow it, but for value parameters only. For var and const parameter, different rules
apply, because there we have conformant strings for example (strings without length) etc.;
so I call a different parsing function, when I have a var or const keyword. Without var or const,
I call the same parsing function for types which I call in var declarations etc, too.

So now the following program compiles (and runs) without problem:

program TESTPTR ( OUTPUT ) ;
//**********************************************************************
//$A+
//**********************************************************************
type CFORW = record
                SOMEV : INTEGER ;
                C : -> CHAIN ;
              end ;
      CHAIN = record
                N : INTEGER ;
                NEXT : -> CHAIN ;
              end ;
var K : -> CHAIN ;
     X : CFORW ;
procedure PRINT ( X : -> CHAIN ) ;
    begin (* PRINT *)
      while X  NIL do
        begin
          WRITELN ( X -> . N ) ;
          X := X -> . NEXT
        end (* while *)
    end (* PRINT *) ;
begin (* HAUPTPROGRAMM *)
   NEW ( K ) ;
   X . C := K ;
   K -> . N := 1 ;
   NEW ( K -> . NEXT ) ;
   K := K -> . NEXT ;
   K -> . N := 2 ;
   NEW ( K -> . NEXT ) ;
   K := K -> . NEXT ;
   K -> . N := 3 ;
   K -> . NEXT := NIL ;
   PRINT ( X . C ) ;
end (* HAUPTPROGRAMM *) .

- I use a different notation for the pointer symbol; ^ is possible, too

- there is no declaration for the -> CHAIN pointer type, nowhere

- it is even possible to use it in the CFORW record, prior to the definition of CHAIN
(those forward references are checked later)

Kind regards

Bernd

Ben Grasset wrote 18 lines
On Sun, Jun 9, 2019 at 8:37 PM Bernd Oppolzer < > wrote: I am still not sure, if it is a good idea, because this would be an exception for pointer types; other type constructors like arrays, records, enumerations etc. are still not supported ... and it does not make sense IMO to support them.  People keep saying this as though the *entire concept *of adding even the smallest new thing syntactically to FPC is a completely new idea (which it obviously is not.) Adding this would *not *be any kind of notable "exception" in any practical sense, unless you're holding FPC to a purely fictional standard for Pascal that it does not actually currently follow in reality.

Reply by email

Ben Grasset
to Martin Frb: Well a few points from my side. Your first post (if I have it right) was about generics:…
AM Martin Frb wrote
If you did have "procedure P1(x: ^Byte); overload;", how would you call it?

I would think it should be compatible *not* with this:

type PB = type ^byte;

but with anything declared like this:

type PB = ^byte;
AM Martin Frb wrote
This is not allowed in type: type PPFoo = ^^Foo; But what if you need it for a param?

Well, double-caret would still just be generally invalid syntax, presumably. You wouldn't just introduce it for no reason here.

As far as the rest, certainly, some of that could work in theory, but I don't think it necessarily would *need* to be all added at the same time, if 's no reason not to consider / evaluate each bit separately, I wouldn't say.

Reply by email