[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