Thread overview
[Issue 7417] New: One-definition rule for version specification - allow version expressions
Feb 01, 2012
Don
Jan 30, 2013
Martin Nowak
Jan 30, 2013
Martin Nowak
Jan 30, 2013
Martin Nowak
Jan 30, 2013
Martin Nowak
Jan 30, 2013
Martin Nowak
February 01, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=7417

           Summary: One-definition rule for version specification - allow
                    version expressions
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: clugdbug@yahoo.com.au


--- Comment #0 from Don <clugdbug@yahoo.com.au> 2012-02-01 03:51:32 PST ---
This enhancement adds a new syntax for version specifications, which would allow us to eliminate the bird's nest of version statements that occurs when code has a complicated version dependency.

The new syntax makes version specifications look like boolean variable declarations:

version identifier = expression;

It would become illegal to reference a version identifier which hasn't been declared. The spec already says that version declarations may only occur at module scope; this new form of version specification would additionally be disallowed inside version blocks (this enforces the one-definition rule).

version identifier = extern;
means that the identifier is externally specified (either on the command line,
or as a compiler built-in).

version VersionIdentifier = VersionExpression;

extern version VersionIdentifier;
// means this version is set from command line, or is a compiler built-in

VersionExpression:
     VersionExpression && VersionExpression
     VersionExpression || VersionExpression
    !VersionExpression
    ( VersionExpression )
        VersionIdentifier
        true
        false
        extern

version(A)
{
   version = AorNotB;
}
version(B)
{
}
else {
   version = AorNotB;
}

becomes:
version AorNotB = A || !B;

----
Note that this is backwards-compatible, it doesn't collide with the existing syntax. To get the full benefit from it, though, we would need to eventually disallow existing version specifications from being inside version blocks. version = XXX; outside of a version block would be the same as version XXX = true; so most code would continue to work.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 30, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7417


Martin Nowak <code@dawg.eu> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |code@dawg.eu


--- Comment #1 from Martin Nowak <code@dawg.eu> 2013-01-30 06:18:10 PST ---
Now we've accidentally led the necessary discussion in a pull request. https://github.com/D-Programming-Language/d-programming-language.org/pull/243

Maybe we should archive this here.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 30, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7417



--- Comment #2 from Martin Nowak <code@dawg.eu> 2013-01-30 07:41:11 PST ---
> WalterBright

>A far more robust and organized approach is to figure out just what you're trying to abstract away in these version blocks, and then abstract it away as a struct, class, function, or import. Then,

>version (B)
>feature() { return foo(); }
>else version (C)
>feature() { return foo(); }
>else version (D)
>feature() { return creature(); }
>else
>static assert(0, "version not supported");

>This is clear, simple, organized, and forces the programmer adding E to check each one of those, instead of assuming they will work.

>I know that D users will continue to try and write C style version blocks, but I will continue to try and show a better way. I also am painfully aware that druntime/phobos have turned to C style versioning, despite my exhortations. It should be fixed, not embraced.

Please do. It's an important design principle, deserves a proper name and
getting popularized.
It takes some getting used to it because it apparently contradicts other design
principles.
But we DO use it in druntime/phobos all over the place.
I hope you can write an article or give a talk about this at some point.

I do not agree though that it's the right approach for all problems. Take ELFOBJ in DMD as an example.
>#define ELFOBJ (TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS)
If what you want to specialize is ELF code you need exactly this abstraction.
It solves the maintenance issue of having to restate it over and over again,
therefor I mentioned DRY.
Adding a new ELF target could use a compilation/fix/test-cycle approach and
testing has become the method of choice for most projects.

>The recent attempt to replace in the DMD source code a bunch of the operating system predefines with POSIX was a failure, and the reason for the failure was a fine example of why the C approach is inferior and why it isn't supported in D.

I didn't follow that but as you said before it would have been naive to think everything would just work. For POSIX to work you need two sides, a fully compliant implementation and POSIX correct client code. This is doomed to fail but it doesn't make POSIX a bad abstraction layer.

The problem is that forcing people to use something they feel is a bad match to
their problem won't make this popular.
This is the reason why "final switch" is a winner, it optionally allows people
to improve their code correctness but it doesn't get in the way.
It would be more fruitful to warn/error about a missing default case in an
if-else ladder.
If you thoroughly read through Dons proposal you see that he enforces to
declare all used version identifiers before usage. This would open a door for
better compile time checks. Maybe we could even check that no value combination
of the induced extern version identifiers would lead to taking a branch of an
if-else ladder.
This would be something I'd call a worthy D implementation.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 30, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7417



--- Comment #3 from Martin Nowak <code@dawg.eu> 2013-01-30 08:00:22 PST ---
And from a personal experience of a vibe.d app for mips-openwrt.
Having to solve all problems at once was the reason I spend 2 weeks
trying to implement what I wanted in one of the already supported languages.
I then spend 1.5 days on my vibe app and more than 1 week on understanding
glibc's and ulibc's header structure and compiling/fixing/debugging druntime
MIPS. Being faced with tons of compilation issues in a complex OpenWRT/GCC/GDC
build chain is not funny. In the end most of the issues were a missing "static
if(0, "Unsupported platform")" in the default branch of a "static if" or
"version" ladder, easy to fix but unnecessary. Some other issues were outright
bugs like a stat64 redeclaration in phobos's std.file, I think that got fixed
in the meanwhile.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 30, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7417



--- Comment #4 from Martin Nowak <code@dawg.eu> 2013-01-30 09:33:31 PST ---
Scratch the version combination idea it's too complex and doesn't yield the
wanted result.
What might work out really well is to detect version-static-if-else ladders as
constructs and warn if no branch was taken.
This depends on the current set of defined version identifiers and static if
conditions and would have been an actual game changer for porting.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
January 30, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=7417



--- Comment #5 from Martin Nowak <code@dawg.eu> 2013-01-30 09:39:24 PST ---
IMHO we should support version imports. When an extern identifier is not specified we could perform an import search and pickup public version declarations. Hijacking protection included of course.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------