www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - static version proposal

reply Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
So many times did i feel the need for this feature:

// ---------- first module ----------
module first;

static version = MY_API;

/*
 * My API implementation.
 */

// ---------- second module ----------
module second;

import first;

version(MY_API)
{
    // My API usage.
}

The behavior is exactly the same as with -version=MY_API passed to command
prompt.

This doesn't look like a difficult feature to implement, and AFAIK a very
useful one (especially when binding C libraries, which define compile-time
version information).
Sep 23 2011
next sibling parent reply Trass3r <un known.com> writes:
Yep, I'd also like defined versions to be global, but the problem is this  
introduces an order-of-evaluation issue.
What if module second is processed before module one?
Also what if you compile each module separately with -c?
Sep 23 2011
parent Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
The same way C/C++ does it: put it into a single .di file and import it from
both
implementation and client code.
Sep 23 2011
prev sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
This is the way to do it in D:

// ---------- first module ----------
module first;

enum USE_MY_API = true;

/*
 * My API implementation.
 */

// ---------- second module ----------
module second;

import first;

static if (USE_MY_API)
{
    // My API usage.
}

One idiom used in C/C++ is
#if API_VER >= 0xABCD
    ....
#end if
Which naturally maps to static if, which can refer to symbols in other 
modules. 
Sep 23 2011
parent reply Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
Not exactly.
You'll also need to include code, which checks if the symbol API_VER is defined
before checking it's value. This will make the code bloated. One way to do it is
to define a template which takes the symbol in the form of a string, but that
would look very ugly.
Sep 23 2011
parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Gor F. Gyolchanyan" <gor.f.gyolchanyan gmail.com> wrote in message 
news:j5i2kv$2abh$1 digitalmars.com...
 Not exactly.
 You'll also need to include code, which checks if the symbol API_VER is 
 defined
 before checking it's value. This will make the code bloated. One way to do 
 it is
 to define a template which takes the symbol in the form of a string, but 
 that
 would look very ugly.
Why would you do that? You'll get an error if it's undefined, just like you would with #if in c/c++. If you wanted to use existance of a symbol instead of an enum's value, static if(is(typeof())) should do the job. Essentially, static if can already do what you're asking for, and is much more flexible.
Sep 23 2011
parent reply Trass3r <un known.com> writes:
 If you wanted to use existance of a symbol instead of an enum's value,
 static if(is(typeof())) should do the job.
 Essentially, static if can already do what you're asking for, and is much
 more flexible.
Which again raises the question why we have version at all. I know it has its very own namespace but you could also let static if have access to that and simply make undefined versions evaluate to false.
Sep 23 2011
next sibling parent reply Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
I suggest to rewrite the version functionality as follows.
Replace all existing functionality regarding version with a single compile-time
built-in construct (much like the `is` expression)

version(/* boolean expression */)

, which will returns true if all symbols withing the expression are defined
(including identifiers) and the expression yields true.

then, the process of version tracking will look like this:

enum MY_API = true;
enum MY_API_VERSION = 4;

static if(version(MY_API) && version(MY_API_VERSION >= 2))
{
   // ...
   // Note, that if either MY_API or MY_API_VERSION is not defined, the static
if's expression will be false.
}
Sep 23 2011
parent reply Trass3r <un known.com> writes:
Am 23.09.2011, 17:14 Uhr, schrieb Gor F. Gyolchanyan  
<gor.f.gyolchanyan gmail.com>:

 I suggest to rewrite the version functionality as follows.
 Replace all existing functionality regarding version with a single  
 compile-time
 built-in construct (much like the `is` expression)

 version(/* boolean expression */)

 , which will returns true if all symbols withing the expression are  
 defined
 (including identifiers) and the expression yields true.

 then, the process of version tracking will look like this:

 enum MY_API = true;
 enum MY_API_VERSION = 4;

 static if(version(MY_API) && version(MY_API_VERSION >= 2))
 {
    // ...
    // Note, that if either MY_API or MY_API_VERSION is not defined, the  
 static
 if's expression will be false.
 }
That would unnecessarily and heavily break existing code. Also it's a good thing to get an error if you want to use enums for versioning and they don't exist (including spell check results).
Sep 23 2011
parent reply Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
Well, i know, that it breaks code, so i intended it for D3.
About enums:
the version keyword can also be made a storage class for global compile-time
declarations to distinguish version identifiers with all other identifiers.
Sep 23 2011
next sibling parent reply Adam Ruppe <destructionator gmail.com> writes:
I hope there's no D3 for a very long time. Maybe 2020.
Sep 23 2011
next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Adam Ruppe" <destructionator gmail.com> wrote in message 
news:j5iac7$2ole$1 digitalmars.com...
I hope there's no D3 for a very long time. Maybe 2020.
I completely agree.
Sep 23 2011
parent reply Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
Why don't you want D to have a backwards compatibility breaking release?
D2 got here, but D1 is still out there and gets it's occasional bug-fixes.

Having a backwards compatibility breaking release is a good way to fix mistakes,
made in the past. Not doing so leads to overly complicated and unintuitive
language like C++, where new functionality is crammed in with sacrifices to
intuitiveness.
Sep 23 2011
next sibling parent reply "Daniel Murphy" <yebblies nospamgmail.com> writes:
"Gor F. Gyolchanyan" <gor.f.gyolchanyan gmail.com> wrote in message 
news:j5ibrn$2rn8$1 digitalmars.com...
 Why don't you want D to have a backwards compatibility breaking release?
 D2 got here, but D1 is still out there and gets it's occasional bug-fixes.

 Having a backwards compatibility breaking release is a good way to fix 
 mistakes,
 made in the past. Not doing so leads to overly complicated and unintuitive
 language like C++, where new functionality is crammed in with sacrifices 
 to
 intuitiveness.
Basically, because D2 is not ready to be left behind yet. There are a huge number of compiler and library bugs to be fixed, hundreds of rough corners to be polished, and huge gaps in the toolchain to be fixed. To fork D again before these issues are better resolved would be catastrophic.
Sep 23 2011
parent Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
oh, you mean the timing. I completely agree. D2 is far from being ready to let
go.
When i said D3, i meant in a galaxy far far away, where there's nothing left to
do
for D2. :-)
Sep 23 2011
prev sibling parent Adam Ruppe <destructionator gmail.com> writes:
There's several reasons backward compatibility is important:

1) Breaking it annoys me. There's still stuff I like for new features,
   so I'm not at the point where I'll never update again yet, but I
   don't want my code to break more. Especially if non-trivial.

2) It splits people. Suppose you grab a lib and it uses D3 features.
   If you're on D2, you can't touch it.

3) It gives a perception of instability. There's already enough
   complaints on this about D1 and D2.

With the costs, the benefit has to be huge to break compatibility.
Sep 23 2011
prev sibling next sibling parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 09/23/11 10:59, Adam Ruppe wrote:
 I hope there's no D3 for a very long time. Maybe 2020.
There won't. D2 is our flagship. Andrei
Sep 23 2011
prev sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Adam Ruppe" <destructionator gmail.com> wrote in message 
news:j5iac7$2ole$1 digitalmars.com...
I hope there's no D3 for a very long time. Maybe 2020.
I still hope there is one at some not-too-distant point, though. The whole version system really does need an overhaul. One of the big things, if not the key one, is that basing it on "symbol defined" vs "symbol not defined" (rather than a compile-time bool) is far too problematic. There's been discussion and effort before (that I was heavily involved in) about trying to made a proper version system as a D2 library. There were some real clever strategies people worked out for certain aspects of it, but it ultimately ended up being intractable in D2.
Sep 23 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, September 23, 2011 14:14 Nick Sabalausky wrote:
 "Adam Ruppe" <destructionator gmail.com> wrote in message
 news:j5iac7$2ole$1 digitalmars.com...
 
I hope there's no D3 for a very long time. Maybe 2020.
I still hope there is one at some not-too-distant point, though. The whole version system really does need an overhaul. One of the big things, if not the key one, is that basing it on "symbol defined" vs "symbol not defined" (rather than a compile-time bool) is far too problematic.
That's by design. That's the way that Walter wants it. I wouldn't expect that to change in any future version of D unless you can come up with a really good argument to change Walter's mind or someone else takes over as the benevolent dictator at some point. - Jonathan M Davis
Sep 23 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.96.1316813793.26225.digitalmars-d puremagic.com...
 On Friday, September 23, 2011 14:14 Nick Sabalausky wrote:
 "Adam Ruppe" <destructionator gmail.com> wrote in message
 news:j5iac7$2ole$1 digitalmars.com...

I hope there's no D3 for a very long time. Maybe 2020.
I still hope there is one at some not-too-distant point, though. The whole version system really does need an overhaul. One of the big things, if not the key one, is that basing it on "symbol defined" vs "symbol not defined" (rather than a compile-time bool) is far too problematic.
That's by design. That's the way that Walter wants it. I wouldn't expect that to change in any future version of D unless you can come up with a really good argument to change Walter's mind or someone else takes over as the benevolent dictator at some point.
Really? I had no idea. What's the reasoning? (I honestly can't imagine anything.) One big problem with it, off the top of my head, is that there's zero safety from mistyping: // Crap, this should be FrizzBang: version(Fizzbang) {...} else {...} And that's silently accepted and results in the wrong code. Crap, this is the whole damn reason we have variable declarations in the first place. I seem to remember there being another issue or two, but I don't recall offhand what.
Sep 23 2011
parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Friday, September 23, 2011 14:54 Nick Sabalausky wrote:
 "Jonathan M Davis" <jmdavisProg gmx.com> wrote in message
 news:mailman.96.1316813793.26225.digitalmars-d puremagic.com...
 
 On Friday, September 23, 2011 14:14 Nick Sabalausky wrote:
 "Adam Ruppe" <destructionator gmail.com> wrote in message
 news:j5iac7$2ole$1 digitalmars.com...
 
I hope there's no D3 for a very long time. Maybe 2020.
I still hope there is one at some not-too-distant point, though. The whole version system really does need an overhaul. One of the big things, if not the key one, is that basing it on "symbol defined" vs "symbol not defined" (rather than a compile-time bool) is far too problematic.
That's by design. That's the way that Walter wants it. I wouldn't expect that to change in any future version of D unless you can come up with a really good argument to change Walter's mind or someone else takes over as the benevolent dictator at some point.
Really? I had no idea. What's the reasoning? (I honestly can't imagine anything.)
I believe that it comes down to complexity. In C and C++, you get stuff like #if COND1 || COND2 || (COND3 && COND4) and it can become fairly easy to screw up when you manage versions that way - especially when each of those conditions can be arbitrarily complex _and_ they can be affected in entertaining ways by whatever #includes you happen to have before them. Simply adding or removing a #include could completely change the result of such conditions (as could reordering them in some cases). By having version restricted to what's defined and having it unaffected by imports, it simplifies the situation considerably. You can still do similarly screwy stuff with static ifs, but if you're using version blocks for version stuff and static ifs for templated stuff, then the static ifs don't usually get screwy in the same way, and the overall situtation is much cleaner. - Jonathan M Davis
Sep 23 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.100.1316815714.26225.digitalmars-d puremagic.com...
 On Friday, September 23, 2011 14:54 Nick Sabalausky wrote:
 "Jonathan M Davis" <jmdavisProg gmx.com> wrote in message
 news:mailman.96.1316813793.26225.digitalmars-d puremagic.com...

 On Friday, September 23, 2011 14:14 Nick Sabalausky wrote:
 "Adam Ruppe" <destructionator gmail.com> wrote in message
 news:j5iac7$2ole$1 digitalmars.com...

I hope there's no D3 for a very long time. Maybe 2020.
I still hope there is one at some not-too-distant point, though. The whole version system really does need an overhaul. One of the big things, if not the key one, is that basing it on "symbol defined" vs "symbol not defined" (rather than a compile-time bool) is far too problematic.
That's by design. That's the way that Walter wants it. I wouldn't expect that to change in any future version of D unless you can come up with a really good argument to change Walter's mind or someone else takes over as the benevolent dictator at some point.
Really? I had no idea. What's the reasoning? (I honestly can't imagine anything.)
I believe that it comes down to complexity. In C and C++, you get stuff like #if COND1 || COND2 || (COND3 && COND4) and it can become fairly easy to screw up when you manage versions that way - especially when each of those conditions can be arbitrarily complex _and_ they can be affected in entertaining ways by whatever #includes you happen to have before them. Simply adding or removing a #include could completely change the result of such conditions (as could reordering them in some cases). By having version restricted to what's defined and having it unaffected by imports, it simplifies the situation considerably.
But version is *not* restricted to what's defined. It *also* deals with what's *not* defined. That's the main problem I'm talking about. If Walter wants to limit the logic operations and import implications, none of that necessitates that the version identifiers be based on "defined vs undefined". What I mean is this: Using an undefined version identifier should be an error: version(ThisIsNeverDeclaredAnywhere) {} else {} That is currently accepted, but it should be a compile-time error. If you want that to work, you should be forced to do one of the following: // A: version ThisIsDeclared = true; version(ThisIsDeclared) {} else {} // B: version ThisIsDeclared = false; version(ThisIsDeclared) {} else {} // C: version(ThisIsDeclared) {} else {}
dmd foo.d -version:ThisIsDeclared
// D: version(ThisIsDeclared) {} else {}

maybe -versionoff:ThisIsDeclared
Obviously you wouldn't need to (or be allowed to) declare any of the built-in version identifiers like Windows. They would be always be implicity declared and set to either true or false.
Sep 23 2011
next sibling parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:j5j1bh$14oc$1 digitalmars.com...
 // D:
 version(ThisIsDeclared) {} else {}

maybe -versionoff:ThisIsDeclared
Heh, the stupid email/ng system (or client or whatever) tried to "fix" that "quote" by adding a ">" before "maybe". Stoopid compooters.
Sep 23 2011
prev sibling parent reply Sean Kelly <sean invisibleduck.org> writes:
On Sep 23, 2011, at 3:30 PM, Nick Sabalausky wrote:
=20
 But version is *not* restricted to what's defined. It *also* deals =
with=20
 what's *not* defined. That's the main problem I'm talking about.
=20
 If Walter wants to limit the logic operations and import implications, =
none=20
 of that necessitates that the version identifiers be based on "defined =
vs=20
 undefined".
=20
 What I mean is this: Using an undefined version identifier should be =
an=20
 error:
=20
 version(ThisIsNeverDeclaredAnywhere) {} else {}
=20
 That is currently accepted, but it should be a compile-time error.
I'm not sure I understand. If this were the case, how could we use = version(Windows) etc in our code?=
Sep 23 2011
parent "Nick Sabalausky" <a a.a> writes:
"Sean Kelly" <sean invisibleduck.org> wrote in message 
news:mailman.107.1316819890.26225.digitalmars-d puremagic.com...
On Sep 23, 2011, at 3:30 PM, Nick Sabalausky wrote:
 But version is *not* restricted to what's defined. It *also* deals with
 what's *not* defined. That's the main problem I'm talking about.

 If Walter wants to limit the logic operations and import implications, 
 none
 of that necessitates that the version identifiers be based on "defined vs
 undefined".

 What I mean is this: Using an undefined version identifier should be an
 error:

 version(ThisIsNeverDeclaredAnywhere) {} else {}

 That is currently accepted, but it should be a compile-time error.
I'm not sure I understand. If this were the case, how could we use version(Windows) etc in our code?=
That would be a built-in. It would be defined as "true" on Windows and "false" on non-Windows. Then: version(Windows) {} else {} But that difference with that, being that it's a built-in, these would be illegal (because they would be re-definitions of an already-defined version identifier): version Windows = ...;
dmd -version:Windows
dmd -versionoff:Windows
Sep 23 2011
prev sibling parent reply Trass3r <un known.com> writes:
 About enums:
 the version keyword can also be made a storage class for global  
 compile-time
 declarations to distinguish version identifiers with all other  
 identifiers.
How would that be superior to 'version = identifier;'?
Sep 23 2011
parent Gor F. Gyolchanyan <gor.f.gyolchanyan gmail.com> writes:
because version = identifier is only local to a module.
because version can be either an identifier or an integer, whereas the version
tagged variable can be anything (string, for example).
Sep 23 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 9/23/2011 7:35 AM, Trass3r wrote:
 Which again raises the question why we have version at all.
They're meant for a more global view of generating different versions from the same source code.
Sep 23 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, September 23, 2011 12:59:20 Walter Bright wrote:
 On 9/23/2011 7:35 AM, Trass3r wrote:
 Which again raises the question why we have version at all.
They're meant for a more global view of generating different versions from the same source code.
Not to mention that version blocks be affected by compiler flags (unlike static if). Probably the thing that I like most about them though is that It's much nicer to split out OS differences with explicit version blocks than having them be just another set static ifs. Yes, we technically _could_ get rid of version and do it all with static ifs, but it wouldn't be as clean IMHO. - Jonathan M Davis
Sep 23 2011
parent Walter Bright <newshound2 digitalmars.com> writes:
On 9/23/2011 1:09 PM, Jonathan M Davis wrote:
 Yes, we technically _could_ get rid of version and do it all with static ifs,
 but it wouldn't be as clean IMHO.
Right. It's the same reason for the existence of the debug conditionals. Such could be done with version or with static if, but experience with C is that every group invents their own convention for doing conditional debug code, all incompatible. Having it wired in the language tends to standardize it and make it interoperable.
Sep 23 2011