www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2370] New: Version statement enhancement: versioned identifiers

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370

           Summary: Version statement enhancement: versioned identifiers
           Product: D
           Version: unspecified
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: snake.scaly gmail.com


I propose version identifiers to have a numeric value and to add the following
version statement syntax:

VersionCondition:
  version ( Identifier, Integer )

This version condition is satisfied when the Identifier's value is equal or
greater than the Integer.  This way, the code in

version (D_Version, 2)
{
...
}

will be compiled only when the compiler version is 2 or greater.  The version
specification syntax can be

VersionSpecification:
  version = Identifier ( Integer ) ;


-- 
Sep 22 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #1 from jarrett.billingsley gmail.com  2008-09-22 22:27 -------
Please please please.  It seems odd that such an obvious use of preprocessor
macros for versioning was not carried forward into D.  


-- 
Sep 22 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #2 from benoit tionex.de  2008-09-23 03:41 -------
This would have helped me a lot in the past.


-- 
Sep 23 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370


shro8822 vandals.uidaho.edu changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |shro8822 vandals.uidaho.edu




------- Comment #3 from shro8822 vandals.uidaho.edu  2008-09-23 13:34 -------

Vote += Lots


-- 
Sep 23 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370


brunodomedeiros+bugz gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |brunodomedeiros+bugz gmail.c
                   |                            |om




------- Comment #4 from brunodomedeiros+bugz gmail.com  2008-10-03 10:04 -------
Like I said in the original thread, isn't it enough to have:
  version(D_Version_2OrAbove) { ...
?
Or just
  version(D_Version1) { 
    ...
  } else {
    //version 2 or above here...
  }
?
It doesn't seem this feature is justified.


-- 
Oct 03 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #5 from snake.scaly gmail.com  2008-10-03 10:53 -------
(In reply to comment #4)
 Like I said in the original thread, isn't it enough to have:
   version(D_Version_2OrAbove) { ...
 ?
 Or just
   version(D_Version1) { 
     ...
   } else {
     //version 2 or above here...
   }
 ?
 It doesn't seem this feature is justified.

Imagine I've got MyLib v.21. There was nice API introduced in v.17 and I have a special cased code which should work from version 17 on. In my approach: module myapp; import mylib; version(MyLib, 17) { NiftyMyLibCall(); } else { ...lots of code... } module mylib; version = MyLib(21); In your approach I'm either going to have 21 version statements in mylib which is tedious, error-prone and is hardly automated, or I must have 5 version clauses in my source which all mix in the same piece of code and I must add new version clause every time a new version of lib is published. --
Oct 03 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #6 from brunodomedeiros+bugz gmail.com  2008-10-03 11:31 -------
If you add a specific feature in a given version, it's best (clearer) to add a:
  version = NiftyMyLibCallAvailable;
and then use:
  version(NiftyMyLibCallAvailable)
  {
    NiftyMyLibCall();
  }
instead of version numbers.

In any case, when releasing a new version:
Your approach:
  * go to the 'version = MyLibVersion(20);' statement
  * change it to 'version = MyLibVersion(21);'

My approach:
  * go to the 'version = MyLibVersion20OrAbove;' statement
  * add a 'version = MyLibVersion21OrAbove;' statement

How is my approach any more tedious, error-prone, or less automated? They are
both one line changes you have to make (mine has an extra copy&paste), and they
are both dead easy to make. My approach may end up with more code written, but
that's hardly ever more error-prone, since that code is not supposed to change
or be maintained (one doesn't usually downgrade the version number of a lib).


-- 
Oct 03 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #7 from snake.scaly gmail.com  2008-10-03 15:46 -------
(In reply to comment #6)
 If you add a specific feature in a given version, it's best (clearer) to add a:
   version = NiftyMyLibCallAvailable;
 and then use:
   version(NiftyMyLibCallAvailable)
   {
     NiftyMyLibCall();
   }
 instead of version numbers.

Is there *any* library around that has a version/#define for every single interface and every single change in that interface? I don't think so, it's just not feasible.
 In any case, when releasing a new version:
 Your approach:
   * go to the 'version = MyLibVersion(20);' statement
   * change it to 'version = MyLibVersion(21);'
 
 My approach:
   * go to the 'version = MyLibVersion20OrAbove;' statement
   * add a 'version = MyLibVersion21OrAbove;' statement
 
 How is my approach any more tedious, error-prone, or less automated? They are
 both one line changes you have to make (mine has an extra copy&paste), and they
 are both dead easy to make. My approach may end up with more code written, but
 that's hardly ever more error-prone, since that code is not supposed to change
 or be maintained (one doesn't usually downgrade the version number of a lib).

A version number in one particular place can be replaced by a script, or by a version control system. It's significantly harder to add a line automatically. Though adding a line for every version is definitely much better than adding a version statement for every interface change. --
Oct 03 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #8 from shro8822 vandals.uidaho.edu  2008-10-03 15:55 -------
Several of the comments seem to be forgetting that "version = bob" in an
imported file has no effect on "version(bob)" statements in the importing file.


importer.d:

  import imported;
  version(bob) { pragma(msg,"bob"); }
  else { pragma(msg,"!bob"); }

imported.d:

  version = bob;

output:

  !bob


-- 
Oct 03 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #9 from snake.scaly gmail.com  2008-10-03 16:10 -------
(In reply to comment #8)
 Several of the comments seem to be forgetting that "version = bob" in an
 imported file has no effect on "version(bob)" statements in the importing file.

You're right. This is a very strange and undocumented behavior. Well, this adds more value to my proposal: writing 21 version statements in command line is... well, tedious. --
Oct 03 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #10 from terranium yandex.ru  2008-10-09 07:06 -------
(In reply to comment #0)

why do you think that code working for d2 will work for d3?


-- 
Oct 09 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370


snake.scaly gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |alan akbkhome.com




------- Comment #11 from snake.scaly gmail.com  2008-10-09 07:22 -------
(In reply to comment #10)
 (In reply to comment #0)
 why do you think that code working for d2 will work for d3?

It's my best guess that D3 will likely support D2 way of doing things rather than D1, if at all. If I'm wrong I'll fix my version statement to support whatever D3 requires. But if I'm right I won't be needing to change anything. Note that D version is only an example. This sort of version compatibility is required when you need to support multiple versions of a library or a host application. If I write a plug-in for 3dsmax that must support versions 8, 9, 2008, 2009 and as many future versions as possible, and I know that a particular API is only available from 9 onwards, I put its use under version(max,9) and hope that 2010 will support it as well. --
Oct 09 2008
prev sibling next sibling parent reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #12 from brunodomedeiros+bugz gmail.com  2008-10-15 09:57
-------
(In reply to comment #7)
 (In reply to comment #6)
 If you add a specific feature in a given version, it's best (clearer) to add a:
   version = NiftyMyLibCallAvailable;
 and then use:
   version(NiftyMyLibCallAvailable)
   {
     NiftyMyLibCall();
   }
 instead of version numbers.

interface and every single change in that interface? I don't think so, it's just not feasible.

I've seen the equivalent, in Java. Namely in Eclipse, where the API is managed through the use of interfaces. Whenever new functionality is added, they don't changed the existing interface, but add a new one, with a name like IFooExtension4 Example: http://help.eclipse.org/stable/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextViewerExtension7.html There are dozens of interfaces like that. (although few reach as many as a 7th version) (In reply to comment #8)
 Several of the comments seem to be forgetting that "version = bob" in an
 imported file has no effect on "version(bob)" statements in the importing file.

Dang, forgot about that indeed. (In reply to comment #9)
 (In reply to comment #8)
 Several of the comments seem to be forgetting that "version = bob" in an
 imported file has no effect on "version(bob)" statements in the importing file.

adds more value to my proposal: writing 21 version statements in command line is... well, tedious.

If you use a proper build tool, editor, or IDE (which you obviously should), you should only have to write these statements *once*, which hardly counts as tedious or even significant. --
Oct 15 2008
parent Sergey Gromov <snake.scaly gmail.com> writes:
I don't see a point in continuing to spam bugzilla, so I'll answer here.

 ------- Comment #12 from brunodomedeiros+bugz gmail.com  2008-10-15 09:57
-------
 (In reply to comment #7)
 (In reply to comment #6)
 If you add a specific feature in a given version, it's best (clearer) to add a:
   version = NiftyMyLibCallAvailable;
 and then use:
   version(NiftyMyLibCallAvailable)
   {
     NiftyMyLibCall();
   }
 instead of version numbers.

interface and every single change in that interface? I don't think so, it's just not feasible.

I've seen the equivalent, in Java. Namely in Eclipse, where the API is managed through the use of interfaces. Whenever new functionality is added, they don't changed the existing interface, but add a new one, with a name like IFooExtension4 Example: http://help.eclipse.org/stable/index.jsp?topic=/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/ITextViewerExtension7.html There are dozens of interfaces like that. (although few reach as many as a 7th version)

It's not the same as defining a separate version statement for every feature, especially when there's nowhere to define them. I think this solution can be applied to D directly, with either run-time or compile-time checks for available interfaces. But this approach doesn't seem to be widely adopted and I believe there are reasons behind it. For instance, I don't want to check all and every interface in my code and support workarounds and fallbacks. I want to use a specific interface subset available in a particular library version. If later I want to use a particular cool feature from a newer version then it doesn't quite matter whether it is implemented via versions or interfaces, but if I want *all* the cool stuff I probably don't want to mess with all the interface details again. I simply use the older code if all the cool features are not available. It's a matter of usage patterns, and I don't think many developers want to support any combination of features provided by a library.
 (In reply to comment #9)
 (In reply to comment #8)
 Several of the comments seem to be forgetting that "version = bob" in an
 imported file has no effect on "version(bob)" statements in the importing file.

adds more value to my proposal: writing 21 version statements in command line is... well, tedious.

If you use a proper build tool, editor, or IDE (which you obviously should), you should only have to write these statements *once*, which hardly counts as tedious or even significant.

I use whatever I want. And I tend not to use IDEs unless I'm forced to. Anyway, should I write these statements "once" for every Hello World? Or for every library I attach to my hypothetical IDE? The result should be a bunch of version statements for every library I use in my project. How do they get there?
Oct 15 2008
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2370





------- Comment #13 from brunodomedeiros+bugz gmail.com  2008-10-15 10:12
-------
(In reply to comment #8)
 Several of the comments seem to be forgetting that "version = bob" in an
 imported file has no effect on "version(bob)" statements in the importing file.
 

In fact, I think this fact alone shows that D's version statement mechanism should not be used for version management of user libraries, but only runtime related aspects (the platform/CPU, the compiler, the D version, etc.) For user libraries, I would suggestion using (manifest) constants to define the lib version, and users of you library could use static if to perform tasks depending on the existing version (including compile-time duck typing like code). Example: static if(OpenGL.VersionMajor == 2) { ... static if(is(com.foo.MyLib.myXptoFunc)) { // check if myXptoFunc is available ... --
Oct 15 2008