www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Defining a version after it's tested for

reply Robert Clipsham <robert octarineparrot.com> writes:
I recently came across this:

version( BackendFoo ) {}
else version( BackendBar ) {}
else version( BackendCar ) {}
else
{
   pragma( msg, "Warning: backend version undefined" );
   pragma( msg, "Attempting to guess backend" );
   version( Windows )
   {
     version = BackendFoo;
     pragma( msg, "Selected the Foo backend." );
   }
   else version(...)
   { /* You get the idea */ }
}

However, when trying to compile I get the following error:

Error: version BackendFoo defined after use

What is the reasoning behind this? It could be extremely useful to have 
this functionality. The only reason I can think of for doing this is 
that this code could be evaluated after modules that depend on the 
version being defined, causing it not to work. Surely there would be a 
way around that?

If it's not possible to fix this, what way would you recommend I get 
around this? The only idea I've come up with so far is to do:

else
{
   static assert( false, "Please compile with 
-version=Backend(Foo|Bar|Bar)" );
}

Which is less than optimal.
May 21 2009
next sibling parent "Tim Matthews" <tim.matthews7 gmail.com> writes:
------------BlKq31CYPBdTAKLNvjfMO1
Content-Type: text/plain; format=flowed; delsp=yes; charset=iso-8859-15
Content-Transfer-Encoding: 7bit

On Fri, 22 May 2009 02:45:24 +1200, Robert Clipsham  
<robert octarineparrot.com> wrote:


 If it's not possible to fix this, what way would you recommend I get  
 around this?

I think versions are powerfull enough so I created a wrapper around which makes best use of static asserts (attached) I think the reason behind this is to discourage version usage. ------------BlKq31CYPBdTAKLNvjfMO1 Content-Disposition: attachment; filename=Vers.d Content-Type: application/octet-stream; name=Vers.d Content-Transfer-Encoding: Base64 DQptb2R1bGUgVmVyczsNCg0KLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioNCg0KICAgICAgICBBIHNpbXBsZSB0ZW1wbGF0ZSB3cmFwcGVyIGFyb3VuZCBE IHZlcnNpb25zLiBFeGFtcGxlIHVzYWdlOg0KDQogICAgICAgIHN0YXRpYyBhc3Nl cnQodmVycyEoTGl0dGxlRW5kaWFuKSB8fCB2ZXJzIShCaWdFbmRpYW4pLA0KICAg ICAgICAiWW91IGFyZSBhIHdlaXJkIGVuZGlhbiIpOw0KDQoqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioq KioqKioqKioqKioqKioqKioqLw0KDQoNCnRlbXBsYXRlIHZlcnMoY2hhcltdIFYp DQp7DQogICAgICBtaXhpbigidmVyc2lvbigiIH4gViB+ICIpDQogICAgICB7DQog ICAgICAgICAgICBjb25zdCBib29sIHZlcnMgPSB0cnVlOw0KICAgICAgfQ0KICAg ICAgZWxzZQ0KICAgICAgew0KICAgICAgICAgICAgY29uc3QgYm9vbCB2ZXJzID0g ZmFsc2U7DQogICAgICB9Iik7DQp9DQoNCmNvbnN0IERpZ2l0YWxNYXJzID0gIkRp Z2l0YWxNYXJzIjsNCmNvbnN0IFg4NiA9ICJYODYiOw0KY29uc3QgWDg2XzY0ID0g Ilg4Nl82NCI7DQpjb25zdCBXaW5kb3dzID0gIldpbmRvd3MiOw0KY29uc3QgV2lu MzIgPSAiV2luMzIiOw0KY29uc3QgV2luNjQgPSAiV2luNjQiOw0KY29uc3QgbGlu dXggPSAibGludXgiOw0KY29uc3QgTGl0dGxlRW5kaWFuID0gIkxpdHRsZUVuZGlh biI7DQpjb25zdCBCaWdFbmRpYW4gPSAiQmlnRW5kaWFuIjsNCmNvbnN0IERfQ292 ZXJhZ2UgPSAiRF9Db3ZlcmFnZSI7DQpjb25zdCBEX0Rkb2MgPSAiRF9EZG9jIjsN CmNvbnN0IERfSW5saW5lQXNtX1g4NiA9ICJEX0lubGluZUFzbV9YODYiOw0KY29u c3QgRF9JbmxpbmVBc21fWDg2XzY0ID0gIkRfSW5saW5lQXNtX1g4Nl82NCI7DQpj b25zdCBEX0xQNjQgPSAiRF9MUDY0IjsNCmNvbnN0IERfUElDID0gIkRfUElDIjsN CmNvbnN0IG5vbmUgPSAibm9uZSI7DQpjb25zdCBhbGwgPSAiYWxsIjsNCg0KDQo= ------------BlKq31CYPBdTAKLNvjfMO1--
May 21 2009
prev sibling next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 21 May 2009 10:45:24 -0400, Robert Clipsham  
<robert octarineparrot.com> wrote:

 I recently came across this:

 version( BackendFoo ) {}
 else version( BackendBar ) {}
 else version( BackendCar ) {}
 else
 {
    pragma( msg, "Warning: backend version undefined" );
    pragma( msg, "Attempting to guess backend" );
    version( Windows )
    {
      version = BackendFoo;
      pragma( msg, "Selected the Foo backend." );
    }
    else version(...)
    { /* You get the idea */ }
 }

 However, when trying to compile I get the following error:

 Error: version BackendFoo defined after use

 What is the reasoning behind this? It could be extremely useful to have  
 this functionality. The only reason I can think of for doing this is  
 that this code could be evaluated after modules that depend on the  
 version being defined, causing it not to work. Surely there would be a  
 way around that?

 If it's not possible to fix this, what way would you recommend I get  
 around this? The only idea I've come up with so far is to do:

 else
 {
    static assert( false, "Please compile with  
 -version=Backend(Foo|Bar|Bar)" );
 }

 Which is less than optimal.

Versions are intended to be predefined before usage. It's the same thing as using a variable before it's defined. The rational is, to flag errors to the user where he thinks forward referencing of versions works. Unfortunately, you have to do the following workaround: version(BackendFoo) { version=BackendFoo_;} else version(BackendBar) { version=BackendBar_;} else version(BackendCar) { version=BackendCar_;} else { version(Windows) {version=BackendFoo_;} } And now, you must use Backend*_ in your code. It should work, but it's ugly. Maybe Walter has a better method. -Steve
May 21 2009
parent reply Robert Clipsham <robert octarineparrot.com> writes:
Steven Schveighoffer wrote:
 Versions are intended to be predefined before usage.  It's the same 
 thing as using a variable before it's defined.  The rational is, to flag 
 errors to the user where he thinks forward referencing of versions works.
 
 Unfortunately, you have to do the following workaround:
 
 version(BackendFoo) { version=BackendFoo_;}
 else version(BackendBar) { version=BackendBar_;}
 else version(BackendCar) { version=BackendCar_;}
 else
 {
   version(Windows) {version=BackendFoo_;}
 }
 
 And now, you must use Backend*_ in your code.  It should work, but it's 
 ugly.
 
 Maybe Walter has a better method.
 
 -Steve

Unfortunately I thought this might be the case. Thanks.
May 21 2009
parent reply Robert Clipsham <robert octarineparrot.com> writes:
Tim Matthews wrote:
 
 I think this would be less ugly:
 
 template vers(char[] V)
 {
      mixin("version(" ~ V ~ ")
      {
            const bool vers = true;
      }
      else
      {
            const bool vers = false;
      }");
 }
 
 static if(vers!("BackendFoo") || vers!("Windows"))
 {
       //
 }
 else static if(vers!("BackendBar"))
 {
      //
 }
 else static if (vers!("BackendCar"))
 {
     //
 }
 else
 {
     //
 }
 
 I would prefer the normal version statement to work like that directly 
 though.

This still doesn't solve my problem though, all it does is remove the usage of the version statement, which seems... pointless :S
May 22 2009
parent Robert Clipsham <robert octarineparrot.com> writes:
Tim Matthews wrote:
  From what can I see you have a few different posssible versions but 
 when no version is defined you can select a default version based on 
 other stuff like windows operating system. Rather than modify the 
 versions or add aditional to match the system you can create complex 
 'static if' statements which also are a compile time feature but can 
 have other static ifs and logical comparisons like '&&' and '||'. When 
 you have put the right checks in you can match your select target 
 systems all within a single static if.

Ah, I see what you mean now, you don't mean to use this on its own, but rather use it along with other tests, so rather than using a version identifier it would resolve to something internally which could be tested in a static if... this would work nicely actually, thanks!
May 22 2009
prev sibling next sibling parent "Tim Matthews" <tim.matthews7 gmail.com> writes:
On Fri, 22 May 2009 07:54:07 +1200, Robert Clipsham
<robert octarineparrot.com> wrote:

 Steven Schveighoffer wrote:
 Versions are intended to be predefined before usage.  It's the same  
 thing as using a variable before it's defined.  The rational is, to  
 flag errors to the user where he thinks forward referencing of versions  
 works.
  Unfortunately, you have to do the following workaround:
  version(BackendFoo) { version=BackendFoo_;}
 else version(BackendBar) { version=BackendBar_;}
 else version(BackendCar) { version=BackendCar_;}
 else
 {
   version(Windows) {version=BackendFoo_;}
 }
  And now, you must use Backend*_ in your code.  It should work, but  
 it's ugly.
  Maybe Walter has a better method.
  -Steve

Unfortunately I thought this might be the case. Thanks.

I think this would be less ugly: template vers(char[] V) { mixin("version(" ~ V ~ ") { const bool vers = true; } else { const bool vers = false; }"); } static if(vers!("BackendFoo") || vers!("Windows")) { // } else static if(vers!("BackendBar")) { // } else static if (vers!("BackendCar")) { // } else { // } I would prefer the normal version statement to work like that directly though.
May 21 2009
prev sibling next sibling parent Don <nospam nospam.com> writes:
Robert Clipsham wrote:
 I recently came across this:
 
 version( BackendFoo ) {}
 else version( BackendBar ) {}
 else version( BackendCar ) {}
 else
 {
   pragma( msg, "Warning: backend version undefined" );
   pragma( msg, "Attempting to guess backend" );
   version( Windows )
   {
     version = BackendFoo;
     pragma( msg, "Selected the Foo backend." );
   }
   else version(...)
   { /* You get the idea */ }
 }
 
 However, when trying to compile I get the following error:
 
 Error: version BackendFoo defined after use
 
 What is the reasoning behind this? It could be extremely useful to have 
 this functionality. The only reason I can think of for doing this is 
 that this code could be evaluated after modules that depend on the 
 version being defined, causing it not to work. Surely there would be a 
 way around that?

Versions are like in functional programming, they are NOT variables. Once you've tested the existence of a non-existent version identifier, you've implicitly declared it. When there was a discussion about 'version' some time back, I made a proposal which (among other things) would require you to explicitly state that a particular version identifier is set from the command line; that would make this case clearer.
May 22 2009
prev sibling parent "Tim Matthews" <tim.matthews7 gmail.com> writes:
On Fri, 22 May 2009 20:29:03 +1200, Robert Clipsham  
<robert octarineparrot.com> wrote:

 Tim Matthews wrote:
  I think this would be less ugly:
  template vers(char[] V)
 {
      mixin("version(" ~ V ~ ")
      {
            const bool vers = true;
      }
      else
      {
            const bool vers = false;
      }");
 }
  static if(vers!("BackendFoo") || vers!("Windows"))
 {
       //
 }
 else static if(vers!("BackendBar"))
 {
      //
 }
 else static if (vers!("BackendCar"))
 {
     //
 }
 else
 {
     //
 }
  I would prefer the normal version statement to work like that directly  
 though.

This still doesn't solve my problem though, all it does is remove the usage of the version statement, which seems... pointless :S

From what can I see you have a few different posssible versions but when no version is defined you can select a default version based on other stuff like windows operating system. Rather than modify the versions or add aditional to match the system you can create complex 'static if' statements which also are a compile time feature but can have other static ifs and logical comparisons like '&&' and '||'. When you have put the right checks in you can match your select target systems all within a single static if.
May 22 2009