Recent

Author Topic: Overloading system function  (Read 1525 times)

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Overloading system function
« 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?
Conscience is the debugger of the mind

winni

  • Hero Member
  • *****
  • Posts: 3197
Re: Overloading system function
« Reply #1 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

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Overloading system function
« Reply #2 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.

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Re: Overloading system function
« Reply #3 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.  :)
Conscience is the debugger of the mind

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Overloading system function
« Reply #4 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.


Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Overloading system function
« Reply #5 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.
« Last Edit: April 16, 2020, 12:49:20 pm by Thaddy »
Specialize a type, not a var.

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Overloading system function
« Reply #6 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 helper:'( (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.

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Re: Overloading system function
« Reply #7 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 helper:'( (or did they change that with newer Delphi versions?)
Ok well then I will stick to IncF. Sounds nice.
Conscience is the debugger of the mind

Thaddy

  • Hero Member
  • *****
  • Posts: 14197
  • Probably until I exterminate Putin.
Re: Overloading system function
« Reply #8 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
Specialize a type, not a var.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11382
  • FPC developer.
Re: Overloading system function
« Reply #9 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 helper:'( (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 :-)

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Overloading system function
« Reply #10 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 helper:'( (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...).

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1312
    • Lebeau Software
Re: Overloading system function
« Reply #11 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 helper:'( (or did they change that with newer Delphi versions?)

That has not changed, no.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Re: Overloading system function
« Reply #12 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.
Conscience is the debugger of the mind

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: Overloading system function
« Reply #13 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)

circular

  • Hero Member
  • *****
  • Posts: 4195
    • Personal webpage
Re: Overloading system function
« Reply #14 on: April 18, 2020, 05:22:10 pm »
Cool  :)
Conscience is the debugger of the mind

 

TinyPortal © 2005-2018