[fpc-devel] [] property overloads

Ondrej Pokorny lazarus at kluug.net
Tue Jul 2 07:25:24 CEST 2019


On 01.07.2019 23:25, Michael Van Canneyt wrote:
> I understand. But all depends on how the compiler parses and evaluates 
> this.
>
> Let me put brackets to make it more clear: is
>
> MyTest.StringArray[i]
>
> parsed & evaluated as
>
> (MyTest.StringArray)([(i)])
>
> or as
>
> (MyTest.StringArray[(i)])
>
> In the former case, the compiler cannot know what the result type is 
> of the
> first set of brackets in your proposal. In the latter case, it can be OK.
>
> But I simply do not know, someone with more intimate knowledge of the
> compiler needs to shed light on this.

I happened to study this part of FPC code back in 2015 when I worked on 
issue #28820. I can say that FPC directly transfers indexed properties 
to method calls with the parameters from []-brackets without checking if 
the property definition exists - and even without checking if the 
[]-brackets are there. That means, in case StringArray is an array property:

MyTest.StringArray[i]

is always evaluated as

MyTest.StringArrayGetter(i)

and never as

(MyTest.StringArray)[i]

the same goes for

MyTest.StringArray -> MyTest.StringArrayGetter()
MyTest.StringArray[] -> MyTest.StringArrayGetter()
MyTest.StringArray['abc'] -> MyTest.StringArrayGetter('abc')
MyTest.StringArray['abc', 123, 3.14] -> MyTest.StringArrayGetter('abc', 
123, 3.14)

But you can explicitly add the brackets around MyTest.StringArray - the 
compiler allows this.

Let me show you some code to prove myself:

program Project1;
{$mode objfpc}
type
   TValue = record A: Integer end;
   TMyClass = class
   private
     function GetValue: string;
     function GetValue(aindex: string): Double;
   public
     property Index[aindex: string]: Double read GetValue;
   end;
{ TMyClass }
function TMyClass.GetValue(aindex: string): Double;
begin
   Writeln('double indexed overload called');
   Result := Length(aindex);
end;
function TMyClass.GetValue: string;
begin
   Writeln('string not-indexed overload called.');
   Result := 'abc';
end;
var
   c: TMyClass;
begin
   c := TMyClass.Create;
   Writeln(c.Index);        // allowed - string overload
   Writeln(c.Index[]);      // allowed - string overload
   Writeln(c.Index[2]);     // not allowed - overload does not exist 
(comment out to compile the program)
   Writeln(c.Index[][2]);   // allowed - string overload
   Writeln((c.Index)[2]);   // allowed - string overload
   Writeln(c.Index['abc']); // allowed - double overload
   ReadLn;
end.

---

So actually, what you call as "my proposal" is not really a proposal - 
the whole property overload feature is already present in FPC. But now 
it's just by accident and with wrong syntax. We only need 2 steps to 
convert this bug into a feature:
1.) Check the indexed property definition before calling the 
getter/setter + allow indexed property overloads.
2.) Forbid the empty-[]-brackets-syntax so that "c.Index[]" and 
"c.Index[][2]" from example above will become invalid.

Ondrej



More information about the fpc-devel mailing list