supporting DMD-1.016 and DMD-2.000 with the same source code

Walter Bright newshound1 at digitalmars.com
Mon Jun 18 11:48:23 PDT 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.



More information about the Digitalmars-d mailing list