Bernard 18 Posted May 13, 2020 Hi All, Is there a better way of doing the following, getting rid of the tPolarHelper, without changing to classes. tPolar2D = record Radius: Double; azimuth: Double; end; tPoint2D = record x: Double; y: Double; function ToPolar: tPolar2D; end; tPolarHelper = record helper for tPolar2D function ToCartesian: tPoint2D; end; I know if the above were classes then I could write tPoint2D = class; tPolar2D = class Radius: Double; azimuth: Double; function ToCartesian: tPoint2D; end; tPoint2D = class x: Double; y: Double; function ToPolar: tPolar2D; end; Thanks. Share this post Link to post
Uwe Raabe 2057 Posted May 13, 2020 (edited) What about operators: tPoint2D = record x: Double; y: Double; class function Implicit(A: tPoint2D): tPolar2d; class function Implicit(A: tPolar2D): tPoint2D; end; Edited May 13, 2020 by Uwe Raabe Share this post Link to post
David Heffernan 2345 Posted May 13, 2020 I personally don't think you can do better than helpers. That's what I do. 1 Share this post Link to post
Bernard 18 Posted May 13, 2020 It would be great with all the record enhancements in the next version to be able to write tPoint2D = record; tPolar2D = record Radius: Double; azimuth: Double; function ToCartesian: tPoint2D; end; tPoint2D = record x: Double; y: Double; function ToPolar: tPolar2D; end; Thanks again for the feedback Share this post Link to post
David Heffernan 2345 Posted May 13, 2020 28 minutes ago, Bernard said: It would be great with all the record enhancements in the next version to be able to write tPoint2D = record; tPolar2D = record Radius: Double; azimuth: Double; function ToCartesian: tPoint2D; end; tPoint2D = record x: Double; y: Double; function ToPolar: tPolar2D; end; Thanks again for the feedback Bloody annoying that this can't be done 3 Share this post Link to post
Bernard 18 Posted May 13, 2020 2 hours ago, Uwe Raabe said: What about operators: tPoint2D = record x: Double; y: Double; class function Implicit(A: tPoint2D): tPolar2d; class function Implicit(A: tPolar2D): tPoint2D; end; Does this get rid of the Circular reference issue? I have always found it starange that records have class functions instead of record functions. Feels funny naming a record function a class function. Its like when one of my young kids calls a poo a pee. I know that they were trying to say 🙂 Share this post Link to post
Uwe Raabe 2057 Posted May 13, 2020 1 hour ago, Bernard said: Does this get rid of the Circular reference issue? Yes, because the reference to tPolar2D is only inside tPoint2D, which still has to be declared after tPolar2D. The benefit of the operators is the ease of conversion by assignment. This is the (corrected) declaration with some example assignments (TBD: calculations): type tPolar2D = record Radius: Double; azimuth: Double; end; type tPoint2D = record x: Double; y: Double; public class operator Implicit(A: tPoint2D): tPolar2d; overload; class operator Implicit(A: tPolar2D): tPoint2D; overload; end; class operator tPoint2D.Implicit(A: tPoint2D): tPolar2d; begin Result.Radius := ... Result.azimuth := ... end; class operator tPoint2D.Implicit(A: tPolar2D): tPoint2D; begin Result.x := ... Result.y := ... end; var cart: tPoint2D; pol: tPolar2D; begin cart := pol; pol := cart; end. 2 Share this post Link to post
Remy Lebeau 1394 Posted May 13, 2020 4 hours ago, Bernard said: It would be great with all the record enhancements in the next version to be able to write Not going to happen. You can't forward-declare records. Share this post Link to post
David Heffernan 2345 Posted May 13, 2020 2 hours ago, Remy Lebeau said: Not going to happen. You can't forward-declare records. You should be able to forward declare their methods. No reason not to be able to do that. Share this post Link to post
Anders Melander 1782 Posted May 13, 2020 55 minutes ago, David Heffernan said: No reason not to be able to do that. Without access to the compiler source it's hard to tell, but I'll bet there are some. For one, as far as I can tell, it would require forward declaration of the record and I know there are good reasons why that isn't possible. How would you envision forward declaration of a record method would look? Share this post Link to post
David Heffernan 2345 Posted May 13, 2020 10 minutes ago, Anders Melander said: Without access to the compiler source it's hard to tell, but I'll bet there are some. For one, as far as I can tell, it would require forward declaration of the record and I know there are good reasons why that isn't possible. How would you envision forward declaration of a record method would look? The argument is that its a single pass compile. So make it two pass. Simples. 1 1 Share this post Link to post
Remy Lebeau 1394 Posted May 13, 2020 1 hour ago, David Heffernan said: So make it two pass. Simples. Yeah, THAT is not going to happen anytime soon, either. Share this post Link to post
David Heffernan 2345 Posted May 13, 2020 7 minutes ago, Remy Lebeau said: Yeah, THAT is not going to happen anytime soon, either. Well no, of course not. So we are stuck with this second rate language. Share this post Link to post
Bernard 18 Posted May 14, 2020 9 hours ago, Uwe Raabe said: Yes, because the reference to tPolar2D is only inside tPoint2D, which still has to be declared after tPolar2D. The benefit of the operators is the ease of conversion by assignment. This is the (corrected) declaration with some example assignments (TBD: calculations): The class operators for records with calculations that fit my example are a great solution for this issue. Thanks for that. Share this post Link to post
Bernard 18 Posted May 14, 2020 4 hours ago, Anders Melander said: Without access to the compiler source it's hard to tell, but I'll bet there are some. For one, as far as I can tell, it would require forward declaration of the record and I know there are good reasons why that isn't possible. How would you envision forward declaration of a record method would look? Could you elaborate on why it is not possible? Share this post Link to post
David Heffernan 2345 Posted May 14, 2020 3 hours ago, Bernard said: Could you elaborate on why it is not possible? It is possible. Plenty of languages can handle this. Emba could implement it if they chose to. Share this post Link to post
Sherlock 663 Posted May 14, 2020 7 hours ago, David Heffernan said: Well no, of course not. So we are stuck with this second rate language. A second rate language that compiles fast as hell...at least for Windows. Now I wonder why 😉 1 Share this post Link to post
David Heffernan 2345 Posted May 14, 2020 53 minutes ago, Sherlock said: A second rate language that compiles fast as hell...at least for Windows. Now I wonder why 😉 C# compilation is pretty darn fast. Delphi compilation for 64 bit on Windows is not exactly fast. I'm sure that a first pass to define record type layouts followed by a second pass for everything else would not be costly. This isn't going to be about compilation speedy. It's about the pain of refactoring the front end. 2 Share this post Link to post
Anders Melander 1782 Posted May 14, 2020 8 hours ago, David Heffernan said: So we are stuck with this second rate language. You are not stuck. There's always choice. I'm assuming you've chosen to stick with Delphi because you like the language. With the benefits Delphi provides comes some limitations. That's just part of the equation. 4 hours ago, Bernard said: Could you elaborate on why it is not possible? Because it's a one-pass compiler (mostly). The benefit is that it is fast. The price is that there are some things that are not possible. Reference types can be forward declared because their size are always known (=SizeOf(pointer)). The size of record types are not known until they have been fully declared. This means that the compiler cannot determine the layout of a record type if it contains other record types that have not been fully declared, and it needs to know the layout in order to generate the code that uses it. This problem can be solved, with certain limitations, while still staying a one-pass compiler, but at a cost of added complexity in the compiler and longer compile time. Share this post Link to post
Vandrovnik 214 Posted May 14, 2020 4 minutes ago, David Heffernan said: I'm sure that a first pass to define record type layouts followed by a second pass for everything else would not be costly. Something like a record helper 🙂 I always wonder why there can be just one class/record helper... Share this post Link to post
Anders Melander 1782 Posted May 14, 2020 4 minutes ago, David Heffernan said: This isn't going to be about compilation speedy. It's about the pain of refactoring the front end. Yes, probably although I don't think the front end is enough. But more importantly I think it's about cost/benefit and the limited resources available to them. Share this post Link to post
David Heffernan 2345 Posted May 14, 2020 20 minutes ago, Anders Melander said: You are not stuck. With over a million lines of code, it's an epic task to migrate. 22 minutes ago, Anders Melander said: This problem can be solved, with certain limitations, while still staying a one-pass compiler, but at a cost of added complexity in the compiler and longer compile time. I can't believe that the increase in compiler time would be significant. 1 Share this post Link to post
Bernard 18 Posted May 14, 2020 4 hours ago, Anders Melander said: Because it's a one-pass compiler (mostly). The benefit is that it is fast. The price is that there are some things that are not possible. Reference types can be forward declared because their size are always known (=SizeOf(pointer)). The size of record types are not known until they have been fully declared. This means that the compiler cannot determine the layout of a record type if it contains other record types that have not been fully declared, and it needs to know the layout in order to generate the code that uses it. This problem can be solved, with certain limitations, while still staying a one-pass compiler, but at a cost of added complexity in the compiler and longer compile time. I wonder if the solution could be a post processor that processed the forward declarations and created a helper file for the compiler to use during compilation time. Now the compiler could remain a single pass. Share this post Link to post
Anders Melander 1782 Posted May 14, 2020 11 hours ago, Bernard said: I wonder if the solution could be a post processor that processed the forward declarations and created a helper file for the compiler to use during compilation time. Now the compiler could remain a single pass. You mean a preprocessor. Adding a preprocessor would amount to the same as making the compiler multi-pass. Share this post Link to post
Bernard 18 Posted May 15, 2020 On 5/14/2020 at 8:08 AM, Anders Melander said: Because it's a one-pass compiler (mostly). The benefit is that it is fast. The price is that there are some things that are not possible. Reference types can be forward declared because their size are always known (=SizeOf(pointer)). The size of record types are not known until they have been fully declared. This means that the compiler cannot determine the layout of a record type if it contains other record types that have not been fully declared, and it needs to know the layout in order to generate the code that uses it. This problem can be solved, with certain limitations, while still staying a one-pass compiler, but at a cost of added complexity in the compiler and longer compile time. Is this different than Classes with forward declarations? Share this post Link to post