digitalmars.D - Why version() ?
- bobef (3/3) Feb 10 2009 I was thinking... what is the point of version() ? It is so inflexible. ...
- Trass3r (3/5) Feb 10 2009 Cause nobody wants to write something ugly like that every time.
- grauzone (30/34) Feb 10 2009 One of my pet peeves.
- Trass3r (6/8) Feb 10 2009 version(linux)
- Don (3/13) Feb 10 2009 A&&B is not so terrible, since you can do it by nesting, as above.
- Derek Parnell (10/12) Feb 10 2009 version(A) version = AorB;
- Don (8/19) Feb 10 2009 Yes. And that sucks, because you've got the version statement in two
- Denis Koroskin (24/42) Feb 10 2009 Version has so many shortcomings that it should definitely be redesigned...
- Daniel Keep (6/24) Feb 10 2009 I think I once tried something where I was building a list of interface
- Ary Borenszweig (2/29) Feb 10 2009 Just syntactically correct.
- bearophile (14/16) Feb 10 2009 I think I don't like that.
- Frits van Bommel (6/8) Feb 10 2009 Unless Apple has plans to s/BSD/Linux/ in MacOS that I'm not aware of,
- grauzone (7/19) Feb 10 2009 Well, my argument is that CTFE already provides all version features and...
- Sergey Gromov (3/23) Feb 15 2009 #if is no different from #ifdef because any undefined identifier
- Nick Sabalausky (6/50) Feb 10 2009 I wholeheartedly agree with this 100%. I'd also have to agree with Denis...
- Lutger (8/12) Feb 10 2009 There is no even version(!...). Why not "static if(version(DMD))" or sta...
- Tim M (29/34) Feb 10 2009 You could try something like this:
- Tim M (47/47) Feb 10 2009 It gets even better with constants and works in static asserts too:
- Chris Nicholson-Sauls (18/62) Feb 10 2009 You beat me to it. I actually use this a little here and there. But
- Don (5/9) Feb 10 2009 version() is MUCH older than static if. It dates from a very early time
- bearophile (4/6) Feb 10 2009 Walter does almost the impossible, sometimes. I'll have to remember this...
- Don (5/13) Feb 10 2009 The traditional way to get an engineer to do something, is to tell him
- John Reimer (5/21) Feb 10 2009 So I assume it must follow that engineers should never be taught computa...
- Walter Bright (3/7) Feb 10 2009 I've suspected that's why breakthroughs are made by the young, as they
- Walter Bright (39/42) Feb 10 2009 The version statement is designed to be inflexible. It's designed to
- Derek Parnell (16/26) Feb 10 2009 I understand and support this view. However, it creates a new problem; c...
- Walter Bright (8/35) Feb 10 2009 I don't think that duplicating a small run of code is a problem. If it's...
- Derek Parnell (15/26) Feb 10 2009 My apology. The problem is more than run-time performance issues. The mo...
- Walter Bright (79/104) Feb 10 2009 Let's take an example, like the enum for O_XXXX in std.c.linux.linux.
- Sean Kelly (9/19) Feb 10 2009 [snip]
- Sean Kelly (3/8) Feb 10 2009 I suggest UltraCompare, if you're a Windows user.
- Nick Sabalausky (4/11) Feb 10 2009 I've been a big fan of Beyond Compare for a long time now. I'll have to ...
- Derek Parnell (171/176) Feb 10 2009 Yes, the duplicated code is a better approach here because the apparent
- Walter Bright (3/6) Feb 10 2009 I agree it's hard to see clearly, and often can only be seen after
- Nick Sabalausky (52/68) Feb 10 2009 {snip}
- Walter Bright (15/46) Feb 10 2009 Yeah, but I guarantee you that there will be some "common to all" ones
- Sergey Gromov (5/51) Feb 15 2009 There's Antenna for Java. It's nearly impossible to do without some
- BCS (5/11) Feb 10 2009 A little fun with a C compiler/preprocessor and you could make a C file ...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (10/23) Feb 11 2009 Maybe I'm missing something here, but why is Mac OS X including
- Walter Bright (5/24) Feb 11 2009 You're not missing anything. This needs to be cleaned up. (BTW, it will
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (10/16) Feb 11 2009 "darwin" is the uname(1) name of Mac OS X, sort of like the
- Walter Bright (7/21) Feb 11 2009 Apple can't seem to make up their mind. uname does return "Darwin". gcc
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (4/11) Feb 11 2009 Will you set version(darwin) though, or would that be "version(osx)" ?
- Walter Bright (7/20) Feb 12 2009 version(OSX)
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (6/7) Feb 12 2009 That breaks GDC and LDC compatibility, unfortunately...
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (15/19) Feb 12 2009 GDC uses the same GNU triplets as GCC and configure, with the "os" part.
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (13/18) Feb 12 2009 Once upon a time, there was a difference between Darwin and Mac OS X.
- Jacob Carlborg (6/28) Feb 13 2009 I'm not going to argue about what is the best version identifier for Mac...
- Nick Sabalausky (8/36) Feb 13 2009 I don't have an opinion on the correct identifier to use, but not
- Jacob Carlborg (27/62) Feb 14 2009 I guess I have to start to argue. In this case I don't see that some
- Nick Sabalausky (7/68) Feb 14 2009 I see what you're saying. In that case, perhaps the best thing to do is,...
- Yigal Chripun (8/82) Feb 14 2009 I'm no Mac user but it seems to me that OS X is a superset of darwin
- Nick Sabalausky (3/10) Feb 14 2009 *Seems* to make sense to me, but then again, I'm not a mac user either.
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (14/21) Feb 14 2009 Sortof, just that OpenDarwin/PureDarwin are normally "puredarwin"
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (2/4) Feb 14 2009 ... and it did. :-)
- Christian Kamm (3/5) Feb 15 2009 LDC will also add the OSX version specifier for Mac OS X.
- Leandro Lucarella (10/21) Feb 11 2009 You should probably distribute meld with DMD then ;)
- Walter Bright (3/4) Feb 11 2009 sudo apt-get install meld
- BCS (4/12) Feb 11 2009 doesn't work unless you have apt-get working, doesn't work unless you ha...
- Walter Bright (2/18) Feb 11 2009 You can't download dmd.zip without a net connection, either!
- BCS (2/21) Feb 11 2009 last I checked you cant use apt-get over sneeker net.
- Chris Nicholson-Sauls (6/31) Feb 11 2009 I believe 'apt-get install' actually will work so long as the
- Daniel Keep (6/29) Feb 11 2009 `wget $URL_OF_PACKAGE` to download it, and (I believe; it's been a while
- Steven Schveighoffer (46/71) Feb 10 2009 There can exist a happy medium between the rigid current design and the
- Walter Bright (99/130) Feb 10 2009 If you find yourself doing that a lot in the code, then I suggest a
- Denis Koroskin (76/211) Feb 10 2009 Ok, I've imagined that Boehm GC is written in D and went into a trouble ...
- Walter Bright (27/37) Feb 10 2009 Of course doing it that way doesn't look any better, because it still
- Nick Sabalausky (8/13) Feb 10 2009 Which just goes to show that the restrictions you've placed on D's versi...
- Walter Bright (5/21) Feb 10 2009 But they do make it more painful to write the rat's nest, which can be
- Steven Schveighoffer (16/37) Feb 10 2009 And when the rats nest MUST be created? Why make it more painful? I'm ...
- Walter Bright (9/14) Feb 10 2009 Hans is in a trap with it. If he reengineered it, he very likely would
- Steven Schveighoffer (11/40) Feb 10 2009 All you have done is split the mess into separate files. This does not
- Walter Bright (4/36) Feb 10 2009 See my example of O_APPEND for the proof that it does solve the problem
- Steven Schveighoffer (24/59) Feb 10 2009 I assume that the rats nest is necessary for the code to function.
- Walter Bright (28/46) Feb 10 2009 I cannot prove to you in any mathematical sort of way. All I can say is
- Steve Schveighoffer (50/111) Feb 10 2009 It's bad. I agree with you. I also have bad experiences with the
- Steve Schveighoffer (5/20) Feb 10 2009 This should have been
- Nick Sabalausky (442/452) Feb 10 2009 {horrid mess of C snipped}
- Walter Bright (8/14) Feb 10 2009 I'll argue that I've never seen anyone create such a mess in D, while I
- Jarrett Billingsley (14/21) Feb 10 2009 D is also only _really truly_ supported on about three or four
- Joel C. Salomon (5/16) Feb 11 2009 version(!Windows)
- Jarrett Billingsley (4/7) Feb 11 2009 I use versions for things other than platform-specific code. Like
- Joel C. Salomon (3/5) Feb 11 2009 So what would your use-case look like?
- Jarrett Billingsley (18/22) Feb 11 2009 version(TurnOffSomeFeature) {} else
- Walter Bright (14/33) Feb 11 2009 Even if a feature is on by default, versions should still be a positive
- Joel C. Salomon (5/13) Feb 11 2009 Apologies if this is obvious, but:
- Walter Bright (4/17) Feb 11 2009 Either via the command line, or by the statement:
- Jarrett Billingsley (6/13) Feb 11 2009 It might be clearer in the code, but it's far less intuitive for the
- Walter Bright (4/8) Feb 11 2009 Define it by default in your makefile or by a version=SomeFeature;
- Bill Baxter (12/27) Feb 11 2009 I thought he meant this:
- Nick Sabalausky (6/9) Feb 11 2009 It would be a hell of a lot nicer if we could just write that as:
- Jarrett Billingsley (6/15) Feb 11 2009 I don't know whether or not Walter _was_ actually insinuating that but
- Chris Nicholson-Sauls (11/29) Feb 11 2009 I had the same thought at first when reading the 'version declarations'
- Nick Sabalausky (24/37) Feb 10 2009 Agreed, but I'm certain that a significant reason for that is the fact t...
- Andrei Alexandrescu (8/38) Feb 10 2009 But this is clearly the wrong way of cutting the pie. What you need is
- Walter Bright (9/10) Feb 10 2009 Right, and I also suggest that it is the C preprocessor way of doing
- Steven Schveighoffer (30/67) Feb 10 2009 Sometimes, coming up with a better identifier than this || that is not e...
- Sean Kelly (20/59) Feb 10 2009 There's one slightly irritating issue I've run into with versions
- Nick Sabalausky (15/34) Feb 10 2009 This strikes me as throwing away the baby with the bathwater. If your co...
- Walter Bright (30/56) Feb 10 2009 True, but that never, ever happens. It's always "I can get my few
- Denis Koroskin (10/64) Feb 10 2009 Why did you catch that controversial !Linux example? Just imagine it is ...
- Walter Bright (3/16) Feb 10 2009 This is to combat the pernicious problem of having features that
- Don (3/21) Feb 10 2009 I've got two words for you, Walter.
- Walter Bright (2/8) Feb 10 2009 I've never heard of those before. Are they like VW Bugs?
- Don (2/11) Feb 11 2009 Yes, but they're not as cute.
- Tim M (7/61) Feb 10 2009 It would be nice if version just evaluated to a bool of true if the
- Nick Sabalausky (28/36) Feb 10 2009 It seems to me that D's versioning, conditional compilation, and overall...
- grauzone (6/6) Feb 10 2009 I see your points, although I don't quite agree. Programmers will
- Daniel Keep (23/30) Feb 10 2009 Versions are not boolean flags that are either true or false [1].
- Nick Sabalausky (9/15) Feb 10 2009 lol :)
- Jason House (6/14) Feb 10 2009 Would you be willing to introduce an alternative to /+ +/ which would be...
- Walter Bright (2/6) Feb 10 2009 That is an interesting idea. I never thought of that.
- Daniel Keep (11/20) Feb 10 2009 What about this?
- Brian (5/8) Feb 11 2009 is that just a neater way to do this?
- Brian (3/12) Feb 11 2009 after writing that i realized the mixin is probably evaluated even if th...
- Don (2/15) Feb 11 2009 mixin( version(Identifier) { `//code!` } else { ``});
- Nick Sabalausky (6/8) Feb 11 2009 One thing that's nice about that in a really bizarre sort of way is that...
- Jason House (3/10) Feb 11 2009 Would you be willing to add it as a new feature to both D1 and D2?
- Walter Bright (2/19) Feb 11 2009 I don't see druntime supporting D1, it's pretty in bed with D2 features.
- Sean Kelly (11/30) Feb 11 2009 There's a druntime branch that is compatible with D1. I created it most...
- Ary Borenszweig (5/21) Feb 10 2009 Why not have special versions like D1, D2, D3 for the compiler to treat
- Ary Borenszweig (3/27) Feb 10 2009 Ah, mmm... the lexer also needs to know this. Doesn't work. :-(
- =?ISO-8859-1?Q?Anders_F_Bj=F6rklund?= (6/16) Feb 11 2009 And for code that can't/won't be rewritten, there's the workaround:
I was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))? Regards, bobef
Feb 10 2009
bobef schrieb:Why not "static if(version(DMD))" or static if(is(version == DMD))?Cause nobody wants to write something ugly like that every time. version(DMD) is nice and clear.
Feb 10 2009
bobef wrote:I was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))? Regards, bobefOne of my pet peeves. The only advantages of version() over static if() are: 1. You can pass version flags as command line parameters 2. It is shorter. Some severe disadvantages of version(): 1. They can't contain expressions (like "version(linux && mac)"). 2. Typos are not catched! "version(linxu)" will just silently compile. Proposal to solve these problems: Remove "version()" and replace it by "static if()" (actually, it would make sense to turn version into an alias for static if). Introduce const declarations, which get their value from commandline: //command line for dmd to set the constant cLinux dmd -version cLinux=true //define a const variable, whose value is taken from the commandline //they always need to be declared, the compiler shouldn't just //arbitrarily introduce new symbols into the modules' scope! //(exact syntax needs to be discussed) const bool cLinux = $cmdarg; //instead of version(linux) //unlike version, arbitrary expressions are allowed static if(cLinux) { //Linux code goes here } static if(cLinxu) { //oops, typo, the compiler will loudly complain! As an additional feature, you could allow passing of additional data types instead of only bool. Strings, for example. Unlike version(), cLinux always needs to be defined on the command line. I don't consider this a disadvantage. I'd also leave debug() as it is.
Feb 10 2009
grauzone schrieb:Some severe disadvantages of version(): 1. They can't contain expressions (like "version(linux && mac)").version(linux) version(mac) { } But yeah, that's a feature that could be added.
Feb 10 2009
Trass3r wrote:grauzone schrieb:A&&B is not so terrible, since you can do it by nesting, as above. The big problem is A || B. It creates a mess.Some severe disadvantages of version(): 1. They can't contain expressions (like "version(linux && mac)").version(linux) version(mac) { } But yeah, that's a feature that could be added.
Feb 10 2009
On Tue, 10 Feb 2009 13:08:03 +0100, Don wrote:A&&B is not so terrible, since you can do it by nesting, as above. The big problem is A || B. It creates a mess.version(A) version = AorB; version(B) version = AorB; version(AorB) { . . . } -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Feb 10 2009
Derek Parnell wrote:On Tue, 10 Feb 2009 13:08:03 +0100, Don wrote:Yes. And that sucks, because you've got the version statement in two places. And you've had to create an essentially meaningless temporary. [1] Then when you have a more complex expression, especially where A and B appear more than once, it gets disgusting. [1] I know Walter's idea is that you create meaningful identifiers, but in practice this kind of versioning can be a workaround. EG B is "everything except WindowsME".A&&B is not so terrible, since you can do it by nesting, as above. The big problem is A || B. It creates a mess.version(A) version = AorB; version(B) version = AorB; version(AorB) { . . . }
Feb 10 2009
On Tue, 10 Feb 2009 17:14:00 +0300, Don <nospam nospam.com> wrote:Derek Parnell wrote:Version has so many shortcomings that it should definitely be redesigned. My biggest complaint is that code inside version () {} block should be semantically correct. It creates many obstacles and disallows good use-cases: - you cannot mix D1, D2 and (in future) D3 in a single source code file without helf of mixins. - you cannot mix asm for different platforms in one source code file (because DMD doesn't understand ARM assembly, for instance) - etc Other use-case I came across recently reading .NET Framework source code: class String : IFoo, IBar, IBaz, #if SUPPORT_GENERICS IComparable<Foo>, #endif IWhee { // *very* large amount of code } How would you port it to D without code duplication and meaningless intermediate classes?On Tue, 10 Feb 2009 13:08:03 +0100, Don wrote:Yes. And that sucks, because you've got the version statement in two places. And you've had to create an essentially meaningless temporary. [1] Then when you have a more complex expression, especially where A and B appear more than once, it gets disgusting. [1] I know Walter's idea is that you create meaningful identifiers, but in practice this kind of versioning can be a workaround. EG B is "everything except WindowsME".A&&B is not so terrible, since you can do it by nesting, as above. The big problem is A || B. It creates a mess.version(A) version = AorB; version(B) version = AorB; version(AorB) { . . . }
Feb 10 2009
Denis Koroskin wrote:[snip] Other use-case I came across recently reading .NET Framework source code: class String : IFoo, IBar, IBaz, #if SUPPORT_GENERICS IComparable<Foo>, #endif IWhee { // *very* large amount of code } How would you port it to D without code duplication and meaningless intermediate classes?I think I once tried something where I was building a list of interface types as a tuple, then tried this: class Foo : InterfaceTuple { ... } Didn't work, though. -- Daniel
Feb 10 2009
Denis Koroskin wrote:On Tue, 10 Feb 2009 17:14:00 +0300, Don <nospam nospam.com> wrote:Just syntactically correct.Derek Parnell wrote:Version has so many shortcomings that it should definitely be redesigned. My biggest complaint is that code inside version () {} block should be semantically correct.On Tue, 10 Feb 2009 13:08:03 +0100, Don wrote:Yes. And that sucks, because you've got the version statement in two places. And you've had to create an essentially meaningless temporary. [1] Then when you have a more complex expression, especially where A and B appear more than once, it gets disgusting. [1] I know Walter's idea is that you create meaningful identifiers, but in practice this kind of versioning can be a workaround. EG B is "everything except WindowsME".A&&B is not so terrible, since you can do it by nesting, as above. The big problem is A || B. It creates a mess.version(A) version = AorB; version(B) version = AorB; version(AorB) { . . . }
Feb 10 2009
grauzone:Unlike version(), cLinux always needs to be defined on the command line. I don't consider this a disadvantage.I think I don't like that. But I may like something like this: static if (__version__ == DMD) {...} more than: version(DMD) {...} It's longer, but it doesn't need the version keyword, it's more uniform and easy anyway to remember and use, and it can be used in more refined ways. I may even appreciate other boolean constants like: static if (__debug__) {...} static if (__unittest__) {...} static if (__ismain__) {...} Where bud and similar tools define __ismain__ as true only inside the main module. Bye, bearophile
Feb 10 2009
grauzone wrote:Some severe disadvantages of version(): 1. They can't contain expressions (like "version(linux && mac)").Unless Apple has plans to s/BSD/Linux/ in MacOS that I'm not aware of, version(linux || mac) would probably be more useful... Allowing boolean expressions (using only version identifiers) in version() would be a very welcome feature. I'm not sure about the rest of your post though.
Feb 10 2009
Frits van Bommel wrote:grauzone wrote:Well, my argument is that CTFE already provides all version features and even more. version is redundant, and even dangerous, because it can't catch typos in version identifiers. Actually, C/C++ has something similar: #if (is similar to static if) versus #ifdef (is similar to version). ffmpeg recently switched from using #ifdef to #if.Some severe disadvantages of version(): 1. They can't contain expressions (like "version(linux && mac)").Unless Apple has plans to s/BSD/Linux/ in MacOS that I'm not aware of, version(linux || mac) would probably be more useful... Allowing boolean expressions (using only version identifiers) in version() would be a very welcome feature. I'm not sure about the rest of your post though.
Feb 10 2009
Tue, 10 Feb 2009 13:34:35 +0100, grauzone wrote:Frits van Bommel wrote:#if is no different from #ifdef because any undefined identifier evaluates to 0 within the #if context.grauzone wrote:Well, my argument is that CTFE already provides all version features and even more. version is redundant, and even dangerous, because it can't catch typos in version identifiers. Actually, C/C++ has something similar: #if (is similar to static if) versus #ifdef (is similar to version). ffmpeg recently switched from using #ifdef to #if.Some severe disadvantages of version(): 1. They can't contain expressions (like "version(linux && mac)").Unless Apple has plans to s/BSD/Linux/ in MacOS that I'm not aware of, version(linux || mac) would probably be more useful... Allowing boolean expressions (using only version identifiers) in version() would be a very welcome feature. I'm not sure about the rest of your post though.
Feb 15 2009
"grauzone" <none example.net> wrote in message news:gmrpj5$1hea$1 digitalmars.com...bobef wrote:I wholeheartedly agree with this 100%. I'd also have to agree with Denis's point about the semantic/syntactic restrictions: "Denis Koroskin" <2korden gmail.com> wrote in message news:op.uo433jipo7cclz proton.creatstudio.intranet...I was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))? Regards, bobefOne of my pet peeves. The only advantages of version() over static if() are: 1. You can pass version flags as command line parameters 2. It is shorter. Some severe disadvantages of version(): 1. They can't contain expressions (like "version(linux && mac)"). 2. Typos are not catched! "version(linxu)" will just silently compile. Proposal to solve these problems: Remove "version()" and replace it by "static if()" (actually, it would make sense to turn version into an alias for static if). Introduce const declarations, which get their value from commandline: //command line for dmd to set the constant cLinux dmd -version cLinux=true //define a const variable, whose value is taken from the commandline //they always need to be declared, the compiler shouldn't just //arbitrarily introduce new symbols into the modules' scope! //(exact syntax needs to be discussed) const bool cLinux = $cmdarg; //instead of version(linux) //unlike version, arbitrary expressions are allowed static if(cLinux) { //Linux code goes here } static if(cLinxu) { //oops, typo, the compiler will loudly complain! As an additional feature, you could allow passing of additional data types instead of only bool. Strings, for example. Unlike version(), cLinux always needs to be defined on the command line. I don't consider this a disadvantage. I'd also leave debug() as it is.My biggest complaint is that code inside version () {} block should be semantically correct. It creates many obstacles and disallows good use-cases: - you cannot mix D1, D2 and (in future) D3 in a single source code file without helf of mixins. - you cannot mix asm for different platforms in one source code file (because DMD doesn't understand ARM assembly, for instance) - etc
Feb 10 2009
bobef wrote:I was thinking... what is the point of version() ? It is so inflexible.There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))?Regards, bobefWhat would be the difference except more verbosity? You can use version(x) { } else { } The rationale of version() is a simple, coarse grained conditional compilation of features. It is not meant for metaprogramming like static if is.
Feb 10 2009
On Wed, 11 Feb 2009 00:28:21 +1300, bobef <bobef nospam-abv.bg> wrote:I was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))? Regards, bobefYou could try something like this: module Vers; template vers(char[] V) { mixin("version(" ~ V ~ ") { const bool vers = true; } else { const bool vers = false; }"); } int main() { static if(vers!("X86_64")) { long a; pragma(msg, "64 bit"); } else { int a; pragma(msg, "32 bit"); } a = 2; return a; }
Feb 10 2009
It gets even better with constants and works in static asserts too: module Vers; template vers(char[] V) { mixin("version(" ~ V ~ ") { const bool vers = true; } else { const bool vers = false; }"); } const DigitalMars = "DigitalMars"; const X86 = "X86"; const X86_64 = "X86_64"; const Windows = "Windows"; const Win32 = "Win32"; const Win64 = "Win64"; const LittleEndian = "LittleEndian"; const BigEndian = "BigEndian"; const D_Coverage = "D_Coverage"; const D_Ddoc = "D_Ddoc"; const D_InlineAsm_X86 = "D_InlineAsm_X86"; const D_InlineAsm_X86_64 = "D_InlineAsm_X86_64"; const D_LP64 = "D_LP64"; const D_PIC = "D_PIC"; const none = "none"; const all = "all"; int main() { const bool forceLong = false; static if(vers!(X86_64) || forceLong) { long a; pragma(msg, "64 bit"); } else { int a; pragma(msg, "32 bit"); } static assert(vers!(LittleEndian) || vers!(BigEndian), "You are a weird endian"); a = 2; return a; }
Feb 10 2009
Tim M wrote:On Wed, 11 Feb 2009 00:28:21 +1300, bobef <bobef nospam-abv.bg> wrote:You beat me to it. I actually use this a little here and there. But honestly, I find that the cases where I just want 'version(X){...}else{...}' far outweigh the cases where I want 'X && Y' or the like. While it is technically a hack/workaround, I've been perfectly happy with it. Now, what would be nice, would be if version() could appear in places it currently can't, following a few rules. In mid-statement, for example, so long as its body is a complete expression. And then the same for mixin expressions. Might be daydreaming too much, there. Imagine though... template vers (char[] V) { const vers = mixin("version("~V~") {true} else {false}") ; } Add to that a deep shorthand syntax a la: template vers (char[] V) = mixin("version("~V~") {true} else {false}") ; Okay, I'll come down from the clouds now. -- Chris Nicholson-SaulsI was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))? Regards, bobefYou could try something like this: module Vers; template vers(char[] V) { mixin("version(" ~ V ~ ") { const bool vers = true; } else { const bool vers = false; }"); } int main() { static if(vers!("X86_64")) { long a; pragma(msg, "64 bit"); } else { int a; pragma(msg, "32 bit"); } a = 2; return a; }
Feb 10 2009
bobef wrote:I was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))? Regards, bobefversion() is MUCH older than static if. It dates from a very early time in D's history. I requested module-scope static if, and Walter said "that's probably almost impossible to implement", but he did it anyway <g>.
Feb 10 2009
Don:I requested module-scope static if, and Walter said "that's probably almost impossible to implement", but he did it anyway <g>.Walter does almost the impossible, sometimes. I'll have to remember this :-) Bye, bearophile
Feb 10 2009
bearophile wrote:Don:The traditional way to get an engineer to do something, is to tell him you believe it's impossible. Works very well with Walter. Also Walter tends not to promise to do something, unless he's already finished it <g>.I requested module-scope static if, and Walter said "that's probably almost impossible to implement", but he did it anyway <g>.Walter does almost the impossible, sometimes. I'll have to remember this :-) Bye, bearophile
Feb 10 2009
Hello Don,bearophile wrote:So I assume it must follow that engineers should never be taught computational complexity theory... determining that a problem is intractable might affect their attempts at ingenious solutions that shouldn't exist. :D -JJRDon:The traditional way to get an engineer to do something, is to tell him you believe it's impossible. Works very well with Walter. Also Walter tends not to promise to do something, unless he's already finished it <g>.I requested module-scope static if, and Walter said "that's probably almost impossible to implement", but he did it anyway <g>.Walter does almost the impossible, sometimes. I'll have to remember this :-) Bye, bearophile
Feb 10 2009
John Reimer wrote:So I assume it must follow that engineers should never be taught computational complexity theory... determining that a problem is intractable might affect their attempts at ingenious solutions that shouldn't exist. :DI've suspected that's why breakthroughs are made by the young, as they don't yet understand what's impossible.
Feb 10 2009
bobef wrote:I was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))?The version statement is designed to be inflexible. It's designed to encourage abstracting and modularizing version differences, rather than encouraging line-by-line differences. I've used #if/#endif for decades. Over time, it *always* degenerates into an utter rat's nest of nested, incomprehensible complexity (and this includes my own code). For a lovely example of how bad it can get, take a look at the source code to Hans Boehm's garbage collector. I defy anyone to figure it out without running the code through the preprocessor first to see which statements are actually getting compiled. A far better way to do versioning is to find the abstraction lines separating versions, and put version specific code in separate modules that are then imported. It makes for nice, clean, understandable code. Static if can be used for version control, but that is not what it's for. Static if is for use inside templates to control code generation based on template parameters, not for producing different versions of the program. 1. Why not version(!feature) ? Because cognitive studies show that people just don't see the negation. Secondly, when you see things like: version (!linux) { ... } they're almost always wrong. Versions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux. 2. version (A || B) can be done as: version (A) version=AorB; version (B) version=AorB; 3. version (A && B) can be done as: version (A) version (B) { ... } though if you find yourself doing that a lot, I suggest abstracting away the A and B version into its own AandB version. 4. Conditional compilation can be done with version(all) and version(none). 5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do. If you need to 'comment out' a section of syntactically invalid code, use the /+ ... +/ nesting comment.
Feb 10 2009
On Tue, 10 Feb 2009 13:14:24 -0800, Walter Bright wrote:The version statement is designed to be inflexible. It's designed to encourage abstracting and modularizing version differences, rather than encouraging line-by-line differences.I understand and support this view. However, it creates a new problem; code duplication. Is it possible to provide some syntax or technique to avoid having to cut&paste /small/ runs of code lines. Larger sections of code can be separated into functions or modules, but it because problematic when dealing with small sections (a few lines) of code. The overheads of function calling can be an issue.5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do.Agreed, this is a problem. How can it be solved? The problem is often found when supporting V1 and V2 code in the same source file. The string mixin trick is NOT, repeat NOT, a satisfactory solution. Duplicating (nearly all of a) source file is NOT, repeat NOT, a satisfatory solution. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Feb 10 2009
Derek Parnell wrote:On Tue, 10 Feb 2009 13:14:24 -0800, Walter Bright wrote:I don't think that duplicating a small run of code is a problem. If it's larger than a small run, it can be abstracted into a function (the overhead is not an issue, as small functions are inlined).The version statement is designed to be inflexible. It's designed to encourage abstracting and modularizing version differences, rather than encouraging line-by-line differences.I understand and support this view. However, it creates a new problem; code duplication. Is it possible to provide some syntax or technique to avoid having to cut&paste /small/ runs of code lines. Larger sections of code can be separated into functions or modules, but it because problematic when dealing with small sections (a few lines) of code. The overheads of function calling can be an issue.I agree that the mixin trick is horrific.5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do.Agreed, this is a problem. How can it be solved? The problem is often found when supporting V1 and V2 code in the same source file. The string mixin trick is NOT, repeat NOT, a satisfactory solution.Duplicating (nearly all of a) source file is NOT, repeat NOT, a satisfatory solution.I'm not insensitive to this as I do it myself in maintaining Phobos. It is a problem, but not a huge one. I find that the meld utility (on linux) makes this chore a snap.
Feb 10 2009
On Tue, 10 Feb 2009 14:01:29 -0800, Walter Bright wrote:Derek Parnell wrote:My apology. The problem is more than run-time performance issues. The more pressing problem, IMHO, is the one of maintenance costs. Duplicated code is a significant cost burden. Not only may each duplication require updating, but there is extra effort in analyizing every duplicate to see if it *does* need updating. And every act of updating increases the opportunity for introducing bugs. Coders need languages that help them do their job, and one way to help is to reduce the need for duplicated code.... it creates a new problem; code duplication.I don't think that duplicating a small run of code is a problem.Because of D's limited support for text macros, I am using third party tools to get me out of this problem too. -- Derek Parnell Melbourne, Australia skype: derek.j.parnellDuplicating (nearly all of a) source file is NOT, repeat NOT, a satisfatory solution.I'm not insensitive to this as I do it myself in maintaining Phobos. It is a problem, but not a huge one. I find that the meld utility (on linux) makes this chore a snap.
Feb 10 2009
Derek Parnell wrote:On Tue, 10 Feb 2009 14:01:29 -0800, Walter Bright wrote:Let's take an example, like the enum for O_XXXX in std.c.linux.linux. Some of those values are common between platforms, and some are unique to particular platforms. So you might be tempted to write: enum { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, O_CREAT = 0100, version(OSX) O_SYMLINK = 0x200000, } instead of: version (linux) { enum { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, O_CREAT = 0100, } } else version (OSX) { enum { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, O_CREAT = 0100, O_SYMLINK = 0x200000, } } else { static assert(0); // need platform support } The first version is definitely shorter. But is it easier to maintain? I argue that it is *harder* and *buggier* to maintain. Let's say I am using linux and I need to add O_APPEND to it. I just stuff it in like: enum { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, O_CREAT = 0100, O_APPEND = 02000, version(OSX) O_SYMLINK = 0x200000, } and it works great for linux. Now I port my code to OSX, and it mysteriously dies. After much frustration, I discover that O_APPEND for OSX is 8, not 02000. (Yes, this kind of thing has happened to me. I only found it by suspecting the problem, and then going through every fscking definition comparing it to the one in the system .h file. Yeech.) Now let's try the other way. I add O_APPEND to the linux branch, and linux works great. Now I port to OSX, and the compiler dies with "O_APPEND is undefined". I know immediately exactly what is wrong, look up the .h file, and insert the right O_APPEND into the OSX version of the declaration. Furthermore, when I build a FreeBSD version, the compiler bings at me for every declaration that needs some porting attention, instead of silently using the wrong values. This would be even better if the OSX and linux declarations were split into separate "personality" modules. That way you can develop happily on OSX without fear of accidentally breaking linux support. You can defer dealing with the linux version until you actually on the linux machine and are in an efficient position to take care of it.Derek Parnell wrote:My apology. The problem is more than run-time performance issues. The more pressing problem, IMHO, is the one of maintenance costs. Duplicated code is a significant cost burden. Not only may each duplication require updating, but there is extra effort in analyizing every duplicate to see if it *does* need updating. And every act of updating increases the opportunity for introducing bugs.... it creates a new problem; code duplication.I don't think that duplicating a small run of code is a problem.Coders need languages that help them do their job, and one way to help is to reduce the need for duplicated code.I know there's a risk by getting in the way of programmers wanting to do things a particular way. To do it, I have to be pretty convinced that there is a better way. The C preprocessor is like crack, everyone knows it's bad but they snort it anyway because it feels so good <g>. C++ was supposed to get a bunch of features that obviate the preprocessor, but have a look at the premier C++ library - Boost - which uses the preprocessor heavily. Boost also uses every last iota of what the preprocessor can do, because if your cpp implementation is not 100% most of Boost will not compile (I know this from experience, DMC++ is 100% now).meld is particularly nice. Andrei showed it to me: http://www.linux.com/feature/61372Because of D's limited support for text macros, I am using third party tools to get me out of this problem too.Duplicating (nearly all of a) source file is NOT, repeat NOT, a satisfatory solution.I'm not insensitive to this as I do it myself in maintaining Phobos. It is a problem, but not a huge one. I find that the meld utility (on linux) makes this chore a snap.
Feb 10 2009
== Quote from Walter Bright (newshound1 digitalmars.com)'s article ...Let's take an example, like the enum for O_XXXX in std.c.linux.linux. Some of those values are common between platforms, and some are unique to particular platforms. So you might be tempted to write:[snip]The first version is definitely shorter. But is it easier to maintain? I argue that it is *harder* and *buggier* to maintain.This is definitely true of header modules. There's absolutely no way I could manage the Posix headers in Tango/druntime with the non-duplicating approach.This would be even better if the OSX and linux declarations were split into separate "personality" modules. That way you can develop happily on OSX without fear of accidentally breaking linux support. You can defer dealing with the linux version until you actually on the linux machine and are in an efficient position to take care of it.With version blocks, working with one version shouldn't break another version anyway, unless I'm misunderstanding your point. Sean
Feb 10 2009
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleDerek Parnell wrote:I suggest UltraCompare, if you're a Windows user. SeanBecause of D's limited support for text macros, I am using third party tools to get me out of this problem too.meld is particularly nice. Andrei showed it to me: http://www.linux.com/feature/61372
Feb 10 2009
"Sean Kelly" <sean invisibleduck.org> wrote in message news:gmt9pl$11mt$1 digitalmars.com...== Quote from Walter Bright (newshound1 digitalmars.com)'s articleI've been a big fan of Beyond Compare for a long time now. I'll have to take a look at UltraCompare.Derek Parnell wrote:I suggest UltraCompare, if you're a Windows user.Because of D's limited support for text macros, I am using third party tools to get me out of this problem too.meld is particularly nice. Andrei showed it to me: http://www.linux.com/feature/61372
Feb 10 2009
On Tue, 10 Feb 2009 17:16:22 -0800, Walter Bright wrote:Let's take an example, like the enum for O_XXXX in std.c.linux.linux. Some of those values are common between platforms, and some are unique to particular platforms...Yes, the duplicated code is a better approach here because the apparent common code is the key in this example. The lines that are the same are only coincidently common and and not common due to any inate factors of the operating system or data being declared.This would be even better if the OSX and linux declarations were split into separate "personality" modules.Agreed. The example I offer here is more the sort of thing that it seems you are also finding when maintaining Phobos ... Current my code loks like this ... //--------------- Using version() w/o duplicating code -------- //------------------------------------------------------- int RunCommand(string pExeName, string pCommand, runCallBack pCallBack=null) //------------------------------------------------------- { version(Windows) { if (std.path.getExt(pExeName).length == 0) pExeName ~= ".exe"; } if (util.pathex.IsRelativePath(pExeName) == True) { string lExePath; lExePath = util.pathex.FindFileInPathList("PATH", pExeName); if (util.str.ends(lExePath, std.path.sep) == False) lExePath ~= std.path.sep; version(Windows) pExeName = util.pathex.CanonicalPath(lExePath ~ pExeName, False, False); version(Posix) pExeName = util.pathex.CanonicalPath(lExePath ~ pExeName, False, True); } if (util.file2.FileExists(pExeName) == false) { throw new FileExException(std.string.format( "Cannot find application '%s' to run", pExeName)); } return RunCommand( util.str.enquote(pExeName) ~ " " ~ pCommand, pCallBack); } //------------------------------------------------------- int RunCommand(string pCommand, runCallBack pCallBack = null) //------------------------------------------------------- { int lRC; if (pCallBack !is null) { lRC = pCallBack(1, pCommand, 0); if (lRC != 0) return 0; } lRC = system(std.string.toStringz(pCommand)); version(Posix) lRC = ((lRC & 0xFF00) >> 8); if (pCallBack !is null) pCallBack(2, pCommand, lRC); return lRC; } But if I split the opsys versioning out I get ... //--------------- Using version() with duplicating code -------- alias int function(int, string, int) runCallBack; version(Windows) { //------------------------------------------------------- int RunCommand(string pExeName, string pCommand, runCallBack pCallBack=null) //------------------------------------------------------- { if (std.path.getExt(pExeName).length == 0) pExeName ~= ".exe"; if (util.pathex.IsRelativePath(pExeName) == True) { string lExePath; lExePath = util.pathex.FindFileInPathList("PATH", pExeName); if (util.str.ends(lExePath, std.path.sep) == False) lExePath ~= std.path.sep; pExeName = util.pathex.CanonicalPath(lExePath ~ pExeName, False, False); } if (util.file2.FileExists(pExeName) == false) { throw new FileExException(std.string.format( "Cannot find application '%s' to run", pExeName)); } return RunCommand( util.str.enquote(pExeName) ~ " " ~ pCommand, pCallBack); } //------------------------------------------------------- int RunCommand(string pCommand, runCallBack pCallBack = null) //------------------------------------------------------- { int lRC; if (pCallBack !is null) { lRC = pCallBack(1, pCommand, 0); if (lRC != 0) return 0; } lRC = system(std.string.toStringz(pCommand)); if (pCallBack !is null) pCallBack(2, pCommand, lRC); return lRC; } } version(Posix) { //------------------------------------------------------- int RunCommand(string pExeName, string pCommand, runCallBack pCallBack=null) //------------------------------------------------------- { if (util.pathex.IsRelativePath(pExeName) == True) { string lExePath; lExePath = util.pathex.FindFileInPathList("PATH", pExeName); if (util.str.ends(lExePath, std.path.sep) == False) lExePath ~= std.path.sep; pExeName = util.pathex.CanonicalPath(lExePath ~ pExeName, False, True); } if (util.file2.FileExists(pExeName) == false) { throw new FileExException(std.string.format( "Cannot find application '%s' to run", pExeName)); } return RunCommand( util.str.enquote(pExeName) ~ " " ~ pCommand, pCallBack); } //------------------------------------------------------- int RunCommand(string pCommand, runCallBack pCallBack = null) //------------------------------------------------------- { int lRC; if (pCallBack !is null) { lRC = pCallBack(1, pCommand, 0); if (lRC != 0) return 0; } lRC = system(std.string.toStringz(pCommand)); lRC = ((lRC & 0xFF00) >> 8); if (pCallBack !is null) pCallBack(2, pCommand, lRC); return lRC; } } Now we have almost twice the code and whenever an enhancement to the RunCommand function is needed, I must examine and correctly update twice as many lines now, because *most*, but not quite all, the logic is identical between both operating systems. This is the sort of scenario that will cause bugs to be introduced. The fine line that divides when to duplicate and when not to duplicate, is hard to see clearly. I tend to favour the less duplication approach, but only when it leads to lower maintenance costs. -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Feb 10 2009
Derek Parnell wrote:The fine line that divides when to duplicate and when not to duplicate, is hard to see clearly. I tend to favour the less duplication approach, but only when it leads to lower maintenance costs.I agree it's hard to see clearly, and often can only be seen after attempting a couple of ports.
Feb 10 2009
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmt8t7$1042$1 digitalmars.com...Derek Parnell wrote:{snip} I have to admit, that's a very compelling example. I hadn't thought of anything like that. I guess the moral is "DRY is normally great, but be very careful with it when using it across multiple builds." But I'm still not sure we should be going that far. For instance: enum { version(Linux || OSX) { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, O_CREAT = 0100, } version(Linux) { O_APPEND = 02000, } version(OSX) { O_APPEND = 8, O_SYMLINK = 0x200000, } } That seems reasonable to me. Granted, with a small enum like that, completely replicating the whole enum would be fine, but imagine if it were something much larger, like MS or Apple error codes (though that may not be an ideal example since they're platform-specific). Unlike Walter's example, this method clearly allows for DRY, would would be quite an improvement on large enums. But I would argue that this method also provides for just as much robustness: Scenario 1: Porting to Windows, BSD, or Joe's Embedded OS: Walter's example results in an obvious compile-time failure at the enum. Mine might not do that (but maybe it *could* still do some sort of "version(Linux||OSX) {...} else fail" ), however mine does still cause an error anytime there's an attempt to call (or maybe even define) the "file open" function (Since there's no valid value for the paramater. Even the default value would be invalid). Scenario 2: Linux User Joe wants to add an "O_PREPEND" (Yea, I know that's *very* contrived): He's going to see three sections, Linux, Mac, and Both. The "Linux||OSX" part makes it clear to him that he should double-check the value of O_PREPEND on OSX if he wants to stick it in "Both", or else he knows he can just leave it in the Linux-only part or check with the project's manager. Later on, if Project Manager Suzy uses both systems and knows that O_PREPEND is the same on both, she can just move it to the "Both" section. Besides, without expression-level version(), the project's author might just as likely think "Shoot, this is stupid that D doesn't let me make this nicely DRY. But I really like DRY, so I guess I'll just resort to an external C-like pre-processor".On Tue, 10 Feb 2009 14:01:29 -0800, Walter Bright wrote: My apology. The problem is more than run-time performance issues. The more pressing problem, IMHO, is the one of maintenance costs. Duplicated code is a significant cost burden. Not only may each duplication require updating, but there is extra effort in analyizing every duplicate to see if it *does* need updating. And every act of updating increases the opportunity for introducing bugs.Let's take an example, like the enum for O_XXXX in std.c.linux.linux. Some of those values are common between platforms, and some are unique to particular platforms. So you might be tempted to write:
Feb 10 2009
Nick Sabalausky wrote:I have to admit, that's a very compelling example. I hadn't thought of anything like that.I didn't either, until I got bit by it <g>.I guess the moral is "DRY is normally great, but be very careful with it when using it across multiple builds." But I'm still not sure we should be going that far. For instance: enum { version(Linux || OSX) { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, O_CREAT = 0100, } version(Linux) { O_APPEND = 02000, } version(OSX) { O_APPEND = 8, O_SYMLINK = 0x200000, } } That seems reasonable to me.Yeah, but I guarantee you that there will be some "common to all" ones and an irresistible temptation to put them in outside any version block. I also like to have all the enums for one platform in one list, not broken up by other stuff for other platforms, because then it is easier to verify against the C headers.Besides, without expression-level version(), the project's author might just as likely think "Shoot, this is stupid that D doesn't let me make this nicely DRY. But I really like DRY, so I guess I'll just resort to an external C-like pre-processor".There's something wrong with that option, because although it's always been on the table (not just for D, but for any language) nobody ever uses it. Back in the '80s people would often complain about the limitations of the C preprocessor, and the answer was always "if you want a real macro preprocessor, use m4". But I've never heard of anyone ever actually using m4 to preprocess C. The "just use m4" meme became a joke, like Bob Villa saying "just use track lighting".
Feb 10 2009
Tue, 10 Feb 2009 19:57:47 -0800, Walter Bright wrote:Nick Sabalausky wrote:There's Antenna for Java. It's nearly impossible to do without some preprocessor in Java if you want some mid-level library to work reliably on many different mobile phones. Compile once, run anywhere--sounds like a joke to me.I have to admit, that's a very compelling example. I hadn't thought of anything like that.I didn't either, until I got bit by it <g>.I guess the moral is "DRY is normally great, but be very careful with it when using it across multiple builds." But I'm still not sure we should be going that far. For instance: enum { version(Linux || OSX) { O_RDONLY = 0, O_WRONLY = 1, O_RDWR = 2, O_CREAT = 0100, } version(Linux) { O_APPEND = 02000, } version(OSX) { O_APPEND = 8, O_SYMLINK = 0x200000, } } That seems reasonable to me.Yeah, but I guarantee you that there will be some "common to all" ones and an irresistible temptation to put them in outside any version block. I also like to have all the enums for one platform in one list, not broken up by other stuff for other platforms, because then it is easier to verify against the C headers.Besides, without expression-level version(), the project's author might just as likely think "Shoot, this is stupid that D doesn't let me make this nicely DRY. But I really like DRY, so I guess I'll just resort to an external C-like pre-processor".There's something wrong with that option, because although it's always been on the table (not just for D, but for any language) nobody ever uses it.
Feb 15 2009
Hello Walter,and it works great for linux. Now I port my code to OSX, and it mysteriously dies. After much frustration, I discover that O_APPEND for OSX is 8, not 02000. (Yes, this kind of thing has happened to me. I only found it by suspecting the problem, and then going through every fscking definition comparing it to the one in the system .h file. Yeech.)A little fun with a C compiler/preprocessor and you could make a C file that gives you the value by name. Then a bit of fun with D unittest that call into the C code and you could have a system to check if something got messed up for the next OS you port to.
Feb 10 2009
Walter Bright wrote:Now let's try the other way. I add O_APPEND to the linux branch, and linux works great. Now I port to OSX, and the compiler dies with "O_APPEND is undefined". I know immediately exactly what is wrong, look up the .h file, and insert the right O_APPEND into the OSX version of the declaration.Maybe I'm missing something here, but why is Mac OS X including std.c.linux.linux ? Shouldn't it use std.c.darwin.darwin instead ?Furthermore, when I build a FreeBSD version, the compiler bings at me for every declaration that needs some porting attention, instead of silently using the wrong values.GDC got tired of porting std.c.linux.linux over, so it generates a std.c.unix.unix module from the C headers at configure time instead. Also helps with the constants that have different values for different architectures, in addition to having different values for different OS.This would be even better if the OSX and linux declarations were split into separate "personality" modules. That way you can develop happily on OSX without fear of accidentally breaking linux support. You can defer dealing with the linux version until you actually on the linux machine and are in an efficient position to take care of it.The version(linux) and version(darwin) should keep those separated, right ? And save you when you include the wrong std.c module, too... --anders
Feb 11 2009
Anders F Björklund wrote:Walter Bright wrote:You're not missing anything. This needs to be cleaned up. (BTW, it will be osx, not darwin, as "darwin" seems to be only used in internal Apple documentation, whereas the published stuff says "OSX".)Now let's try the other way. I add O_APPEND to the linux branch, and linux works great. Now I port to OSX, and the compiler dies with "O_APPEND is undefined". I know immediately exactly what is wrong, look up the .h file, and insert the right O_APPEND into the OSX version of the declaration.Maybe I'm missing something here, but why is Mac OS X including std.c.linux.linux ? Shouldn't it use std.c.darwin.darwin instead ?Doing it automatically is better, of course.Furthermore, when I build a FreeBSD version, the compiler bings at me for every declaration that needs some porting attention, instead of silently using the wrong values.GDC got tired of porting std.c.linux.linux over, so it generates a std.c.unix.unix module from the C headers at configure time instead. Also helps with the constants that have different values for different architectures, in addition to having different values for different OS.
Feb 11 2009
Walter Bright skrev:"darwin" is the uname(1) name of Mac OS X, sort of like the "linux" for GNU/Linux. Darwin is also a stand-alone OS, but that isn't used much anymore (but still available from Apple as a CD download, or from the http://puredarwin.org project). OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix. --anders PS. I personally think it looks bad, but it is slightly better than OS/X at least (which makes you think of OS/2 Warp)Maybe I'm missing something here, but why is Mac OS X including std.c.linux.linux ? Shouldn't it use std.c.darwin.darwin instead ?You're not missing anything. This needs to be cleaned up. (BTW, it will be osx, not darwin, as "darwin" seems to be only used in internal Apple documentation, whereas the published stuff says "OSX".)
Feb 11 2009
Anders F Björklund wrote:"darwin" is the uname(1) name of Mac OS X, sort of like the "linux" for GNU/Linux. Darwin is also a stand-alone OS, but that isn't used much anymore (but still available from Apple as a CD download, or from the http://puredarwin.org project). OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.--anders PS. I personally think it looks bad, but it is slightly better than OS/X at least (which makes you think of OS/2 Warp)OS/2 was the dumbest name for an operating system, because it is not an identifier so everyone invents a different identifier for it. I used to work for Data I/O. Try spelling that over the phone to someone.
Feb 11 2009
Walter Bright wrote:Will you set version(darwin) though, or would that be "version(osx)" ? The existing D code for Mac OS X all uses version(darwin) from before. --andersOSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.
Feb 11 2009
Anders F Björklund wrote:Walter Bright wrote:version(OSX) I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX". Fortunately, (darwin) => (OSX) is a trivial global search/replace.Will you set version(darwin) though, or would that be "version(osx)" ? The existing D code for Mac OS X all uses version(darwin) from before.OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.
Feb 12 2009
Walter Bright wrote:Fortunately, (darwin) => (OSX) is a trivial global search/replace.That breaks GDC and LDC compatibility, unfortunately... So it'll be something like the Unix vs. Posix sitation. (where GDC pre-defines Unix and LDC pre-defines Posix) Maybe version(DigitalMars) version(OSX) version=darwin; --anders
Feb 12 2009
Walter Bright wrote:I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX".GDC uses the same GNU triplets as GCC and configure, with the "os" part. (there's normally a cpu part, a vendor part, and a gnu part for linux) So the version used would be similar to the powerpc-apple-darwin8 or i686-apple-darwin9, or any of the other common variants on Mac OS X ? Like powerpc-unknown-linux-gnu and i686-pc-linux-gnu for Linux, it is usually the same as the uname(1) but in lower case (see config.guess) http://cvs.savannah.gnu.org/viewvc/*checkout*/config/config/config.guess These GNU triplets are also used when cross-compiling, for instance... They're not identical to the GDC versions, but I prefer using "darwin". The other common version(Unix) ones were: linux, darwin, cygwin, freebsd, solaris --anders PS. uname(1) on cygwin is somewhat weird, like "CYGWIN_NT-5.1" or so. And I think Solaris still returns "SunOS" for the system name...
Feb 12 2009
Walter Bright wrote:version(OSX) I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX".Once upon a time, there was a difference between Darwin and Mac OS X. Where Darwin was the underlying (open source) operating system, but excluding the (proprietary) frameworks such as Carbon and Cocoa... So you had two: Darwin OS and Mac OS X. And both of them were "Darwin", so the term "puredarwin" was being used to refer to the open source OS. If you only target the vendor product, and not the open source one, then it doesn't really matter whether "Darwin" or "MacOSX" is used. (or "OSX", which includes both iPhone OS and Mac OS X in one term) Like you mentioned, GCC only predefines __APPLE__ and __MACH__... Now, I still hate the term "OSX" but that's without technical reasons. --anders PS. See also http://en.wikipedia.org/wiki/Darwin_(operating_system)
Feb 12 2009
Walter Bright wrote:Anders F Björklund wrote:I'm not going to argue about what is the best version identifier for Mac OS X, the I only thing I care about is consistency and "darwin" is already used by LDC and GDC. Don't make things harder.Walter Bright wrote:version(OSX) I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX".Will you set version(darwin) though, or would that be "version(osx)" ? The existing D code for Mac OS X all uses version(darwin) from before.OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.Fortunately, (darwin) => (OSX) is a trivial global search/replace.And I assume it's equally trivial to implement "darwin" as the version identifier. Again, don't make things harder by breaking existing code.
Feb 13 2009
"Jacob Carlborg" <doob me.com> wrote in message news:gn49b6$49b$1 digitalmars.com...Walter Bright wrote:I don't have an opinion on the correct identifier to use, but not implementing a change that makes something more correct *just* because it breaks existing code (particularly in an easy-to-fix way) is a terrible strategy. That's exactly what's turned C++ into the abysmal mess that it is today, which in turn is one of the primary reasons for D's existence. I don't want to end up with yet another C++.Anders F Björklund wrote:I'm not going to argue about what is the best version identifier for Mac OS X, the I only thing I care about is consistency and "darwin" is already used by LDC and GDC. Don't make things harder.Walter Bright wrote:version(OSX) I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX".Will you set version(darwin) though, or would that be "version(osx)" ? The existing D code for Mac OS X all uses version(darwin) from before.OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.Fortunately, (darwin) => (OSX) is a trivial global search/replace.And I assume it's equally trivial to implement "darwin" as the version identifier. Again, don't make things harder by breaking existing code.
Feb 13 2009
Nick Sabalausky wrote:"Jacob Carlborg" <doob me.com> wrote in message news:gn49b6$49b$1 digitalmars.com...I guess I have to start to argue. In this case I don't see that some version identifier is more correct than the other, you just have to make a choice. Either you choose to be as close to the official name of the operating system as possible, in this case I guess it should be "Mac OS X". Or you choose the uname that I've seen some people here talk about or a part of the target triple or what it's called, for example i386-apple-darwin. Then there's the question about upper/lowercase and spaces in the name. Or any other suggestions. I have know idea what the initial thought was when Walter chose the version identifiers and therefore I have no idea what would be the most correct version identifier to choose in this case. Because of gdc and ldc already use "darwin" you have to make a special case for dmd. Of course they could change the version identifier but at least for gdc I don't see that's very likely. GDC seems quite dead but it's still the most reliable compiler for Mac OS X at this point. I have no problem using dmd when it becomes equally reliable on Mac OS X as on linux/windows but as far as I know it will only be for x86 and there are three other targets for osx (excluding iphone): x86-64, ppc and ppc64. So what is the most correct version identifier? I don't know. But I think you should choose one option form the beginning and then try to be as consistent as possible. I guess I have to add this to every dsss file: version (DigitalMars) version (OSX) version = darwin /Jacob CarlborgWalter Bright wrote:I don't have an opinion on the correct identifier to use, but not implementing a change that makes something more correct *just* because it breaks existing code (particularly in an easy-to-fix way) is a terrible strategy. That's exactly what's turned C++ into the abysmal mess that it is today, which in turn is one of the primary reasons for D's existence. I don't want to end up with yet another C++.Anders F Björklund wrote:I'm not going to argue about what is the best version identifier for Mac OS X, the I only thing I care about is consistency and "darwin" is already used by LDC and GDC. Don't make things harder.Walter Bright wrote:version(OSX) I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX".Will you set version(darwin) though, or would that be "version(osx)" ? The existing D code for Mac OS X all uses version(darwin) from before.OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.Fortunately, (darwin) => (OSX) is a trivial global search/replace.And I assume it's equally trivial to implement "darwin" as the version identifier. Again, don't make things harder by breaking existing code.
Feb 14 2009
"Jacob Carlborg" <doob me.com> wrote in message news:gn693c$14de$1 digitalmars.com...Nick Sabalausky wrote:I see what you're saying. In that case, perhaps the best thing to do is, for now, keep it as something that's consistent across all D compilers, and then once GDC is finally made *completely* obsolete by combined effort of LDC and DMD (or revived by someone brave enough to dig into the gcc code), then we could make it whatever seems to be most accurate."Jacob Carlborg" <doob me.com> wrote in message news:gn49b6$49b$1 digitalmars.com...I guess I have to start to argue. In this case I don't see that some version identifier is more correct than the other, you just have to make a choice. Either you choose to be as close to the official name of the operating system as possible, in this case I guess it should be "Mac OS X". Or you choose the uname that I've seen some people here talk about or a part of the target triple or what it's called, for example i386-apple-darwin. Then there's the question about upper/lowercase and spaces in the name. Or any other suggestions. I have know idea what the initial thought was when Walter chose the version identifiers and therefore I have no idea what would be the most correct version identifier to choose in this case. Because of gdc and ldc already use "darwin" you have to make a special case for dmd. Of course they could change the version identifier but at least for gdc I don't see that's very likely. GDC seems quite dead but it's still the most reliable compiler for Mac OS X at this point. I have no problem using dmd when it becomes equally reliable on Mac OS X as on linux/windows but as far as I know it will only be for x86 and there are three other targets for osx (excluding iphone): x86-64, ppc and ppc64. So what is the most correct version identifier? I don't know. But I think you should choose one option form the beginning and then try to be as consistent as possible. I guess I have to add this to every dsss file: version (DigitalMars) version (OSX) version = darwinWalter Bright wrote:I don't have an opinion on the correct identifier to use, but not implementing a change that makes something more correct *just* because it breaks existing code (particularly in an easy-to-fix way) is a terrible strategy. That's exactly what's turned C++ into the abysmal mess that it is today, which in turn is one of the primary reasons for D's existence. I don't want to end up with yet another C++.Anders F Björklund wrote:I'm not going to argue about what is the best version identifier for Mac OS X, the I only thing I care about is consistency and "darwin" is already used by LDC and GDC. Don't make things harder.Walter Bright wrote:version(OSX) I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX".Will you set version(darwin) though, or would that be "version(osx)" ? The existing D code for Mac OS X all uses version(darwin) from before.OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.Fortunately, (darwin) => (OSX) is a trivial global search/replace.And I assume it's equally trivial to implement "darwin" as the version identifier. Again, don't make things harder by breaking existing code.
Feb 14 2009
Nick Sabalausky wrote:"Jacob Carlborg"<doob me.com> wrote in message news:gn693c$14de$1 digitalmars.com...I'm no Mac user but it seems to me that OS X is a superset of darwin (i.e darwin plus apple's proprietery APIs like cocoa, carbon). if that's true isn't it more acurate to have version darwin for the darwin OS (someone mentioned opendarwin), and osx version for Apple's Mac OS X in addition to darwin version? i.e Mac OS X is both "osx" and "darwin" whereas opendarwin is only "darwin". does that make sense?Nick Sabalausky wrote:I see what you're saying. In that case, perhaps the best thing to do is, for now, keep it as something that's consistent across all D compilers, and then once GDC is finally made *completely* obsolete by combined effort of LDC and DMD (or revived by someone brave enough to dig into the gcc code), then we could make it whatever seems to be most accurate."Jacob Carlborg"<doob me.com> wrote in message news:gn49b6$49b$1 digitalmars.com...I guess I have to start to argue. In this case I don't see that some version identifier is more correct than the other, you just have to make a choice. Either you choose to be as close to the official name of the operating system as possible, in this case I guess it should be "Mac OS X". Or you choose the uname that I've seen some people here talk about or a part of the target triple or what it's called, for example i386-apple-darwin. Then there's the question about upper/lowercase and spaces in the name. Or any other suggestions. I have know idea what the initial thought was when Walter chose the version identifiers and therefore I have no idea what would be the most correct version identifier to choose in this case. Because of gdc and ldc already use "darwin" you have to make a special case for dmd. Of course they could change the version identifier but at least for gdc I don't see that's very likely. GDC seems quite dead but it's still the most reliable compiler for Mac OS X at this point. I have no problem using dmd when it becomes equally reliable on Mac OS X as on linux/windows but as far as I know it will only be for x86 and there are three other targets for osx (excluding iphone): x86-64, ppc and ppc64. So what is the most correct version identifier? I don't know. But I think you should choose one option form the beginning and then try to be as consistent as possible. I guess I have to add this to every dsss file: version (DigitalMars) version (OSX) version = darwinWalter Bright wrote:I don't have an opinion on the correct identifier to use, but not implementing a change that makes something more correct *just* because it breaks existing code (particularly in an easy-to-fix way) is a terrible strategy. That's exactly what's turned C++ into the abysmal mess that it is today, which in turn is one of the primary reasons for D's existence. I don't want to end up with yet another C++.Anders F Björklund wrote:I'm not going to argue about what is the best version identifier for Mac OS X, the I only thing I care about is consistency and "darwin" is already used by LDC and GDC. Don't make things harder.Walter Bright wrote:version(OSX) I just don't think darwin is a good idea, as Apple doesn't even use it. See http://developer.apple.com/unix/index.html, where "darwin" is clearly second string. It looks like Apple is pushing aside "darwin" in favor of "OSX".Will you set version(darwin) though, or would that be "version(osx)" ? The existing D code for Mac OS X all uses version(darwin) from before.OSX is the new name for Apple's OSes: Mac OS X and iPhone OS. And of course DMD can use anything, but GDC uses darwin/Unix.Apple can't seem to make up their mind. uname does return "Darwin". gcc predefines "__MACH__" and "__APPLE__", but neither darwin nor osx. The documentation all says osx.Fortunately, (darwin) => (OSX) is a trivial global search/replace.And I assume it's equally trivial to implement "darwin" as the version identifier. Again, don't make things harder by breaking existing code.
Feb 14 2009
"Yigal Chripun" <yigal100 gmail.com> wrote in message news:gn76f3$big$1 digitalmars.com...I'm no Mac user but it seems to me that OS X is a superset of darwin (i.e darwin plus apple's proprietery APIs like cocoa, carbon). if that's true isn't it more acurate to have version darwin for the darwin OS (someone mentioned opendarwin), and osx version for Apple's Mac OS X in addition to darwin version? i.e Mac OS X is both "osx" and "darwin" whereas opendarwin is only "darwin". does that make sense?*Seems* to make sense to me, but then again, I'm not a mac user either.
Feb 14 2009
Yigal Chripun wrote:I'm no Mac user but it seems to me that OS X is a superset of darwin (i.e darwin plus apple's proprietery APIs like cocoa, carbon). if that's true isn't it more acurate to have version darwin for the darwin OS (someone mentioned opendarwin), and osx version for Apple's Mac OS X in addition to darwin version? i.e Mac OS X is both "osx" and "darwin" whereas opendarwin is only "darwin". does that make sense?Sortof, just that OpenDarwin/PureDarwin are normally "puredarwin" while Mac OS X is "macosx" - both in addition to regular "darwin". At least those are the "variants" that DarwinPorts/MacPorts uses, Apple recommends to check for specific functionality (Carbon/Cocoa) using something like autoconf and not assume things from the OS name. But D could still do user-level versions of those features, though ? In MacPorts, the toggle for +puredarwin/+macosx is a simple Tcl check: [file isdirectory /System/Library/Frameworks/Carbon.framework] But yeah, it would be nice if DMD could set *both* "version(darwin)" and "version(OSX)" for Mac OS X. That way the old code would work too. There would still be some library issues between Phobos and gPhobos, like std.c.osx.osx verus std.c.unix.unix, but that's another story... --anders
Feb 14 2009
But yeah, it would be nice if DMD could set *both* "version(darwin)" and "version(OSX)" for Mac OS X. That way the old code would work too.... and it did. :-) --anders
Feb 14 2009
Anders F Björklund wrote:But yeah, it would be nice if DMD could set both "version(darwin)" and "version(OSX)" for Mac OS X. That way the old code would work too.LDC will also add the OSX version specifier for Mac OS X. Christian
Feb 15 2009
Walter Bright, el 10 de febrero a las 17:16 me escribiste:You should probably distribute meld with DMD then ;) -- Leandro Lucarella (luca) | Blog colectivo: http://www.mazziblog.com.ar/blog/ ---------------------------------------------------------------------------- GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145 104C 949E BFB6 5F5A 8D05) ---------------------------------------------------------------------------- Hey you, out there on your own Sitting naked by the phone Would you touch me?meld is particularly nice. Andrei showed it to me: http://www.linux.com/feature/61372Because of D's limited support for text macros, I am using third party tools to get me out of this problem too.Duplicating (nearly all of a) source file is NOT, repeat NOT, a satisfatory solution.I'm not insensitive to this as I do it myself in maintaining Phobos. It is a problem, but not a huge one. I find that the meld utility (on linux) makes this chore a snap.
Feb 11 2009
Leandro Lucarella wrote:You should probably distribute meld with DMD then ;)sudo apt-get install meld isn't that hard <g>.
Feb 11 2009
Reply to Walter,Leandro Lucarella wrote:doesn't work unless you have apt-get working, doesn't work unless you have a net connection, doesn't work if you don't have root... OTOH a tarball doesn't work on any other platform, but then again nether does DMD.You should probably distribute meld with DMD then ;)sudo apt-get install meld isn't that hard <g>.
Feb 11 2009
BCS wrote:Reply to Walter,You can't download dmd.zip without a net connection, either!Leandro Lucarella wrote:doesn't work unless you have apt-get working, doesn't work unless you have a net connection, doesn't work if you don't have root... OTOH a tarball doesn't work on any other platform, but then again nether does DMD.You should probably distribute meld with DMD then ;)sudo apt-get install meld isn't that hard <g>.
Feb 11 2009
Hello Walter,BCS wrote:last I checked you cant use apt-get over sneeker net.Reply to Walter,You can't download dmd.zip without a net connection, either!Leandro Lucarella wrote:doesn't work unless you have apt-get working, doesn't work unless you have a net connection, doesn't work if you don't have root... OTOH a tarball doesn't work on any other platform, but then again nether does DMD.You should probably distribute meld with DMD then ;)sudo apt-get install meld isn't that hard <g>.
Feb 11 2009
BCS wrote:Hello Walter,I believe 'apt-get install' actually will work so long as the sources/.deb are in the right location. That said, I haven't ever tried it. ;) If nothing else, you should be able to use dpkg. Lucky Gentoo users can use emerge directly. -- Chris Nicholson-SaulsBCS wrote:last I checked you cant use apt-get over sneeker net.Reply to Walter,You can't download dmd.zip without a net connection, either!Leandro Lucarella wrote:doesn't work unless you have apt-get working, doesn't work unless you have a net connection, doesn't work if you don't have root... OTOH a tarball doesn't work on any other platform, but then again nether does DMD.You should probably distribute meld with DMD then ;)sudo apt-get install meld isn't that hard <g>.
Feb 11 2009
BCS wrote:Hello Walter,`wget $URL_OF_PACKAGE` to download it, and (I believe; it's been a while since I did this...) `dpkg -i $PACKAGE_FILE` to install it. That, or you can apt-get on one machine, look at what it downloads and installs, and copy the cached .debs to another machine. :) -- DanielBCS wrote:last I checked you cant use apt-get over sneeker net.Reply to Walter,You can't download dmd.zip without a net connection, either!Leandro Lucarella wrote:doesn't work unless you have apt-get working, doesn't work unless you have a net connection, doesn't work if you don't have root... OTOH a tarball doesn't work on any other platform, but then again nether does DMD.You should probably distribute meld with DMD then ;)sudo apt-get install meld isn't that hard <g>.
Feb 11 2009
"Walter Bright" wrotebobef wrote:There can exist a happy medium between the rigid current design and the disaster that is #if.I was thinking... what is the point of version() ? It is so inflexible. There is no even version(!...). Why not "static if(version(DMD))" or static if(is(version == DMD))?The version statement is designed to be inflexible. It's designed to encourage abstracting and modularizing version differences, rather than encouraging line-by-line differences. I've used #if/#endif for decades. Over time, it *always* degenerates into an utter rat's nest of nested, incomprehensible complexity (and this includes my own code). For a lovely example of how bad it can get, take a look at the source code to Hans Boehm's garbage collector. I defy anyone to figure it out without running the code through the preprocessor first to see which statements are actually getting compiled.2. version (A || B) can be done as: version (A) version=AorB; version (B) version=AorB;And it would be much nicer NOT to have to do this. I think your original position of "let's not get into #if hell" has absolutely (and I mean *absolutely*) no merit as an argument against this one change. Think of code that is versioned around architecture that would look horrendous if you have to do version statements that have all different combinations of stuff. If I have 5 different architectures to support, I don't want to have to define a module that has 2^5 different version combinations. On top of that, the way versioning works, you need 2^4 * 5 different statements: version(A) { version = AorB; version = AorC; version = AorD; version = AorE; version = AorBorC; version = AorBorD; // ad nauseum. } version(B) { // oh fun! let's do it again!!!! version = AorB; version = BorC; version = BorD; ... } When I add another architecture, *gasp* I have to double the statements (to do them now with and without version(F) ), and now I have to do another 2^5 statements for the version(F) block. Wheee! Add to this nightmare that I have to worry about syntax errors, or doing stupid shit like: version(BorA) // whoops, it's spelled AorB stupid! no compiler error given All this can be reduced to 0 statements, and 0 headache if the logical || can be used. This is why we have computers, so we don't have to calculate this stuff. Please don't make me use my brain and typing skills where a computer is soooo much better.3. version (A && B) can be done as: version (A) version (B) { ... }This isn't as bad of a problem as ||, but still could be nicer as the suggested && syntax. But I'd be ok with having just the ||.5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do. If you need to 'comment out' a section of syntactically invalid code, use the /+ ... +/ nesting comment.Just so you know, this is not a solution. We all know that the main reason people ask for this is to have code that can compile with D1 or D2 using versioning. /+ .. +/ doesn't help there. -Steve
Feb 10 2009
Steven Schveighoffer wrote:"Walter Bright" wroteIf you find yourself doing that a lot in the code, then I suggest a better solution is to rethink exactly which versions are being produced, and come up with a set of version identifiers, one for each actual version.2. version (A || B) can be done as: version (A) version=AorB; version (B) version=AorB;And it would be much nicer NOT to have to do this.I think your original position of "let's not get into #if hell" has absolutely (and I mean *absolutely*) no merit as an argument against this one change.The defense submits as Exhibit A just one snippet from Hans Boehm gc's os_dep.c (note all it uses in #if expressions is ||): =============================== typedef void (*handler)(int); typedef void (*handler)(); || defined(HURD) || defined(NETBSD) static struct sigaction old_segv_act; || defined(HURD) || defined(NETBSD) static struct sigaction old_bus_act; static handler old_segv_handler, old_bus_handler; void GC_set_and_save_fault_handler(handler h) void GC_set_and_save_fault_handler(h) handler h; { || defined(OSF1) || defined(HURD) || defined(NETBSD) struct sigaction act; act.sa_handler = h; /* NetBSD bugs. */ act.sa_flags = SA_RESTART | SA_NODEFER; act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0); (void) sigaction(SIGSEGV, &act, &old_segv_act); || defined(HPUX) || defined(HURD) || defined(NETBSD) /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); old_segv_handler = signal(SIGSEGV, h); old_bus_handler = signal(SIGBUS, h); } =============================== The rest of that file is ALL like that. That one little innocuous change opens the door to hell <g>. (Disclaimer: I do not mean to throw tomatoes specifically at Hans here, I know Hans personally and I am in awe of his programming knowledge skill. It's just that many developers have worked on that gc, each one layering on another gob of conditional compilation. This result is typical of C code that's been maintained for years, and you'll find a similar mess in my own code. I didn't want to use my own code as the example of hell because that is too easily dismissed as a personal failing of mine, and that professionals wouldn't do that. But they do. C lends itself to and encourages this kind of programming.)Think of code that is versioned around architecture that would look horrendous if you have to do version statements that have all different combinations of stuff. If I have 5 different architectures to support, I don't want to have to define a module that has 2^5 different version combinations.Is your code really intended to actually build 32 different versions? May I suggest instead building the 5 architecture versions, and using runtime switches for the variants? Or perhaps abstracting the particular features out into separate modules?When I add another architecture, *gasp* I have to double the statements (to do them now with and without version(F) ), and now I have to do another 2^5 statements for the version(F) block. Wheee!You're right, that is untenable. What I suggest instead is creating a module: module PersonalityForF; with all the oddities for F exported as constants, aliases, types and functions. This makes it easier for the maintenance developer who needs to do G, he knows he's just got to write a PersonalityForG module rather than edit the source code for dozens of other modules that have embedded version stuff. It also eliminates the risk of breakage of those other modules for the other platforms. (When I do a port of my projects to new platform F, I often inadvertently break A and C because the code for A, C and F are all mixed up together.) I'm currently working on the Mac port, and am encountering exactly these kinds of problems. One bright spot is I abstracted all the platform specific library reading/writing code out into a separate file rather than using any conditional compilation. This has worked out extremely well. No "os_dep.c" disaster file.I know, and I have the same issues with Phobos. See my reply to Derek.5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do. If you need to 'comment out' a section of syntactically invalid code, use the /+ ... +/ nesting comment.Just so you know, this is not a solution. We all know that the main reason people ask for this is to have code that can compile with D1 or D2 using versioning. /+ .. +/ doesn't help there.
Feb 10 2009
On Wed, 11 Feb 2009 01:33:12 +0300, Walter Bright <newshound1 digitalmars.com> wrote:Steven Schveighoffer wrote:Ok, I've imagined that Boehm GC is written in D and went into a trouble of rewriting the #if/else/endif stuf into versioning blocks: version(NEED_FIND_LIMIT) version = NEED_FIND_LIMIT_or_UNIT_LIKE; version(UNIX_LIKE) version = NEED_FIND_LIMIT_or_UNIT_LIKE; version(NEED_FIND_LIMIT_or_UNIT_LIKE) { version (__STDC__) { typedef void (*handler)(int); } else { typedef void (*handler)(); } version (SUNOS5SIGS) version = SUNOS5SIGS_or_IRIX5_or_OSF1_or_HURD_or_NETBSD; version (IRIX5) version = SUNOS5SIGS_or_IRIX5_or_OSF1_or_HURD_or_NETBSD; version (OSF1) version = SUNOS5SIGS_or_IRIX5_or_OSF1_or_HURD_or_NETBSD; version (HURD) version = SUNOS5SIGS_or_IRIX5_or_OSF1_or_HURD_or_NETBSD; version (NETBSD) version = SUNOS5SIGS_or_IRIX5_or_OSF1_or_HURD_or_NETBSD; version (IRIX5) version = IRIX5_or_HPUX_or_HURD_or_NETBSD; version (HPUX) version = IRIX5_or_HPUX_or_HURD_or_NETBSD; version (HURD) version = IRIX5_or_HPUX_or_HURD_or_NETBSD; version (NETBSD) version = IRIX5_or_HPUX_or_HURD_or_NETBSD; version (SUNOS5SIGS_or_IRIX5_or_OSF1_or_HURD_or_NETBSD) { static struct sigaction old_segv_act; version (IRIX5_or_HPUX_or_HURD_or_NETBSD) { static struct sigaction old_bus_act; } } else { static handler old_segv_handler, old_bus_handler; } version (__STDC__) { void GC_set_and_save_fault_handler(handler h) } else { void GC_set_and_save_fault_handler(h) handler h; } { version(SUNOS5SIGS_or_IRIX5_or_OSF1_or_HURD_or_NETBSD) { struct sigaction act; act.sa_handler = h; version(false) { /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ act.sa_flags = SA_RESTART | SA_NODEFER; } else { act.sa_flags = SA_RESTART; } (void) sigemptyset(&act.sa_mask); version(GC_IRIX_THREADS) { /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0); } else { (void) sigaction(SIGSEGV, &act, &old_segv_act); version (IRIX5_or_HPUX_or_HURD_or_NETBSD) { /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); } } } else { old_segv_handler = signal(SIGSEGV, h); version (SIGBUS) { old_bus_handler = signal(SIGBUS, h); } } } } more powerful that I'd happily exchange version them just to avoid code duplication hell in my source code files."Walter Bright" wroteIf you find yourself doing that a lot in the code, then I suggest a better solution is to rethink exactly which versions are being produced, and come up with a set of version identifiers, one for each actual version.2. version (A || B) can be done as: version (A) version=AorB; version (B) version=AorB;And it would be much nicer NOT to have to do this.I think your original position of "let's not get into #if hell" has absolutely (and I mean *absolutely*) no merit as an argument against this one change.The defense submits as Exhibit A just one snippet from Hans Boehm gc's os_dep.c (note all it uses in #if expressions is ||): =============================== typedef void (*handler)(int); typedef void (*handler)(); || defined(HURD) || defined(NETBSD) static struct sigaction old_segv_act; || defined(HURD) || defined(NETBSD) static struct sigaction old_bus_act; static handler old_segv_handler, old_bus_handler; void GC_set_and_save_fault_handler(handler h) void GC_set_and_save_fault_handler(h) handler h; { || defined(OSF1) || defined(HURD) || defined(NETBSD) struct sigaction act; act.sa_handler = h; */ /* NetBSD bugs. */ act.sa_flags = SA_RESTART | SA_NODEFER; act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0); (void) sigaction(SIGSEGV, &act, &old_segv_act); || defined(HPUX) || defined(HURD) || defined(NETBSD) /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); old_segv_handler = signal(SIGSEGV, h); old_bus_handler = signal(SIGBUS, h); } ===============================The rest of that file is ALL like that. That one little innocuous change opens the door to hell <g>. (Disclaimer: I do not mean to throw tomatoes specifically at Hans here, I know Hans personally and I am in awe of his programming knowledge skill. It's just that many developers have worked on that gc, each one layering on another gob of conditional compilation. This result is typical of C code that's been maintained for years, and you'll find a similar mess in my own code. I didn't want to use my own code as the example of hell because that is too easily dismissed as a personal failing of mine, and that professionals wouldn't do that. But they do. C lends itself to and encourages this kind of programming.)The story is not about different functionality on different platforms but rather about a common code which is 98% the same on all the platforms and is different in *small* details. For example, I'd like to make my library D1 and D2 compatible. Do you suggest me to maintain 2 different libraries? This is ridiculous, and that's why there is no Tango2 release yet - there is *no* point in supporting such a large library as Tango (or DWT) for two language versions without a sane versioning mechanism.Think of code that is versioned around architecture that would look horrendous if you have to do version statements that have all different combinations of stuff. If I have 5 different architectures to support, I don't want to have to define a module that has 2^5 different version combinations.Is your code really intended to actually build 32 different versions? May I suggest instead building the 5 architecture versions, and using runtime switches for the variants? Or perhaps abstracting the particular features out into separate modules?When I add another architecture, *gasp* I have to double the statements (to do them now with and without version(F) ), and now I have to do another 2^5 statements for the version(F) block. Wheee!You're right, that is untenable. What I suggest instead is creating a module: module PersonalityForF; with all the oddities for F exported as constants, aliases, types and functions. This makes it easier for the maintenance developer who needs to do G, he knows he's just got to write a PersonalityForG module rather than edit the source code for dozens of other modules that have embedded version stuff. It also eliminates the risk of breakage of those other modules for the other platforms. (When I do a port of my projects to new platform F, I often inadvertently break A and C because the code for A, C and F are all mixed up together.) I'm currently working on the Mac port, and am encountering exactly these kinds of problems. One bright spot is I abstracted all the platform specific library reading/writing code out into a separate file rather than using any conditional compilation. This has worked out extremely well. No "os_dep.c" disaster file.I know, and I have the same issues with Phobos. See my reply to Derek.5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do. If you need to 'comment out' a section of syntactically invalid code, use the /+ ... +/ nesting comment.Just so you know, this is not a solution. We all know that the main reason people ask for this is to have code that can compile with D1 or D2 using versioning. /+ .. +/ doesn't help there.
Feb 10 2009
Denis Koroskin wrote:Does it look any better? No way!Of course doing it that way doesn't look any better, because it still just replicates the C preprocessor style of doing it. A far better solution is to create a series of modules: gcnetbsd.d gchurd.d gcsunos5.d ... and inside each one put the specifics for that particular system. The huge advantage of this is that if I want to create a BrightBSD operating system, I just have to write a: gcbrightbsd.d rather than trying to carefully fold it into that conditional compilation mess without inadvertently breaking other platform support. (And I cannot even tell if I broke the SunOS5 platform support or not, because I don't have a SunOS5 platform to test it on.)The story is not about different functionality on different platforms but rather about a common code which is 98% the same on all the platforms and is different in *small* details. For example, I'd like to make my library D1 and D2 compatible. Do you suggest me to maintain 2 different libraries? This is ridiculous, and that's why there is no Tango2 release yet - there is *no* point in supporting such a large library as Tango (or DWT) for two language versions without a sane versioning mechanism.There are two very different things going on here. One is accounting for differences in the *language*, the other is about generating different builds based on language independent different desired features and platform characteristics. I agree that version is not a solution to the D1/D2 language difference problem, and furthermore contend it cannot be coerced into being one. The only real solution, other than maintaining separate source files, is to use a text macro preprocessor. (Sadly, the C preprocessor cannot be used, because it is a tokenizing textual preprocessor, and C preprocessor tokens are different from D tokens.)
Feb 10 2009
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmt6l0$rff$1 digitalmars.com...Denis Koroskin wrote:Which just goes to show that the restrictions you've placed on D's version() (in order to eliminate rat's nest versioning) DON'T eliminate rat's nest versioning.Does it look any better? No way!Of course doing it that way doesn't look any better, because it still just replicates the C preprocessor style of doing it.A far better solution...And we can come up with better solutions for C as well. Granted, the optimal D solution is going to be much better than the optimal C solution, but it won't be due to version()'s lack of !, ||, &&, etc...
Feb 10 2009
Nick Sabalausky wrote:"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmt6l0$rff$1 digitalmars.com...But they do make it more painful to write the rat's nest, which can be motivating to find a more appropriate solution.Denis Koroskin wrote:Which just goes to show that the restrictions you've placed on D's version() (in order to eliminate rat's nest versioning) DON'T eliminate rat's nest versioning.Does it look any better? No way!Of course doing it that way doesn't look any better, because it still just replicates the C preprocessor style of doing it.When cookies and veggies are laid out on the buffet, I tend to reach for the cookies <g>.A far better solution...And we can come up with better solutions for C as well. Granted, the optimal D solution is going to be much better than the optimal C solution, but it won't be due to version()'s lack of !, ||, &&, etc...
Feb 10 2009
"Walter Bright" wroteNick Sabalausky wrote:And when the rats nest MUST be created? Why make it more painful? I'm sure if Hans Bohem could write it in a clearer fashion he would have. To be perfectly clear, I absolutely agree with version statements not messing with the separation between semantic analysis and parsing, but these shortcuts for having multiple version identifiers in one statement do not hurt anything. I contend it is the lack of separation in C's preprocessor that makes it difficult to understand, not the lack of requirements on the #if itself. At least, that's what I've always hated about C/C++ preprocessor. The same arguments could be said about actual if statements in code, yet you have no qualms not forcing people to combine their logic into boolean variables before using an if statement."Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmt6l0$rff$1 digitalmars.com...But they do make it more painful to write the rat's nest, which can be motivating to find a more appropriate solution.Denis Koroskin wrote:Which just goes to show that the restrictions you've placed on D's version() (in order to eliminate rat's nest versioning) DON'T eliminate rat's nest versioning.Does it look any better? No way!Of course doing it that way doesn't look any better, because it still just replicates the C preprocessor style of doing it.It's more like moldy cookies and half-eaten donuts :) Neither looks appetizing, but when your really hungry... -SteveWhen cookies and veggies are laid out on the buffet, I tend to reach for the cookies <g>.A far better solution...And we can come up with better solutions for C as well. Granted, the optimal D solution is going to be much better than the optimal C solution, but it won't be due to version()'s lack of !, ||, &&, etc...
Feb 10 2009
Steven Schveighoffer wrote:And when the rats nest MUST be created? Why make it more painful? I'm sure if Hans Bohem could write it in a clearer fashion he would have.Hans is in a trap with it. If he reengineered it, he very likely would break many platforms, and he does not have those platforms and has no way to test. The code is very brittle, and it would take a lot of guts to try and reorganize it. The hbgc is a collection of code submitted by many, many people.The same arguments could be said about actual if statements in code, yet you have no qualms not forcing people to combine their logic into boolean variables before using an if statement.It's not the same, because versions tend to slice through whole programs in an unstructured manner, while garden variety if statements are structured and local.
Feb 10 2009
"Walter Bright" wroteDenis Koroskin wrote:All you have done is split the mess into separate files. This does not solve the problem.Does it look any better? No way!Of course doing it that way doesn't look any better, because it still just replicates the C preprocessor style of doing it. A far better solution is to create a series of modules: gcnetbsd.d gchurd.d gcsunos5.d ... and inside each one put the specifics for that particular system. The huge advantage of this is that if I want to create a BrightBSD operating system, I just have to write a: gcbrightbsd.drather than trying to carefully fold it into that conditional compilation mess without inadvertently breaking other platform support. (And I cannot even tell if I broke the SunOS5 platform support or not, because I don't have a SunOS5 platform to test it on.).But you have, because inadvertently, you changed some code in the actual implementation to use the new identifiers you made in your special new file. Now you have to go back and rethink the sunos include because you broke it. Mess still exists. (of course, I have no idea, but I gave you as much of an example/proof as you did ;)That I would agree, and it turns out your example suffers from the same issues, i.e. #if __STDC__ -SteveThe story is not about different functionality on different platforms but rather about a common code which is 98% the same on all the platforms and is different in *small* details. For example, I'd like to make my library D1 and D2 compatible. Do you suggest me to maintain 2 different libraries? This is ridiculous, and that's why there is no Tango2 release yet - there is *no* point in supporting such a large library as Tango (or DWT) for two language versions without a sane versioning mechanism.There are two very different things going on here. One is accounting for differences in the *language*, the other is about generating different builds based on language independent different desired features and platform characteristics.
Feb 10 2009
Steven Schveighoffer wrote:"Walter Bright" wroteHow does it not solve the problem?Denis Koroskin wrote:All you have done is split the mess into separate files. This does not solve the problem.Does it look any better? No way!Of course doing it that way doesn't look any better, because it still just replicates the C preprocessor style of doing it. A far better solution is to create a series of modules: gcnetbsd.d gchurd.d gcsunos5.d ... and inside each one put the specifics for that particular system. The huge advantage of this is that if I want to create a BrightBSD operating system, I just have to write a: gcbrightbsd.dSee my example of O_APPEND for the proof that it does solve the problem without breaking other platforms.rather than trying to carefully fold it into that conditional compilation mess without inadvertently breaking other platform support. (And I cannot even tell if I broke the SunOS5 platform support or not, because I don't have a SunOS5 platform to test it on.).But you have, because inadvertently, you changed some code in the actual implementation to use the new identifiers you made in your special new file. Now you have to go back and rethink the sunos include because you broke it. Mess still exists. (of course, I have no idea, but I gave you as much of an example/proof as you did ;)
Feb 10 2009
"Walter Bright" wroteSteven Schveighoffer wrote:I assume that the rats nest is necessary for the code to function. Splitting up the rats nest into either a) mostly duplicated rats nests, or b) individual chunks of rats nest still constitutes a rat's nest."Walter Bright" wroteHow does it not solve the problem?Denis Koroskin wrote:All you have done is split the mess into separate files. This does not solve the problem.Does it look any better? No way!Of course doing it that way doesn't look any better, because it still just replicates the C preprocessor style of doing it. A far better solution is to create a series of modules: gcnetbsd.d gchurd.d gcsunos5.d ... and inside each one put the specifics for that particular system. The huge advantage of this is that if I want to create a BrightBSD operating system, I just have to write a: gcbrightbsd.dThat example has nothing to do with || being allowed, and nothing to do with your exhibit B. Your simple example makes sense to split into multiple files, but you simply waved your magic "split into multiple files" wand at Hans' code and because of the simplicity of D's versioning system, it's more maintainable? I find it hard to believe without proof. Besides, your example exists *without* any new features to the versioning system. That is, your example just shows how it's easier to maintain if you put the version identifier at the outermost layer, instead of in the innermost layer, and I agree with you there. I just want to try and get rid of the cruft of: version(A) version = AorB; version(B) version = AorB; If you want to prove how much easier it is, actually split Hans' rat's nest into multiple files how you would do it, and I'll show you that it isn't any harder to maintain if you use ||. I think Nick already showed how much more readable it is in one file (although he did also use ! in addition to || and &&). -SteveSee my example of O_APPEND for the proof that it does solve the problem without breaking other platforms.rather than trying to carefully fold it into that conditional compilation mess without inadvertently breaking other platform support. (And I cannot even tell if I broke the SunOS5 platform support or not, because I don't have a SunOS5 platform to test it on.).But you have, because inadvertently, you changed some code in the actual implementation to use the new identifiers you made in your special new file. Now you have to go back and rethink the sunos include because you broke it. Mess still exists. (of course, I have no idea, but I gave you as much of an example/proof as you did ;)
Feb 10 2009
Steven Schveighoffer wrote:That example has nothing to do with || being allowed, and nothing to do with your exhibit B. Your simple example makes sense to split into multiple files, but you simply waved your magic "split into multiple files" wand at Hans' code and because of the simplicity of D's versioning system, it's more maintainable? I find it hard to believe without proof.I cannot prove to you in any mathematical sort of way. All I can say is that I have a lot of experience doing things both ways, and what the results are. I can readily believe that it isn't obvious until one has done it both ways; programming is full of examples of such. Such as: #define BEGIN { #define END } I can't prove that's a bad idea, either. But experience shows it is <g>.Besides, your example exists *without* any new features to the versioning system. That is, your example just shows how it's easier to maintain if you put the version identifier at the outermost layer, instead of in the innermost layer, and I agree with you there. I just want to try and get rid of the cruft of: version(A) version = AorB; version(B) version = AorB;I think I've been misunderstood here. I never intended one to actually use the "or" string in a version, my intent was that one determine just what the feature is that is AorB, and name the identifier that. For example: version (linux) version = Pthreads; version (OSX) version = Pthreads; version (Pthreads) ... else version (Windows) ... I don't consider that cruft, but very reasonable self-documentation.If you want to prove how much easier it is, actually split Hans' rat's nest into multiple files how you would do it, and I'll show you that it isn't any harder to maintain if you use ||.I already did port it once, many years ago, it's why I know how hard it is. Take a look at D's gc which uses personality modules. I ported that to the mac pretty easily and never touched the main code. I can't even figure out where the mac osx code is in the hbgc or what would need to be changed for it. I couldn't even figure out if the hbgc supported OSX or not. To sum up, I've done it both ways. The personality module method approach is head and shoulders the clear winner.
Feb 10 2009
On Tue, 10 Feb 2009 19:28:46 -0800, Walter Bright wrote:Steven Schveighoffer wrote:It's bad. I agree with you. I also have bad experiences with the preprocessor, one of the reasons I looked for something like D in the first place, and one of the reasons I'm leary of macros. I'm not asking for the C preprocessor. I'm asking for a bit of syntax sugar to avoid unmaintainable tables of expanded if statements. What I mean by expanded if statements is that you are making me expand: if(a || b) statement; into bool aorb = false; if(a) aorb = true; if(b) aorb = true; if(c) statement; Let's take a trip to analogy land. It's like you are saying you have been bit by a tiger in the past. Therefore, you dislike all animals, because they remind you of tigers, and who could blame you. But because of your position of power, you have passed a law that *nobody* can like animals, for their own good. Why not just avoid animals on your own, and let others have their tame animals?That example has nothing to do with || being allowed, and nothing to do with your exhibit B. Your simple example makes sense to split into multiple files, but you simply waved your magic "split into multiple files" wand at Hans' code and because of the simplicity of D's versioning system, it's more maintainable? I find it hard to believe without proof.I cannot prove to you in any mathematical sort of way. All I can say is that I have a lot of experience doing things both ways, and what the results are. I can readily believe that it isn't obvious until one has done it both ways; programming is full of examples of such. Such as: #define BEGIN { #define END } I can't prove that's a bad idea, either. But experience shows it is <g>.This is still cruft. I'd consider this to be more succinct and just as self documenting (as well as more maintainable, I no longer have to change the string Pthreads in multiple locations in the declaration of it). version(linux || OSX) version = Pthreads; ...Besides, your example exists *without* any new features to the versioning system. That is, your example just shows how it's easier to maintain if you put the version identifier at the outermost layer, instead of in the innermost layer, and I agree with you there. I just want to try and get rid of the cruft of: version(A) version = AorB; version(B) version = AorB;I think I've been misunderstood here. I never intended one to actually use the "or" string in a version, my intent was that one determine just what the feature is that is AorB, and name the identifier that. For example: version (linux) version = Pthreads; version (OSX) version = Pthreads; version (Pthreads) ... else version (Windows) ... I don't consider that cruft, but very reasonable self-documentation.That's all fine, and I pretty much agree with you, but I think we are arguing apples and oranges. In what way does using || in a version statement prevent or even discourage you from separating out your versions into modules based on platforms or personality? It seems like a design preference that is orthogonal to this feature. For instance, two developers quite easily translated the complicated C preprocessor example you gave into version statements for the *current* version system. So it's still possible to have unmaintainable, unreadable code without || as a feature. All I'm asking is to make this: version(x || y) turn into this: version(x) version = xory; version(y) version = xory; version(xory) automatically by the compiler. I shouldn't have to do that bit of manual compilation. -SteveIf you want to prove how much easier it is, actually split Hans' rat's nest into multiple files how you would do it, and I'll show you that it isn't any harder to maintain if you use ||.I already did port it once, many years ago, it's why I know how hard it is. Take a look at D's gc which uses personality modules. I ported that to the mac pretty easily and never touched the main code. I can't even figure out where the mac osx code is in the hbgc or what would need to be changed for it. I couldn't even figure out if the hbgc supported OSX or not. To sum up, I've done it both ways. The personality module method approach is head and shoulders the clear winner.
Feb 10 2009
On Wed, 11 Feb 2009 05:43:48 +0000, Steve Schveighoffer wrote:What I mean by expanded if statements is that you are making me expand: if(a || b) statement; into bool aorb = false; if(a) aorb = true; if(b) aorb = true; if(c) statement;This should have been if(aorb) statement; -Steve
Feb 10 2009
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmsvb8$e1p$1 digitalmars.com...Steven Schveighoffer wrote:{horrid mess of C snipped}I think your original position of "let's not get into #if hell" has absolutely (and I mean *absolutely*) no merit as an argument against this one change.The defense submits as Exhibit A just one snippet from Hans Boehm gc's os_dep.c (note all it uses in #if expressions is ||): ============================================================== The rest of that file is ALL like that. That one little innocuous change opens the door to hell <g>.Ok, but now with D-style version(), that horrid mess becomes this horrid mess: ====================== version(SUNOS5SIGS) { version=SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD; version=IRIX5orHPUXorHURDorNETBSD; } version(IRIX5) { version=SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD; version=IRIX5orHPUXorHURDorNETBSD; } version(OSF1) { version=SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD; } version(HURD) { version=SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD; version=IRIX5orHPUXorHURDorNETBSD; } version(NETBSD) { version=SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD; version=IRIX5orHPUXorHURDorNETBSD; } version(HPUX) { version=IRIX5orHPUXorHURDorNETBSD; } version(NEED_FIND_LIMIT) { version=NEED_FIND_LIMITorUNIX_LIKE; } version(UNIX_LIKE) { version=NEED_FIND_LIMITorUNIX_LIKE; } version(NEED_FIND_LIMITorUNIX_LIKE) { version(__STDC__) typedef void (*handler)(int); else typedef void (*handler)(); version(SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD) { static struct sigaction old_segv_act; version(IRIX5orHPUXorHURDorNETBSD) static struct sigaction old_bus_act; } else static handler old_segv_handler, old_bus_handler; version(__STDC__) // This would need an additional workaround due to syntax issues { void GC_set_and_save_fault_handler(handler h) { version(SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD) { struct sigaction act; act.sa_handler = h; version(none) /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ act.sa_flags = SA_RESTART | SA_NODEFER; else act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); version(GC_IRIX_THREADS) { /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0); } else { (void) sigaction(SIGSEGV, &act, &old_segv_act); version(IRIX5orHPUXorHURDorNETBSD) { /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); } } } else { old_segv_handler = signal(SIGSEGV, h); version(SIGBUS) old_bus_handler = signal(SIGBUS, h); } } } else { void GC_set_and_save_fault_handler(h) handler h; { version(SUNOS5SIGSorIRIX5orOSF1orHURDorNETBSD) { struct sigaction act; act.sa_handler = h; version(none) /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ act.sa_flags = SA_RESTART | SA_NODEFER; else act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); version(GC_IRIX_THREADS) { /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0); } else { (void) sigaction(SIGSEGV, &act, &old_segv_act); version(IRIX5orHPUXorHURDorNETBSD) { /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); } } } else { old_segv_handler = signal(SIGSEGV, h); version(SIGBUS) old_bus_handler = signal(SIGBUS, h); } } } } ====================== Ok, look, we're still knee-deep in hell! So now you say, "But wait! In D-style, you should change all that to this:" ====================== module MyGC; version(SUNOS5SIGS) version=SunnyishOS; version(IRIX5) version=SunnyishOS; version(HURD) version=SunnyishOS; version(NETBSD) version=SunnyishOS; version(NEED_FIND_LIMIT) version=SomethingMeaningful; version(UNIX_LIKE) version=SomethingMeaningful; version(SomethingMeaningful) { version(__STDC__) typedef void (*handler)(int); else typedef void (*handler)(); // Alternatively, we could "invert" these, // ie, #include all of them, and have those // headers take care of their own #ifdef stuff. // Downside is: all platforms would need all sources. version(SunnyishOS) { version(__STDC__) { version(GC_IRIX_THREADS) public import MyGC_SunnyishOS_STDC_IrixThreads; else public import MyGC_SunnyishOS_STDC_NonIrixThreads; } else { version(GC_IRIX_THREADS) public import MyGC_SunnyishOS_KR_IrixThreads; else public import MyGC_SunnyishOS_KR_NonIrixThreads; } } else version(OSF1) { version(__STDC__) { version(GC_IRIX_THREADS) public import MyGC_OSF1_STDC_IrixThreads; else public import MyGC_OSF1_STDC_NonIrixThreads; } else { version(GC_IRIX_THREADS) public import MyGC_OSF1_KR_IrixThreads; else public import MyGC_OSF1_KR_NonIrixThreads; } } //etc... else { version(__STDC__) public import MyGC_MISC_STDC; else public import MyGC_MISC_KR; } } ----- module MyGC_SunnyishOS_STDC_IrixThreads; static struct sigaction old_segv_act; static struct sigaction old_bus_act; void GC_set_and_save_fault_handler(handler h) { struct sigaction act; act.sa_handler = h; /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ //act.sa_flags = SA_RESTART | SA_NODEFER; act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0); } ----- module MyGC_SunnyishOS_KR_NonIrixThreads; static struct sigaction old_segv_act; static struct sigaction old_bus_act; void GC_set_and_save_fault_handler(h) handler h; { struct sigaction act; act.sa_handler = h; /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ //act.sa_flags = SA_RESTART | SA_NODEFER; act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); (void) sigaction(SIGSEGV, &act, &old_segv_act); /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); } ----- module MyGC_MISC_STDC; static handler old_segv_handler, old_bus_handler; void GC_set_and_save_fault_handler(handler h) { old_segv_handler = signal(SIGSEGV, h); version(SIGBUS) old_bus_handler = signal(SIGBUS, h); } ====================== To which I reply, "Yes, and in C-style you should do exactly the same:" ====================== // MyGC.h; #if defined(SUNOS5SIGS) || defined(IRIX5) || defined(HURD) || defined(NETBSD) #endif #if defined(NEED_FIND_LIMIT) || defined(UNIX_LIKE) #endif #ifdef SOMETHING_MEANINGFUL typedef void (*handler)(int); typedef void (*handler)(); // Alternatively, we could "invert" these, // ie, #include all of them, and have those // headers take care of their own #ifdef stuff. // Downside is: all platforms would need all sources. #endif /*SOMETHING_MEANINGFUL*/ ----- // MyGC_SunnyishOS_STDC_IrixThreads.h; static struct sigaction old_segv_act; static struct sigaction old_bus_act; void GC_set_and_save_fault_handler(handler h) { struct sigaction act; act.sa_handler = h; /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ //act.sa_flags = SA_RESTART | SA_NODEFER; act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); /* Older versions have a bug related to retrieving and */ /* and setting a handler at the same time. */ (void) sigaction(SIGSEGV, 0, &old_segv_act); (void) sigaction(SIGSEGV, &act, 0); (void) sigaction(SIGBUS, 0, &old_bus_act); (void) sigaction(SIGBUS, &act, 0); } ----- // MyGC_SunnyishOS_KR_NonIrixThreads.h static struct sigaction old_segv_act; static struct sigaction old_bus_act; void GC_set_and_save_fault_handler(h) handler h; { struct sigaction act; act.sa_handler = h; /* Was necessary for Solaris 2.3 and very temporary */ /* NetBSD bugs. */ //act.sa_flags = SA_RESTART | SA_NODEFER; act.sa_flags = SA_RESTART; (void) sigemptyset(&act.sa_mask); (void) sigaction(SIGSEGV, &act, &old_segv_act); /* Under Irix 5.x or HP/UX, we may get SIGBUS. */ /* Pthreads doesn't exist under Irix 5.x, so we */ /* don't have to worry in the threads case. */ (void) sigaction(SIGBUS, &act, &old_bus_act); } ----- // MyGC_MISC_STDC.h static handler old_segv_handler, old_bus_handler; void GC_set_and_save_fault_handler(handler h) { old_segv_handler = signal(SIGSEGV, h); version(SIGBUS) old_bus_handler = signal(SIGBUS, h); } ====================== And for the record, with the suggested improvements to D's version(), the "good" D-style can change from this: ====================== module MyGC; version(SUNOS5SIGS) version=SunnyishOS; version(IRIX5) version=SunnyishOS; version(HURD) version=SunnyishOS; version(NETBSD) version=SunnyishOS; version(NEED_FIND_LIMIT) version=SomethingMeaningful; version(UNIX_LIKE) version=SomethingMeaningful; version(SomethingMeaningful) { // ugly junk... } // etc... ====================== To this: ====================== module MyGC; version(SUNOS5SIGS || IRIX5 || HURD || NETBSD) version=SunnyishOS; version(NEED_FIND_LIMIT || UNIX_LIKE) { // Alternatively, we could blah blah blah... version(SunnyishOS) { version( __STDC__ && GC_IRIX_THREADS) public import MyGC_SunnyishOS_STDC_IrixThreads; version( __STDC__ && !GC_IRIX_THREADS) public import MyGC_SunnyishOS_STDC_NonIrixThreads; version(!__STDC__ && GC_IRIX_THREADS) public import MyGC_SunnyishOS_KR_IrixThreads; version(!__STDC__ && !GC_IRIX_THREADS) public import MyGC_SunnyishOS_KR_NonIrixThreads; } else version(OSF1) { version( __STDC__ && GC_IRIX_THREADS) public import MyGC_OSF1_STDC_IrixThreads; version( __STDC__ && !GC_IRIX_THREADS) public import MyGC_OSF1_STDC_NonIrixThreads; version(!__STDC__ && GC_IRIX_THREADS) public import MyGC_OSF1_KR_IrixThreads; version(!__STDC__ && !GC_IRIX_THREADS) public import MyGC_OSF1_KR_NonIrixThreads; } //etc... else { version( __STDC__) public import MyGC_MISC_STDC; version(!__STDC__) public import MyGC_MISC_KR; } } //etc... ====================== The point is, the current semantics for D's version() are *plenty* susceptible to most of same versioning mess as C's #if/#ifdef, and in some cases (such as ||), even worse. With either style, the solution is exactly the same as any other chunk of messy code: Clean it up! Not only is gimping the version-control mechanism the wrong solution, it doesn't even solve the problem anyway.
Feb 10 2009
Nick Sabalausky wrote:The point is, the current semantics for D's version() are *plenty* susceptible to most of same versioning mess as C's #if/#ifdef, and in some cases (such as ||), even worse. With either style, the solution is exactly the same as any other chunk of messy code: Clean it up! Not only is gimping the version-control mechanism the wrong solution, it doesn't even solve the problem anyway.I'll argue that I've never seen anyone create such a mess in D, while I see it regularly in C. So something about D is discouraging developing those things. I think the tipping point is that it's too easy in C to slip into writing such a mess without actually trying to, while in D you have to work harder to do it. Hard enough that one might as well do it better in the first place.
Feb 10 2009
On Tue, Feb 10, 2009 at 8:50 PM, Walter Bright <newshound1 digitalmars.com> wrote:I'll argue that I've never seen anyone create such a mess in D, while I see it regularly in C. So something about D is discouraging developing those things.D is also only _really truly_ supported on about three or four platforms, has been around for a fraction of the time C has, and has a core code-producing community of I'd say around 100~150 people. Sample bias.I think the tipping point is that it's too easy in C to slip into writing such a mess without actually trying to, while in D you have to work harder to do it. Hard enough that one might as well do it better in the first place.If nothing - NOTHING - else, please give us version(!something). Out of everything wrong with it, that is the worst. You say that according to "cognitive studies" that people don't see the !; then why didn't you remove it from the rest of the language? And how is THIS: version(Poopy) {} else { } supposedly better?!
Feb 10 2009
Jarrett Billingsley wrote:If nothing - NOTHING - else, please give us version(!something). Out of everything wrong with it, that is the worst. You say that according to "cognitive studies" that people don't see the !; then why didn't you remove it from the rest of the language? And how is THIS: version(Poopy) {} else { } supposedly better?!version(!Windows) // some added functionality that depends on UNIX-like semantics Then port the code to something oddball—Plan 9, say, or VMS. —Joel Salomon
Feb 11 2009
On Wed, Feb 11, 2009 at 9:49 AM, Joel C. Salomon <joelcsalomon gmail.com> w= rote:version(!Windows) // some added functionality that depends on UNIX-like semantics Then port the code to something oddball=97Plan 9, say, or VMS.I use versions for things other than platform-specific code. Like library compilation options.
Feb 11 2009
Jarrett Billingsley wrote:I use versions for things other than platform-specific code. Like library compilation options.So what would your use-case look like? —Joel Salomon
Feb 11 2009
On Wed, Feb 11, 2009 at 2:14 PM, Joel C. Salomon <joelcsalomon gmail.com> wrote:Jarrett Billingsley wrote:version(TurnOffSomeFeature) {} else { codeForFeature(); } Sometimes you want to have things that turn _off_ code from a default of being on. I know, I know, Walter said that "[v]ersions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux." But the fact is, platform-specific stuff and code options are two very different use cases. Platform-specific things are completely invisible to the user of a library and only one configuration can ever be in use on a single platform. Code options, on the other hand, are based on user preference. Some things are extra, and it makes sense to have switches to turn them on. But some things are the other way, where you want them *on* by default and want to have the option of turning them *off*.I use versions for things other than platform-specific code. Like library compilation options.So what would your use-case look like?
Feb 11 2009
Jarrett Billingsley wrote:version(TurnOffSomeFeature) {} else { codeForFeature(); } Sometimes you want to have things that turn _off_ code from a default of being on. I know, I know, Walter said that "[v]ersions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux." But the fact is, platform-specific stuff and code options are two very different use cases. Platform-specific things are completely invisible to the user of a library and only one configuration can ever be in use on a single platform. Code options, on the other hand, are based on user preference. Some things are extra, and it makes sense to have switches to turn them on. But some things are the other way, where you want them *on* by default and want to have the option of turning them *off*.Even if a feature is on by default, versions should still be a positive thing, otherwise you have a double negative: version (!TurnOffSomeFeature) Even in regular code, I try to avoid naming things that way, because double negatives are twice as hard to comprehend when things get complicated. I've gone through my code to remove such double negatives as much as possible. So I suggest: version (SomeFeature) { codeForFeature(); } is clearer, even if SomeFeature is the default.
Feb 11 2009
Walter Bright wrote:So I suggest: version (SomeFeature) { codeForFeature(); } is clearer, even if SomeFeature is the default.Apologies if this is obvious, but: • How do you set SomeFeature as default? and • How do you declare the non-implementation of SomeFeature? —Joel Salomon
Feb 11 2009
Joel C. Salomon wrote:Walter Bright wrote:Either via the command line, or by the statement: version = SomeFeature;So I suggest: version (SomeFeature) { codeForFeature(); } is clearer, even if SomeFeature is the default.Apologies if this is obvious, but: • How do you set SomeFeature as default? and• How do you declare the non-implementation of SomeFeature?Don't declare the version SomeFeature.
Feb 11 2009
On Wed, Feb 11, 2009 at 2:57 PM, Walter Bright <newshound1 digitalmars.com> wrote:Jarrett Billingsley wrote: So I suggest: version (SomeFeature) { codeForFeature(); } is clearer, even if SomeFeature is the default.It might be clearer in the code, but it's far less intuitive for the library user! And if SomeFeature is _not_ defined by default, it's not a very good default, is it!
Feb 11 2009
Jarrett Billingsley wrote:It might be clearer in the code, but it's far less intuitive for the library user!I don't see how.And if SomeFeature is _not_ defined by default, it's not a very good default, is it!Define it by default in your makefile or by a version=SomeFeature; declaration.
Feb 11 2009
On Thu, Feb 12, 2009 at 6:02 AM, Jarrett Billingsley <jarrett.billingsley gmail.com> wrote:On Wed, Feb 11, 2009 at 2:57 PM, Walter Bright <newshound1 digitalmars.com> wrote:I thought he meant this: // once at the top version(SomeFeatureDisabled) { } else { version = SomeFeature; } // in rest of code ... version (SomeFeature) { codeForFeature(); } --bbJarrett Billingsley wrote: So I suggest: version (SomeFeature) { codeForFeature(); } is clearer, even if SomeFeature is the default.It might be clearer in the code, but it's far less intuitive for the library user! And if SomeFeature is _not_ defined by default, it's not a very good default, is it!
Feb 11 2009
"Bill Baxter" <wbaxter gmail.com> wrote in message news:mailman.689.1234386722.22690.digitalmars-d puremagic.com...// once at the top version(SomeFeatureDisabled) { } else { version = SomeFeature; }It would be a hell of a lot nicer if we could just write that as: version SomeFeature = !SomeFeatureDisabled; or even better, something like: version SomeFeature.default = true;
Feb 11 2009
On Wed, Feb 11, 2009 at 4:11 PM, Bill Baxter <wbaxter gmail.com> wrote:I thought he meant this: // once at the top version(SomeFeatureDisabled) { } else { version = SomeFeature; } // in rest of code ... version (SomeFeature) { codeForFeature(); }I don't know whether or not Walter _was_ actually insinuating that but it's a pretty good idea ;) the only disadvantage of course being that I have to copy the //once at the top part into every file that wants to use the SomeFeature version, though that probably wouldn't/shouldn't be a big issue in practice.
Feb 11 2009
Jarrett Billingsley wrote:On Wed, Feb 11, 2009 at 4:11 PM, Bill Baxter <wbaxter gmail.com> wrote:I had the same thought at first when reading the 'version declarations' proposal elsewhere in this thread, and was going to put forth having to write 'version Tango = extern;' at the top of modules as an example of what could be bad about it... but then it occurred to me how often I've ever had to use version(Tango) in the first place. (Not very often at all.) It would be the sort of thing you use just here and there, and is actually self-documenting in the process, as it makes it clear that /this/ module is going to fork on certain versions. Despite reservations, its all growing on me. -- Chris Nicholson-SaulsI thought he meant this: // once at the top version(SomeFeatureDisabled) { } else { version = SomeFeature; } // in rest of code ... version (SomeFeature) { codeForFeature(); }I don't know whether or not Walter _was_ actually insinuating that but it's a pretty good idea ;) the only disadvantage of course being that I have to copy the //once at the top part into every file that wants to use the SomeFeature version, though that probably wouldn't/shouldn't be a big issue in practice.
Feb 11 2009
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmtatl$12om$2 digitalmars.com...Nick Sabalausky wrote:Agreed, but I'm certain that a significant reason for that is the fact that (and I mean no disrespect to D by this) C has had far more people working on a far larger number of projects that each span far more platforms all for a far longer time. Just look at all of the platforms supported by that GC example. Even the D language itself isn't that multi-platform yet. And then there's all of that GNU C code that's been around much longer than even D itself. If D had the ubiquity of C (as I hope someday it will), then D would have plenty of mess too. Not as much, granted (for reasons I argue below), but still a fair amount.The point is, the current semantics for D's version() are *plenty* susceptible to most of same versioning mess as C's #if/#ifdef, and in some cases (such as ||), even worse. With either style, the solution is exactly the same as any other chunk of messy code: Clean it up! Not only is gimping the version-control mechanism the wrong solution, it doesn't even solve the problem anyway.I'll argue that I've never seen anyone create such a mess in D, while I see it regularly in C.So something about D is discouraging developing those things. I think the tipping point is that it's too easy in C to slip into writing such a mess without actually trying to, while in D you have to work harder to do it.I agree there are things about D that discourage such messy tactics, but I don't think it's the lack of !, ||, && and expression-level usage. I think, as Steven said, that the discouragement comes more from version() being a syntactic/semantic part of the language itself instead of a blunt text-replacement engine that neither knows nor cares what it tramples over. That's why you have to work harder to make a conditional-compilation mess, not because it lacks a few features. Plus, the C preprocessor's syntax automatically invokes a mental association with "blunt text-editing tool" and I think that's a big part of why C coders slip into the mess. D's version() and static if() *look* like an ordinary if(), so that alone is going to decrease urges to use them like a C preprocessor.
Feb 10 2009
Steven Schveighoffer wrote:"Walter Bright" wrote Think of code that is versioned around architecture that would look horrendous if you have to do version statements that have all different combinations of stuff. If I have 5 different architectures to support, I don't want to have to define a module that has 2^5 different version combinations. On top of that, the way versioning works, you need 2^4 * 5 different statements: version(A) { version = AorB; version = AorC; version = AorD; version = AorE; version = AorBorC; version = AorBorD; // ad nauseum. } version(B) { // oh fun! let's do it again!!!! version = AorB; version = BorC; version = BorD; ... } When I add another architecture, *gasp* I have to double the statements (to do them now with and without version(F) ), and now I have to do another 2^5 statements for the version(F) block. Wheee!But this is clearly the wrong way of cutting the pie. What you need is define features that are supported by some of the versions. You don't need to judge in terms of logical operators between versions. version (A) version = canBeUsedToPickupChicks; version (C) version = canBeUsedToPickupChicks; // version (B) no good Andrei
Feb 10 2009
Andrei Alexandrescu wrote:But this is clearly the wrong way of cutting the pie.Right, and I also suggest that it is the C preprocessor way of doing versioning. We're all deep in the C preprocessor rut, and find it difficult to think another way. For example, I learned to program in Fortran. My early C code looks an awful lot like Fortran. People who came to C from Pascal would write things like: #define BEGIN { #define END }
Feb 10 2009
"Andrei Alexandrescu" wroteSteven Schveighoffer wrote:Sometimes, coming up with a better identifier than this || that is not easy. For example, in Tango, there is a version for Posix, which is defined if linux or darwin or bsd is defined, but we sometimes get people arguing that Windows is posix compliant too! Not only that, but are you going to want to define a special identifier in the header file that is used exactly ONCE in your code? Often times, I see this in source files: version(linux) version = specialWay; version(darwin) version = specialWay; Because they need that combination of linux || darwin in one spot, but nowhere else. I see no reason why this is more readable than version(linux || darwin) in that one spot. I do not have to go looking for specialWay in this file, or some other header file, or simply have to read through useless repetitive statements. It's perfectly clear what it means. How does this promote confusing versioning? Many people have pointed out the possibility of spelling mistakes now more likely because you have to repetitively specify the same version under other version branches. I see allowing version(x || y) as something that has absolutely no drawbacks. None of the arguments against it have had any merit, because the examples of how bad it would be are not bad because of the existance of that construct. They are simply complicated examples of versioned code, which would probably benefit from allowing ||. It would even make code more maintainable in your example: version(A || C) version = canBeUsedToPickUpChicks; Note no duplication of the long token you chose ;) -Steve"Walter Bright" wrote Think of code that is versioned around architecture that would look horrendous if you have to do version statements that have all different combinations of stuff. If I have 5 different architectures to support, I don't want to have to define a module that has 2^5 different version combinations. On top of that, the way versioning works, you need 2^4 * 5 different statements: version(A) { version = AorB; version = AorC; version = AorD; version = AorE; version = AorBorC; version = AorBorD; // ad nauseum. } version(B) { // oh fun! let's do it again!!!! version = AorB; version = BorC; version = BorD; ... } When I add another architecture, *gasp* I have to double the statements (to do them now with and without version(F) ), and now I have to do another 2^5 statements for the version(F) block. Wheee!But this is clearly the wrong way of cutting the pie. What you need is define features that are supported by some of the versions. You don't need to judge in terms of logical operators between versions. version (A) version = canBeUsedToPickupChicks; version (C) version = canBeUsedToPickupChicks; // version (B) no good
Feb 10 2009
Andrei Alexandrescu wrote:Steven Schveighoffer wrote:There's one slightly irritating issue I've run into with versions recently. In the spare few instances where I actually need to do something like this, I like to put everything together so I know at a glance what's going on. However, versions may not be defined in class scope, so: class C { version (A) version = useSomeFancyThing; version (B) version = useSomeFancyThing; version (useSomeFancyThing) { Fancy[1024] fancyPants; } } This is illegal. Kind of a small issue, but I grumbled about it for a minute or two before I broken down and just duplicated the declaration for each version. I could have easily put the tests at module scope before the class declaration, but I wanted everything together. Sean"Walter Bright" wrote Think of code that is versioned around architecture that would look horrendous if you have to do version statements that have all different combinations of stuff. If I have 5 different architectures to support, I don't want to have to define a module that has 2^5 different version combinations. On top of that, the way versioning works, you need 2^4 * 5 different statements: version(A) { version = AorB; version = AorC; version = AorD; version = AorE; version = AorBorC; version = AorBorD; // ad nauseum. } version(B) { // oh fun! let's do it again!!!! version = AorB; version = BorC; version = BorD; ... } When I add another architecture, *gasp* I have to double the statements (to do them now with and without version(F) ), and now I have to do another 2^5 statements for the version(F) block. Wheee!But this is clearly the wrong way of cutting the pie. What you need is define features that are supported by some of the versions. You don't need to judge in terms of logical operators between versions. version (A) version = canBeUsedToPickupChicks; version (C) version = canBeUsedToPickupChicks; // version (B) no good
Feb 10 2009
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmsqnh$6qi$1 digitalmars.com...The version statement is designed to be inflexible. It's designed to encourage abstracting and modularizing version differences, rather than encouraging line-by-line differences. I've used #if/#endif for decades. Over time, it *always* degenerates into an utter rat's nest of nested, incomprehensible complexity (and this includes my own code). For a lovely example of how bad it can get, take a look at the source code to Hans Boehm's garbage collector. I defy anyone to figure it out without running the code through the preprocessor first to see which statements are actually getting compiled. A far better way to do versioning is to find the abstraction lines separating versions, and put version specific code in separate modules that are then imported. It makes for nice, clean, understandable code.This strikes me as throwing away the baby with the bathwater. If your code starts degenerating towards a versioning rat's nest, then the solution is to take a moment and refactor it into a larger granularity, not to throw away features that are useful in moderation.1. Why not version(!feature) ? Because cognitive studies show that people just don't see the negation.Isn't that moreso a case against the ! operator in general? I don't see how "if(!blah)" is any less susceptible to overlooking the ! than "version(!blah)".Secondly, when you see things like: version (!linux) { ... } they're almost always wrong. Versions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux.True, we don't build to a NotLinux, but we do however build to "everything except platform X". And I don't see how a "LinuxOrMac" (or worse yet, a "LinuxOr_MacAndSomeOtherCharacteristic_") is any more or less of a realistic platform than a "NotLinux". Also, you didn't respond to the concerns about typos in a version identifier. Can we assume you agree that's a problem?
Feb 10 2009
Nick Sabalausky wrote:This strikes me as throwing away the baby with the bathwater. If your code starts degenerating towards a versioning rat's nest, then the solution is to take a moment and refactor it into a larger granularity, not to throw away features that are useful in moderation.True, but that never, ever happens. It's always "I can get my few additions to this rat's nest in and just get it working, and worry about proper abstraction later."Yes, you're right, it's both a minor and an inconsistent point, despite it being right <g>.1. Why not version(!feature) ? Because cognitive studies show that people just don't see the negation.Isn't that moreso a case against the ! operator in general? I don't see how "if(!blah)" is any less susceptible to overlooking the ! than "version(!blah)".We do, and they're always wrong. I always find when doing that and porting to another machine that those #if !linux must be reengineered. I have switched entirely over to: #if Windows ... #elif linux ... #elif __APPLE__ ... #else assert(0); // fix when adding a new platform #endif because otherwise I *miss* sections that need updating when porting to a new platform, and have a bug that needs tracking down. The point is, when writing portable code, especially code that will be ported by others, you have *no idea* what platforms will fall into the "notLinux" section and what peculiarities those platforms might have. It works much better to have the compiler ding me when it encounters platform specific code that doesn't have a section for the platform I'm compiling for.Secondly, when you see things like: version (!linux) { ... } they're almost always wrong. Versions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux.True, we don't build to a NotLinux, but we do however build to "everything except platform X".And I don't see how a "LinuxOrMac" (or worse yet, a "LinuxOr_MacAndSomeOtherCharacteristic_") is any more or less of a realistic platform than a "NotLinux".Based on my experience porting code, LinuxOrMac is a far better solution (i.e. faster to code, faster to port, fewer bugs) than notWindows.Also, you didn't respond to the concerns about typos in a version identifier. Can we assume you agree that's a problem?It's a problem without a solution unless you propose adding some sort of declaration syntax for all the version identifiers.
Feb 10 2009
On Wed, 11 Feb 2009 02:16:16 +0300, Walter Bright <newshound1 digitalmars.com> wrote:Nick Sabalausky wrote:Why did you catch that controversial !Linux example? Just imagine it is !HasFeatureX: version(!HasFeatureX) { ... } is so much more intuitive than version (HasFeatureX) { } else { ... }This strikes me as throwing away the baby with the bathwater. If your code starts degenerating towards a versioning rat's nest, then the solution is to take a moment and refactor it into a larger granularity, not to throw away features that are useful in moderation.True, but that never, ever happens. It's always "I can get my few additions to this rat's nest in and just get it working, and worry about proper abstraction later."Yes, you're right, it's both a minor and an inconsistent point, despite it being right <g>.1. Why not version(!feature) ? Because cognitive studies show that people just don't see the negation.Isn't that moreso a case against the ! operator in general? I don't see how "if(!blah)" is any less susceptible to overlooking the ! than "version(!blah)".We do, and they're always wrong. I always find when doing that and porting to another machine that those #if !linux must be reengineered. I have switched entirely over to: #if Windows ... #elif linux ... #elif __APPLE__ ... #else assert(0); // fix when adding a new platform #endif because otherwise I *miss* sections that need updating when porting to a new platform, and have a bug that needs tracking down. The point is, when writing portable code, especially code that will be ported by others, you have *no idea* what platforms will fall into the "notLinux" section and what peculiarities those platforms might have. It works much better to have the compiler ding me when it encounters platform specific code that doesn't have a section for the platform I'm compiling for.Secondly, when you see things like: version (!linux) { ... } they're almost always wrong. Versions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux.True, we don't build to a NotLinux, but we do however build to "everything except platform X".And I don't see how a "LinuxOrMac" (or worse yet, a "LinuxOr_MacAndSomeOtherCharacteristic_") is any more or less of a realistic platform than a "NotLinux".Based on my experience porting code, LinuxOrMac is a far better solution (i.e. faster to code, faster to port, fewer bugs) than notWindows.Also, you didn't respond to the concerns about typos in a version identifier. Can we assume you agree that's a problem?It's a problem without a solution unless you propose adding some sort of declaration syntax for all the version identifiers.
Feb 10 2009
Denis Koroskin wrote:Why did you catch that controversial !Linux example? Just imagine it is !HasFeatureX: version(!HasFeatureX) { ... } is so much more intuitive than version (HasFeatureX) { } else { ... }This is to combat the pernicious problem of having features that subtract code <g>.
Feb 10 2009
Walter Bright wrote:Denis Koroskin wrote:I've got two words for you, Walter. Compiler bugs.Why did you catch that controversial !Linux example? Just imagine it is !HasFeatureX: version(!HasFeatureX) { ... } is so much more intuitive than version (HasFeatureX) { } else { ... }This is to combat the pernicious problem of having features that subtract code <g>.
Feb 10 2009
Don wrote:Walter Bright wrote:I've never heard of those before. Are they like VW Bugs?This is to combat the pernicious problem of having features that subtract code <g>.I've got two words for you, Walter. Compiler bugs.
Feb 10 2009
Walter Bright wrote:Don wrote:Yes, but they're not as cute.Walter Bright wrote:I've never heard of those before. Are they like VW Bugs?This is to combat the pernicious problem of having features that subtract code <g>.I've got two words for you, Walter. Compiler bugs.
Feb 11 2009
On Wed, 11 Feb 2009 12:16:16 +1300, Walter Bright <newshound1 digitalmars.com> wrote:Nick Sabalausky wrote:It would be nice if version just evaluated to a bool of true if the version is defined or false otherwise and you have to use it in static if statements, drop the old syntax. This would be very consistent, powerfull and if that is considered bad style then it shouldn't have to be used in the same way goto statements are rarely used yet they still exist.This strikes me as throwing away the baby with the bathwater. If your code starts degenerating towards a versioning rat's nest, then the solution is to take a moment and refactor it into a larger granularity, not to throw away features that are useful in moderation.True, but that never, ever happens. It's always "I can get my few additions to this rat's nest in and just get it working, and worry about proper abstraction later."Yes, you're right, it's both a minor and an inconsistent point, despite it being right <g>.1. Why not version(!feature) ? Because cognitive studies show that people just don't see the negation.Isn't that moreso a case against the ! operator in general? I don't see how "if(!blah)" is any less susceptible to overlooking the ! than "version(!blah)".We do, and they're always wrong. I always find when doing that and porting to another machine that those #if !linux must be reengineered. I have switched entirely over to: #if Windows ... #elif linux ... #elif __APPLE__ ... #else assert(0); // fix when adding a new platform #endif because otherwise I *miss* sections that need updating when porting to a new platform, and have a bug that needs tracking down. The point is, when writing portable code, especially code that will be ported by others, you have *no idea* what platforms will fall into the "notLinux" section and what peculiarities those platforms might have. It works much better to have the compiler ding me when it encounters platform specific code that doesn't have a section for the platform I'm compiling for.Secondly, when you see things like: version (!linux) { ... } they're almost always wrong. Versions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux.True, we don't build to a NotLinux, but we do however build to "everything except platform X".And I don't see how a "LinuxOrMac" (or worse yet, a "LinuxOr_MacAndSomeOtherCharacteristic_") is any more or less of a realistic platform than a "NotLinux".Based on my experience porting code, LinuxOrMac is a far better solution (i.e. faster to code, faster to port, fewer bugs) than notWindows.Also, you didn't respond to the concerns about typos in a version identifier. Can we assume you agree that's a problem?It's a problem without a solution unless you propose adding some sort of declaration syntax for all the version identifiers.
Feb 10 2009
"Walter Bright" <newshound1 digitalmars.com> wrote in message news:gmt1s1$i7f$1 digitalmars.com...Nick Sabalausky wrote:It seems to me that D's versioning, conditional compilation, and overall feature set are already different enough that people aren't necessarily going to be falling into the "c preprocessor style" rut. Plus, as someone else mentioned, there *are* still concerns about code duplication. So it really becomes a balancing act between clear abstraction and DRY. D's version() just makes this balancing act harder because it keeps pushing in the one direction. I'll grant that if there's a bad habit that most coders are doing (such as messy versioning), then it's certainly worthwhile to create a design that prevents it. But the more I think about it, the more convinced I become that most of version()'s restrictions are just red herrings. I really think you're attacking the wrong thing (not that I have any idea where the ideal place to attack would be). After all, Denis and I have both demonstrated that D's version() is just as susceptible to mess as C's #if/#ifdef versioning. If people are going to make a version() mess, they're going to do it. Things like !, ||, && and expression-level versions are just drops in the pond, they would allow certain things to be cleaned up, but they're not going to break the dam any more than it already is, and they would even make a few things better. It would be great to have a way to eliminate messy versioning, but things such as prohibiting !, ||, && and expression-versions are doing very little to accomplish that. Modeling the version() syntax after the conditional syntax, and giving it less-than-"BEGIN"->"{"-level of power is already accomplishing far more in that regard. The benefits of preventing typos in version identifiers would also dwarf any benefits that might be gained from prohibiting !, ||, && and expression-versions.This strikes me as throwing away the baby with the bathwater. If your code starts degenerating towards a versioning rat's nest, then the solution is to take a moment and refactor it into a larger granularity, not to throw away features that are useful in moderation.True, but that never, ever happens. It's always "I can get my few additions to this rat's nest in and just get it working, and worry about proper abstraction later."
Feb 10 2009
I see your points, although I don't quite agree. Programmers will continue to do stupid things, even if it hurts. And in these cases, having an "intentionally hard to use" version-statement might increase the overall mess even further. But what do you say about the possibility of uncatched typos? (the "version(linxu) {" example)
Feb 10 2009
grauzone wrote:I see your points, although I don't quite agree. Programmers will continue to do stupid things, even if it hurts. And in these cases, having an "intentionally hard to use" version-statement might increase the overall mess even further. But what do you say about the possibility of uncatched typos? (the "version(linxu) {" example)Versions are not boolean flags that are either true or false [1]. They're zero-state flags that either exist or don't. You can't spell-check something which simply may not exist. So let's say you have to define all version identifiers. The problem with this is that the more you use versioning, the more hideous your compile-lines are going to become... dmd foo --version=UseMMX=false --version=UseSSE=false --version=UseSSE2=true --version=Use3DNow=false --version=UseSSE2_AMD=false --version=UseSSE3=false --version=UseSSE4=false --version=UseSPARCExtension=false --version=UseAltivec=false --version=UseARMStuff=false --version=OhGodMakeItStop=false As opposed to dmd foo --version=UseSSE2 You might be able to rework the syntax so that you can define the default value of a version symbol in a module, then override it from the command line. module simd_versions; version UseMMX=false, UseSSE=false, UseSSE2=false, ...; -- Daniel [1] I'm ignoring integer versions which have a similar problem, but would just make this post longer :P
Feb 10 2009
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:gmtf5g$1ban$1 digitalmars.com...--version=OhGodMakeItStop=falselol :) I love all of the contrived code we come up with on this newsgroup. Other gems just from this "Why version()?" thread alone: version=canBeUsedToPickupChicks version(Poopy) {} elseYou might be able to rework the syntax so that you can define the default value of a version symbol in a module, then override it from the command line. module simd_versions; version UseMMX=false, UseSSE=false, UseSSE2=false, ...;I think you've just demonstrated here that this feature *can* be made to work.
Feb 10 2009
Walter Bright Wrote:5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do. If you need to 'comment out' a section of syntactically invalid code, use the /+ ... +/ nesting comment.Would you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/
Feb 10 2009
Jason House wrote:Would you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/That is an interesting idea. I never thought of that.
Feb 10 2009
Walter Bright wrote:Jason House wrote:What about this? /+{{VersionIdentifier}} ... +/ The lexer doesn't have to know whether a particular version identifier is defined or not. That said, I don't know whether you could keep a "sort-of comment" around in the AST until the semantic pass; haven't had much luck deciphering the compiler yet. :P Plus, it's backwards-compatible! :D As for what's allowed in the {{..}}, you could always restrict it to a set of version identifiers that represent syntax-incompatible changes. -- DanielWould you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/That is an interesting idea. I never thought of that.
Feb 10 2009
On Wed, 11 Feb 2009 14:07:29 +1100, Daniel Keep wrote:What about this? /+{{VersionIdentifier}} ... +/is that just a neater way to do this? version(Identifier) { mixin(` //code! `)}
Feb 11 2009
On Wed, 11 Feb 2009 08:51:10 +0000, Brian wrote:On Wed, 11 Feb 2009 14:07:29 +1100, Daniel Keep wrote:after writing that i realized the mixin is probably evaluated even if the version is false, that kind of destroys that idea.What about this? /+{{VersionIdentifier}} ... +/is that just a neater way to do this? version(Identifier) { mixin(` //code! `)}
Feb 11 2009
Brian wrote:On Wed, 11 Feb 2009 08:51:10 +0000, Brian wrote:mixin( version(Identifier) { `//code!` } else { ``});On Wed, 11 Feb 2009 14:07:29 +1100, Daniel Keep wrote:after writing that i realized the mixin is probably evaluated even if the version is false, that kind of destroys that idea.What about this? /+{{VersionIdentifier}} ... +/is that just a neater way to do this? version(Identifier) { mixin(` //code! `)}
Feb 11 2009
"Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:gmtfd9$1bjk$1 digitalmars.com...What about this? /+{{VersionIdentifier}} ... +/One thing that's nice about that in a really bizarre sort of way is that none of the code editors I've tried support syntax highlighting of nested comments, so all the code inside there would automatically be properly highlighted ;-)
Feb 11 2009
Walter Bright Wrote:Jason House wrote:Would you be willing to add it as a new feature to both D1 and D2? I wonder how viable having one code base would be at that point? Would druntime be a good way to test that? Druntime would be a good guinea pig. I'd really hope a smooth transition for druntime would be enough to inspire more projects to support D1and D2 with a single code base.Would you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/That is an interesting idea. I never thought of that.
Feb 11 2009
Jason House wrote:Walter Bright Wrote:I don't see druntime supporting D1, it's pretty in bed with D2 features.Jason House wrote:Would you be willing to add it as a new feature to both D1 and D2? I wonder how viable having one code base would be at that point? Would druntime be a good way to test that? Druntime would be a good guinea pig. I'd really hope a smooth transition for druntime would be enough to inspire more projects to support D1and D2 with a single code base.Would you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/That is an interesting idea. I never thought of that.
Feb 11 2009
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleJason House wrote:There's a druntime branch that is compatible with D1. I created it mostly in case the Tango folks wanted to build off it, but that never happened and I've gotten a bit lazy about keeping it up to date. As you say however, as time goes on, the D1 branch will become increasingly difficult to keep in sync with the D2 version, since most new features will not be supported by the D1 compiler. I'm going to try and keep the branch operational for anyone who cares, but don't plan to add any new features to it since most of the new stuff requires D2 anyway. SeanWalter Bright Wrote:I don't see druntime supporting D1, it's pretty in bed with D2 features.Jason House wrote:Would you be willing to add it as a new feature to both D1 and D2? I wonder how viable having one code base would be at that point? Would druntime be a good way to test that? Druntime would be a good guinea pig. I'd really hope a smooth transition for druntime would be enough to inspire more projects to support D1and D2 with a single code base.Would you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/That is an interesting idea. I never thought of that.
Feb 11 2009
Jason House escribió:Walter Bright Wrote:Why not have special versions like D1, D2, D3 for the compiler to treat them differently? If a version(DX) is found that is not the current's compiler version, it just consumes tokens (counting opening and closing of brackets, etc.) until the curly's close. Much like the asm statement.5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do. If you need to 'comment out' a section of syntactically invalid code, use the /+ ... +/ nesting comment.Would you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/
Feb 10 2009
Ary Borenszweig escribió:Jason House escribió:Ah, mmm... the lexer also needs to know this. Doesn't work. :-( Well, it could work if you lookahead a few tokens...Walter Bright Wrote:Why not have special versions like D1, D2, D3 for the compiler to treat them differently? If a version(DX) is found that is not the current's compiler version, it just consumes tokens (counting opening and closing of brackets, etc.) until the curly's close. Much like the asm statement.5. Why can't one 'version out' syntax that is not recognized by the compiler? The problem is that supporting this requires semantic analysis in order to successfully lex and parse the source code. Breaking this will make the lexing and parsing an order of magnitude harder for third party tools to do. If you need to 'comment out' a section of syntactically invalid code, use the /+ ... +/ nesting comment.Would you be willing to introduce an alternative to /+ +/ which would be treated differently by the D1 and D2 compilers? Here are some examples with no attempt at creativity: beginD1 endD1 D1 D1 (works like string delimiters) /D2 D2/
Feb 10 2009
Walter Bright wrote:1. Why not version(!feature) ? Because cognitive studies show that people just don't see the negation. Secondly, when you see things like: version (!linux) { ... } they're almost always wrong. Versions should be positive things, because a version is something that is being build - one doesn't craft a makefile to build a notLinux.And for code that can't/won't be rewritten, there's the workaround: version (linux) {} else { ... } But yeah, using Unix or Posix would be better than using !Windows. (only problem there being that both those versions are in use now) --anders
Feb 11 2009