www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Smooth transition to D2 for Tango users?

reply bobef <bobef nosmap-abv.bg> writes:
Hello guys,

I want to share my concerns because I read something here and there and I
probably don't get the whole picture. From time to time I read about some new
fancy D2 feature. They all seem very useful, but many of them are very
different from D1. My concern is this: as a Tango user, I am not able to switch
to D2 before there is steady Tango development based on D2. So I am unable to
switch to D2 for the moment and it is constantly getting new features which
makes the gap between D1 and D2 bigger and bigger. One day when all the issues
are sorted out and D2 is stable and Tango moves to D2 I will want (and probably
be forced to) to move to D2. But by that time the gap between D1 and D2 could
be huge, so it could make porting my code very hard. I mean all this
discussions I read about opCall getting deprecated, new way for doing opApply,
delegates on the heap (or something like that) and the other discussions I
skip. All these things that are more or less silently breaking the D1
compatibility. On other hand if there was a mature D2 Tango now, I would do my
development in D2. I don't care it is not called stable. I was using D1 for
years before it was called stable and I never found it more unstable that the
'final' version. Maybe few rare bugs here and there... If this was the case I
could change my code gradually along with the changes to D2, but currently this
doesn't seem possible. This seems like a problem to me. Can someone more
intimately involved in this situation shed some light? Is this kind of problem
a factor in the priority list of the D2 development, because I guess it will
apply to most of the Tango users, which are most (I think) of the D users...

Regards,
bobef
Sep 17 2008
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 17 Sep 2008 11:00:12 +0400, bobef <bobef nosmap-abv.bg> wrote:

 Hello guys,

 I want to share my concerns because I read something here and there and  
 I probably don't get the whole picture. From time to time I read about  
 some new fancy D2 feature. They all seem very useful, but many of them  
 are very different from D1. My concern is this: as a Tango user, I am  
 not able to switch to D2 before there is steady Tango development based  
 on D2. So I am unable to switch to D2 for the moment and it is  
 constantly getting new features which makes the gap between D1 and D2  
 bigger and bigger. One day when all the issues are sorted out and D2 is  
 stable and Tango moves to D2 I will want (and probably be forced to) to  
 move to D2. But by that time the gap between D1 and D2 could be huge, so  
 it could make porting my code very hard. I mean all this discussions I  
 read about opCall getting deprecated, new way for doing opApply,  
 delegates on the heap (or something like that) and the other discussions  
 I skip. All these things that are more or less silently breaking the D1  
 compatibility. On other hand if there was a mature D2 Tango now, I would  
 do my development in D2. I don't care it is not called stable. I was  
 using D1 for years before it was called stable and I never found it more  
 unstable that the 'final' version. Maybe few rare bugs here and there...  
 If this was the case I could change my code gradually along with the  
 changes to D2, but currently this doesn't seem possible. This seems like  
 a problem to me. Can someone more intimately involved in this situation  
 shed some light? Is this kind of problem a factor in the priority list  
 of the D2 development, because I guess it will apply to most of the  
 Tango users, which are most (I think) of the D users...

 Regards,
 bobef

There is an experimental D2.0 branch in development: http://www.dsource.org/projects/tango/browser/branches/experimental/D2.0
Sep 17 2008
parent Frank Benoit <keinfarbton googlemail.com> writes:
Denis Koroskin schrieb:
 There is an experimental D2.0 branch in development:
 http://www.dsource.org/projects/tango/browser/branches/experimental/D2.0

there is currently not happening much. More ppl for contribution needed.
Sep 17 2008
prev sibling next sibling parent Moritz Warning <moritzwarning web.de> writes:
On Wed, 17 Sep 2008 03:00:12 -0400, bobef wrote:

 Hello guys,
 
 I want to share my concerns because I read something here and there and
 I probably don't get the whole picture. From time to time I read about
 some new fancy D2 feature. They all seem very useful, but many of them
 are very different from D1. My concern is this: as a Tango user, I am
 not able to switch to D2 before there is steady Tango development based
 on D2. So I am unable to switch to D2 for the moment and it is
 constantly getting new features which makes the gap between D1 and D2
 bigger and bigger. One day when all the issues are sorted out and D2 is
 stable and Tango moves to D2 I will want (and probably be forced to) to
 move to D2. But by that time the gap between D1 and D2 could be huge, so
 it could make porting my code very hard. I mean all this discussions I
 read about opCall getting deprecated, new way for doing opApply,
 delegates on the heap (or something like that) and the other discussions
 I skip. All these things that are more or less silently breaking the D1
 compatibility. On other hand if there was a mature D2 Tango now, I would
 do my development in D2. I don't care it is not called stable. I was
 using D1 for years before it was called stable and I never found it more
 unstable that the 'final' version. Maybe few rare bugs here and there...
 If this was the case I could change my code gradually along with the
 changes to D2, but currently this doesn't seem possible. This seems like
 a problem to me. Can someone more intimately involved in this situation
 shed some light? Is this kind of problem a factor in the priority list
 of the D2 development, because I guess it will apply to most of the
 Tango users, which are most (I think) of the D users...
 
 Regards,
 bobef

Afaik, there is only one big issue left for Tango moving D2 (the closure always on heap issue). When D2 won't change very much anymore, then there is probably no big reason for the Tango team not to switch.
Sep 17 2008
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
I'd like to see a smooth transition for Tango, not just the users! I made
several posts on the topic. The latest was titled "forward compatibility" --
Making the D1 compiler tolerant of code that looks like D2, but not adding new
functionality...

bobef Wrote:

 Hello guys,
 
 I want to share my concerns because I read something here and there and I
probably don't get the whole picture. From time to time I read about some new
fancy D2 feature. They all seem very useful, but many of them are very
different from D1. My concern is this: as a Tango user, I am not able to switch
to D2 before there is steady Tango development based on D2. So I am unable to
switch to D2 for the moment and it is constantly getting new features which
makes the gap between D1 and D2 bigger and bigger. One day when all the issues
are sorted out and D2 is stable and Tango moves to D2 I will want (and probably
be forced to) to move to D2. But by that time the gap between D1 and D2 could
be huge, so it could make porting my code very hard. I mean all this
discussions I read about opCall getting deprecated, new way for doing opApply,
delegates on the heap (or something like that) and the other discussions I
skip. All these things that are more or less silently breaking the D1
compatibility. On other hand if there was a mature D2 Tango now, I would do my
development in D2. I don't care it is not called stable. I was using D1 for
years before it was called stable and I never found it more unstable that the
'final' version. Maybe few rare bugs here and there... If this was the case I
could change my code gradually along with the changes to D2, but currently this
doesn't seem possible. This seems like a problem to me. Can someone more
intimately involved in this situation shed some light? Is this kind of problem
a factor in the priority list of the D2 development, because I guess it will
apply to most of the Tango users, which are most (I think) of the D users...
 
 Regards,
 bobef

Sep 17 2008
next sibling parent reply "Denis Koroskin" <2korden gmail.com> writes:
On Wed, 17 Sep 2008 18:31:02 +0400, Jason House  
<jason.james.house gmail.com> wrote:

 I'd like to see a smooth transition for Tango, not just the users! I  
 made several posts on the topic. The latest was titled "forward  
 compatibility" -- Making the D1 compiler tolerant of code that looks  
 like D2, but not adding new functionality...

Please, Walter, comment on this! Shall we put the request into bugzilla?
Sep 17 2008
parent reply Jason House <jason.james.house gmail.com> writes:
Denis Koroskin Wrote:

 On Wed, 17 Sep 2008 18:31:02 +0400, Jason House  
 <jason.james.house gmail.com> wrote:
 
 I'd like to see a smooth transition for Tango, not just the users! I  
 made several posts on the topic. The latest was titled "forward  
 compatibility" -- Making the D1 compiler tolerant of code that looks  
 like D2, but not adding new functionality...

Please, Walter, comment on this! Shall we put the request into bugzilla?

My last bugzilla request still doesn't have a response... Walter has said before that he doesn't like raining on people's parade, so maybe his silence should be assumed to be a rejection?
Sep 17 2008
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
<posted & mailed>

Bruce Adams wrote:

 On Wed, 17 Sep 2008 18:31:02 +0400, Jason House
 <jason.james.house gmail.com> wrote:

 I'd like to see a smooth transition for Tango, not just the users! I
 made several posts on the topic. The latest was titled "forward
 compatibility" -- Making the D1 compiler tolerant of code that looks
 like D2, but not adding new functionality...

The thing is what you are asking for is a major change to the D1.0 spec. D1.0 is frozen. Bug fixes (to the spec) are permitted but major additions are not.

That means almost nothing to me. Is the spec on how users should write their D1 code or a spec on how compiler writers should handle D1 code? If it's the former, my suggestion poses no problems because old D1 code will still compile and execute the exact same way it always did. If it's the latter, I don't see much of a problem since all alternative D1 compilers base their execution on dmd's front end source code.
 Moreoever this addition does not add any functionality. So while 
 it
 may seem like a sensible thing to do from a pragmatic programmer's point
 of view
  from a language design point of view its very silly indeed.

You're absolutely right that it depends on the point of view. While I may like the pragmatic programmer's point of view, I'm motivated by the library maintainer's point of view and the library users' point of view. Users would want freedom to choose their D version and the libraries that they use. The more incompatibilities that exist, the more it splits apart the D community. Such splits leave a sour taste for current users and for prospective users of D. Users will also want to read through library code from time to time, and the last thing they want to see is code that's littered with preprocessor directives. Library maintainers are left with the task of maintaining code. They need to have code with little or no duplication. Library maintainers are also users, and I bet that they were attracted to D by its elegance and simplicity.
 You need to find a difficult way to tackle the problem.

One time difficulty or increased difficulty for all library writers and users? Either way, a solution needs to be found that the community at large supports.
 * strip const's and invariants from the source in appropriate contexts

I've suggested this before too :)
 * use source code annotations specific to your Doneificator program

You mean add an unofficial D preprocessor? IMHO, if there's a need for this, it should be part of the D specification.
 Have a configure script which checks which versions of the compiler you
 have available.

ick. I can guarantee there are many here who have explicitly tried to avoid that kind of thing when coming to D.
Sep 20 2008
next sibling parent reply Jason House <jason.james.house gmail.com> writes:
Bruce Adams wrote:

 Maybe I've misunderstood but what I thought was being asked for was for
 the D1.0
 language to be changed to accept D2.0 syntax and ignore it at some point
 within blocks
 marked as D1.0 versions.
 This would mean that for a D1.0 compiler vendor to comply with the
 standard the
 D1.0 compiler would have to extended to parse D2.0.
 A bit like asking a C compiler to ignore C++ class definitions.
 Having D2.0 compilers accept D1.0 syntax in D1.0 version sections makes
 more sense.

I've proposed many things :) My ultimate goal is for a smooth transition between D1.0 and D2.0. For that to happen requires providing a path for Tango users and therefore Tango. Obviously, that's not the only important project, but it does have the largest user base. I have to assume that a smooth transition for a project as large as Tango means it would exist for other D1 projects. There are many ways to achieve that ultimate goal: 1. Backward compatibility (D2 parsing of all D1 code) 2. Forward compatibility (D1 parsing of a subset of D2 code) 3. version(D1), version(D2), with lightened parsing restrictions 4. Replace D's pre-processor 5. 3rd party pre-processor 6. D2 to D1 converter Below I tried to quickly make a list of pros and cons of each approach before having to run out the door. I've probably missed an alternative and many pros and cons. I hope we can find an alternative, or combination of alternatives, that allow this to happen. #1: (backward compatibility) pros: * Enables a single D1 code base that compiles with either D dialect * Allows legacy code to compile and run without modification * Least effort for library maintainers cons: * Requires allowing exceptions to const/invariant rules * Requires Walter to commit to the approach * Walter has previously stated that he felt C was held back by backwards compatibility. It's unlikely that he'd support this approach. #2: (forward compatibility) pros: * Enables a single "D1" code base that compiles with either D dialect * Partial adoption makes other alternatives easier/simpler cons: * Allows D1 to look like D2 code * Requires Walter's to commit (at least partially) to the approach #3: (version(D1), version(D2)) pros: * Easy to spot code intended for D1 and D2 * Allows gradual phasing out of old D versions cons: * Can't wrap function prototypes in a version statement by themselves * Will cause massive code duplication and restrict code maintainability * Requires Walter to commit to one of two altrnatives: * Parsing of alternate D dialects in one D dialect * Ignoring of code within these special version blocks * Fraction of code that must be covered with version statements #4: (Replace D's pre-processor) pros: * Allows versioned function prototypes without duplicating all containing code. cons: * Requires Walter to commit to this approach * Pre-processor is more C-like and Walter has already stated he's against that #5: (3rd party pre-processor) pros: * Allows versioned function prototypes without duplicating all containing code. * Unrestricted by D language design or Walter's choices cons: * Non-standard and unlikely to gain wide adoption * Makes use of library code tougher because of extra tools and compilation steps. Could be alleviated by distributing 3 code bases. #6: (D2 to D1 converter) pros: * Enables a single D2 code base that compiles with either D dialect cons: * Impossible to downconvert all code automatically. * Must be combined with another approach
Sep 21 2008
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Bruce Adams <tortoise_74 yeah.who.co.uk> wrote:
 I don't think its unreasonable to expect that braces will be balanced
 in all future versions of the language.

Braces can be in strings or comments. It's quite likely to have braces in strings in many kinds of parser programs. If you want code hidden from a compiler, put it in a string and mix in. enum veryD2Code = ` auto foo(T)(T x) if (__traits(hasMember, "opCall")) { return x(); } `; version (D_Version2) { mixin(veryD2Code); } In D2 you can use token strings for that purpose, so that the code will even be highlighted in your editor, but will not interfere with the compiler.
Sep 21 2008
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Sergey Gromov" wrote
 Bruce Adams <tortoise_74 yeah.who.co.uk> wrote:
 I don't think its unreasonable to expect that braces will be balanced
 in all future versions of the language.

Braces can be in strings or comments. It's quite likely to have braces in strings in many kinds of parser programs. If you want code hidden from a compiler, put it in a string and mix in. enum veryD2Code = ` auto foo(T)(T x) if (__traits(hasMember, "opCall")) { return x(); } `; version (D_Version2) { mixin(veryD2Code); } In D2 you can use token strings for that purpose, so that the code will even be highlighted in your editor, but will not interfere with the compiler.

oops, D1 doesn't support that type of enum ;) If the problem can't be solved with the current compilers, then the solution provided to make it work should be easy to use. I don't see this type of solution as easy to use, nor the 'version(D2)' type of solution. What if you have const member functions? If we had a preprocessor, I'd say: #ifdef Dv2 const int f() #else int f() #endif But we don't, so the reality is you must duplicate the function just to change the signature. Unless you do some hacky stuff like the mixin above. The two best solutions I've read are the original post (make D1 compile D2 as if it were D1), and a D2toD1 translator program. -Steve
Sep 22 2008
next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Steven Schveighoffer <schveiguy yahoo.com> wrote:
 oops, D1 doesn't support that type of enum ;)

I think you've got the idea. The code version (D_Version2) { mixin("some very specific code"); } works in any version of D, current or future.
Sep 22 2008
parent reply Sean Kelly <sean invisibleduck.org> writes:
Sergey Gromov wrote:
 Steven Schveighoffer <schveiguy yahoo.com> wrote:
 oops, D1 doesn't support that type of enum ;)

I think you've got the idea. The code version (D_Version2) { mixin("some very specific code"); } works in any version of D, current or future.

String mixins don't work directly for everything though. If you want to change a return value from non-const to const, for example, you need to make an alias for it using a versioned string mixin and then use the alias in the function declaration. And then there are things like this: // D1 const x = "hello"; // D2 enum x = "hello"; With string mixins you end up having to duplicate the entire line, and this can be a disaster if you're trying to maintain large header files with tons of declarations. Finally, I think the version(D_Version2) idea is backwards. It should be version(D_Version1). The current method isn't forwards-compatible, so all the code with these version statements in it will break when we get D version 3. Sean
Sep 22 2008
parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Sean Kelly <sean invisibleduck.org> wrote:
 Sergey Gromov wrote:
 Steven Schveighoffer <schveiguy yahoo.com> wrote:
 oops, D1 doesn't support that type of enum ;)

I think you've got the idea. The code version (D_Version2) { mixin("some very specific code"); } works in any version of D, current or future.

String mixins don't work directly for everything though. If you want to change a return value from non-const to const, for example, you need to make an alias for it using a versioned string mixin and then use the alias in the function declaration. And then there are things like this:

template Const(T) { version (D_Version2) { alias const(T) Const; } else { alias T Const; } } then Const!(int) bar; is just one char more than const(int) bar;
 // D1
 const x = "hello";
 
 // D2
 enum x = "hello";
 
 With string mixins you end up having to duplicate the entire line, and 
 this can be a disaster if you're trying to maintain large header files 
 with tons of declarations.

const keyword can be used to declare manifest constants in D2: const x = "foo"; pragma(msg, typeof(x).stringof); // invariant(char[3u])
 Finally, I think the version(D_Version2) idea is backwards.  It should 
 be version(D_Version1).  The current method isn't forwards-compatible, 
 so all the code with these version statements in it will break when we 
 get D version 3.

I agree here, there's not enough flexibility. The version identifiers should also have a numeric value, so that you can write: version (D_Version, 2) { ... } and the versioned code compiles only if D_Version has value of 2 or greater.
Sep 22 2008
next sibling parent Sergey Gromov <snake.scaly gmail.com> writes:
Sergey Gromov <snake.scaly gmail.com> wrote:
 template Const(T) {
   version (D_Version2) {
     alias const(T) Const;
   } else {
     alias T Const;
   }
 }

errata: template Const(T) { version (D_Version2) { mixin("alias const(T) Const;"); } else { alias T Const; } } this time actually tested with both 1.035 and 2.019.
Sep 22 2008
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
Sergey Gromov wrote:
 Sean Kelly <sean invisibleduck.org> wrote:
 Sergey Gromov wrote:
 Steven Schveighoffer <schveiguy yahoo.com> wrote:
 oops, D1 doesn't support that type of enum ;)

version (D_Version2) { mixin("some very specific code"); } works in any version of D, current or future.

change a return value from non-const to const, for example, you need to make an alias for it using a versioned string mixin and then use the alias in the function declaration. And then there are things like this:

template Const(T) { version (D_Version2) { alias const(T) Const; } else { alias T Const; } } then Const!(int) bar; is just one char more than const(int) bar;
 // D1
 const x = "hello";

 // D2
 enum x = "hello";


Good point.
 With string mixins you end up having to duplicate the entire line, and 
 this can be a disaster if you're trying to maintain large header files 
 with tons of declarations.

const keyword can be used to declare manifest constants in D2: const x = "foo"; pragma(msg, typeof(x).stringof); // invariant(char[3u])

The reason I brought this up is because multiprogramming can potentially avoid locking when using invariant data (const in D1), but it can't when using const data. So a diligent programmer would have to replace all uses of "const" in D1 with "invariant" in D2. But it would be easy enough to do with with a template as you've suggested above.
 Finally, I think the version(D_Version2) idea is backwards.  It should 
 be version(D_Version1).  The current method isn't forwards-compatible, 
 so all the code with these version statements in it will break when we 
 get D version 3.

I agree here, there's not enough flexibility. The version identifiers should also have a numeric value, so that you can write: version (D_Version, 2) { ... } and the versioned code compiles only if D_Version has value of 2 or greater.

That'd be pretty nifty. Sean
Sep 22 2008
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Sergey Gromov wrote:
 Sean Kelly <sean invisibleduck.org> wrote:
 
 Finally, I think the version(D_Version2) idea is backwards.  It should 
 be version(D_Version1).  The current method isn't forwards-compatible, 
 so all the code with these version statements in it will break when we 
 get D version 3.

I agree here, there's not enough flexibility. The version identifiers should also have a numeric value, so that you can write: version (D_Version, 2) { ... } and the versioned code compiles only if D_Version has value of 2 or greater.

Or just have: version(D_Version_2OrAbove) { ... ? Unless you plan on putting expressions in the version identifier (which I don't see a case for), it's just as good. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 23 2008
prev sibling parent Mosfet <mosfet anonymous.org> writes:
Denis Koroskin wrote:
 On Tue, 23 Sep 2008 02:00:36 +0400, Steven Schveighoffer 
 <schveiguy yahoo.com> wrote:
 
 "Sergey Gromov" wrote
 Bruce Adams <tortoise_74 yeah.who.co.uk> wrote:
 I don't think its unreasonable to expect that braces will be balanced
 in all future versions of the language.

Braces can be in strings or comments. It's quite likely to have braces in strings in many kinds of parser programs. If you want code hidden from a compiler, put it in a string and mix in. enum veryD2Code = ` auto foo(T)(T x) if (__traits(hasMember, "opCall")) { return x(); } `; version (D_Version2) { mixin(veryD2Code); } In D2 you can use token strings for that purpose, so that the code will even be highlighted in your editor, but will not interfere with the compiler.

oops, D1 doesn't support that type of enum ;) If the problem can't be solved with the current compilers, then the solution provided to make it work should be easy to use. I don't see this type of solution as easy to use, nor the 'version(D2)' type of solution. What if you have const member functions? If we had a preprocessor...

We do have some kind of it: #!/usr/bin/dmd -run #line 42 "foo.d" #pragma(msg, "bar"); ... C# has also support for the following "preprocessor" directives (although it doesn't have a preprocessor): #if #else #elif #endif #warning #error #line #region #endregion #define #undef These are widely known and understandable to many programmers, so D could extend the preprocessor directives list with some of them. An import point is that unlike C and C++, you cannot use these directives to create macros! D ought to have a way to mark some section of code so that it won't get parsed and semantically analyzed. Balancing of the curly braces is one of the solutions: version (Dv2) { const int f() } else { int f() } #if/#else/#elif/#endif is another, also a good one:
 #ifdef Dv2
    const int f()
 #else
    int f()
 #endif


way C# handle it and the other proposal looks like bad hack.
Sep 23 2008
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Bruce Adams wrote:
 Having D2.0 compilers accept D1.0 syntax in D1.0 version sections makes 
 more sense.
 

And who (which compiler) would compile the D1.0 version of the program?... /Pois.../ "Pois..." is a portuguese expression, said when one realizes something important and which is an impediment of the person's current plan. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 23 2008
prev sibling parent Matti Niemenmaa <see_signature for.real.address> writes:
Bruce Adams wrote:
 D1.0 is frozen. Bug fixes (to the spec) are permitted but major additions
 are not.

Major additions in the 1.0 series: - string mixins, string imports in 1.005 - CTFE in 1.006 - CTFE changes in 1.007 and 1.014 - addition of the "ref" and "macro" keywords in 1.011 - struct/AA literals in 1.014 - array operations in 1.034 All of the above broke backwards compatibility with earlier 1.0 versions. Many minor changes that could be argued as being more than just bug fixes: - removal of === and !== in 1.005 - "final" changes in 1.011 - the infamous .init change in 1.017 All of the above broke code that compiled with earlier 1.0 versions. The suggestion under discussion doesn't seem so bad to me, considering all that... -- E-mail address: matti.niemenmaa+news, domain is iki (DOT) fi
Sep 20 2008
prev sibling next sibling parent "Bruce Adams" <tortoise_74 yeah.who.co.uk> writes:
On Thu, 18 Sep 2008 03:43:22 +0100, Jason House  
<jason.james.house gmail.com> wrote:

 Denis Koroskin Wrote:

 On Wed, 17 Sep 2008 18:31:02 +0400, Jason House
 <jason.james.house gmail.com> wrote:

 I'd like to see a smooth transition for Tango, not just the users! I
 made several posts on the topic. The latest was titled "forward
 compatibility" -- Making the D1 compiler tolerant of code that looks
 like D2, but not adding new functionality...

Please, Walter, comment on this! Shall we put the request into bugzilla?

My last bugzilla request still doesn't have a response... Walter has said before that he doesn't like raining on people's parade, so maybe his silence should be assumed to be a rejection?

The thing is what you are asking for is a major change to the D1.0 spec. D1.0 is frozen. Bug fixes (to the spec) are permitted but major additions are not. Moreoever this addition does not add any functionality. So while it may seem like a sensible thing to do from a pragmatic programmer's point of view from a language design point of view its very silly indeed. You need to find a difficult way to tackle the problem. Its not a simple as the vanilla case of wanting one code base to support two dialects of the same language (e.g. two difficult non standard C++ compilers before we had a standard). As I understand it its the const system in D2.0 makes it more complicated. People have posted clever suggestions using templates but these make both the D1 and D2 code ugly. How about using source code transformation instead. Generate D1.0 compliant code from D2.0 code (with a minimum number of version blocks for the ugly stuff). Kind of a DFront if you like. It needs specing in more detail but here are some ideas to ponder: * strip const's and invariants from the source in appropriate contexts - const is legal/sensible in some places in D1.0 which is why sed -e s/const//g won't be enough - ideally use a D1.0 parser (you can only do simple source code transformations without it - maybe that would be enough) * use source code annotations specific to your Doneificator program (for the bits a brain dead translator can't handle alone) - deletemethod - remove the method entirely from the translation - noconst - remove const from the following line / block of code - keepconst - do not remove const from the following line / block of code Have a configure script which checks which versions of the compiler you have available. For library developers the build system would build both variants in different sub-directories source/ foo.d (annotated D2.0) v1/ foo.d - D1.0 variant V2/ foo.d - D2.0 variant Put the clever stuff into your makefile: V1/foo.d: foo.d dtrans --toD1 $< $ V2/foo.d: foo.d dtrans --toD2 $< $ or DIALECT=--toD1 foo.o: foo.d dtrans $(DIALECT) $< $ dmd $(DFLAGS) ... You have have your configure script set your DIALECT appropriately to your environment and ensure your DFLAGS includes the right version setting for the bits 'dtrans' can't handle. Having to do this sort of is why having a build system means more than just having an IDE with a half arsed notion of projects (I'm talking to you windows VC++ :) If you do need to write such a beast it would probably fit well with one of the build tools like DSSS but it should be standalone so everyone that care's can benefit. Regards, Bruce.
Sep 20 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sat, 20 Sep 2008 14:04:08 +0400, Bruce Adams  
<tortoise_74 yeah.who.co.uk> wrote:

 On Thu, 18 Sep 2008 03:43:22 +0100, Jason House  
 <jason.james.house gmail.com> wrote:

 Denis Koroskin Wrote:

 On Wed, 17 Sep 2008 18:31:02 +0400, Jason House
 <jason.james.house gmail.com> wrote:

 I'd like to see a smooth transition for Tango, not just the users! I
 made several posts on the topic. The latest was titled "forward
 compatibility" -- Making the D1 compiler tolerant of code that looks
 like D2, but not adding new functionality...

Please, Walter, comment on this! Shall we put the request into bugzilla?

My last bugzilla request still doesn't have a response... Walter has said before that he doesn't like raining on people's parade, so maybe his silence should be assumed to be a rejection?

The thing is what you are asking for is a major change to the D1.0 spec. D1.0 is frozen. Bug fixes (to the spec) are permitted but major additions are not. Moreoever this addition does not add any functionality. So while it may seem like a sensible thing to do from a pragmatic programmer's point of view from a language design point of view its very silly indeed.

Why is it? All we ask is to make the versioning *slightly* smarter and not raise an error in the following code: class Foo { version(D_Version2) { int bar() const { return 42; } } else { int bar() { return 42; } } } Okay, why is D_Version2 introduced in the first place? Isn't it supposed to be used to check against D compiler version? Yes, it is. Why do I what to check compiler version in my source code? Because I want my source code to be compilable with both DMD1 *and* DMD2. I want to write a library and I want it so be useful to as much people as possible. What language should I write it in? D1 or D2? Well, almost everyone is using D1, that's why D2 is not an option. D2 is released *more that a year* ago but is still not popular. Do you think no one wants to use it? No, that's not the case. Lots of people still using D1 just because there is no way to write code so that it is compilable with both versions. I *do* want to use it but I can't. And I won't do any serious programming in D2 until this issue is resolved. And if it won't get resolved... well, I'll most probably quit the community. It is too much restricting and frustrating. Thanks for listening.
 You need to find a difficult way to tackle the problem.
 Its not a simple as the vanilla case of wanting one code base to support  
 two
 dialects of the same language (e.g. two difficult non standard C++  
 compilers before
 we had a standard). As I understand it its the const system in D2.0  
 makes it more
 complicated. People have posted clever suggestions using templates but  
 these make
 both the D1 and D2 code ugly.
 How about using source code transformation instead. Generate D1.0  
 compliant code from
 D2.0 code (with a minimum number of version blocks for the ugly stuff).  
 Kind of a
 DFront if you like. It needs specing in more detail but here are some  
 ideas to ponder:

 * strip const's and invariants from the source in appropriate contexts
 - const is legal/sensible in some places in D1.0  which is why sed -e  
 s/const//g won't be enough
 - ideally use a D1.0 parser (you can only do simple source code  
 transformations without it - maybe that would be enough)

 * use source code annotations specific to your Doneificator program (for  
 the bits a brain dead translator can't handle alone)
 -  deletemethod   - remove the method entirely from the translation
 -  noconst        - remove const from the following line / block of code
 -  keepconst      - do not remove const from the following line / block  
 of code

 Have a configure script which checks which versions of the compiler you  
 have available.
 For library developers the build system would build both variants in  
 different sub-directories

 source/
     foo.d    (annotated D2.0)
     v1/
        foo.d   - D1.0 variant
     V2/
        foo.d   - D2.0 variant

 Put the clever stuff into your makefile:

 V1/foo.d: foo.d
      dtrans --toD1 $< $ 

 V2/foo.d: foo.d
      dtrans --toD2 $< $ 

 or

 DIALECT=--toD1

 foo.o: foo.d
      dtrans $(DIALECT) $< $ 
      dmd $(DFLAGS) ...

 You have have your configure script set your DIALECT appropriately to  
 your environment and ensure your
 DFLAGS includes the right version setting for the bits 'dtrans' can't  
 handle.

 Having to do this sort of is why having a build system means more than  
 just having an IDE with a half arsed notion of projects
 (I'm talking to you windows VC++ :)

 If you do need to write such a beast it would probably fit well with one  
 of the build tools like DSSS
 but it should be standalone so everyone that care's can benefit.

 Regards,

 Bruce.

No-no-no, I won't read this. That's a no-go (for me, at least). I would write it C/C++ with its preprocessor instead.
Sep 20 2008
prev sibling next sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Sat, Sep 20, 2008 at 1:05 PM, Matti Niemenmaa
<see_signature for.real.address> wrote:
 Bruce Adams wrote:
 D1.0 is frozen. Bug fixes (to the spec) are permitted but major additions
 are not.

Major additions in the 1.0 series: - string mixins, string imports in 1.005 - CTFE in 1.006 - CTFE changes in 1.007 and 1.014 - addition of the "ref" and "macro" keywords in 1.011 - struct/AA literals in 1.014 - array operations in 1.034 All of the above broke backwards compatibility with earlier 1.0 versions. Many minor changes that could be argued as being more than just bug fixes: - removal of === and !== in 1.005 - "final" changes in 1.011 - the infamous .init change in 1.017 All of the above broke code that compiled with earlier 1.0 versions. The suggestion under discussion doesn't seem so bad to me, considering all that...

But see, every time we mention these things to Walter he says "no more, that was the last thing." I.. somehow don't buy it, especially with array ops coming out of the blue so recently. The fact remains that Walter is horrid at communication and no one knows for sure whether anything will be implemented, either soon or in the distant future. Feature requests like this might go completely unnoticed, or he might be feverishly working on implementing them as we speak. No one knows. The development of D is a black box, and even after five years of experience with it, I _still_ have not determined what inputs you have to poke and prod to effect the desired outputs.
Sep 20 2008
prev sibling next sibling parent "Bruce Adams" <tortoise_74 yeah.who.co.uk> writes:
On Sat, 20 Sep 2008 15:18:38 +0100, Jason House  
<jason.james.house gmail.com> wrote:

 <posted & mailed>

 Bruce Adams wrote:

 On Wed, 17 Sep 2008 18:31:02 +0400, Jason House
 <jason.james.house gmail.com> wrote:

 I'd like to see a smooth transition for Tango, not just the users! I
 made several posts on the topic. The latest was titled "forward
 compatibility" -- Making the D1 compiler tolerant of code that looks
 like D2, but not adding new functionality...

The thing is what you are asking for is a major change to the D1.0 spec. D1.0 is frozen. Bug fixes (to the spec) are permitted but major additions are not.

That means almost nothing to me. Is the spec on how users should write their D1 code or a spec on how compiler writers should handle D1 code? If it's the former, my suggestion poses no problems because old D1 code will still compile and execute the exact same way it always did. If it's the latter, I don't see much of a problem since all alternative D1 compilers base their execution on dmd's front end source code.

the D1.0 language to be changed to accept D2.0 syntax and ignore it at some point within blocks marked as D1.0 versions. This would mean that for a D1.0 compiler vendor to comply with the standard the D1.0 compiler would have to extended to parse D2.0. A bit like asking a C compiler to ignore C++ class definitions. Having D2.0 compilers accept D1.0 syntax in D1.0 version sections makes more sense. Now I think I understand what people are saying. You want different version sections to not report errors for versions of the language they do not support. By default the compiler parses code in all version sections. One purpose of the version statement is so that you can always tell your code is syntactically correct for all versions. Another possible solution is to add an option to the compiler that modifies this behaviour so the compiler doesn't bother parsing the other version block. This defeats the purpose above. Still I think it is probably the correct thing to do (by default) for D1 compilers to accept D2 code and for D2 compilers to accept D3 code. For a D2 compiler it would be down to the vendor as to whether to have a D1.0 parser builtin as well and switch modes within version blocks or simply ignore them. But there is going to be significant code bloat in having a compiler support every variant of the language so at some point your going to have to say ignore code in other version blocks. The parser needs a way of identifying the end of the version block without doing too much analysis on the code inbetween which is a bit gnarly.
 Moreoever this addition does not add any functionality. So while
 it
 may seem like a sensible thing to do from a pragmatic programmer's point
 of view
  from a language design point of view its very silly indeed.

You're absolutely right that it depends on the point of view. While I may like the pragmatic programmer's point of view, I'm motivated by the library maintainer's point of view and the library users' point of view. Users would want freedom to choose their D version and the libraries that they use. The more incompatibilities that exist, the more it splits apart the D community. Such splits leave a sour taste for current users and for prospective users of D. Users will also want to read through library code from time to time, and the last thing they want to see is code that's littered with preprocessor directives. Library maintainers are left with the task of maintaining code. They need to have code with little or no duplication. Library maintainers are also users, and I bet that they were attracted to D by its elegance and simplicity.

source code in the version of the language they are using. Library developers have the choice of using version statements or some kind of annotation whichever they find cleaner. There is overhead and complexity which may not be justified but if you want flexibility sometimes you have to pay for it.
 You need to find a difficult way to tackle the problem.

One time difficulty or increased difficulty for all library writers and users? Either way, a solution needs to be found that the community at large supports.

there :)
 * strip const's and invariants from the source in appropriate contexts

I've suggested this before too :)

discussed without being resolved :).
 * use source code annotations specific to your Doneificator program

You mean add an unofficial D preprocessor? IMHO, if there's a need for this, it should be part of the D specification.

doesn't support and your tool vendor doesn't look likely to implement then your options are limited. Source code transformation isn't inherantly evil though. You just need a very good reason to justify the expense of doing it.
 Have a configure script which checks which versions of the compiler you
 have available.

ick. I can guarantee there are many here who have explicitly tried to avoid that kind of thing when coming to D.

Regardless of how you handle multiple language versions in the source code you need some way to set the flags that say what you are going to build and how you are going to build it. You can only avoid having something doing the job of a configure script if you only plan on having a single configuration. If you know you will have a D2.0 compiler you shouldn't need to worry.
Sep 21 2008
prev sibling next sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Sun, 21 Sep 2008 19:55:48 +0400, Jason House  
<jason.james.house gmail.com> wrote:

 Bruce Adams wrote:

 Maybe I've misunderstood but what I thought was being asked for was for
 the D1.0
 language to be changed to accept D2.0 syntax and ignore it at some point
 within blocks
 marked as D1.0 versions.
 This would mean that for a D1.0 compiler vendor to comply with the
 standard the
 D1.0 compiler would have to extended to parse D2.0.
 A bit like asking a C compiler to ignore C++ class definitions.
 Having D2.0 compilers accept D1.0 syntax in D1.0 version sections makes
 more sense.

I've proposed many things :) My ultimate goal is for a smooth transition between D1.0 and D2.0. For that to happen requires providing a path for Tango users and therefore Tango. Obviously, that's not the only important project, but it does have the largest user base. I have to assume that a smooth transition for a project as large as Tango means it would exist for other D1 projects. There are many ways to achieve that ultimate goal: 1. Backward compatibility (D2 parsing of all D1 code) 2. Forward compatibility (D1 parsing of a subset of D2 code) 3. version(D1), version(D2), with lightened parsing restrictions 4. Replace D's pre-processor 5. 3rd party pre-processor 6. D2 to D1 converter Below I tried to quickly make a list of pros and cons of each approach before having to run out the door. I've probably missed an alternative and many pros and cons. I hope we can find an alternative, or combination of alternatives, that allow this to happen. #1: (backward compatibility) pros: * Enables a single D1 code base that compiles with either D dialect * Allows legacy code to compile and run without modification * Least effort for library maintainers cons: * Requires allowing exceptions to const/invariant rules * Requires Walter to commit to the approach * Walter has previously stated that he felt C was held back by backwards compatibility. It's unlikely that he'd support this approach. #2: (forward compatibility) pros: * Enables a single "D1" code base that compiles with either D dialect * Partial adoption makes other alternatives easier/simpler cons: * Allows D1 to look like D2 code * Requires Walter's to commit (at least partially) to the approach #3: (version(D1), version(D2)) pros: * Easy to spot code intended for D1 and D2 * Allows gradual phasing out of old D versions cons: * Can't wrap function prototypes in a version statement by themselves * Will cause massive code duplication and restrict code maintainability * Requires Walter to commit to one of two altrnatives: * Parsing of alternate D dialects in one D dialect * Ignoring of code within these special version blocks * Fraction of code that must be covered with version statements #4: (Replace D's pre-processor) pros: * Allows versioned function prototypes without duplicating all containing code. cons: * Requires Walter to commit to this approach * Pre-processor is more C-like and Walter has already stated he's against that #5: (3rd party pre-processor) pros: * Allows versioned function prototypes without duplicating all containing code. * Unrestricted by D language design or Walter's choices cons: * Non-standard and unlikely to gain wide adoption * Makes use of library code tougher because of extra tools and compilation steps. Could be alleviated by distributing 3 code bases. #6: (D2 to D1 converter) pros: * Enables a single D2 code base that compiles with either D dialect cons: * Impossible to downconvert all code automatically. * Must be combined with another approach

I would like to show some other aspect of the issue. D has support for inline assembly. Different processors might have different assembly syntax and it is unlikely that every future D compiler would support all the syntaxes and recognize all command. Take a look at the tango.core.Atomic module. It contains x86 and x64 assembly instructions so far. However, it is likely that implementation for other platforms will be added soner or later (ARM, PowerPC and others). And they should somehow co-exist in one source code, like this: bool cas(ref int value, int newValue, int oldValue) { version (X86) { asm { mov EDX, newValue; mov EAX, oldValue; mov ECX, value; lock; cmpxchg [ECX], EDX; setz AL; } } else version (PowerPC) { asm { // an implementaion using load-linked/store-conditional } } } (I am no expert in assembly, so I copied x86 code and left ppc code blank :)). Current parsing rules state that the code in version block should be semantically correct, even if it is ignored. But since DMD knows basically nothing about those ll/sc op-codes, the code can't be placed in one source file, which is bad for maintainability. Besides, I foresee "Smoth D2 to D3 transition", "Smooth D3 to D4 transition" etc topics in future, so we should solve the issue once and for all.
Sep 21 2008
prev sibling next sibling parent "Bruce Adams" <tortoise_74 yeah.who.co.uk> writes:
On Sun, 21 Sep 2008 21:13:04 +0100, Denis Koroskin <2korden gmail.com>  
wrote:
 I would like to show some other aspect of the issue.

 D has support for inline assembly. Different processors might have  
 different assembly syntax and it is unlikely that every future D  
 compiler would support all the syntaxes and recognize all command. Take  
 a look at the tango.core.Atomic module. It contains x86 and x64 assembly  
 instructions so far. However, it is likely that implementation for other  
 platforms will be added soner or later (ARM, PowerPC and others). And  
 they should somehow co-exist in one source code, like this:

 bool cas(ref int value, int newValue, int oldValue) {
    version (X86) {
      asm {
        mov EDX, newValue;
        mov EAX, oldValue;
        mov ECX, value;
        lock;
        cmpxchg [ECX], EDX;
        setz AL;
      }
    } else version (PowerPC) {
      asm {
        // an implementaion using load-linked/store-conditional
      }
    }
 }

 (I am no expert in assembly, so I copied x86 code and left ppc code  
 blank :)).

 Current parsing rules state that the code in version block should be  
 semantically correct, even if it is ignored. But since DMD knows  
 basically nothing about those ll/sc op-codes, the code can't be placed  
 in one source file, which is bad for maintainability.

 Besides, I foresee "Smoth D2 to D3 transition", "Smooth D3 to D4  
 transition" etc topics in future, so we should solve the issue once and  
 for all.

The inline assembly and language variant cases both demonstrate there are at minimum 2 incompatible use cases for the version statement. The language currently only supports the case where the code is syntactically correct for all versions. Though if the alternate assembly versions work in Tango there must already be a special case that asm blocks are ignored outside the currently active version. To handle it on the language/compiler side two things are required. 1) a way to indicate the differences between the two kinds of version block 2) a way to handle 'non'-parsing blocks. I don't think its unreasonable to expect that braces will be balanced in all future versions of the language. So a compiler could re-synchronise following the next balanced code brace. The tokeniser will choke on unidentified keywords unless they are parsed as strings and ignored rather than producing an unknown token. The lexer is going to have to know enough to handle braces and detect braces that do not apply because they are within strings or comment whatever. It would take a lot of care to get right. However its done, compiler, preprocessor or whatever its going to be a bit yucky somewhere. Maybe a different kind of bracket would make things easier. Say version { /* don't parse me */ }, though that's dangerously close to #endif :). I cant' help thinking the safest thing is some kind of source 2 source translator. D1 to D2 would help ease the transition greatly but result in a lot of crappy quality D2 code out there. D2 to D1 might be a bigger project but possibly more useful. I previously suggested annotatations as they might simplify the implementation of a converter significantly. They could be deprecated as time went on and the project grew more mature. But what do I know, I'm just tha window cleaner :-)
Sep 21 2008
prev sibling parent "Denis Koroskin" <2korden gmail.com> writes:
On Tue, 23 Sep 2008 02:00:36 +0400, Steven Schveighoffer  
<schveiguy yahoo.com> wrote:

 "Sergey Gromov" wrote
 Bruce Adams <tortoise_74 yeah.who.co.uk> wrote:
 I don't think its unreasonable to expect that braces will be balanced
 in all future versions of the language.

Braces can be in strings or comments. It's quite likely to have braces in strings in many kinds of parser programs. If you want code hidden from a compiler, put it in a string and mix in. enum veryD2Code = ` auto foo(T)(T x) if (__traits(hasMember, "opCall")) { return x(); } `; version (D_Version2) { mixin(veryD2Code); } In D2 you can use token strings for that purpose, so that the code will even be highlighted in your editor, but will not interfere with the compiler.

oops, D1 doesn't support that type of enum ;) If the problem can't be solved with the current compilers, then the solution provided to make it work should be easy to use. I don't see this type of solution as easy to use, nor the 'version(D2)' type of solution. What if you have const member functions? If we had a preprocessor...

We do have some kind of it: #!/usr/bin/dmd -run #line 42 "foo.d" #pragma(msg, "bar"); ... C# has also support for the following "preprocessor" directives (although it doesn't have a preprocessor): #if #else #elif #endif #warning #error #line #region #endregion #define #undef These are widely known and understandable to many programmers, so D could extend the preprocessor directives list with some of them. An import point is that unlike C and C++, you cannot use these directives to create macros! D ought to have a way to mark some section of code so that it won't get parsed and semantically analyzed. Balancing of the curly braces is one of the solutions: version (Dv2) { const int f() } else { int f() } #if/#else/#elif/#endif is another, also a good one:
 #ifdef Dv2
    const int f()
 #else
    int f()
 #endif

Sep 22 2008