www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Language Versioning

reply Jonathan Marler <johnnymarler gmail.com> writes:
This is an informal proposal to add a versioning scheme to the D 
Language.  If you'd like to take the time to read, please let 
everyone know your thoughts and suggestions for the idea.  To 
Walter and Andrei, please let me know your thoughts, if you think 
the idea has merit and if so what the next steps should be (i.e. 
DIP/PR/More Resarch Discussion Needed).

As I've been thinking about various proposals and additions to 
the D language, it occurred to me that I'd like to be able to 
declare inside my code that it requires a certain version or 
certain features of the D language in order to work properly.  
For example, when I look at the changelog for DMD version 2.085, 
I see that support for Objective-C classes was added.  However, I 
would be hesitant to use that feature until a certain amount of 
time has passed. This is because using it would make my 
libraries/applications only work with a small percentage of 
compilers in the world, those who have recently updated their 
compiler, and the error messages people would get could make it 
difficult to know that they just need to update their compiler 
for it to work with my code.  Currently the only way to solve 
this problem is to wait a certain amount of time until I feel its 
reasonable that enough people will have updated their compiler.

I think we can do better.

My current idea is to implement a list of versions and feature 
names.  Such a list could be dumped with something like:

 dmd --list-versions
2018_02_03 StaticForeach 2018_02_20 NoGCExceptions 2018_03_10 ObjectiveCClasses Implemented StaticForeach Implemented NamedParameters NotImplemented CopyConstructor NotImplemented ExpressionBasedContracts The idea here is that once a feature has been implemented and has been enabled by default, the version would be updated and that particular feature would be assigned to that version. Also note that the version number represents a date, which allows the compiler to know when that version was implemented so it can know how "out-of-date" it is (i.e. 2 years, 1 month etc). You'll also notice that some features were not assigned a version number but were either assigned an "Implemented" or "NotImplmeented" tag. This indicates whether or the feature can be enabled, where "Implemented" means it can. Once a feature has been implemented and enabled by default, then it will be assigned a version number representing the date it was enabled by default. Then we can add ways for modules to declare version/feature requirements, such as: pragma(dlangVersionAtLeast, 2017_11_25); pragma(dlangVersionUpTo, 2018_09_02); pragma(requireFeature, ObjectiveCClasses); The way the compiler handles these pragmas can allow the compiler to print nice error messages when it can't satisfy the version/feature requirements of the module. For example, if a module declares `pragma(dlangVersionAtLeast, 2019_01_02)`, but it only support up to version 2018_05_06, then it can print an error message like: Error: module 'x' requires dlang version '2019_01_02' but you're at version '2018_05_06'. Your compiler is 7 months too old to compile this code. Notice that since the version has the date encoded into it, the compiler knows how old it is compared to the compiler version it needs to compile this module. Since each version is also tied to a feature name, this would also allow modules to enable features even when they aren't turned on by default, i.e. pragma(requireFeature, NoGCExceptions); If possible, this could have the same affect as specifying `-dip1008` on the command-line. In some cases, there may be features that can't be enabled once you've already started compilation of modules, and in this cases you could get a nice error message like: Error: module 'x' requires the 'NoGCExceptions' feature. Please provide the '-dip1008' option to compile this code. Of course, if this versioning is enabled, each version could use a general command-line syntax such as `--enable-feature=NoGCExceptions`. Along with these pragmas, another feature would be to allow code to obtain the version and/or check whether certain features can be enabled at compile time to work with multiple version of the lanaguage. So adding a couple traits like __traits(tryEnableFeature, NoGCExceptions) And could be used like: static if (__traits(tryEnableFeature, NoGCExceptions)) { nogc: } As D matures, these versioning mechanisms could alleviate some of the pain in introducing new features to the language by allowing the compilers of today to be aware of the timeline and feature names of features that are yet to be implemented. It also allows the code to declare what features it can work with and even allow it to work adapt based on the version of the compiler you are using. Furthermore, it provides the opportunity to support a consistent command-line syntax that will always work when a new feature is introduced.
Apr 04 2019
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-04-04 14:38, Jonathan Marler wrote:
 This is an informal proposal to add a versioning scheme to the D 
 Language.  If you'd like to take the time to read, please let everyone 
 know your thoughts and suggestions for the idea.  To Walter and Andrei, 
 please let me know your thoughts, if you think the idea has merit and if 
 so what the next steps should be (i.e. DIP/PR/More Resarch Discussion 
 Needed).
 
 As I've been thinking about various proposals and additions to the D 
 language, it occurred to me that I'd like to be able to declare inside 
 my code that it requires a certain version or certain features of the D 
 language in order to work properly. For example, when I look at the 
 changelog for DMD version 2.085, I see that support for Objective-C 
 classes was added.  However, I would be hesitant to use that feature 
 until a certain amount of time has passed. This is because using it 
 would make my libraries/applications only work with a small percentage 
 of compilers in the world, those who have recently updated their 
 compiler, and the error messages people would get could make it 
 difficult to know that they just need to update their compiler for it to 
 work with my code.  Currently the only way to solve this problem is to 
 wait a certain amount of time until I feel its reasonable that enough 
 people will have updated their compiler.
Today it's possible to use the special `__VERSION__` token [1]. There's also `__traits(compiles)` which can be used to check if a feature is available. The latest version of Dub supports specifying tool chain requirements. That include which compiler, which version or which version of the frontend that is required [2].
 I think we can do better.
 
 My current idea is to implement a list of versions and feature names.  
 Such a list could be dumped with something like:
 
 dmd --list-versions
2018_02_03 StaticForeach 2018_02_20 NoGCExceptions 2018_03_10 ObjectiveCClasses Implemented StaticForeach Implemented NamedParameters NotImplemented CopyConstructor NotImplemented ExpressionBasedContracts
Which features would be included in the list, all? In general I think it's better to query if a specific feature is available or not instead of query a version or date. [1] https://dlang.org/spec/lex.html#special-token-sequence [2] https://dub.pm/package-format-sdl.html#toolchain-requirements -- /Jacob Carlborg
Apr 04 2019
prev sibling parent KnightMare <black80 bk.ru> writes:
 pragma(dlangVersionAtLeast, 2017_11_25);
IMO pragmas are not very well in all cases. For example I have thousands LOCs with using std.xml ver1, but current version is ver2.2. I dont want rewrite code to ver2.2, I should point to ver1. In your case I see it like this: import std.stdio; pragma(dlangVersionAtLeast, 2017_11_25); // I dont sure that it will work now import std.xml; pragma(dlangVersionAtLeast, Uptodate); import std.anotherModules; // or we can use some attribute version("2017_11_15") In my vision I request it explicitly: import std.xml 1.*; // or import std.xml 1.* : someFuncAndClassList; // or import std.xml 2017_11; // or/and setup some fixed date in project settings for implicit modules I wrote my vision in topic https://forum.dlang.org/post/hgspjuiqjjtptdexwlus forum.dlang.org Probably better to continue talks in one topic.
May 26 2019