Re: version(StdDoc)

2018-11-26 Thread H. S. Teoh via Digitalmars-d-learn
On Sun, Nov 25, 2018 at 09:53:50PM +, Stanislav Blinov via 
Digitalmars-d-learn wrote:
> On Sunday, 25 November 2018 at 21:38:43 UTC, H. S. Teoh wrote:
> 
> > Actually, I just thought of a way to do this with the existing language:
> > use a struct to simulate an enum:
> > 
> > struct E {
> > alias Basetype = int;
> > Basetype impl;
> > alias impl this;
> > 
> > enum a = E(1);
> > enum b = E(2);
> > version(Windows) {
> > enum c = E(3);
> > }
> > version(Posix) {
> > enum c = E(4);
> > enum d = E(100);
> > }
> > }
> 
> Heh, that can work in a pinch. Disgusting though :D

I dunno, given that D structs are supposed to be "glorified ints"
according to TDPL, I see enum declarations more-or-less as a shorthand
for structs of the above sort. :-D  Much like template functions / enums
/ etc. are shorthands for eponymous templates.


> > It's not 100% the same thing, but gets pretty close, e.g., you can
> > reference enum values as E.a, E.b, you can declare variables of type
> > E and pass it to functions and it implicitly converts to the base
> > type, etc..
> > 
> > There are some differences, like cast(E) won't work like an enum...
> 
> It should, you can cast values of same sizeof to a struct.
[...]

Haha, didn't know that.


T

-- 
Dogs have owners ... cats have staff. -- Krista Casada


Re: version(StdDoc)

2018-11-25 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 25 November 2018 at 21:38:43 UTC, H. S. Teoh wrote:

Actually, I just thought of a way to do this with the existing 
language: use a struct to simulate an enum:


struct E {
alias Basetype = int;
Basetype impl;
alias impl this;

enum a = E(1);
enum b = E(2);
version(Windows) {
enum c = E(3);
}
version(Posix) {
enum c = E(4);
enum d = E(100);
}
}


Heh, that can work in a pinch. Disgusting though :D

It's not 100% the same thing, but gets pretty close, e.g., you 
can reference enum values as E.a, E.b, you can declare 
variables of type E and pass it to functions and it implicitly 
converts to the base type, etc..


There are some differences, like cast(E) won't work like an 
enum...


It should, you can cast values of same sizeof to a struct.

and .max has to be manually declared, etc.. You'll also need to 
explicitly assign values to each member, but for OS-dependent 
enums you have to do that already anyway.


Yeah, those aren't a huge concern for that particular scenario.


Re: version(StdDoc)

2018-11-25 Thread H. S. Teoh via Digitalmars-d-learn
On Sun, Nov 25, 2018 at 07:22:54AM +, Stanislav Blinov via 
Digitalmars-d-learn wrote:
> On Sunday, 25 November 2018 at 07:19:50 UTC, Stanislav Blinov wrote:
> 
> > Granted, it may require some special syntax, i.e.
> > 
> > enum E {
> > a,
> > b if version(Windows),
> > c if version(Windows),
> > d if version(Posix),
> > }
> > 
> > or something to that effect.
> 
> Come to think of it, since UDAs are now allowed, the compiler could
> potentially be taught this:
> 
> enum E {
> a,
> @version(Windows) b,
> @version(Windows) c,
> @version(Posix)   d,
> }

Actually, I just thought of a way to do this with the existing language:
use a struct to simulate an enum:

struct E {
alias Basetype = int;
Basetype impl;
alias impl this;

enum a = E(1);
enum b = E(2);
version(Windows) {
enum c = E(3);
}
version(Posix) {
enum c = E(4);
enum d = E(100);
}
}

It's not 100% the same thing, but gets pretty close, e.g., you can
reference enum values as E.a, E.b, you can declare variables of type E
and pass it to functions and it implicitly converts to the base type,
etc..

There are some differences, like cast(E) won't work like an enum, and
.max has to be manually declared, etc.. You'll also need to explicitly
assign values to each member, but for OS-dependent enums you have to do
that already anyway.


T

-- 
Let's eat some disquits while we format the biskettes.


Re: version(StdDoc)

2018-11-25 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, November 24, 2018 10:41:56 PM MST H. S. Teoh via Digitalmars-d-
learn wrote:
> On Sat, Nov 24, 2018 at 05:48:16PM +, Stanislav Blinov via 
Digitalmars-d-learn wrote:
> > On Saturday, 24 November 2018 at 17:43:35 UTC, Jonathan M Davis wrote:
> > > I'm still inclined to think though that it should be legal to just
> > > use version directly in the member list.
> >
> > Yup. UDAs did get in there eventually, and version should too.
>
> I think this would be a trivial DIP, by making it such that a version
> block inside an enum would lower to the above code. Of course, it could
> be taken further: the above trick doesn't quite handle this case:
>
>   enum E {
>   a,
>   version(Windows) {
>   b, c
>   }
>   version(Posix) {
>   d
>   }
>   }
>
> But this looks like such an antipattern that it probably should be
> written differently anyway, or just generated via a string mixin.

It's something that comes up fairly frequently actually when dealing with
system APIs. For instance, if you want your socket API to provide the full
functionality of the underlying C API, then you're going to have to provide
not only differing enum values for things like socket options or socket
family, but you're actually going to have to provide different enum members
in some cases.

So, sure, if you're writing something that's purely D and can be properly
platform-agnostic, then having different enum members for different
platforms would be bad, but once C APIs get involved, I definitely would not
consider it to be an anti-pattern. At that point, it has a tendency to
become a necessity, and I've had several occasions where being able to
version enum members would have made the code shorter. It also would have
eliminated the need for version(D_Ddoc) (or the druntime or Phobos
equivalents).

- Jonathan M Davis





Re: version(StdDoc)

2018-11-24 Thread Stanislav Blinov via Digitalmars-d-learn
On Sunday, 25 November 2018 at 07:19:50 UTC, Stanislav Blinov 
wrote:



Granted, it may require some special syntax, i.e.

enum E {
a,
b if version(Windows),
c if version(Windows),
d if version(Posix),
}

or something to that effect.


Come to think of it, since UDAs are now allowed, the compiler 
could potentially be taught this:


enum E {
a,
@version(Windows) b,
@version(Windows) c,
@version(Posix)   d,
}


Re: version(StdDoc)

2018-11-24 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 25 November 2018 at 05:41:56 UTC, H. S. Teoh wrote:
On Sat, Nov 24, 2018 at 05:48:16PM +, Stanislav Blinov via 
Digitalmars-d-learn wrote:



Yup. UDAs did get in there eventually, and version should too.


I think this would be a trivial DIP, by making it such that a 
version block inside an enum would lower to the above code. Of 
course, it could be taken further: the above trick doesn't 
quite handle this case:


enum E {
a,
version(Windows) {
b, c
}
version(Posix) {
d
}
}


That is what Jonathan (and I concur) is talking about.

But this looks like such an antipattern that it probably should 
be written differently anyway, or just generated via a string 
mixin.


Why is it an antipattern? Having to version the whole enum just 
because some stupid C API has two out of a hundred items 
versioned per platform is an antipattern :)


Granted, it may require some special syntax, i.e.

enum E {
a,
b if version(Windows),
c if version(Windows),
d if version(Posix),
}

or something to that effect. But there has to be a better way 
than just versioning the whole enum or resorting to clumsy mixins.


Re: version(StdDoc)

2018-11-24 Thread H. S. Teoh via Digitalmars-d-learn
On Sat, Nov 24, 2018 at 05:48:16PM +, Stanislav Blinov via 
Digitalmars-d-learn wrote:
> On Saturday, 24 November 2018 at 17:43:35 UTC, Jonathan M Davis wrote:
> > On Saturday, November 24, 2018 9:28:47 AM MST Stanislav Blinov via
> > Digitalmars-d-learn wrote:
[...]
> > > enum Foo
> > > {
> > >  a,
> > >  b,
> > >  c = {
> > > version(linux) return 42;
> > > else version(Windows) return 54;
> > >  } ()
> > > }
> > > 
> > > /pedantry
> > 
> > LOL. That's an interesting trick. It's ugly and hacky, but it does
> > work around the problem.
> 
> :)

That's an awesome trick! Genius.


> > I'm still inclined to think though that it should be legal to just
> > use version directly in the member list.
> 
> Yup. UDAs did get in there eventually, and version should too.

I think this would be a trivial DIP, by making it such that a version
block inside an enum would lower to the above code. Of course, it could
be taken further: the above trick doesn't quite handle this case:

enum E {
a,
version(Windows) {
b, c
}
version(Posix) {
d
}
}

But this looks like such an antipattern that it probably should be
written differently anyway, or just generated via a string mixin.


T

-- 
Knowledge is that area of ignorance that we arrange and classify. -- Ambrose 
Bierce


Re: version(StdDoc)

2018-11-24 Thread H. S. Teoh via Digitalmars-d-learn
On Sat, Nov 24, 2018 at 10:27:07PM +, Adam D. Ruppe via Digitalmars-d-learn 
wrote:
[...]
> (Though a parsing thing: /// version(linux) void foo(); - is that doc
> on version linux or on void foo or on both? I guess it could only
> apply it in if there are {}... but eh I still don't love it.)

Yeah that's a tricky case.


[...]
> > It's a bad thing to separate the docs from the actual code, because
> > then the two are liable to go out-of-sync with each other.
> 
> that depends on what kind of docs. for api reference, sure, but other
> docs prolly should be separate because they are bigger picture, and
> thus don't naturally fit well in with the code.

That's what module docs are for. Or docs on aggregates as opposed to
docs on individual members.


> But of course, version(D_Ddoc) is the worst of both worlds.

Agreed.


T

-- 
Customer support: the art of getting your clients to pay for your own 
incompetence.


Re: version(StdDoc)

2018-11-24 Thread Adam D. Ruppe via Digitalmars-d-learn

On Saturday, 24 November 2018 at 16:16:08 UTC, H. S. Teoh wrote:
Actually, what would be ideal is if each platform-specific 
version of the symbol can have its own associated 
platform-specific docs, in addition to the one common across 
all platforms, and the doc system would automatically compile 
these docs into a single block in the output, possibly by 
introducing platform specific sections, e.g.:


Well, I probably could do that, but I'm not so sure it would make 
since since it separates stuff quite a bit and may have weird 
cases. Like what if the arguments are different? Should it merge 
the params sections? (That is doable btw)


But also from the user side, when they are looking for 
differences, it is a pain if most the stuff is shared and there 
is just a different sentence at the bottom or something. I'd 
prolly insist that it be called out. Of course, the doc gen could 
automatically merge the docs with headers too... but that brings 
us to something we already have:


I just use...

/++
Does whatever.

Note on Windows it does something a bit different.
+/
version(linux)
void foo();

/// ditto
version(Windows)
void foo();


So the ditto covers the case and tells the doc gen they share the 
same stuff, and the header is written however we want in the 
comment.


I don't *hate* having shared docs on version blocks, I am just 
being lazy and avoiding implementation by pushing back :P



(Though a parsing thing: /// version(linux) void foo(); - is that 
doc on version linux or on void foo or on both? I guess it could 
only apply it in if there are {}... but eh I still don't love it.)




It's a bad thing to separate the docs from the actual code, 
because then the two are liable to go out-of-sync with each 
other.


that depends on what kind of docs. for api reference, sure, but 
other docs prolly should be separate because they are bigger 
picture, and thus don't naturally fit well in with the code.



But of course, version(D_Ddoc) is the worst of both worlds.


Re: version(StdDoc)

2018-11-24 Thread Stanislav Blinov via Digitalmars-d-learn
On Saturday, 24 November 2018 at 17:43:35 UTC, Jonathan M Davis 
wrote:
On Saturday, November 24, 2018 9:28:47 AM MST Stanislav Blinov 
via Digitalmars-d-learn wrote:

On Saturday, 24 November 2018 at 07:00:31 UTC, Jonathan M Davis

wrote:
> [not legal]
>
> enum Foo
> {
>
> a,
> b,
> version(linux) c = 42,
> else version(Windows) c = 54,
>
> }
>
> You're forced to version the entire enum.

Not in this case, no:

enum Foo
{
 a,
 b,
 c = {
version(linux) return 42;
else version(Windows) return 54;
 } ()
}

/pedantry


LOL. That's an interesting trick. It's ugly and hacky, but it 
does work around the problem.


:)

I'm still inclined to think though that it should be legal to 
just use version directly in the member list.


Yup. UDAs did get in there eventually, and version should too.


Re: version(StdDoc)

2018-11-24 Thread Jonathan M Davis via Digitalmars-d-learn
On Saturday, November 24, 2018 9:28:47 AM MST Stanislav Blinov via 
Digitalmars-d-learn wrote:
> On Saturday, 24 November 2018 at 07:00:31 UTC, Jonathan M Davis
>
> wrote:
> > [not legal]
> >
> > enum Foo
> > {
> >
> > a,
> > b,
> > version(linux) c = 42,
> > else version(Windows) c = 54,
> >
> > }
> >
> > You're forced to version the entire enum.
>
> Not in this case, no:
>
> enum Foo
> {
>  a,
>  b,
>  c = {
> version(linux) return 42;
> else version(Windows) return 54;
>  } ()
> }
>
> /pedantry

LOL. That's an interesting trick. It's ugly and hacky, but it does work
around the problem. I'm still inclined to think though that it should be
legal to just use version directly in the member list.

- Jonathan M Davis





Re: version(StdDoc)

2018-11-24 Thread Stanislav Blinov via Digitalmars-d-learn
On Saturday, 24 November 2018 at 07:00:31 UTC, Jonathan M Davis 
wrote:



[not legal]

enum Foo
{
a,
b,
version(linux) c = 42,
else version(Windows) c = 54,
}

You're forced to version the entire enum.


Not in this case, no:

enum Foo
{
a,
b,
c = {
   version(linux) return 42;
   else version(Windows) return 54;
} ()
}

/pedantry


Re: version(StdDoc)

2018-11-24 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Nov 23, 2018 at 09:43:01PM -0700, Jonathan M Davis via 
Digitalmars-d-learn wrote:
[...]
> Honestly, I would argue that if you have multiple versions of the
> documentation, then there's a serious problem. The documentation
> shouldn't be platform-dependent even if the symbols are. Even if the
> documentation needs some extra notes for a specific platform, it
> should all be in one documentation block that anyone using the symbol
> can read. Providing different documentation for different platforms
> just leads to folks not understanding how the symbol differs across
> platforms, leading to code that is even more platform-dependent when
> it really should be as platform independent as possible.

Actually, what would be ideal is if each platform-specific version of
the symbol can have its own associated platform-specific docs, in
addition to the one common across all platforms, and the doc system
would automatically compile these docs into a single block in the
output, possibly by introducing platform specific sections, e.g.:

Code:
/**
 * Does something really fun that applied across platforms!
 */
version(Windows)
{
/**
 * On Windows, this function displays a really funny
 * icon!
 */
int fun(int a) { ... }
}
version(Linux)
{
/**
 * On Linux, this function displays a funny penguin!
 */
int fun(int a) { ... }
}

Doc output:
int fun(int a)

Does something really fun that applied across platforms!

Windows notes: On Windows, this function displays a really funny
icon!

Linux notes: On Linux, this function displays a funny penguin!


If the function signatures are different, then it should be displayed as
"overloads", as Adam suggested. Maybe something like this:

Code:
/**
 * This function takes a different parameter depending on the
 * OS.
 */
version(Windows)
int fun(int x) { ... }
version(Linux)
int fun(long x) { ... }

Output:
int fun(int x)  // on Windows
int fun(long x) // on Linux

This function takes a different parameter depending on the OS.


[...]
> As such, I'm not sure that the fact that ddoc forces you to have a
> separate set of declarations just for the documentation is really a
> bad thing. It puts all of the documentation in one place.

It's a bad thing to separate the docs from the actual code, because then
the two are liable to go out-of-sync with each other. It's even worse
when the docs document a fake declaration that isn't actually part of
the real code. Then the docs won't even show the right declaration when
the code changes, and users won't even realize what has happened.


> The bigger problem IMHO is how -D affects the build. Both it and
> -unittest have the fundamental problem that because they create their
> own version identifiers, they really shouldn't be part of the normal
> build, and yet the way that they're set up to be used, it's as if
> they're expected to be part of the normal build - with -D just causing
> the compiler to generate the documentation in addition to the binary,
> and -unittest making the unit tests run before main rather than
> replacing main.
[...]

You can argue for it both ways.  Having the compiler generate docs per
compilation isn't necessarily a bad thing -- it ensures the docs are
up-to-date.  Running unittests also isn't necessarily a bad thing,
though I agree it's sorta weird that unittests are setup to run before
the main program. Technically, you want to run unittests first,
independently of main(), which should be put in a separate executable.
But you can argue for it both ways.

For larger projects, it does make more sense for unittests to be put in
a separate executable and run separately.  But for small programs,
especially when you're coding-compiling-testing, it's handy to have
unittests automatically run before main(), so that any regressions are
quickly noticed and fixed.  This doesn't make sense for larger programs,
e.g., in my Android project, I really want unittests to run on the host
system where possible, not as part of the APK installed to the device,
because it's much easier to debug on the host system than to deal with
crashlogs and remote debugging on the target machine.

(Of course, deploying unittests to the final execution environment also
has its value. But not as part of the main executable, since tests
should be run only once, not every time you invoke the executable, which
depending on your application could be multiple times during a typical
usage session.)


> As for the issue of versioning the documentation, I don't really see a
> clean one. Having the documentation build affected by version and
> static if and the like causes some 

Re: version(StdDoc)

2018-11-23 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, November 23, 2018 11:22:24 PM MST Neia Neutuladh via Digitalmars-
d-learn wrote:
> On Fri, 23 Nov 2018 21:43:01 -0700, Jonathan M Davis wrote:
> > A solution like that might work reasonably well, but you still
> > have the problem of what to do when a symbol is documented in multiple
> > version blocks, and having almost all the documentation in one version
> > block and a few pieces of it in other version blocks would risk getting
> > confusing and messy.
>
> Keeping symbol names and function arguments consistent between them is
> also an issue; it's not just the documentation. The normal solution is to
> put the version blocks inside the relevant symbols -- sometimes type
> aliases inside version blocks and consistent code outside, sometimes
> functions where the entire body is a set of version blocks.

When you're versioning the implementation, it's trivial to just version the
function internals. Where version(D_Ddoc) becomes critical is with stuff
like structs or enums where the members actually differ across systems. And
while it's generally better to try to avoid such situations, there are
definitely situations where there isn't much choice. Fortunately, in the
vast majority of situations, versioning across systems isn't required at
all, and in most of the situations where it is, its only the implementation
that needs to differ, but that's not true in all cases.

I do wish though that it were legal to use version blocks in more situations
than is currently the case. For instance,

enum Foo
{
a,
b,
version(linux) l,
else version(Windows) w,
}

is not legal, nor is

enum Foo
{
a,
b,
version(linux) c = 42,
else version(Windows) c = 54,
}

You're forced to version the entire enum. Fortunately, structs and classes,
do not have that restriction, so having to version an entire struct or class
at once is usually only required when the type needs to be declared on some
systems but not others (as is the case with WindowsTimeZone), and such
situations are rare.

- Jonathan M Davis





Re: version(StdDoc)

2018-11-23 Thread Neia Neutuladh via Digitalmars-d-learn
On Fri, 23 Nov 2018 21:43:01 -0700, Jonathan M Davis wrote:
> A solution like that might work reasonably well, but you still
> have the problem of what to do when a symbol is documented in multiple
> version blocks, and having almost all the documentation in one version
> block and a few pieces of it in other version blocks would risk getting
> confusing and messy.

Keeping symbol names and function arguments consistent between them is 
also an issue; it's not just the documentation. The normal solution is to 
put the version blocks inside the relevant symbols -- sometimes type 
aliases inside version blocks and consistent code outside, sometimes 
functions where the entire body is a set of version blocks.


Re: version(StdDoc)

2018-11-23 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, November 23, 2018 7:55:04 PM MST H. S. Teoh via Digitalmars-d-
learn wrote:
> Adam does have a very good point about showing all alternatives to docs,
> though.  Arguably, that's what ddoc *should* do.  If the programmer
> wrote a ddoc comment in the code, it probably should be processed as
> part of doc generation, regardless of whether that code sits in some
> deeply-nested version blocks that ends up not being compiled.  Binding
> ddoc generation to the compile process seems not such a good idea in
> retrospect.

Honestly, I would argue that if you have multiple versions of the
documentation, then there's a serious problem. The documentation shouldn't
be platform-dependent even if the symbols are. Even if the documentation
needs some extra notes for a specific platform, it should all be in one
documentation block that anyone using the symbol can read. Providing
different documentation for different platforms just leads to folks not
understanding how the symbol differs across platforms, leading to code that
is even more platform-dependent when it really should be as platform
independent as possible.

The only situation I can think of at the moment where anything along the
lines of combining documentation across platforms makes sense would be if
there is a nested symbol that exists on only one platform (e.g. a member
function of a struct or a member of an enum). In that case, one platform
would have the main documentation, and then system-specific symbols would be
documented in those version blocks - but only those symbols. A solution like
that might work reasonably well, but you still have the problem of what to
do when a symbol is documented in multiple version blocks, and having almost
all the documentation in one version block and a few pieces of it in other
version blocks would risk getting confusing and messy. As such, I'm not sure
that the fact that ddoc forces you to have a separate set of declarations
just for the documentation is really a bad thing. It puts all of the
documentation in one place.

The bigger problem IMHO is how -D affects the build. Both it and -unittest
have the fundamental problem that because they create their own version
identifiers, they really shouldn't be part of the normal build, and yet the
way that they're set up to be used, it's as if they're expected to be part
of the normal build - with -D just causing the compiler to generate the
documentation in addition to the binary, and -unittest making the unit tests
run before main rather than replacing main.

At this point, I really wish that at minimum, -D were not set up to be part
of the normal build process so that version(D_Ddoc) would not affect it. The
same with -unittest. Ideally, it really would have replaced main rather than
putting the unit tests before it, with it providing main if one wasn't
there. That still doesn't solve all of the problems when using
version(unittest), but I doubt that much of anyone really wants to be
running unit tests as part of their application, and having such flags
clearly designed to create special builds rather than being designed such
that they could be used with the normal build would have fixed certain
classes of problems.

As for the issue of versioning the documentation, I don't really see a clean
one. Having the documentation build affected by version and static if and
the like causes some problems, but having it ignore them would likely cause
other problems. Regardless, I suspect that having the version identifiers
and static ifs be ignored almost requires a separate tool from the compiler
(such as Adam's documentation generator or ddox), because it's pretty clear
that ddoc was set up to generate the documentation for symbols as the
compiler compiles them, whereas a tool that ignored version identifiers and
static ifs would be processing the file quite differently.

- Jonathan M Davis





Re: version(StdDoc)

2018-11-23 Thread Jonathan M Davis via Digitalmars-d-learn
On Friday, November 23, 2018 2:47:51 PM MST Tony via Digitalmars-d-learn 
wrote:
> In std.compiler there is this code:
>
>  /// Which vendor produced this compiler.
>  version(StdDdoc)  Vendor vendor;
>  else version(DigitalMars) Vendor vendor = Vendor.digitalMars;
>  else version(GNU) Vendor vendor = Vendor.gnu;
>  else version(LDC) Vendor vendor = Vendor.llvm;
>  else version(D_NET)   Vendor vendor = Vendor.dotNET;
>  else version(SDC) Vendor vendor = Vendor.sdc;
>  else  Vendor vendor = Vendor.unknown;
>
> What is the situation in which the identifier StdDoc is set?

It's a Phobos-only replacement for the D_Ddoc version identifier and is
defined as part of the Phobos build. As the others have been complaining
about in this thread, ddoc is set up so that it takes whatever version is
currently being compiled. So, version(D_Ddoc) is the standard way to provide
documentation that is agnostic of the platform in the cases where a
documented symbol doesn't exist on all platforms, or its definition differs
such that it needs separate declarations - e.g. if the values of members in
an enum differ across systems, then you're forced to provide completely
separate enum declarations for the entire enum. If you have separate
declarations on different platforms, then in general there are only three
choices

1. Duplicate the documentation.

2. Set it up so that your documentation can only be built on one platform.

3. Use version(D_Ddoc) to provide a separate declaration just for the
documentation.

There are some cases where you can put the documentation outside the version
block and have it work - e.g.

/// my documentation
version(linux) int foo(string bar) { ... }
else version(Windows) int foo(string bar) { ... }
else ...

but that only works when you only need to document the top-level symbol
(such as with a function). It does not work with anything that needs to have
symbols inside it documented (such as with a struct, class, or enum).

Fortunately, most code does need to be versioned like this (especially if
you're trying to write platform-independent code like we try to do with
Phobos), and often, when you do need to version stuff, it's inside
implementations, but sometimes it does affect the top level. std.file has
this problem in a few places as does std.datetime with WindowsTimeZone
(since it only exists on Windows). The solution the language provides is to
use version(D_Ddoc) to version such documentation. And that's what Phobos
used to do.

The problem is that once you start using version(D_Ddoc), you _must_ have a
separate documentation build. You can't build your documentation as part of
your normal build, because you'd be getting the version(D_Ddoc) stubs
instead of the correct implementation for your platform (or instead of
nothing at all if that platform isn't supposed to have that particular
symbol). Phobos already had a separate documentation build because of how it
generates the documentation for the website, but many people's projects do
not. Most projects don't ever need to use version(D_Ddoc), because they
don't have symbols that are platform-dependent, and so before Phobos started
using it, they could compile their documentation as part of their normal
build just fine, because version(D_Ddoc) wasn't in their code anywhere. But
as soon as Phobos started using it, their code broke. If they had had a
separate documentation build, then they wouldn't have had any problems, but
as it was, their code was broken.

So, for better or worse, rather than saying that it was just bad practice to
do the documentation build as part of your normal build (and I would
strongly argue that building the documentation as part of the normal build
is bad practice given how doing so defines a new version identifier that can
affect the build), it was decided that Phobos would stop using
version(D_Ddoc) as the language intended and instead use its own custom,
version identifier for the documentation - which is why we now have
version(StdDoc) in Phobos and version(CoreDdoc) in druntime. With this
change, anyone building with the -D flag as part of their normal build
doesn't end up with version(D_Ddoc) screwing up their code because of
druntime or Phobos. Some other project they depend on could screw it up, and
if they ever use version(D_Ddoc) in their code, they'll have trouble again,
but Phobos and druntime aren't going to mess them up in that regard.

And while version(D_Ddoc) is the standard solution, because of this general
problem with folks using -D with their normal build, it's arguably best
practice at this point to create your own version identifier for your own
documentation for any library that you release that needs to version its
documentation. Otherwise, anyone using your library will have the same
problems that resulted in Phobos switching from version(D_Ddoc) to
version(StdDdoc) -

Re: version(StdDoc)

2018-11-23 Thread Adam D. Ruppe via Digitalmars-d-learn

On Saturday, 24 November 2018 at 02:55:04 UTC, H. S. Teoh wrote:
But then that would be reinventing what Adam has already done, 
right? :-D


Precisely, I already do all that. And people are even actually 
using it!


Re: version(StdDoc)

2018-11-23 Thread H. S. Teoh via Digitalmars-d-learn
On Sat, Nov 24, 2018 at 02:09:22AM +, Neia Neutuladh via 
Digitalmars-d-learn wrote:
> On Fri, 23 Nov 2018 17:21:25 -0800, H. S. Teoh wrote:
> > Ddoc may have its stink points, but in this case, the stuff inside
> > version(Windows) blocks simply isn't compiled, so you can't expect
> > ddoc to do much about it.  You can't just arbitrarily ddoc
> > everything inside version blocks, because then you'll end up with
> > ddocs for stuff inside version(none) and/or conflicting docs for
> > alternative declarations in, say, OS-specific version blocks, or
> > user-defined static if's.
> 
> That means that, instead of one site showing my project's
> documentation, I need a separate site for every combination of
> platform and version flags.  And users who care about differences
> between platforms and version flags need to manually cross-reference
> docs for every symbol and overload.
> 
> It's a pretty terrible status quo.

True.  I've tried to tackle this before, but conceded defeat after I
realized that dmd just can't handle it because of the way ddoc is
implemented.

Adam does have a very good point about showing all alternatives to docs,
though.  Arguably, that's what ddoc *should* do.  If the programmer
wrote a ddoc comment in the code, it probably should be processed as
part of doc generation, regardless of whether that code sits in some
deeply-nested version blocks that ends up not being compiled.  Binding
ddoc generation to the compile process seems not such a good idea in
retrospect.

Now that I think about this more carefully, I feel tempted to say that
we should write a standalone ddoc generator, or at least a standalone
module in dmd, that process *all* source code regardless of version
blocks and static ifs and what-not. The output should be properly tagged
(e.g., the path of version identifiers / static if conditions that lead
to a particular version of the doc) so that the formatting backend can
render it sensibly, e.g., as a HTML drop-down list of versions, or
whatever.

But then that would be reinventing what Adam has already done, right?
:-D


T

-- 
If I were two-faced, would I be wearing this one? -- Abraham Lincoln


Re: version(StdDoc)

2018-11-23 Thread Neia Neutuladh via Digitalmars-d-learn
On Fri, 23 Nov 2018 17:21:25 -0800, H. S. Teoh wrote:
> Ddoc may have its stink points, but in this case, the stuff inside
> version(Windows) blocks simply isn't compiled, so you can't expect ddoc
> to do much about it.  You can't just arbitrarily ddoc everything inside
> version blocks, because then you'll end up with ddocs for stuff inside
> version(none) and/or conflicting docs for alternative declarations in,
> say, OS-specific version blocks, or user-defined static if's.

That means that, instead of one site showing my project's documentation, I 
need a separate site for every combination of platform and version flags. 
And users who care about differences between platforms and version flags 
need to manually cross-reference docs for every symbol and overload.

It's a pretty terrible status quo.


Re: version(StdDoc)

2018-11-23 Thread Adam D. Ruppe via Digitalmars-d-learn

On Saturday, 24 November 2018 at 01:21:25 UTC, H. S. Teoh wrote:
Ddoc may have its stink points, but in this case, the stuff 
inside version(Windows) blocks simply isn't compiled


That is why I call it "poorly designed" and a major reason why I 
dropped it entirely and created my own doc generator from scratch 
(well, using libdparse, so not exactly scratch, but zero use of 
dmd's code).


You can't just arbitrarily ddoc everything inside version 
blocks, because then you'll end up with ddocs for stuff inside 
version(none) and/or conflicting docs for alternative 
declarations in, say, OS-specific version blocks, or 
user-defined static if's.


That is easy to handle, you just treat it like overloads and 
display the version info along with the rest of it if both are 
documented. My doc generator does this and it is very useful - 
you can show what are under special version specifiers, call out 
OS differences, and more.


And if there are conflicting docs, the user ought to be able to 
see that!




Re: version(StdDoc)

2018-11-23 Thread H. S. Teoh via Digitalmars-d-learn
On Sat, Nov 24, 2018 at 12:51:36AM +, Adam D. Ruppe via Digitalmars-d-learn 
wrote:
> On Friday, 23 November 2018 at 23:13:04 UTC, H. S. Teoh wrote:
> > There are a few cases where this is needed, e.g., to generate docs
> > for Windows-specific modules, since the website script is run on
> > Posix and the Windows APIs would not be compiled at all, leading to
> > empty docs.
> 
> Note that that is only because ddoc is a badly designed piece of
> garbage.  Good doc generators can handle that just fine.

Ddoc may have its stink points, but in this case, the stuff inside
version(Windows) blocks simply isn't compiled, so you can't expect ddoc
to do much about it.  You can't just arbitrarily ddoc everything inside
version blocks, because then you'll end up with ddocs for stuff inside
version(none) and/or conflicting docs for alternative declarations in,
say, OS-specific version blocks, or user-defined static if's.

Having said that, though, it would be nice if there was a way to tell
the compiler "please generate docs for Windows, even though you're
currently running on Posix".  Resorting to hacks like that just to
generate Phobos docs simply sux.


T

-- 
Notwithstanding the eloquent discontent that you have just respectfully 
expressed at length against my verbal capabilities, I am afraid that I must 
unfortunately bring it to your attention that I am, in fact, NOT verbose.


Re: version(StdDoc)

2018-11-23 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 23 November 2018 at 23:13:04 UTC, H. S. Teoh wrote:
There are a few cases where this is needed, e.g., to generate 
docs for Windows-specific modules, since the website script is 
run on Posix and the Windows APIs would not be compiled at all, 
leading to empty docs.


Note that that is only because ddoc is a badly designed piece of 
garbage. Good doc generators can handle that just fine.


Re: version(StdDoc)

2018-11-23 Thread H. S. Teoh via Digitalmars-d-learn
On Fri, Nov 23, 2018 at 09:53:59PM +, Adam D. Ruppe via Digitalmars-d-learn 
wrote:
> On Friday, 23 November 2018 at 21:47:51 UTC, Tony wrote:
> > What is the situation in which the identifier StdDoc is set?
> 
> When the phobos website is being compiled, its own makefile sets that.
> 
> It is basically a hack for website display.

Yes, it's a hack to make the website display something different from
what ddoc would actually generate from the real code.

There are a few cases where this is needed, e.g., to generate docs for
Windows-specific modules, since the website script is run on Posix and
the Windows APIs would not be compiled at all, leading to empty docs.


T

-- 
It's amazing how careful choice of punctuation can leave you hanging:


Re: version(StdDoc)

2018-11-23 Thread Adam D. Ruppe via Digitalmars-d-learn

On Friday, 23 November 2018 at 21:47:51 UTC, Tony wrote:

What is the situation in which the identifier StdDoc is set?


When the phobos website is being compiled, its own makefile sets 
that.


It is basically a hack for website display.



version(StdDoc)

2018-11-23 Thread Tony via Digitalmars-d-learn

In std.compiler there is this code:

/// Which vendor produced this compiler.
version(StdDdoc)  Vendor vendor;
else version(DigitalMars) Vendor vendor = Vendor.digitalMars;
else version(GNU) Vendor vendor = Vendor.gnu;
else version(LDC) Vendor vendor = Vendor.llvm;
else version(D_NET)   Vendor vendor = Vendor.dotNET;
else version(SDC) Vendor vendor = Vendor.sdc;
else  Vendor vendor = Vendor.unknown;

What is the situation in which the identifier StdDoc is set?