Recent

Author Topic: I need to use the "forward" keyword with a record definition  (Read 8729 times)

PascalDragon

  • Hero Member
  • *****
  • Posts: 6403
  • Compiler Developer
Re: I need to use the "forward" keyword with a record definition
« Reply #15 on: November 10, 2023, 10:19:59 pm »
I need to use the "forward" keyword with a record definition, but the Pascal syntax does not allow this.

Correct, because the compiler needs to know the size of the record when you use it as a parameter or a field. Only for pointer types - as 440bx mentioned - forward declarations are allowed, because the size of a pointer type is known.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 12945
  • FPC developer.
Re: I need to use the "forward" keyword with a record definition
« Reply #16 on: November 11, 2023, 11:54:01 am »
PascalDragon:

I was wondering how hard this limit is, is the size really needed at function declaration time?

This limitation is from before records-with-methods, and to avoid having a field of TA in TB and vice versa. But for methods?


ad1mt

  • Sr. Member
  • ****
  • Posts: 488
    • Mark Taylor's Home Page
Re: I need to use the "forward" keyword with a record definition
« Reply #17 on: November 11, 2023, 05:24:43 pm »
You can also use operator overloading by implementing an assignment operator for your record types
Thanks for this suggestion, it looks promising.

However, I can't make sense of what the documentation is saying there, so it's going to take me several days to experiment and figure out how the syntax/semantics work.

TRon

  • Hero Member
  • *****
  • Posts: 4377
Re: I need to use the "forward" keyword with a record definition
« Reply #18 on: November 11, 2023, 05:35:48 pm »
Thanks for this suggestion, it looks promising.
You're welcome and it is a nice way to 'solve' your issue.

Quote
However, I can't make sense of what the documentation is saying there, so it's going to take me several days to experiment and figure out how the syntax/semantics work.
I have to get out the door in a jiffy so no time but when back I'll try to come up with some code for you (unless someone else beats me to it) or perhaps you want to give it try yourself first.

edit: back


example:

Code: Pascal  [Select][+][-]
  1. program test;
  2.  
  3. {$mode objfpc}{$H+}
  4. uses
  5.   sysutils;
  6.  
  7. type
  8.   TRecordType1 = record
  9.     x: integer;
  10.     y: single;
  11.     z: boolean;
  12.   end;
  13.  
  14.   TRecordType2 = record
  15.     x: string;
  16.     y: string;
  17.     z: string;
  18.   end;
  19.  
  20.  
  21. operator := (source: TRecordType1) destination: TRecordType2;
  22. begin
  23.   destination.x := source.x.ToString;
  24.   destination.y := source.y.ToString;
  25.   destination.z := source.z.ToString;
  26. end;
  27.  
  28. operator := (source: TRecordType2) destination: TRecordType1;
  29. begin
  30.   destination.x := source.x.ToInteger;
  31.   destination.y := source.y.ToSingle;
  32.   destination.z := source.z.ToBoolean;
  33. end;
  34.  
  35. var
  36.   R1: TRecordType1;
  37.   R2: TRecordType2;
  38. begin
  39.   R1 := default(TRecordType1);
  40.   R2 := default(TRecordType2);
  41.  
  42.   writeln('R1.x := ', R1.x);
  43.   writeln('R1.y := ', R1.y);
  44.   writeln('R1.z := ', R1.z);
  45.   writeln;
  46.  
  47.   writeln('R2.x := ', R2.x);
  48.   writeln('R2.y := ', R2.y);
  49.   writeln('R2.z := ', R2.z);
  50.   writeln;
  51.  
  52.   R1.x := 12;
  53.   R1.y := 34.56;
  54.   R1.z := true;
  55.  
  56.   R2 := R1;
  57.  
  58.   writeln('R2.x := ', R2.x);
  59.   writeln('R2.y := ', R2.y);
  60.   writeln('R2.z := ', R2.z);
  61.   writeln;
  62.  
  63.   R2.x := '100';
  64.   R2.y := '768.394';
  65.   R2.z := 'false';
  66.  
  67.   R1 := R2;
  68.  
  69.   writeln('R1.x := ', R1.x);
  70.   writeln('R1.y := ', R1.y);
  71.   writeln('R1.z := ', R1.z);
  72. end.
  73.  

which outputs:
Code: [Select]
R1.x := 0
R1.y :=  0.000000000E+00
R1.z := FALSE

R2.x :=
R2.y :=
R2.z :=

R2.x := 12
R2.y := 34.56000137
R2.z := -1

R1.x := 100
R1.y :=  7.683939819E+02
R1.z := FALSE

The destination name in the operator header declaration is perhaps a bit weird but can be omitted (in which case you should address the return value with the result modifier the same as you would for a function result).

Is that example more clear or do you perhaps still have questions ?
« Last Edit: November 11, 2023, 11:57:40 pm by TRon »
Today is tomorrow's yesterday.

hshatti

  • New Member
  • *
  • Posts: 14
  • Be kind!
Re: I need to use the "forward" keyword with a record definition
« Reply #19 on: December 26, 2023, 06:38:46 pm »
If you don't want to use helpers, I simply take advantage of pointers forward declaration capability, it works in both FPC and Delphi since forever for example :

Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.   PRec2=^TRec2;
  4.  
  5.   TRec1=record
  6.      a:integer:
  7.      Rec2:PRec2;
  8.   end;
  9.  
  10.   TRec2=record
  11.      a:Integer;
  12.      Rec1:TRec1
  13.   end;
  14.  
  15. implementation
  16.    
  17. function someFunc(one:TRec1; const two:TRec2):TRec1;
  18. begin
  19.    one.Rec2:=@two;
  20.    result:=one
  21. end;
  22.  
  23. function getRec2(const one:TRec1):TRec2;
  24. begin
  25.   result:=one.rec2^
  26. end;
  27.  
  28.  

and in your case :

Code: Pascal  [Select][+][-]
  1. {$MODE DELPHI}
  2. program forward_record;
  3. type
  4. PT2 = ^T2;  //  <--- forward declaration is allowed for pointers
  5. T1 = record
  6.      private
  7.        I:integer;
  8.      public
  9.        function T2_to_T1(const V1:PT2):T1;  //  <--- identifier T2 not found
  10.      end;
  11. T2 = record
  12.      private
  13.        I:integer;
  14.      public
  15.        function T1_to_T2(const V1:T1):T2;
  16.      end;
  17. begin
  18. end.
  19.  

one consideration that if the @ opereator results a reference for a variable in the stack, or a managed heap type, the compilar may change it later but i find FPC smart enough to decide that and it works most of the time.

Hope this helps

H
Cheers
« Last Edit: December 26, 2023, 06:41:25 pm by hshatti »
Comrades!, Unpython the world

PascalDragon

  • Hero Member
  • *****
  • Posts: 6403
  • Compiler Developer
Re: I need to use the "forward" keyword with a record definition
« Reply #20 on: December 27, 2023, 06:21:54 pm »
If you don't want to use helpers, I simply take advantage of pointers forward declaration capability, it works in both FPC and Delphi since forever for example :

Code: Pascal  [Select][+][-]
  1. type
  2.  
  3.   PRec2=^TRec2;
  4.  
  5.   TRec1=record
  6.      a:integer:
  7.      Rec2:PRec2;
  8.   end;
  9.  
  10.   TRec2=record
  11.      a:Integer;
  12.      Rec1:TRec1
  13.   end;
  14.  
  15. implementation
  16.    
  17. function someFunc(one:TRec1; const two:TRec2):TRec1;
  18. begin
  19.    one.Rec2:=@two;
  20.    result:=one
  21. end;
  22.  
  23. function getRec2(const one:TRec1):TRec2;
  24. begin
  25.   result:=one.rec2^
  26. end;
  27.  
  28.  

[snip]

one consideration that if the @ opereator results a reference for a variable in the stack, or a managed heap type, the compilar may change it later but i find FPC smart enough to decide that and it works most of the time.

It is absolutly not guaranteed that a reference to a const-parameter stays valid beyond the function, because depending on the platform the parameter will simply be passed as a by-value parameter instead of a by-reference one. Use constref or var for that.

 

TinyPortal © 2005-2018