www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Version declaration proposal

reply Don <nospam nospam.com> writes:
I think I have a solution to the versioning problems.
My belief is that version statements are fine, and Walter's 'rats nest' 
argument is valid. Instead, I believe that version declarations limited 
to "version = XXX;" are too weak. They also have syntax which is subtly 
different to the rest of the language.
(version = A; version = B; looks as though you're changing the value of 
the 'version' variable).
My proposal is therefore:

--------
* Keep version statements unchanged.
* Change version declarations to make them almost identical to bool 
declarations:

version _versionidentifier_ = _versionexpression_;

where _versionexpression_ is a boolean expression involving only true, 
false, or other version identifiers, and standard boolean operators.
* If, in addition, we allow:

version _versionidentifier_ = extern;

for versions which are supplied from the command line, it can then 
become illegal to have a version statement referring to an undeclared 
version identifier.
(Any version identifier beginning with D_ is implicitly an "= extern;" 
identifier, so does not need to be declared).
Another possibile syntax is extern version _versionidentifier_; to make 
the syntax identical to normal declarations.

--------

This addresses a few problems:
* typos in version identifiers.
* Comprehensibility. When you see something like:
version (UseLargeSize) {
}

you have no idea if that version identifier declaration is buried in the 
code somewhere, or whether it is a command-line option. It could even be 
both!
* The effect of this would be to encourage you to create a block of 
version declarations at the start of the module, where they are easy to 
analyze and refactor.
* A lint tool could even enforce this, by disallowing any version 
declarations after the first normal declaration is encountered.

I believe this would reduce rats-nest versioning, and also eliminate the 
rats-nesting we have in version declarations right now.
Is there anything wrong with it?
Feb 11 2009
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
I actually quite like the idea of being able to specify which versions
you're allowed to set from the command-line.  The only thing I can think
of which this doesn't cover is how this affects (if indeed it does)
integer versions.

  -- Daniel
Feb 11 2009
parent reply Don <nospam nospam.com> writes:
Daniel Keep wrote:
 I actually quite like the idea of being able to specify which versions
 you're allowed to set from the command-line.  The only thing I can think
 of which this doesn't cover is how this affects (if indeed it does)
 integer versions.
 
   -- Daniel

I reckon those integer versions are a misfeature to drop. Compile this with version=3. --- version(2) { pragma(msg, "surprise!"); } else version(3) { pragma(msg, "I bet you were expecting this."); }
Feb 11 2009
parent reply Michel Fortin <michel.fortin michelf.com> writes:
On 2009-02-11 05:11:26 -0500, Don <nospam nospam.com> said:

 version(2) {
    pragma(msg, "surprise!");
 } else version(3) {
    pragma(msg, "I bet you were expecting this.");
 }

This makes me think of something I tried to do when I started the Cocoa wrappers D/Objective-C bridge. Apple uses a couple of macros to make their headers work accross different versions of Mac OS X. If, for instance, a function has been added in Mac OS X version 10.4, it'll look like this: #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4 ... new stuff ... #endif While compiling on a Mac, you can define MAC_OS_X_VERSION_MAX_ALLOWED to control the availability of functions in the headers you include and thus be sure you're keeping yourself to what's available for the OS you're targeting, even if you're targetting an older OS. I could have gone the way Don demonstrate, using a version number which fortunately includes everything below it, but then I'd be taking that number, preventing others from using it in their own applications. So I though of defining versions flags for each successive release of Mac OS X and ask everyone to define the version flags for all the releases up to what they're targeting... that's not very elegant either. My conclusion is that the only way to do such fine-grained versionning in D is to use static ifs. If there were more than one version number allowed (so I don't eat up the only one available which someone else might want), this would mostly solve the problem. The other variable you can set is MAC_OS_X_VERSION_MIN_REQUIRED and this one isn't likely to be possible in D in the current version of the language. It causes every function not available in the minimum required version to be weak-linked (so you can test for its existance and then use it). It also allow deprecated warnings when you are using functions that were deprecated, done this way: DEPRECATED_IN_MAC_OS_X_VERSION_10_2_AND_LATER void myFunction(); And any use of that function when MAC_OS_X_VERSION_MIN_REQUIRED is higher than 10.2 will give you a deprecation warning. The above is difficult to do in D: static if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2) deprecated void myFunction() { ... } else void myFunction() { ... } Which forces you to duplciate the code. I'd have liked to port that versionning system to by D wrappers, but it seems more trouble than it's worth, so I've just dropped the idea. (Another related problem is that adding/removing functions like this in a class changes the virtual table and makes the library incompatible with any program compiled with different version settings.) -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Feb 11 2009
parent Sergey Gromov <snake.scaly gmail.com> writes:
Wed, 11 Feb 2009 07:24:31 -0500, Michel Fortin wrote:

 My conclusion is that the only way to do such fine-grained versionning 
 in D is to use static ifs. If there were more than one version number 
 allowed (so I don't eat up the only one available which someone else 
 might want), this would mostly solve the problem.

I've proposed this some time ago. Maybe voting can help. http://d.puremagic.com/issues/show_bug.cgi?id=2370
Feb 14 2009
prev sibling next sibling parent "Nick Sabalausky" <a a.a> writes:
"Don" <nospam nospam.com> wrote in message 
news:gmu0lt$2agm$1 digitalmars.com...
I think I have a solution to the versioning problems.
 My belief is that version statements are fine, and Walter's 'rats nest' 
 argument is valid. Instead, I believe that version declarations limited to 
 "version = XXX;" are too weak. They also have syntax which is subtly 
 different to the rest of the language.
 (version = A; version = B; looks as though you're changing the value of 
 the 'version' variable).
 My proposal is therefore:

We can quibble over details of this, but I'm absolutely in full support of this general approach.
Feb 11 2009
prev sibling next sibling parent Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Don wrote:
 I think I have a solution to the versioning problems.
 My belief is that version statements are fine, and Walter's 'rats nest' 
 argument is valid. Instead, I believe that version declarations limited 
 to "version = XXX;" are too weak. They also have syntax which is subtly 
 different to the rest of the language.
 (version = A; version = B; looks as though you're changing the value of 
 the 'version' variable).
 My proposal is therefore:
 
 --------
 * Keep version statements unchanged.
 * Change version declarations to make them almost identical to bool 
 declarations:
 
 version _versionidentifier_ = _versionexpression_;
 
 where _versionexpression_ is a boolean expression involving only true, 
 false, or other version identifiers, and standard boolean operators.
 * If, in addition, we allow:
 
 version _versionidentifier_ = extern;
 
 for versions which are supplied from the command line, it can then 
 become illegal to have a version statement referring to an undeclared 
 version identifier.
 (Any version identifier beginning with D_ is implicitly an "= extern;" 
 identifier, so does not need to be declared).
 Another possibile syntax is extern version _versionidentifier_; to make 
 the syntax identical to normal declarations.
 
 --------
 
 This addresses a few problems:
 * typos in version identifiers.
 * Comprehensibility. When you see something like:
 version (UseLargeSize) {
 }
 
 you have no idea if that version identifier declaration is buried in the 
 code somewhere, or whether it is a command-line option. It could even be 
 both!
 * The effect of this would be to encourage you to create a block of 
 version declarations at the start of the module, where they are easy to 
 analyze and refactor.
 * A lint tool could even enforce this, by disallowing any version 
 declarations after the first normal declaration is encountered.
 
 I believe this would reduce rats-nest versioning, and also eliminate the 
 rats-nesting we have in version declarations right now.
 Is there anything wrong with it?

Looks good to me. -- Chris Nicholson-Sauls
Feb 11 2009
prev sibling parent reply Steve Schveighoffer <schveiguy yahoo.com> writes:
On Wed, 11 Feb 2009 09:01:29 +0100, Don wrote:

 I think I have a solution to the versioning problems. My belief is that
 version statements are fine, and Walter's 'rats nest' argument is valid.
 Instead, I believe that version declarations limited to "version = XXX;"
 are too weak. They also have syntax which is subtly different to the
 rest of the language. (version = A; version = B; looks as though you're
 changing the value of the 'version' variable).
 My proposal is therefore:
 
 --------
 * Keep version statements unchanged.
 * Change version declarations to make them almost identical to bool
 declarations:
 
 version _versionidentifier_ = _versionexpression_;
 

I like this idea. I had one similar last night, but you beat me to it ;) My idea was going to be something that is similar to the current version statements: version = _expression_ ? _identifier_ [ : _elseidentifier_ ] Where the [...] is optional. But your way looks cleaner. Not in love with the version x = extern notation ... -Steve
Feb 11 2009
next sibling parent reply Don <nospam nospam.com> writes:
Steve Schveighoffer wrote:
 On Wed, 11 Feb 2009 09:01:29 +0100, Don wrote:
 
 I think I have a solution to the versioning problems. My belief is that
 version statements are fine, and Walter's 'rats nest' argument is valid.
 Instead, I believe that version declarations limited to "version = XXX;"
 are too weak. They also have syntax which is subtly different to the
 rest of the language. (version = A; version = B; looks as though you're
 changing the value of the 'version' variable).
 My proposal is therefore:

 --------
 * Keep version statements unchanged.
 * Change version declarations to make them almost identical to bool
 declarations:

 version _versionidentifier_ = _versionexpression_;

I like this idea. I had one similar last night, but you beat me to it ;) My idea was going to be something that is similar to the current version statements: version = _expression_ ? _identifier_ [ : _elseidentifier_ ] Where the [...] is optional. But your way looks cleaner. Not in love with the version x = extern notation ...

Me neither. Of the two options I presented, I've decided I prefer extern version x;
Feb 11 2009
parent reply "Nick Sabalausky" <a a.a> writes:
"Don" <nospam nospam.com> wrote in message 
news:gmvg64$1v99$1 digitalmars.com...
 Steve Schveighoffer wrote:
 On Wed, 11 Feb 2009 09:01:29 +0100, Don wrote:

 I think I have a solution to the versioning problems. My belief is that
 version statements are fine, and Walter's 'rats nest' argument is valid.
 Instead, I believe that version declarations limited to "version = XXX;"
 are too weak. They also have syntax which is subtly different to the
 rest of the language. (version = A; version = B; looks as though you're
 changing the value of the 'version' variable).
 My proposal is therefore:

 --------
 * Keep version statements unchanged.
 * Change version declarations to make them almost identical to bool
 declarations:

 version _versionidentifier_ = _versionexpression_;

I like this idea. I had one similar last night, but you beat me to it ;) My idea was going to be something that is similar to the current version statements: version = _expression_ ? _identifier_ [ : _elseidentifier_ ] Where the [...] is optional. But your way looks cleaner. Not in love with the version x = extern notation ...

Me neither. Of the two options I presented, I've decided I prefer extern version x;

But there should be a way to specify a default value. I propose this: // FeatureX *must* be specified on cmd line. extern version FeatureX; version(FeatureX)... // Ok // FeatureX *can* be specified on cmd line, default is true. extern version FeatureX = true; version(FeatureX)... // Ok // FeatureX is true and *cannot* be specified on cmd line version FeatureX = true; version(FeatureX)... // Ok // Same as above. FeatureX is true and *cannot* be specified on cmd line. version FeatureX; version(FeatureX)... // Ok // Boolean expressions with other versions are Ok version FeatureX = (FeatureA || !FeatureB) && Windows; version(FeatureX)... // Ok // FeatureX *can* be specified on cmd line, default is complex. extern version FeatureX = (FeatureA || !FeatureB) && Windows; version(FeatureX)... // Ok // Illegal, FeatureX hasn't been declared version(FeatureX)... // Ok, Windows is a built-in version declared by the language or compiler. // Note that on non-Windows platforms, // the "Windows" version would still exist, // but it would just be set to false. version(Windows)... // Illegal, redefinition of FeatureX version FeatureX = false; // Ok so far... version FeatureX = true; // Illegal redefinition version FeatureX = false; // Also Illegal: same original value, but still a redefinition // Not sure about this version(FeatureX)... version FeatureX;
Feb 11 2009
parent reply Don <nospam nospam.com> writes:
Nick Sabalausky wrote:
 "Don" <nospam nospam.com> wrote in message 
 news:gmvg64$1v99$1 digitalmars.com...
 Steve Schveighoffer wrote:
 On Wed, 11 Feb 2009 09:01:29 +0100, Don wrote:

 I think I have a solution to the versioning problems. My belief is that
 version statements are fine, and Walter's 'rats nest' argument is valid.
 Instead, I believe that version declarations limited to "version = XXX;"
 are too weak. They also have syntax which is subtly different to the
 rest of the language. (version = A; version = B; looks as though you're
 changing the value of the 'version' variable).
 My proposal is therefore:

 --------
 * Keep version statements unchanged.
 * Change version declarations to make them almost identical to bool
 declarations:

 version _versionidentifier_ = _versionexpression_;

I like this idea. I had one similar last night, but you beat me to it ;) My idea was going to be something that is similar to the current version statements: version = _expression_ ? _identifier_ [ : _elseidentifier_ ] Where the [...] is optional. But your way looks cleaner. Not in love with the version x = extern notation ...

extern version x;

But there should be a way to specify a default value.

But only existence can be set on the command line, exactly as now. So default is always false. For an extern identifier, true = it was specified on command line, false = it was not specified. Considering your worst case:
 // FeatureX *can* be specified on cmd line, default is complex.
 extern version FeatureX = (FeatureA || !FeatureB) && Windows;
 version(FeatureX)... // Ok

You could only do this with TWO extern features, one to enable it, one to disable. extern version EnableFeatureX; extern version DisableFeatureX; version FeatureX = (((FeatureA || !FeatureB) && Windows) || EnableFeatureX ) && ! DisableFeatureX; With what you're proposing, you'd need to change the command line syntax too.
Feb 11 2009
parent "Nick Sabalausky" <a a.a> writes:
"Don" <nospam nospam.com> wrote in message 
news:gmviju$24va$1 digitalmars.com...
 Nick Sabalausky wrote:
 But there should be a way to specify a default value.

But only existence can be set on the command line, exactly as now. With what you're proposing, you'd need to change the command line syntax too.

True. I hereby propose that gets changed too. That's really an easy problem to solve anyway.
Feb 11 2009
prev sibling parent Steve Schveighoffer <schveiguy yahoo.com> writes:
On Wed, 11 Feb 2009 16:58:38 -0500, Nick Sabalausky wrote:
 
 // Ok, Windows is a built-in version declared by the language or
 compiler. // Note that on non-Windows platforms, // the "Windows"
 version would still exist, // but it would just be set to false.
 version(Windows)...
 

This won't work. This means that older compilers will fail to compile newer code just because of version statements. In addition, a release of a new platform means a release of all the compilers on the other platforms. This essentially is a language change every time you add a new compiler- defined version. I think there should be some prefix for 'compiler- defined' versions, which are always extern. like D_Windows (As Don suggested), or maybe even adopt hierarchy style identifiers, kind of like java properties: version(Compiler.Windows) Any Compiler.* version is assumed to be extern. -Steve
Feb 11 2009