Lazarus

Programming => General => Topic started by: circular on April 16, 2020, 10:24:50 am

Title: Overloading system function
Post by: circular on April 16, 2020, 10:24:50 am
Hello folks,

I am trying to make BGRABitmap more compatible with Delphi. One of the issue is that += and -= work only with FreePascal.

I don't want though to write:
Code: Pascal  [Select][+][-]
  1. MyLongVariableName:= MyLongVariableName + value

In case of integers one can just write:
Code: Pascal  [Select][+][-]
  1. inc(MyLongVariableName, value);

But for Single that doesn't work. Hence the idea of overloading the Inc function. And use it for all types.

So I tried this:
Code: Pascal  [Select][+][-]
  1. procedure Inc(var AFloat: single; ADelta: single); overload;
  2. begin
  3.   AFloat := AFloat + ADelta;
  4. end;

But this shadows the system function. Now if I do:
Code: Pascal  [Select][+][-]
  1. var i: integer;
  2. begin
  3.   ...
  4.   inc(i, 3);  // <- complains about parameter
  5. end;

So I think maybe to add a function with another name, like Increment.

Or maybe deriving TSingleHelper and add a method Add, but would that be compatible with Delphi?
Title: Re: Overloading system function
Post by: winni on April 16, 2020, 10:40:41 am
Hi1

I call the inc for single/double since years
Code: Pascal  [Select][+][-]
  1. incF (myfloat);

and

Code: Pascal  [Select][+][-]
  1. incF (myFloat, myDeltaFloat);

Winni
Title: Re: Overloading system function
Post by: marcov on April 16, 2020, 10:54:40 am
inc is builtin, not a function, moreover you pass an integer to it, so your call matches inc(single,integer), while inc(integer,integer) and inc(single,single) are defined. I doubt that you can do things like this in Delphi anyway, for the same reason

 The helper might be a better direction. Sysutils already has a helper for single, so best is to inherit from there.

And keep in mind it won't work for properties anyway.
Title: Re: Overloading system function
Post by: circular on April 16, 2020, 12:16:27 pm
inc is builtin, not a function
You're saying builtins cannot be overloaded I presume.

Quote
moreover you pass an integer to it, so your call matches inc(single,integer), while inc(integer,integer) and inc(single,single) are defined.
That's not a problem. If there is one single then it matches (single,single) signature.

Quote
And keep in mind it won't work for properties anyway.
Yes, I thought of that.

I call the inc for single/double since years
Code: Pascal  [Select][+][-]
  1. incF (myfloat);

and

Code: Pascal  [Select][+][-]
  1. incF (myFloat, myDeltaFloat);
I like that.  :)
Title: Re: Overloading system function
Post by: marcov on April 16, 2020, 12:24:35 pm
inc is builtin, not a function
You're saying builtins cannot be overloaded I presume.

I'm no compiler devel, but I wouldn't bet on it. And even if it was somewhat possible, overloading resolution might work differently. And then third, you expect that to work the same in both compilers.

All in all, very unlikely.

Title: Re: Overloading system function
Post by: Thaddy on April 16, 2020, 12:45:18 pm

But this shadows the system function. Now if I do:
Code: Pascal  [Select][+][-]
  1. var i: integer;
  2. begin
  3.   ...
  4.   inc(i, 3);  // <- complains about parameter
  5. end;
Create your overloads also for the integer inc......Overload them all...That works. inc is not a keyword :D
But you must overload them all.
Title: Re: Overloading system function
Post by: PascalDragon on April 16, 2020, 01:56:05 pm
The helper might be a better direction. Sysutils already has a helper for single, so best is to inherit from there.

Delphi does not allow inheritance for record helpers  :'( (or did they change that with newer Delphi versions?)

inc is builtin, not a function
You're saying builtins cannot be overloaded I presume.

I'm no compiler devel, but I wouldn't bet on it. And even if it was somewhat possible, overloading resolution might work differently. And then third, you expect that to work the same in both compilers.

Correct. Intrinsics can't be overloaded. Which is why I had to change Delete and Insert to intrinsics to add support for dynamic arrays.


But this shadows the system function. Now if I do:
Code: Pascal  [Select][+][-]
  1. var i: integer;
  2. begin
  3.   ...
  4.   inc(i, 3);  // <- complains about parameter
  5. end;
Create your overloads also for the integer inc......Overload them all...That works. inc is not a keyword :D
But you must overload them all.

Correct. And one can always enforce the one from System using System.Inc and with the overloads being declared as inline there should be no call in theory.
Title: Re: Overloading system function
Post by: circular on April 16, 2020, 02:19:44 pm
Yeah in theory I could overload them all. But I would like to have a reduced footprint on functions for the user of BGRABitmap.

Delphi does not allow inheritance for record helpers  :'( (or did they change that with newer Delphi versions?)
Ok well then I will stick to IncF. Sounds nice.
Title: Re: Overloading system function
Post by: Thaddy on April 16, 2020, 02:32:41 pm
Yeah in theory I could overload them all. But I would like to have a reduced footprint on functions for the user of BGRABitmap.
As Sven explained, a bunch of overloads have lttle or any footprint for the end-user or code
Title: Re: Overloading system function
Post by: marcov on April 16, 2020, 02:35:07 pm
The helper might be a better direction. Sysutils already has a helper for single, so best is to inherit from there.

Delphi does not allow inheritance for record helpers  :'( (or did they change that with newer Delphi versions?)

I don't know, I don't have it. But I'm not sure if it has a single helper by default either, but I knew FPC had :-)
Title: Re: Overloading system function
Post by: PascalDragon on April 17, 2020, 09:31:40 am
The helper might be a better direction. Sysutils already has a helper for single, so best is to inherit from there.

Delphi does not allow inheritance for record helpers  :'( (or did they change that with newer Delphi versions?)

I don't know, I don't have it. But I'm not sure if it has a single helper by default either, but I knew FPC had :-)

The helpers that FPC provides in the SysUtils unit are also provided by Delphi (one reason why they were added there instead of a custom unit...).
Title: Re: Overloading system function
Post by: Remy Lebeau on April 18, 2020, 05:04:30 am
I don't want though to write:
Code: Pascal  [Select][+][-]
  1. MyLongVariableName:= MyLongVariableName + value

Why not?

So I think maybe to add a function with another name, like Increment.

That is your best option for cross-compiler support.

Or maybe deriving TSingleHelper and add a method Add, but would that be compatible with Delphi?

Record helpers for simple types only works in XE3 and later.  But record helpers can't be inherited from in Delphi.  And Delphi still supports only 1 helper at a time on any given type.

Delphi does not allow inheritance for record helpers  :'( (or did they change that with newer Delphi versions?)

That has not changed, no.
Title: Re: Overloading system function
Post by: circular on April 18, 2020, 08:04:43 am
I don't want though to write:
Code: Pascal  [Select][+][-]
  1. MyLongVariableName:= MyLongVariableName + value
Why not?
Well if is just a long variable name that's ok but if it is a long expression with indexing, it may be evaluated twice.
Title: Re: Overloading system function
Post by: PascalDragon on April 18, 2020, 11:10:22 am
Then how about using a new optimization introduced with 3.2?  :D

Example code:

Code: Pascal  [Select][+][-]
  1. program trdmdst;
  2.  
  3. var
  4.   arr: array of LongInt;
  5.   i, j: LongInt;
  6. begin
  7.   arr := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
  8.   i := 2;
  9.   j := 3;
  10.   arr[i * j] := arr[i * j] + 6;
  11. end.

Assembly of the assignment compiled without optimization:

Code: ASM  [Select][+][-]
  1. # [8] i := 2;
  2.         movl    $2,U_$P$TRDMDST_$$_I(%rip)
  3. # [9] j := 3;
  4.         movl    $3,U_$P$TRDMDST_$$_J(%rip)
  5. # [10] arr[i * j] := arr[i * j] + 6;
  6.         movq    U_$P$TRDMDST_$$_ARR(%rip),%rax
  7.         movslq  U_$P$TRDMDST_$$_I(%rip),%rcx
  8.         movslq  U_$P$TRDMDST_$$_J(%rip),%rdx
  9.         imulq   %rdx,%rcx
  10.         movl    (%rax,%rcx,4),%eax
  11.         leal    6(%eax),%eax
  12.         movq    U_$P$TRDMDST_$$_ARR(%rip),%rdx
  13.         movslq  U_$P$TRDMDST_$$_I(%rip),%rcx
  14.         movslq  U_$P$TRDMDST_$$_J(%rip),%r8
  15.         imulq   %r8,%rcx
  16.         movl    %eax,(%rdx,%rcx,4)
  17.  

Assembly of the assignment compiled with -OoUseLoadModifyStore:

Code: ASM  [Select][+][-]
  1. # [8] i := 2;
  2.         movl    $2,U_$P$TRDMDST_$$_I(%rip)
  3. # [9] j := 3;
  4.         movl    $3,U_$P$TRDMDST_$$_J(%rip)
  5.         movq    U_$P$TRDMDST_$$_ARR(%rip),%rax
  6. # [10] arr[i * j] := arr[i * j] + 6;
  7.         movslq  U_$P$TRDMDST_$$_I(%rip),%rdx
  8.         movslq  U_$P$TRDMDST_$$_J(%rip),%rcx
  9.         imulq   %rcx,%rdx
  10.         addl    $6,(%rax,%rdx,4)

Though to be fair, in this specific case -O2 will handle that as well with the added benefit that i and j will be kept in registers (on the other hand the UseLoadModifyStore optimization is available in general and is not as platform specific like the peephole optimizations):

Code: ASM  [Select][+][-]
  1. # [8] i := 2;
  2.         movl    $2,%ebx
  3. # [9] j := 3;
  4.         movl    $3,%esi
  5.         movq    U_$P$TRDMDST_$$_ARR(%rip),%rcx
  6. # [10] arr[i * j] := arr[i * j] + 6;
  7.         movslq  %ebx,%rax
  8.         movslq  %esi,%rsi
  9.         imulq   %rsi,%rax
  10. # Peephole Optimization: MovOpMov2Op (movl addl movl)
  11. # Peephole Optimization: Lea2Add done
  12.         addl    $6,(%rcx,%rax,4)
Title: Re: Overloading system function
Post by: circular on April 18, 2020, 05:22:10 pm
Cool  :)
TinyPortal © 2005-2018