Recent

Author Topic: Advance Record operators calling the wrong function  (Read 2180 times)

ad1mt

  • Sr. Member
  • ****
  • Posts: 327
    • Mark Taylor's Home Page
Advance Record operators calling the wrong function
« on: December 03, 2023, 11:10:00 am »
I've working on a library to provide a new type, which is using advanced records.
Suddenly, operators like minus and greater-than are calling the wrong function.
For example, I have a record type like this:
Code: Pascal  [Select][+][-]
  1. T1 = record
  2.   private
  3.   var v: array of integer;
  4.   public
  5.   class operator subtract(const v1,v2:T1):T1;
  6.   class operator >=(const v1,v2:T1):T1;
  7.   end;
  8. class operator subtract(const v1,v2:T1):T1; // implementation
  9. class operator >=(const v1,v2:T1):T1; // implementation
Then, later in the code, when the following code is executed
Code: Pascal  [Select][+][-]
  1. var v1,v2:T1;
  2. begin
  3. v1:= 10; v2:= 5;
  4. v3:= (v1 - v2);
at line 4, the >= function is called when I step through the code (when the subtract function should be called), then the value returned makes no sense, and the calling code fails.
I know its unlikely anyone will be able to help, but my head is spinning, and I've got no idea how to proceed.
The only clue I have is that the problem appeared to start when the definition of the advanced record was changed. It used to be like this
Code: Pascal  [Select][+][-]
  1. T1 = record
  2.   private
  3.   var v: array[0..3] of integer;
  4.   public
  5.   class operator subtract(const v1,v2:T1):T1;
  6.   class operator >=(const v1,v2:T1):T1;
  7.   end;
  8. class operator subtract(const v1,v2:T1):T1; // implementation
  9. class operator >=(const v1,v2:T1):T1; // implementation
With the new definition (at top) I had to start initialising the newly created type T1 vars with setlength on the internal array.

Thaddy

  • Hero Member
  • *****
  • Posts: 16145
  • Censorship about opinions does not belong here.
Re: Advance Record operators calling the wrong function
« Reply #1 on: December 03, 2023, 12:42:21 pm »
You are mixing up Delphi syntax with Objfpc syntax, you use T1.subtract(Delphi) instead of T1.- (objfpc).
Here's a correct example for mode objfpc:
Code: Pascal  [Select][+][-]
  1. program testop;
  2. {$mode objfpc}{$modeswitch advancedrecords}
  3.  
  4. type
  5.   T1 = record
  6.     v:integer;
  7.     class operator initialize(var value:T1);
  8.     class operator - (const a,b:T1):T1;
  9.     class operator >=(const a,b:T1):Boolean;
  10.   end;
  11.  
  12.   class operator T1.initialize(var value:T1);
  13.   begin
  14.     value := Default(T1);
  15.   end;
  16.    
  17.   class operator T1.- (const a,b:T1):T1;
  18.   begin
  19.     result.v := a.v-b.v;
  20.   end;
  21.  
  22.   class operator T1.>=(const a,b:T1):Boolean;
  23.   begin
  24.     result := a.v >= b.v;
  25.   end;
  26.  begin
  27.  end.

In mode Delphi you must replace >= with GreaterThanOrEqual:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2.  
  3. type
  4.   T1 = record
  5.     v:integer;
  6.     class operator initialize(var value:T1);
  7.     class operator Subtract (const a,b:T1):T1; // on use this is - (minus)
  8.     class operator GreaterthanOrEqual(const a,b:T1):Boolean;// on use this is >=
  9.   end;
  10.  
  11.   class operator T1.initialize(var value:T1);
  12.   begin
  13.     value := Default(T1);
  14.   end;
  15.    
  16.   class operator T1.Subtract (const a,b:T1):T1;
  17.   begin
  18.     result.v := a.v-b.v;
  19.   end;
  20.  
  21.   class operator T1.GreaterThanOrEqual(const a,b:T1):Boolean;
  22.   begin
  23.     result := a.v >= b.v;
  24.   end;
  25.  begin
  26.  end.


You can not mix the mode specific syntax in a single unit. In this case I prefer objfpc syntax.
I also added auto initialize using a management operator{ you do not have to call setlength anymore if you add that to your code. Default() makes sure your static array is initialized. Not sure this works on a real Delphi..... I believe their syntax slightly differs.
« Last Edit: December 03, 2023, 01:10:21 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

ad1mt

  • Sr. Member
  • ****
  • Posts: 327
    • Mark Taylor's Home Page
Re: Advance Record operators calling the wrong function
« Reply #2 on: December 03, 2023, 01:00:01 pm »
You are mixing up Delphi syntax with Objfpc syntax
You can not mix the mode specific syntax in a single unit.
Thanks for this suggestion.
I've been unable to find the advanced record operator definition syntax in the PDF docs. Do you know where to find it?
What I've had to do is set delphi mode at the top, then see which syntax works by trial and error; which is not the best method.
EDIT - I've found the operator list, but I can't find the syntax used for advanced records
« Last Edit: December 03, 2023, 01:20:11 pm by ad1mt »

Thaddy

  • Hero Member
  • *****
  • Posts: 16145
  • Censorship about opinions does not belong here.
Re: Advance Record operators calling the wrong function
« Reply #3 on: December 03, 2023, 01:14:35 pm »
The delphi syntax is available in the online delphi documentation:
https://docwiki.embarcadero.com/RADStudio/Sydney/en/Operator_Overloading_(Delphi)
and the Freepascal syntax is available in the FreePascal documentation https://www.freepascal.org/docs-html/ref/refch15.html

Btw: my code is not a suggestion but an explanation about the difference in syntax. (mandatory)
« Last Edit: December 03, 2023, 01:16:29 pm by Thaddy »
If I smell bad code it usually is bad code and that includes my own code.

ad1mt

  • Sr. Member
  • ****
  • Posts: 327
    • Mark Taylor's Home Page
Re: Advance Record operators calling the wrong function
« Reply #4 on: December 03, 2023, 06:32:01 pm »
I don't think this needs too much investigation... I went back to a previous stable version, and have started re-applying the changes.
So far, the problem has not re-appeared, so it looks like it might be user error    :o

Zoran

  • Hero Member
  • *****
  • Posts: 1882
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Advance Record operators calling the wrong function
« Reply #5 on: December 03, 2023, 11:03:39 pm »
Although Thaddy explained it correctly, I believe that, if mixing objfpc and delphi mode syntax is not allowed, it should be a compile time error.

Passing compilation and then getting unexpected behaviour in runtime has to be a bug.

Thaddy

  • Hero Member
  • *****
  • Posts: 16145
  • Censorship about opinions does not belong here.
Re: Advance Record operators calling the wrong function
« Reply #6 on: December 04, 2023, 07:51:12 am »
Zoran, I think that because of the syntax mix/up he is actually introducing a new operator. If that is the case, it is hard to fix. But I have to test that.
If that IS the case I will file a bug report, because that would be more serious.
If I smell bad code it usually is bad code and that includes my own code.

ad1mt

  • Sr. Member
  • ****
  • Posts: 327
    • Mark Taylor's Home Page
Re: Advance Record operators calling the wrong function
« Reply #7 on: December 07, 2023, 03:29:14 pm »
From reading the documentation, it looks to me that you can use either the symbols or the names in objfpc mode. But in delphi mode, you can only use the names.
However, in delphi mode, some operators do not have names, and I've found the symbols work in those cases.
The problem I had sprang up suddenly... in the previous version of my code, it was working correctly. If delphi mode did not accept those symbols, then it would never have worked at all.

Zvoni

  • Hero Member
  • *****
  • Posts: 2737
Re: Advance Record operators calling the wrong function
« Reply #8 on: December 07, 2023, 04:15:38 pm »
From reading the documentation, it looks to me that you can use either the symbols or the names in objfpc mode. But in delphi mode, you can only use the names.
However, in delphi mode, some operators do not have names, and I've found the symbols work in those cases.
The problem I had sprang up suddenly... in the previous version of my code, it was working correctly. If delphi mode did not accept those symbols, then it would never have worked at all.
Wrong.
https://www.freepascal.org/docs-html/ref/refse63.html
Quote
As indicated above, in ObjFPC mode, the operators must be indicated with their symbol names. By contrast, in Delphi mode, the names of the operators can also be used, similar to the syntax in Delphi:
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

ad1mt

  • Sr. Member
  • ****
  • Posts: 327
    • Mark Taylor's Home Page
Re: Advance Record operators calling the wrong function
« Reply #9 on: December 07, 2023, 05:04:43 pm »
From reading the documentation, it looks to me that you can use either the symbols or the names in objfpc mode. But in delphi mode, you can only use the names.
However, in delphi mode, some operators do not have names, and I've found the symbols work in those cases.
The problem I had sprang up suddenly... in the previous version of my code, it was working correctly. If delphi mode did not accept those symbols, then it would never have worked at all.
Wrong.
Quote
Sorry... I got it the wrong way round. I'm using delphi mode, and used the symbolic operators when the named operators did not exist.
But my underlying point is, that when things broke and the wrong operator function was being called, this was not caused by mixing-up symbolic operators and operator names. It was caused by something else, most likely a mistake in my code.

Thaddy

  • Hero Member
  • *****
  • Posts: 16145
  • Censorship about opinions does not belong here.
Re: Advance Record operators calling the wrong function
« Reply #10 on: December 08, 2023, 10:43:13 am »
although it is possible to use the symbols for e.g. power and symetrc difference that have no equivalent in Delphi, when you use that syntax, it will break a real Delphi, so I would advise against using it if you need real Delphi compatibility. Maybe the documentation should stress this.

Otherwise my example is still a good guideline for your original question.
If I smell bad code it usually is bad code and that includes my own code.

ad1mt

  • Sr. Member
  • ****
  • Posts: 327
    • Mark Taylor's Home Page
Re: Advance Record operators calling the wrong function
« Reply #11 on: December 08, 2023, 01:08:55 pm »
although it is possible to use the symbols for e.g. power and symetrc difference that have no equivalent in Delphi, when you use that syntax, it will break a real Delphi
What I'm trying to achieve is a big integer library for Free Pascal, that can be used like this:
Code: Pascal  [Select][+][-]
  1. program t;
  2. uses    Multi_Int;
  3. var
  4. A,B,Q   :Multi_Int_X4;
  5. BEGIN
  6. Multi_Init_Initialisation(32);
  7. A:= Multi_Int_X4_MAXINT;
  8. B:= 10007;
  9. Q:= A div B;
  10. writeln(A.tostr,' div ',B.tostr,' = ',Q.tostr);
  11. END.
That code will compile with my library.
Whereas all the libraries I've tried are very complex to use, have a very unfriendly syntax, and require a major rewrite to use against an existing code base.
To get that kind of ease-of-use requires all the operator overloading that its possible to get; and I don't really care if that breaks Delphi compatibility. Delphi probably already has a good big integer library, but if it doesn't, then anyone is free to take my code and make it work for them.
I.M.O. Delphi is a dead duck. It used to be good in the 1990's, but I downloaded a trial copy a few weeks ago, and I found it was totally unusable (straight out of the box).
« Last Edit: December 08, 2023, 08:19:45 pm by ad1mt »

 

TinyPortal © 2005-2018