digitalmars.D - supporting DMD-1.016 and DMD-2.000 with the same source code
- Thomas Kuehne <thomas-dloop kuehne.cn> Jun 18 2007
- Lutger <lutger.blijdestijn gmail.com> Jun 18 2007
- Sean Kelly <sean f4.ca> Jun 18 2007
- Daniel Keep <daniel.keep.lists gmail.com> Jun 18 2007
- Sean Kelly <sean f4.ca> Jun 18 2007
- Walter Bright <newshound1 digitalmars.com> Jun 18 2007
- Henning Hasemann <hhasemann web.de> Jun 18 2007
- Carlos Santander <csantander619 gmail.com> Jun 18 2007
- Walter Bright <newshound1 digitalmars.com> Jun 18 2007
- Thomas Kuehne <thomas-dloop kuehne.cn> Jun 18 2007
- Georg Wrede <georg nospam.org> Jun 18 2007
- Bill Baxter <dnewsgroup billbaxter.com> Jun 18 2007
- Georg Wrede <georg nospam.org> Jun 18 2007
- torhu <fake address.dude> Jul 01 2007
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Below are a few code samples that might help you to make your code
compatible with DMD-1.016 as well as DMD-2.000.
1) What compiler am I running?
==============================
# static if(is(typeof((new char[3]).idup))){
# pragma(msg, "DMD version 2");
# static dmd_version = 2;
# }else{
# pragma(msg, "DMD version 1");
# static dmd_version = 1;
# }
Usually I try to avoid any kind of version detection, however
the class invariant changes (see below) require it this time.
If you are only using Phobos and not alternatives like Tango
the language version can be accessed via:
# import std.compiler : version_major;
# import std.metastrings : ToString;
#
# pragma(msg, "DMD version " ~ ToString!(version_major));
# alias version_major dmd_version;
2) 'string', 'wstring', 'dstring'
=================================
If you defined a 'string' type or alias replace it with myString or
similar. The same is valid for 'wstring' and 'dstring'.
3) Object.toString
==================
In DMD-1 the signature is
char[] Object.toString();
however in DMD-2 the signature is
const(char)[] Object.toString();
An ad-hock solution would be:
# class Foo{
# typeof((new Object()).toString()) toString(){
# return "abc";
# }
# }
This solution works reliably but is 'ugly' and doesn't scale
very well. Thus the slightly longer version:
# static if(!is(string)){
# static if(! is(typeof((new Object()).toString()) string)){
# alias char[] string;
# }
# }
#
# class Foo{
# string toString(){
# return "abc";
# }
# }
4) class invariants
===================
This is the only real trouble spot so far. DMD-1 uses
invariant{ ... assert(...); ... }
however DMD-2 uses
invariant(){ ... assert(...); ... }
There are basically two approaches. Both require dmd_version from
1) "What compiler am I running?" (see above). First the complete
mixin solution:
# class Foo : Object{
# int x;
#
# mixin("invariant" ~ (dmd_version < 2 ? "" : "()") ~
# "{
# assert(x < 100);
# }");
# }
This might be a quick hack however in most cases you are going to
lose nice features like syntax highlighting. Invariants are
prohibited from calling 'public' member function but calling
'private' member functions is OK:
# const char[] invariantCall = "invariant" ~ (dmd_version < 2 ? "" : "()")
# ~ "{ invariant_(); }";
#
# class Foo : Object{
# int x;
#
# mixin(invariantCall);
#
# private void invariant_(){
# assert(x < 100);
# }
# }
5) string functions
===================
Where ever reasonable replace 'char[]' with 'string' (see 3) above).
Due to my general coding style this was basically a search/replace
operation that requires almost no further code changes. In the case of
Flectioned 2 additional ".dup"s were needed.
6) C-strings
============
Sometime I have to interface with C libries this "const char*" is
required:
# static if(1 < dmd_version){
# mixin("alias const(char)* stringz;");
# }else{
# alias char* stringz;
# }
The mixin in required because the content has to be syntactically
correct and "const(char)" isn't a valid DMD-1 construct.
7) the 'rest'
=============
Depending on your coding style you might have to deal with 'final'
parameters and 'final' foreach value variables, but in my case
(3873 lines of cross OS code) not a single change was required.
Thomas
-----BEGIN PGP SIGNATURE-----
iQIVAwUBRnaPP7ZlboUnBhRKAQK46RAAhAOvSpZTtaJ+2OdcLfCkDsJNE/kzQm9A
BK7xVUovXs63uvAGkrOeN5SwRxHhWousdbrYZwAmKrQ9KrEDOZVFON134SEC0IAf
Greg1fYZSXc/g6myWeqGzAXT7OBSQ4EkRTl8lkbTvSO6467ynx88GlATRxsFZ+t6
EHSbqS8M1Gkh3tiXXMQqOBxqmLJujJyS78c4f2pQsvPqYpPgugZsQrpgKseIlH5q
b3v7qji9ACnvZGIMCq5zhrq945J9YvJYQEjqLDs4+SCcgGFzuvLUXTdVlga5MyeI
UmyGDS5fvdDNX35wsKk1St8ZHfxORyI3+FEHeMCxHY5YT1govhkgBqK7suS/Kp6M
ySZsQ9sIpjYwWTIEViflJ9otuY7l/nH1H5OGm2tS+dxDhzLjFw7jCBy/9c0eIxtL
WrXovAv2fVn6MbnkqGs3lBGEj0o518Chc2zHyBQikFUaE8cpdj5PxEP2usnq/WGE
2vQ0fsRUhfnHcV/p9DOyNsQyjBGIBL2BK2sNBDSqkScxVoPE7ZBAHNpsDsQZlUwS
8IlkqAbLPFRJxPBWiR/2dsi6SbM/hg+lfyqOqdzZvNfpICWcXcETab0JEk3WODb0
7EpT9F6CDLpWBvOhxtb/rzTkPpjWdpYg0Q2alT4CgnwjdrYDH1btSxYCPmm/OL23
qi8DHAD+X0o=
=fZxN
-----END PGP SIGNATURE-----
Jun 18 2007
Great tips thank you. These deserve a place on a website and a link from digitalmars imho.
Jun 18 2007
Thomas Kuehne wrote:4) class invariants =================== This is the only real trouble spot so far. DMD-1 uses invariant{ ... assert(...); ... } however DMD-2 uses invariant(){ ... assert(...); ... }
Well that's unfortunate. I don't suppose unittest has gotten parenthesis as well? Sean
Jun 18 2007
Sean Kelly wrote:Thomas Kuehne wrote:4) class invariants =================== This is the only real trouble spot so far. DMD-1 uses invariant{ ... assert(...); ... } however DMD-2 uses invariant(){ ... assert(...); ... }
Well that's unfortunate. I don't suppose unittest has gotten parenthesis as well? Sean
I suspect this is because invariant is now a declaration, a storage class *and* a type constructor. -- Daniel
Jun 18 2007
Daniel Keep wrote:Sean Kelly wrote:Thomas Kuehne wrote:4) class invariants =================== This is the only real trouble spot so far. DMD-1 uses invariant{ ... assert(...); ... } however DMD-2 uses invariant(){ ... assert(...); ... }
parenthesis as well?
I suspect this is because invariant is now a declaration, a storage class *and* a type constructor.
Well sure. But adding parens breaks consistency with other similar blocks. Sean
Jun 18 2007
Daniel Keep wrote:I suspect this is because invariant is now a declaration, a storage class *and* a type constructor.
It's a dessert topping *and* a floor wax! http://www.jibjab.com/view/101069#
Jun 18 2007
Am Mon, 18 Jun 2007 07:57:05 -0700 schrieb Sean Kelly <sean f4.ca>:Well sure. But adding parens breaks consistency with other similar blocks.
What I find more confusing is the "overloading" of keywords with different meanings or even worse *similar* meanings, especially for programmers that down "grow with the language" like most readers of this NG but will start using it at some point in the future. They have to learn a lot of things in order to use a keyword correctly. Henning -- GPG Public Key: http://keyserver.ganneff.de:11371/pks/lookup?op=get&search=0xDDD6D36D41911851 Fingerprint: 344F 4072 F038 BB9E B35D E6AB DDD6 D36D 4191 1851
Jun 18 2007
Thomas Kuehne escribió:4) class invariants =================== This is the only real trouble spot so far. DMD-1 uses invariant{ ... assert(...); ... } however DMD-2 uses invariant(){ ... assert(...); ... } There are basically two approaches. Both require dmd_version from 1) "What compiler am I running?" (see above). First the complete mixin solution: # class Foo : Object{ # int x; # # mixin("invariant" ~ (dmd_version < 2 ? "" : "()") ~ # "{ # assert(x < 100); # }"); # } This might be a quick hack however in most cases you are going to lose nice features like syntax highlighting. Invariants are prohibited from calling 'public' member function but calling 'private' member functions is OK: # const char[] invariantCall = "invariant" ~ (dmd_version < 2 ? "" : "()") # ~ "{ invariant_(); }"; # # class Foo : Object{ # int x; # # mixin(invariantCall); # # private void invariant_(){ # assert(x < 100); # } # }
To avoid this ugly hack, how about supporting invariant(){} in Dv1? -- Carlos Santander Bernal
Jun 18 2007
Thomas Kuehne wrote:Below are a few code samples that might help you to make your code compatible with DMD-1.016 as well as DMD-2.000. 1) What compiler am I running? ============================== # static if(is(typeof((new char[3]).idup))){ # pragma(msg, "DMD version 2"); # static dmd_version = 2; # }else{ # pragma(msg, "DMD version 1"); # static dmd_version = 1; # }
It's obvious I need to put together a predefined compiler version.If you are only using Phobos and not alternatives like Tango the language version can be accessed via: # import std.compiler : version_major; # import std.metastrings : ToString; # # pragma(msg, "DMD version " ~ ToString!(version_major)); # alias version_major dmd_version; 2) 'string', 'wstring', 'dstring' ================================= If you defined a 'string' type or alias replace it with myString or similar. The same is valid for 'wstring' and 'dstring'. 3) Object.toString ================== In DMD-1 the signature is char[] Object.toString(); however in DMD-2 the signature is const(char)[] Object.toString(); An ad-hock solution would be: # class Foo{ # typeof((new Object()).toString()) toString(){ # return "abc"; # } # } This solution works reliably but is 'ugly' and doesn't scale very well. Thus the slightly longer version: # static if(!is(string)){ # static if(! is(typeof((new Object()).toString()) string)){ # alias char[] string; # } # } # # class Foo{ # string toString(){ # return "abc"; # } # }
This is why I put the string aliases into dmd 1.016. Then, just replace the char[] with string, and it'll work with both 1.0 and 2.0.4) class invariants =================== This is the only real trouble spot so far. DMD-1 uses invariant{ ... assert(...); ... } however DMD-2 uses invariant(){ ... assert(...); ... }
I fixed the 1.015 compiler to accept the () as being optional. So, use the () for both, and it should work.There are basically two approaches. Both require dmd_version from 1) "What compiler am I running?" (see above). First the complete mixin solution: # class Foo : Object{ # int x; # # mixin("invariant" ~ (dmd_version < 2 ? "" : "()") ~ # "{ # assert(x < 100); # }"); # } This might be a quick hack however in most cases you are going to lose nice features like syntax highlighting. Invariants are prohibited from calling 'public' member function but calling 'private' member functions is OK: # const char[] invariantCall = "invariant" ~ (dmd_version < 2 ? "" : "()") # ~ "{ invariant_(); }"; # # class Foo : Object{ # int x; # # mixin(invariantCall); # # private void invariant_(){ # assert(x < 100); # } # } 5) string functions =================== Where ever reasonable replace 'char[]' with 'string' (see 3) above). Due to my general coding style this was basically a search/replace operation that requires almost no further code changes. In the case of Flectioned 2 additional ".dup"s were needed.
I find that doing a mechanical global search/replace of char[] with string will successfully convert 95+% of the code, with a little touchup here and there.6) C-strings ============ Sometime I have to interface with C libries this "const char*" is required: # static if(1 < dmd_version){ # mixin("alias const(char)* stringz;"); # }else{ # alias char* stringz; # } The mixin in required because the content has to be syntactically correct and "const(char)" isn't a valid DMD-1 construct.
Hmm, I like the stringz alias. Or maybe cstring?7) the 'rest' ============= Depending on your coding style you might have to deal with 'final' parameters and 'final' foreach value variables, but in my case (3873 lines of cross OS code) not a single change was required.
Jun 18 2007
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Walter Bright schrieb am 2007-06-18:Thomas Kuehne wrote:Below are a few code samples that might help you to make your code compatible with DMD-1.016 as well as DMD-2.000.
[...]This is why I put the string aliases into dmd 1.016. Then, just replace the char[] with string, and it'll work with both 1.0 and 2.0.
[...]I fixed the 1.015 compiler to accept the () as being optional. So, use the () for both, and it should work.
The main problem is that both changes aren't yet incorporated into GDC and unlike GDC DMD can't generate 64bit code. Thomas -----BEGIN PGP SIGNATURE----- iQIVAwUBRneF17ZlboUnBhRKAQJa9Q//Ubhl+WwZcJ5sdcoNhwM6bLZo7Mebc2Po T4S0LWHAwsDQoHlwMaz4iQpuFxThm/EIED90fMZMuRdGb9c4iNsfhIqS6i0SjRTK 2GKSHQFt2dTZHxYdJ8H4l7n32BZssnUXuAKDG0k4O72roCrbZutECIXnFxlwtbcy pP/7poSU/Peuh+Ap5YxuGea3idhUBFSUXmweL6ZruJtIv6OhayVIa0DDkcgds2Wz csYTpBQlN+FhOkZLCF7fhh3uPgQUp7yk4w7R/0rhpuTCGRY2vX2Ffgr5A6ObQWu/ 2dRlAEFnFbE0V3eDq/ps9WlfrVippDcPRic18EnHJH4l9PG5bL4ApvcbVhKXWoUp UBqgd5qFMaVnnOG5GTPbNKD8nUFwY20JsJ4yn/hhpAWByMm97n/O+xAJ1Nyc+9CR Dc77iQw5ggSJBQbeMhR4PKrNysITJ0ub2lOC5Hr+VV+6jAkwsdmfDNqZWOe8gfX/ e4UHotOSbWxyqzB5/sVlZ9t/ZXCwYAIENnxTujsqr4su0NUCcKt385t0q7a7KAOE KfCxiAf5jZJSQ3VH1IrmFxxHn5mZU5Q6+XLJ1XTrI3vgJWIlQeG3nTZOi6jBhHWY OIj+A0OrzzYBx3QuThkJQKEmdYmqFbsbUuHhUYO5jMGHJs4P66VnV4x+BkntrNI4 sxaytxsl3TQ= =fcLc -----END PGP SIGNATURE-----
Jun 18 2007
Thomas Kuehne wrote:-----BEGIN PGP SIGNED MESSAGE----- -----BEGIN PGP SIGNATURE----- -----END PGP SIGNATURE-----
<snip lots of amazing D future info> I hope I'm not the only one who's looking at this in amazement. Have I grossly skipped something fundamentally obvious in this NG, or is it that some info about future improvements are distributed through channels other than this NG?
Jun 18 2007
Georg Wrede wrote:Thomas Kuehne wrote:-----BEGIN PGP SIGNED MESSAGE----- -----BEGIN PGP SIGNATURE----- -----END PGP SIGNATURE-----
<snip lots of amazing D future info> I hope I'm not the only one who's looking at this in amazement. Have I grossly skipped something fundamentally obvious in this NG, or is it that some info about future improvements are distributed through channels other than this NG?
Aside from this NG there is the digitalmars.D.announce NG. Did you miss the announcement of D2.0 over there? Nothing mysterious here. I think Thomas just got busy figuring out how D2.0 works the minute Walter uploaded it. --bb
Jun 18 2007
Bill Baxter wrote:Georg Wrede wrote:Thomas Kuehne wrote:-----BEGIN PGP SIGNED MESSAGE----- -----BEGIN PGP SIGNATURE----- -----END PGP SIGNATURE-----
<snip lots of amazing D future info> I hope I'm not the only one who's looking at this in amazement. Have I grossly skipped something fundamentally obvious in this NG, or is it that some info about future improvements are distributed through channels other than this NG?
Aside from this NG there is the digitalmars.D.announce NG. Did you miss the announcement of D2.0 over there? Nothing mysterious here. I think Thomas just got busy figuring out how D2.0 works the minute Walter uploaded it.
Heh, after two days of nothing new in D.announce, i blink, and pow! it's full of breathtaking news. Sigh. PS, Congrats to Walter!
Jun 18 2007
Thomas Kuehne wrote:6) C-strings ============ Sometime I have to interface with C libries this "const char*" is required: # static if(1 < dmd_version){ # mixin("alias const(char)* stringz;"); # }else{ # alias char* stringz; # } The mixin in required because the content has to be syntactically correct and "const(char)" isn't a valid DMD-1 construct.
Is there any reason not to use 'in' instead? stringz looks a bit alien in C prototypes. Phobos does just that, so I suppose it's okay: char* strcpy(char* s1, in char* s2);
Jul 01 2007









Lutger <lutger.blijdestijn gmail.com> 