Recent

Author Topic: [Closed] polymorphic code via compilation directives  (Read 885 times)

devEric69

  • Sr. Member
  • ****
  • Posts: 331
[Closed] polymorphic code via compilation directives
« on: July 01, 2020, 05:35:39 pm »
Hello,

I have a unit_2 (i must use it, as it has been written) like below:

Code: Pascal  [Select][+][-]
  1. unit unit_2;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils;
  9.  
  10.  
  11. procedure doSomething;
  12.  
  13. implementation
  14.  
  15. uses
  16.   Dialogs;
  17.  
  18. procedure doSomething;
  19. begin
  20.         {$IF defined(COMPILE_THIS)}
  21.                 ShowMessage("unit_2.COMPILE_THIS \ Hello");
  22.         {$EndIf}
  23.  
  24.         {$IF defined(COMPILE_THAT)}
  25.                 ShowMessage("unit_2.COMPILE_THAT \ Bye Bye");
  26.         {$EndIf}
  27. end;
  28.  
  29. end.


I'm trying to use its code from another unit_1, as below:

Code: Pascal  [Select][+][-]
  1. unit unit_1;
  2.  
  3. ...\...
  4.  
  5. implementation
  6.  
  7. procedure TForm1.Button1Click(Sender: TObject);
  8. begin
  9.   {$UnDef COMPILE_THIS}
  10.   {$UnDef COMPILE_THAT}
  11.  
  12.   {$Define COMPILE_THIS}
  13.         unit_2.doSomething;  // I would see here, the messagebox with "unit_2.COMPILE_THIS \ Hello"
  14.   {$UnDef COMPILE_THIS}
  15.   {$Define COMPILE_THAT}
  16.         unit_2.doSomething;  // I would see here, the messagebox with "unit_2.COMPILE_THAT \ Bye Bye"
  17.   {$UnDef COMPILE_THAT}
  18. end;
  19.  
  20. end.

How do you do it (nothing appears, for me) :-\ ?
Say in another way (it seems to me): is it possible to compile the unit_2 into several context-sensitive compiler's passes, depending on how it is called in unit_1.TForm1.Button1Click?

Regards
« Last Edit: July 02, 2020, 04:53:55 pm by devEric69 »
use: Linux 64 bits (Ubuntu 18.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

MarkMLl

  • Hero Member
  • *****
  • Posts: 1221
Re: polymorphic code via compilation directives
« Reply #1 on: July 01, 2020, 05:41:10 pm »
I've done that sort of thing in the past by making (what you're calling) unit_2 into an include file.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

devEric69

  • Sr. Member
  • ****
  • Posts: 331
Re: polymorphic code via compilation directives
« Reply #2 on: July 01, 2020, 05:59:05 pm »
Hello,

I've tried this with an include,  replacing the file unit_2 with the file include2.inc, and modifying the calling unit_1 like this:

unit_1:
Code: Pascal  [Select][+][-]
  1. {$Include include2.inc}
  2. TForm1 = class(TForm)
  3. ...\...
  4.     procedure doSomething;
  5. ...\...
  6. procedure TForm1.Button1Click(Sender: TObject);
  7. begin
  8.   {$UnDef COMPILE_THIS}
  9.   {$UnDef COMPILE_THAT}
  10.  
  11.   {$Define COMPILE_THIS}
  12.     {$Include include2.inc}
  13.     Self.doSomething;  // I would see include2.inc.COMPILE_THIS
  14.   {$UnDef COMPILE_THIS}
  15.  
  16.   {$Define COMPILE_THAT}
  17.     {$Include include2.inc}
  18.     Self.doSomething;  // I would see include2.inc.COMPILE_THAT
  19.   {$UnDef COMPILE_THAT}
  20. end;
  21. ...\...
  22.  

include2.inc:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.doSomething;
  2. begin
  3.         {$IF defined(COMPILE_THIS)}
  4.                 ShowMessage("include2.inc.COMPILE_THIS");
  5.         {$EndIf}
  6.  
  7.         {$IF defined(COMPILE_THAT)}
  8.                 ShowMessage("include2.inc.COMPILE_THAT");
  9.         {$EndIf}
  10. end;

==> I can't compile anymore this code :-[ .
« Last Edit: July 01, 2020, 06:05:03 pm by devEric69 »
use: Linux 64 bits (Ubuntu 18.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

440bx

  • Hero Member
  • *****
  • Posts: 1994
Re: polymorphic code via compilation directives
« Reply #3 on: July 01, 2020, 07:43:37 pm »
==> I can't compile anymore this code :-[ .
It doesn't compile because the include file refers to TForm1 which has not been defined yet at that point.  You need to move that "include" to be after TForm1 has been defined.

As far as the requirement you've mentioned, the code in procedure DoSomething will be determined by whatever was defined at _compile_ time.  That cannot change at runtime, no amount of testing directives or anything else in unit_1 is going to change what happened at compile time.

If you need "DoSomething" to do different things at runtime then you need to create specific and different procedures for the various "DoSomething"(s) you want and, instead of having DoSomething be a procedure, it would be a _pointer_ to the procedure you want to execute depending on the setting of "COMPILE_THIS"/"COMPILE_THAT" (or whatever other directive you want it to depend on).  The fact that the pointer changes is what gives you polymorphism, the program can change the value of the pointer anywhere, anytime and, for any reason.

HTH.
FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

devEric69

  • Sr. Member
  • ****
  • Posts: 331
Re: polymorphic code via compilation directives
« Reply #4 on: July 01, 2020, 07:45:19 pm »
Thank you for the answer.

Quote
As far as the requirement you've mentioned, the code in procedure DoSomething will be determined by whatever was defined at _compile_ time.  That cannot change at runtime, no amount of testing directives or anything else in unit_1 is going to change what happened at compile time.

That's why they say the C is a multi-passes compiler, but the Pascal compiler is single-pass?



To be more precise: i want to use the code from the mysql.inc file.

But, I want to test a mysql41 type connection at some place, ..., and a mysql57 type connection at another place, in the same including unit.

So, if the calling code is arranged from top to bottom (sequentially; let's say in the same method) like this:
- i start with the {$Undef mysql41}, ..., {$Undef mysql57} of all the available compilation directives...
- i write {$DEFINE mysql41} to call the routines\API of mysql.inc with the ad'hoc adapted structures\records, before calling {$UNDEF mysql41},
- i do the same thing with {$DEFINE mysql55},
- ...\...,
- {$UNDEF mysql57},

==> then, can I theoretically really test every possible connection like this? Does the compiler know how to do that?
« Last Edit: July 01, 2020, 07:52:44 pm by devEric69 »
use: Linux 64 bits (Ubuntu 18.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

MarkMLl

  • Hero Member
  • *****
  • Posts: 1221
Re: polymorphic code via compilation directives
« Reply #5 on: July 01, 2020, 08:02:49 pm »
That's why they say the C is a multi-passes compiler, but the Pascal compiler is single-pass?

Completely irrelevant. C can be compiled in a single pass, and I've known Pascal compilers with as many as seven passes.

Cut your program down to the minimum, and give us all something we can play with. Posting fragments and expecting us to make them into a coherent whole with no bits left over isn't fair.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

devEric69

  • Sr. Member
  • ****
  • Posts: 331
Re: polymorphic code via compilation directives
« Reply #6 on: July 01, 2020, 08:27:15 pm »
Quote
Completely irrelevant. C can be compiled in a single pass, and I've known Pascal compilers with as many as seven passes.

All right. Btw, that was an irrelevant question to my problem (just curiosity, for my general knowledge).

Quote
Cut your program down to the minimum, and give us all something we can play with. Posting fragments and expecting us to make them into a coherent whole with no bits left over isn't fair.

In fact, I'm talking about a sort of "polymorphism", by different copy-paste-and_compile codes (from mysql.inc), contextualized, changing according to the compilation directive defined differently just above the calling codes.

I don't have a "real code" yet. As i explained in my § "To be more precise" above, I'm just trying to validate how to use mysql.inc, in different ways. Hence my little tests to understand the compiler.

As a result of this post (https://forum.lazarus.freepascal.org/index.php/topic,50209.msg366128.html#msg366128), i know I can't use a meta-class variable. So, I'm looking for ways to do otherwise.

use: Linux 64 bits (Ubuntu 18.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

HeavyUser

  • Sr. Member
  • ****
  • Posts: 310
Re: polymorphic code via compilation directives
« Reply #7 on: July 01, 2020, 08:59:07 pm »
Quote
Completely irrelevant. C can be compiled in a single pass, and I've known Pascal compilers with as many as seven passes.

All right. Btw, that was an irrelevant question to my problem (just curiosity, for my general knowledge).

Quote
Cut your program down to the minimum, and give us all something we can play with. Posting fragments and expecting us to make them into a coherent whole with no bits left over isn't fair.

In fact, I'm talking about a sort of "polymorphism", by different copy-paste-and_compile codes (from mysql.inc), contextualized, changing according to the compilation directive defined differently just above the calling codes.

I don't have a "real code" yet. As i explained in my § "To be more precise" above, I'm just trying to validate how to use mysql.inc, in different ways. Hence my little tests to understand the compiler.

As a result of this post (https://forum.lazarus.freepascal.org/index.php/topic,50209.msg366128.html#msg366128), i know I can't use a meta-class variable. So, I'm looking for ways to do otherwise.
I have only read the last message of this thread and the last of the linked thread on the above message. I'm assuming that you want to be able to use a single TConnectionName class for all the versions of TMYSQLConnection instead of redeclaring it in each version as a different class. There are two choices
1) use an interface that will be implemented by all versions.
2) use an abstract class in a common unit that will be overridden by all versions.

devEric69

  • Sr. Member
  • ****
  • Posts: 331
Re: polymorphic code via compilation directives
« Reply #8 on: July 02, 2020, 04:53:18 pm »
Thank you for your answer @HeavyUser.

In fact, I've managed to get around the issue of the maximum utility of a *.inc file. I'm slow, i know, but coming from Delphi, it's unusual for me to use such complex files.

Compilation directives that identify pieces of code in a *.inc file, provide several combinations of possible extracting information, from a same *.inc file, depending on the directives that are defined in the "header" unit that requests inclusion.
The thing that appeals to me when using *.inc files, is that it seems to me highly recommended to always call the extracted elements (record, etc.) by prefixing them with their "namespace" i.e. the name of the unit that extracted them, to keep in mind that a homonymy of the same extracted element, but from two different units, could in fact be a different extraction (not the same fields of the original record, etc.).
Said differently, an extraction of a homonymy of form, but not of substance, which the namespace-unit qualifier reminds me.
use: Linux 64 bits (Ubuntu 18.04 LTS).
Lazarus version: 2.0.4 (svn revision: 62502M) compiled with fpc 3.0.4 - fpDebug \ Dwarf3.

MarkMLl

  • Hero Member
  • *****
  • Posts: 1221
Re: [Closed] polymorphic code via compilation directives
« Reply #9 on: July 02, 2020, 05:04:02 pm »
Eric, this probably won't make sense to you yet but one thing that you'll find useful is that you can use the same fragment from an include file to either define entry points in a unit or to define methods in a class definition.

I've used that to allow the same code to either be linked statically (entry points in a unit) or dynamically (methods in a class which defines a linkable library).

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

 

TinyPortal © 2005-2018