Re: build Ldc2 for win xp 32 bit Error
On 26/07/12 09:05, Jacob Carlborg wrote: On 2012-07-25 22:39, Rainer Schuetze wrote: What is the state of the missing exception handling for Windows? I just read an old post on the Clang mailing list, it's not looking good. It seems Microsoft (or someone else) has a patent on SEH, I've heard this, but does anyone know what patent is being referred to? Several times I've heard mention of an old one by Borland, which Microsoft bought. The Borland patent is not a patent on SEH, it's basically a patent on using a thunk. I suspect it is extremely unlikely to be a valid patent, for sure there is prior art. And the only reason for implementing it with a thunk anyway, is as a workaround for the broken thread-local support in Windows prior to Vista. It's not difficult to implement SEH without violating that patent (which is due to expire soon anyway). Is there some other patent that people are referring to? which basically means: never gonna happen. An alternative could be setjmp/longjmp. On 64bit it looks a bit better, where the correct way seems to be to use the Win64 exception ABI. Win64 SEH is scarcely any different to Win32 SEH, it's just better documented. You can do the same thing on Win32. http://clang-developers.42468.n3.nabble.com/LLVM-Clang-and-setjmp-longjmp-exception-handling-on-MinGW-td3407322.html http://msdn.microsoft.com/en-us/library/1eyas8tf.aspx The situation makes no sense to me.
Re: BitArray/BitFields - Review
On 29/07/12 23:36, bearophile wrote: Era Scarecrow: Another commonly needed operation is a very fast bit count. There are very refined algorithms to do this. Likely similar to the hamming weight table mentioned in TDPL. Combined with the canUseBulk I think I could make it fairly fast. There is lot of literature about implementing this operation efficiently. For the first implementation a moderately fast (and short) code is probably enough. Later faster versions of this operation will go in Phobos, coming from papers. See bug 4717. On x86, even on 32 bits you can get close to 1 cycle per byte, on 64 bits you can do much better.
Re: Pull freeze
On 29/07/12 13:43, Robert Clipsham wrote: On Sunday, 29 July 2012 at 06:08:18 UTC, Andrei Alexandrescu wrote: Due to the upcoming release, there will be no regular pull walk-through tomorrow. Thanks for the growing rate of contribution, and let's resume the ritual next Sunday. Andrei I really can't shake the feeling that you guys just don't get git! You never need to freeze pulls with git. Ever! It just slows down development. The work flow is simple enough: 1. Time for a release 2. Create a release branch, it is feature frozen 3. You can keep pulling feature into master, no problem 4. You can pull regression/bug fixes into the release branch 5. A release is made, merge the release branch into master and continue. I don't know why I bothered typing this out - the discussion has been had time and time again with no progress made. From a technical point of view, I think the main thing to be done relates to the auto-tester. We want the autotester to run on the release branch, as well as the development branch. Note of course that we have druntime and Phobos as well as DMD; they all need their own release branches. I guess the easiest way to do this would be to have a single, permanent branch called 'release', that is used for all releases, rather than creating a release branch for each compiler version.
Re: std.variant benchmark
On 30/07/12 13:24, Andrei Alexandrescu wrote: On 7/30/12 4:34 AM, Dmitry Olshansky wrote: On 30-Jul-12 06:01, Andrei Alexandrescu wrote: In fact memcpy could and should be replaced with word by word copy for almost all of struct sizes up to ~32 bytes (as size is known in advance for this particular function pointer i.e. handler!int). In fact memcpy should be smart enough to do all that, but apparently it doesn't. I'd say array ops could and should do this (since compiler has all the info at compile-time). On the other hand memcpy is just one tired C function aimed at fast blitting of any memory chunks. (Even just call/ret pair is too much of overhead in case of int). memcpy is implemented as an intrinsic on many platforms. I'm not sure whether it is on dmd, but it is on dmc (http://www.digitalmars.com/ctg/sc.html), icc, and gcc (http://software.intel.com/en-us/articles/memcpy-performance/). But then clearly using simple word assignments wherever possible makes for a more robust performance profile. It is an intrinsic on DMD, but it isn't done optimally. Mostly it just compiles to a couple of loads + the single instruction rep movsd; / rep movsq; which is perfect for medium-sized lengths when everything is aligned, but once it is longer than a few hundred bytes, it should be done as a function call. (The optimal method involves cache blocking). Also for very short lengths it should be done as a couple of loads.
Re: One against binary searches
On 30/07/12 17:40, bearophile wrote: This author writes very detailed analyses of low-level computational matters, that appear on Reddit. This blog post he suggests to introduce offseted binary or quaternary search instead of binary search in Phobos: http://www.pvk.ca/Blog/2012/07/30/binary-search-is-a-pathological-case-for-caches/ Bye, bearophile Fantastic article, thanks! The fact that physical addressing can influence L2 cache misses was completely new to me.
Re: FYI my experience with D' version
On 30/07/12 14:32, Jacob Carlborg wrote: On 2012-07-30 12:30, torhu wrote: version is good for global options that you set with -version on the command line. And can also be used internally in a module, but doesn't work across modules. But it seems you have discovered this the hard way already. I think there was a discussion about this a few years ago, Walter did it this way on purpose. Can't remember the details, though. He probably wants to avoid the C macro hell. IIRC it's because version identifiers are global. __ module b; version = CoolStuff; __ module a; import b; version (X86) { version = CoolStuff; } version(CoolStuff) { // Looks as though this is only true on X86. // But because module b used the same name, it's actually true always. } __ These types of problems would be avoided if we used the one-definition rule for version statements, bugzilla 7417.
Re: Computed gotos on Reddit
On 26/07/12 00:46, Walter Bright wrote: On 7/25/2012 2:55 PM, Dmitry Olshansky wrote: std\regex.d(5118): Error: undefined identifier 'L_jumptable' I was afraid of that. You may have to approximate it by loading the address of L_jumptable into a register and adding it in instead of using the addressing mode. I failed to load it in any register or interact with it in any way. I think I've stalled. There has to be a way to get label address somehow, I got tired of guess and shot :( BTW that would allow us to do computed gotos but only in inline asm. How to get an address: call jump_table L1: ... jump_table: pop EAX jmp L1 .. the rest of the jump table ... Yes, it's awful, but we're just trying to take some measurements here, so it doesn't matter. What I meant was add these extra instructions in to the switch version as dummies in order to make the extra time they take irrelevant to looking at the difference. But doing that screws up the CPUs stack prediction so badly that it will dominate the timing At least do something like: jump_table: move EAX, [ESP] ret
Re: Coming Soon: Stable D Releases!
On 25/07/12 14:32, Jacob Carlborg wrote: On 2012-07-25 09:43, Don Clugston wrote: We don't need this complexity. The solution is *trivial*. We just need to decide in advance that we will target a release every X weeks, and that it should be delayed only for reasons of stability. Yeah, but what happens when Walter or someone else decides to start a big project, i.e. implementing COFF support, a week before release? We end up with a bunch of half finished things. If we had an agreed release cycle, it would not happen. The release cycle would be a higher authority than any single person, even Walter. A solution to this would be to create a new branch or not push the changes upstream. Although I don't understand why Walter doesn't already do this. An agreement is ALL that is required. But despite repeated requests, I have never been able to get any traction on the idea. Instead, people propose all kinds of crazy technical solutions, the most recent ones being changes to bugzilla, trello, and now dlang-stable. If we say, There will be a new compiler release every 8 weeks, the problem is solved. Seriously. That one-off agreement is ALL that is required. Apparently it seems very difficult to agree upon, since it hasn't happened. The releases just pop up at random. I have tried many times, without success. I've never succeeded in getting more than two or three people interested.
Re: Computed gotos on Reddit
On 25/07/12 09:37, Walter Bright wrote: On 7/24/2012 11:46 PM, Dmitry Olshansky wrote: It's pc = address because one can first preprocess all of byte code doing opcode = address rewrites. But you can't do it unless taking address of labels is possible. All right, that's the piece that was missing. I suppose it is possible for the compiler to recognize that the opcode=address array is invariant, and optimize it out, but that would be a novel optimization. I don't know how hard it would be. Done: http://d.puremagic.com/issues/show_bug.cgi?id=8431 Thanks! Another interesting optimization with final switch would be if each case has about the same code length. final switch(x) { case C1: ... case C2: ... case C3: ... case C4: ... } then if (case c2) - (case C1) == (case C3) - (case C2) change it to goto (case C1) + x *( (case c2) - (case C1) ); so that there is no lookup table, just a multiply.
Re: Computed gotos on Reddit
On 25/07/12 09:55, Dmitry Olshansky wrote: On 25-Jul-12 11:51, Don Clugston wrote: On 25/07/12 09:37, Walter Bright wrote: On 7/24/2012 11:46 PM, Dmitry Olshansky wrote: It's pc = address because one can first preprocess all of byte code doing opcode = address rewrites. But you can't do it unless taking address of labels is possible. All right, that's the piece that was missing. I suppose it is possible for the compiler to recognize that the opcode=address array is invariant, and optimize it out, but that would be a novel optimization. I don't know how hard it would be. Done: http://d.puremagic.com/issues/show_bug.cgi?id=8431 Thanks! Another interesting optimization with final switch would be if each case has about the same code length. final switch(x) { case C1: ... case C2: ... case C3: ... case C4: ... } then if (case c2) - (case C1) == (case C3) - (case C2) change it to goto (case C1) + x *( (case c2) - (case C1) ); so that there is no lookup table, just a multiply. Could be interesting if some other simple progressions could be hardcoded, if say branches are be sorted by length. Ooh, that's an interesting idea too. Also modern CPU seem to be exceptionally fast at skipping NOPs so a bit of padding won't hurt. And an unconditional branch takes no time (only one 1 uop) on modern CPUs too.
Re: Troubles with immutable arrays
On 23/07/12 15:29, bearophile wrote: After a discussion in D.learn started by someone else, after a suggestion of mine Timon Gehr has added a bug report: http://d.puremagic.com/issues/show_bug.cgi?id=8400 But the bug was fixed in the opposite way of what I was thinking. The problem was that the length of global immutable arrays arrays is seen as a compile-time constant. Instead of fixing that, Issue 8400 has done the opposite, now even the lenght of local immutable arrays is seen sometimes as a compile-time constant, and example: Sorry bearophile, I completely disagree with this post. Currently, when a compile time value is required, CTFE is attempted. If it fails, an error message is generated. You are asking for a corner case to be introduced. Under certain circumstances (which aren't clearly defined), you want CTFE to *not* be attempted. immutable int[] A = foo(5); int[A.length] B; This code too compiles, so A is sometimes computed at run-time and sometimes at compile-time: immutable int[] A = foo(n); Now immutable arrays are sometimes seen as enums. That is not correct, an immutable array is always different to an enum. For example, an enum is simply a manifest constant, and does not have an address. An immutable array always has an address. I think this is a problem. I think in D compile-time is run only if it's evaluated in a context where compile-time values are required. But now the situation is more muddy, because knowing n at compile-time is not a way to ask A to be computed at compile-time. The only consequence is that if you don't require it at compile time, a particular optimization might not happen. There is no change to semantics. Another problem is that compile-time arrays in many situations are not efficient, they gets copied every time you use them, and I think that __d_arrayliteralTX performs a heap allocation. So now both enum and immutable arrays perform heap allocations every time you use them, but only in some situations. That's the famous bug 2356, which is completely irrelevant to this situation. I think this is a messy situation, I think the fix for bug 8400 should be undone, and I think Issue 8400 should be fixed the other way, turning global immutable arrays too into run-time entities. Did you even know that initializers of global variables, including arrays, including even mutable arrays, are ALWAYS CTFE'd?
Re: Computed gotos on Reddit
On 25/07/12 12:11, Walter Bright wrote: On 7/25/2012 12:51 AM, Don Clugston wrote: so that there is no lookup table, just a multiply. Rethinking your idea a bit... Suppose the switch jump_address[] array was really an array of hardcoded jmp instructions, 5 bytes each: jmp_table: jmp Lcase1; jmp Lcase2; jmp Lcase3; ... and then the switch(EBX) would be: lea EAX,jmp_table[EBX][EBX*4] jmp EAX is that kick-ass or what? (There'd be some additional complication for PIC code.) Very nice. The jumps in the jump table take effectively zero cycles. That looks quite doable.
Re: Semantics of postfix ops for classes
On 20/07/12 17:12, Andrej Mitrovic wrote: According to TDPL postfix operators are rewritten to call prefix operators, e.g. on this call for some user-type object named a: auto b = a++; // is converted to: auto b = ((ref x) { auto t = x; ++x; return t; })(a); But I don't see how this is reasonable for classes. Examine: struct Struct { int x = 1; Struct opUnary(string op : ++)() { x++; return this; } } class Class { int x = 1; Class opUnary(string op : ++)() { x++; return this; } } void main() { Struct foo1; Struct foo2 = foo1++; assert(foo1.x != foo2.x); // ok Class bar1 = new Class; Class bar2 = bar1++; assert(bar1.x != bar2.x); // fail } It's clear why, the rewrite that calls auto t = x simply binds another reference to the same object. Unfortunately this makes it hard to wrap C++ libraries which have both prefix/postfix operators defined. Currently I wrap these in e.g. preInc/postInc methods and I explicitly disable the prefix/postfix opUnary methods. Are the semantics of this rewrite ok with people who use op overloads? I found them to be surprising, but then again I don't use op overloads that much, I'm just noticing the difference between C++ and D. But classes have reference semantics, so they are already completely different from C++. The question really is, do postfix ++ and -- make sense for reference types? Arguably not. From a theoretical sense, the existing behaviour does make sense, but in practice, every time it is used, it is probably a bug. The only other reasonable option I can think of would be to make class++ be of type void, so that you could still write bar1++; but not bar2 = bar1++; since the existing behaviour can be achieved by writing bar2 = ++ bar1;
Re: Coming Soon: Stable D Releases!
On 16/07/12 09:51, Adam Wilson wrote: As a result of the D Versioning thread, we have decided to create a new organization on Github called dlang-stable. This organization will be responsible for maintaining stable releases of DMD, DRuntime, and Phobos. So what is a stable release? A stable release is a complete build of DMD, DRuntime, and Phobos that ONLY includes the latest bug-fixes and non-breaking enhancements to existing features. It will not include, new features, breaking enhancements, and any other code that the core development team may be working on. I'm not actually sure what this means. I fear that it may be motivated by an inaccurate assessment of the current situation. The existing instability comes almost entirely from Phobos, not from the compiler. Historically there have been very few instances where you might want to choose an older compiler in preference to the latest release. As I've said before, the one time when a language change caused *massive* instability was in the attempt to move AAs from language to library -- even though that wasn't even supposed to affect existing code in any way. The other thing that typically causes regressions is fixes to forward-reference bugs. Historically, addition of new language features has NOT caused instability. What has been true is that features have been added to the compiler before they were really usable, but they have not broken existing code. Fairly obviously the 64 bit compiler was quite buggy when initially released. But even that massive change wasn't much more buggy than the library AAs! So I am not sure that you can correctly guess where instability will come from. In summary -- I would not expect your stable DMD to be very different from the normal DMD. Phobos is where the instability issue is.
Re: feature request: with(var decl) {}
On 23/07/12 17:04, Adam D. Ruppe wrote: On Monday, 23 July 2012 at 14:46:30 UTC, FeepingCreature wrote: The more general form would be to make variable declaration an expression. Right, and that would be pretty amazing, but it would probably be too hard to do in D today... The bizarre thing, however, is that the compiler uses it internally. There's thing called a DeclarationExp. It's created all the time when lowering occurs. Its only in the parser that declarations are not valid as expressions.
Re: D versionning
On 16/07/12 16:51, David Nadlinger wrote: On Monday, 16 July 2012 at 06:00:03 UTC, Walter Bright wrote: Supporting Win64 is absolutely critical for the future of D, and the sooner we get it, the better. The COFF route is the shortest route to doing it, and the most practical for attracting devs, which is why it's the way we're going. Sorry, but I don't think this is a valid argument. Yes, Win64 (and even more so, COFF) support is important to have for DMD, but no, it's not a good idea to delay a pending release because of this (cf. the »Time for a new beta« thread from the end of May). Here is why: http://d.puremagic.com/issues/buglist.cgi?chfieldto=Nowquery_format=advancedchfield=bug_statuschfieldfrom=2012-04-13bug_status=RESOLVEDresolution=FIXED Already 289 issues resolved since 2.059! More than that. Of the official releases, there is no usable 64 bit DMD compiler on ANY platform. Some awful wrong-code bugs were still present in 2.059. They have been fixed for a couple of months in DMD git, but not in an official release.
Re: Why is std.algorithm so complicated to use?
On 10/07/12 16:59, Andrei Alexandrescu wrote: On 7/10/12 9:59 AM, H. S. Teoh wrote: On Tue, Jul 10, 2012 at 09:28:51AM -0400, Andrei Alexandrescu wrote: On 7/10/12 2:50 AM, Jacob Carlborg wrote: On 2012-07-09 22:16, Andrei Alexandrescu wrote: So foo is a range of strings, because each element of it is a string. Then you want to chain a range of strings with a string, which is a range of dchar. That doesn't work, and I agree the error message should be more informative. Is that by design or something that can be fixed? We can arrange things in the library that a custom message is issued, or in the compiler to do it once for all. Please don't do it in the compiler. Custom messages should be in the library. Tying the compiler to phobos is a bad idea; druntime should be the only dependency. The idea there being that the compiler could give good details about what part of a complex constraint has failed. However the compiler doesn't know which constraint was supposed to pass. If it is lucky enough to only have one template, it can do it, but if it has: template1 if (A B) template2 if (C D) template3 if ( (E || F) G) should it print: foo.d(99): Error: no matching template foo.d(10):constraint failed: A foo.d(28):constraint failed: D foo.d(57):constraint failed: (E || F) ? Could be a very long list, if there are many templates. Determining the minimal list of constraints seems like a nice application for BDDs...
Re: cast from void[] to ubyte[] in ctfe
On 13/07/12 12:52, Johannes Pfau wrote: Am Fri, 13 Jul 2012 11:53:07 +0200 schrieb Don Clugston d...@nospam.com: On 13/07/12 11:16, Johannes Pfau wrote: Casting from void[] to ubyte[] is currently not allowed in CTFE. Is there a special reason for this? I don't see how this cast can be dangerous? CTFE doesn't allow ANY form of reinterpret cast, apart from signed-unsigned. In particular, you can't do anything in CTFE which exposes endianness. It might let you cast from ubyte[] to void[] and then back to ubyte[] or byte[], but that would be all. So that's a deliberate decision and won't change? I guess it's a safety measure as the ctfe and runtime endianness could differ? Yes. Anyway, I can understand that reasoning but it also means that the new std.hash could only be used with raw ubyte[] arrays and it wouldn't be possible to generate the CRC/SHA1/MD5 etc sum of e.g. a string in ctfe. (Which might make sense for most types as the result could really differ depending on endianness, but it shouldn't matter for UTF8 strings, right?) Maybe I can special case CTFE so that at least UTF8 strings work. BTW: casting from void[][] to ubyte[][] seems to work. I guess this is only an oversight and nothing I could use as a workaround? Probably a bug. But you can convert from char[] to byte[]/ubyte[]. That's OK, it doesn't depend on endianness.
Re: All right, all right! Interim decision regarding qualified Object methods
On 13/07/12 11:02, F i L wrote: I always wondered why toString() wasn't just to!string() in the first place, short of UFCS not being implemented for all types. toString() comes from the days before D had templates.
Re: D versionning
On 13/07/12 09:11, Jacob Carlborg wrote: On 2012-07-13 08:52, Adam Wilson wrote: I hope Walter isn't against this, because I'm not seeing much community disagreement with this... If he's not against it, I see know reason why this haven't been done already. It has. It's called D1.
Re: cast from void[] to ubyte[] in ctfe
On 13/07/12 11:16, Johannes Pfau wrote: Casting from void[] to ubyte[] is currently not allowed in CTFE. Is there a special reason for this? I don't see how this cast can be dangerous? CTFE doesn't allow ANY form of reinterpret cast, apart from signed-unsigned. In particular, you can't do anything in CTFE which exposes endianness. It might let you cast from ubyte[] to void[] and then back to ubyte[] or byte[], but that would be all.
Re: All right, all right! Interim decision regarding qualified Object methods
On 12/07/12 06:15, Andrei Alexandrescu wrote: Required reading prior to this: http://goo.gl/eXpuX You destroyed, we listened. I think Christophe makes a great point. We've been all thinking inside the box but we should question the very existence of the box. Once the necessity of opCmp, opEquals, toHash, toString is being debated, we get to some interesting points: 1. Polymorphic comparisons for objects has problems even without considering interaction with qualifiers. I wrote quite a few pages about that in TDPL, which add to a lore grown within the Java community. 2. C++ has very, very successfully avoided the necessity of planting polymorphic comparisons in base classes by use of templates. The issue is template code bloat. My impression from being in touch with the C++ community for a long time is that virtually nobody even talks about code bloat anymore. For whatever combination of industry and market forces, it's just not an issue anymore. 3. opCmp, opEquals, and toHash are all needed primarily for one thing: built-in hashes. (There's also use of them in the moribund .sort method.) The thing is, the design of built-in hashes predates the existence of templates. There are reasons to move to generic-based hashes instead of today's runtime hashes (such as the phenomenal success of templated containers in C++), so it can be argued that opCmp, opEquals, and toHash exist for reasons that are going extinct. 4. Adding support for the likes of logical constness is possible, but gravitates between too lax and onerously complicated. Walter and I don't think the aggravation is justified. There are of course more angles and considerations. Walter and I discussed such for a while and concluded we should take the following route: 1. For the time being, rollback the changes. Kenji, could you please do the honors? There's no need to undo everything, only the key parts in object.d. Apologies for having to undo your work! 2. Investigate a robust migration path from the current use of opCmp, opEquals, toHash (we need to also investigate toString) to a world in which these methods don't exist in Object. In that world, associative arrays would probably be entirely generic. Ideally we should allow existing code to still work, while at the same time fostering a better style for new code. What say you? Andrei Well: * having opCmp() defined for all objects is just plain weird. * toString() is a poor design anyway. But we'd need to be very careful, this is a very disruptive change.
Re: All right, all right! Interim decision regarding qualified Object methods
On 12/07/12 12:00, Paulo Pinto wrote: On Thursday, 12 July 2012 at 08:59:46 UTC, Don Clugston wrote: On 12/07/12 06:15, Andrei Alexandrescu wrote: Required reading prior to this: http://goo.gl/eXpuX You destroyed, we listened. I think Christophe makes a great point. We've been all thinking inside the box but we should question the very existence of the box. Once the necessity of opCmp, opEquals, toHash, toString is being debated, we get to some interesting points: 1. Polymorphic comparisons for objects has problems even without considering interaction with qualifiers. I wrote quite a few pages about that in TDPL, which add to a lore grown within the Java community. 2. C++ has very, very successfully avoided the necessity of planting polymorphic comparisons in base classes by use of templates. The issue is template code bloat. My impression from being in touch with the C++ community for a long time is that virtually nobody even talks about code bloat anymore. For whatever combination of industry and market forces, it's just not an issue anymore. 3. opCmp, opEquals, and toHash are all needed primarily for one thing: built-in hashes. (There's also use of them in the moribund .sort method.) The thing is, the design of built-in hashes predates the existence of templates. There are reasons to move to generic-based hashes instead of today's runtime hashes (such as the phenomenal success of templated containers in C++), so it can be argued that opCmp, opEquals, and toHash exist for reasons that are going extinct. 4. Adding support for the likes of logical constness is possible, but gravitates between too lax and onerously complicated. Walter and I don't think the aggravation is justified. There are of course more angles and considerations. Walter and I discussed such for a while and concluded we should take the following route: 1. For the time being, rollback the changes. Kenji, could you please do the honors? There's no need to undo everything, only the key parts in object.d. Apologies for having to undo your work! 2. Investigate a robust migration path from the current use of opCmp, opEquals, toHash (we need to also investigate toString) to a world in which these methods don't exist in Object. In that world, associative arrays would probably be entirely generic. Ideally we should allow existing code to still work, while at the same time fostering a better style for new code. What say you? Andrei Well: * having opCmp() defined for all objects is just plain weird. * toString() is a poor design anyway. But we'd need to be very careful, this is a very disruptive change. I don't find them that weird, because many OO languages do have them. Really? I find that incredible. Ordered comparisons , don't even make sense for many mathematical objects! You can't even define opCmp for a float. Object f = new FtpConnection; Object e = new Employee(Bob); if (f e) // Huh???
Re: stdarg x86_64 problems...
On 12/07/12 11:12, John Colvin wrote: When I compile the following code with -m32 and -m64 i get a totally different result, the documentation suggests that they should be the same... import core.stdc.stdarg, std.stdio; void main() { foo(0,5,4,3); } void foo(int dummy, ...) { va_list ap; for(int i; i10; ++i) { version(X86_64) { va_start(ap, __va_argsave); } else version(X86) { va_start(ap, dummy); } else static assert(false, Unsupported platform); int tmp; va_arg!(int)(ap,tmp); writeln(ap, , tmp); } } when compiled with -m32 I get: FF960278 5 FF960278 5 FF960278 5 FF960278 5 FF960278 5 and with -m64 I get: 7FFFCDF941D0 5 7FFFCDF941D0 4 7FFFCDF941D0 3 7FFFCDF941D0 38 7FFFCDF941D0 -839302560 (the end stuff is garbage, different every time) I'm uncertain, even after looking over the stdarg src, why this would happen. The correct output is all 5s obviously. Known bug, already fixed in git for a couple of months.
Re: Inherited const when you need to mutate
On 10/07/12 19:13, H. S. Teoh wrote: On Tue, Jul 10, 2012 at 06:48:51PM +0200, Timon Gehr wrote: On 07/10/2012 06:45 PM, H. S. Teoh wrote: Yeah, this is logical const. Unfortunately, D doesn't have logical const. Then why on earth is druntime acting as if it does? Y'know, this brings up an interesting question. Do methods like toString _need_ to be const? That is, _physical_ const? Or are we unconsciously conflating physical const with logical const here? Yes, certain runtime operations need to be able to work with const methods, but I wonder if those required const methods really belong to a core set of more primitive operations that guarantee physical const, and perhaps shouldn't be conflated with logical operations like convert this object to a string representation, which _may_ require caching, etc.? Or perhaps application code want to be defining their own non-const versions of certain methods so that they can do whatever they need to do with logical const, without worrying about breaking physical const-ness. I'm starting to think that D's hardline approach to const is clashing with the principle of information hiding. Users of a class shouldn't _need_ to know if an object is caching the value of toString, toHash, or whatever it is. What they care for is that the object doesn't visibly change, that is, logical const. Binary const implies logical const, but the implication doesn't work the other way round. While it's nice to have binary const (strong, enforceable guarantee), it breaks encapsulation: just because a class needs to do caching, means its methods can't be const, and this is a visible (and viral, no less) change in its external API. What should just be an implementation detail has become a visible difference to the outside world -- encapsulation is broken. I don't know how to remedy this. It's clear that physical const does have its value -- it's necessary to properly support immutable, allows putting data in ROM, etc.. But it's also clear that something is missing from the picture. Implementation details are leaking past object APIs, caching and other abstractions can't work with const, etc., and that's not a good thing. T I think you're right. Something I wonder about, though, is how many different use cases are we dealing with? Suppose we had a caching solution (you could think of it as @cached, but it could be done in a library). The user would need to provide a const, pure function which returns the same value that is stored in the cache. This is enforceable. The only way to write to the cache, is by calling the function. How far would that take us? I don't think there are many use cases for logically pure, apart from caching, but I have very little idea about logical const.
Re: just an idea (!! operator)
On 11/07/12 13:47, monarch_dodra wrote: On Wednesday, 11 July 2012 at 11:18:21 UTC, akaz wrote: if needed, the operator !! (double exclamation mark) could be defined. Problem is that operator!! is already used asa twin operator!. This is shorthand for is valid as bool: I wouldn't be surprised if this is happening in D, so I don't think !! can be taken for anything. This is about binary x!!y, not unary !!x.
Re: Exquisite code samples
On 10/07/12 09:49, renoX wrote: On Monday, 9 July 2012 at 11:40:37 UTC, Gor Gyolchanyan wrote: [cut] You're right. This is a bit advanced code sample, which uses templates,template constraints, contract programming among syntax advantages of D. Hum it show the power of D sure, but IMHO it also show its syntax deficiencies.. For me this real[d] bezier(size_t d, Number)(Number[d][] p, Number t) if(d 1 isFloatingPoint!Number) is difficult to read, and a better syntax would be: real[d] bezier!(size_t d d 1, Number isFloatingPoint!Number)(Number[d][] p, Number t) The template parameter would be indicated in a !() (as in a call), and the template constraints inside the template parameter: this way the template parameters are clearly indicated and separated from the function parameter. renoX Well it used to work vaguely in that way, but it gets very ugly once you leave the simplest cases. Even that one you've listed is hard for me to read. And the idea that constraints apply to individual parameters is wrong. If you have a constraint that depends on two template parameters, where do you put it? int bezier (int A, int B)(int t) if ( A + B == 10 )
Re: Two Scala annotations
On 02/07/12 23:20, Walter Bright wrote: On 7/2/2012 1:04 PM, bearophile wrote: Walter Bright: Put final in front of y, and it will compile. Remember, this was done for D1 that didn't have const. I see. So in D2 are we going to require that y to be immutable? No. I don't agree there's a problem. Nor do I care to break existing D1 code (and D2 for that matter) without an awfully good reason, and I don't see one here. This behaviour is *not* currently in the spec. And if you give any other kind of runtime expression, you get an error message which suggests it shouldn't work: void main() { int x; int y; switch(x) { case *y: break; } } bug.d(10): Error: case must be a string or an integral constant, not *y -- It would be really difficult to define the current behaviour. I don't understand it. Let me explain how bizarre it is. What it does is, run optimize(WANTvar) on the expression. If at the end of optimization, it is a VarExp of type integer or class, then it can be a run-time value. It must be a VarExp, it cannot be a DotVar. Now, what does optimize(WANTvar) actually do? Under what circumstances can it produce a VarExp? I'm not sure. You really need to check every code path in optimize.c and constfold.c. It can happen with comma expressions, for example. So this: case 7+8, y: is accepted. Are there circumstances where X.Y can be accepted? Maybe some combination involving alias this or opDispatch ? I don't know.
Re: Raw binary(to work without OS) in D
On 28/06/12 18:37, David Nadlinger wrote: On Thursday, 28 June 2012 at 15:28:10 UTC, Don Clugston wrote: There's an oddity, though: the type of X.significand would be dependent on the type of X […] I don't think this is a problem at all – for example, the type of T.init depends on T as well… David Good point.
Re: Raw binary(to work without OS) in D
On 28/06/12 18:36, Jens Mueller wrote: Don Clugston wrote: On 28/06/12 17:00, Jens Mueller wrote: Andrei Alexandrescu wrote: On 6/28/12 10:07 AM, Roman D. Boiko wrote: On Thursday, 28 June 2012 at 14:04:37 UTC, Mehrdad wrote: I think just exposing them via .sig and .exp might be the way to go? sig is easy to confuse with sign .mantissa and .exp Letting the compiler define these properties is a solution. I thought Don is looking for something more general. But maybe this isn't needed here. Don't know. But using mantissa should be discouraged. I suggest calling them .significand and .exponent significand is preferred over mantissa by IEEE FP committee. I think it's fine to spell them out. There won't be much code using them anyway. Jens Yes, adding new properties would be the easiest way from a CTFE perspective; that way, they are endian-ness independent. It's a bit niche, but then again adding a special case for this in CTFE is niche as well. Maybe it would be the best approach. Sounds good then. With naming, I'm included to agree, but the funny thing is that we have X.mant_dig as the number of digits in the significand. You could add a deprecated alias to X.mant_dig and provide a new name. We should adopt IEEE's vocabulary where possible. There's an oddity, though: the type of X.significand would be dependent on the type of X (and for the non-existent quadruple float, it would be non-existent ucent type!) But this is no problem, is it? Would it include the implicit bit of an 80-bit x87 real (the silly bit)? Not sure what the silly bit is. You mean the bit that is implicitly always 1, don't you? mant_dig says 24 for a float. Means it is included when counting the bits. Then for consistency it should be included. Yes, the implicit bit. For float and double it isn't present, but it's there for 80bit x87 and 68K reals. But it would not be present for quadruple types. I'm not sure if it's always present on Itanium 80-bit reals. It's included in the 80-bit reals only for historical reasons -- it seemed like a good idea at the time. It allowed an optimisation for a long-obsolete algorithm.
Re: Two Scala annotations
On 01/07/12 04:00, Walter Bright wrote: On 6/30/2012 6:05 PM, bearophile wrote: Walter Bright: It's not a bug. It's deliberate, and is there to support mechanical translation of Java code. Is this stuff written somewhere in a D design rationales page? Now that D is several years old, how much Java code was ported to D? (Despite there is no mechanical Java-D translator yet). Yes, a mechanical translator was used extensively to create dwt. Was this automatic translation desire worth the troubles (like inner classes, Yes. like the risk of killing switch optimizations by mistake)? Calling it a risk and killing is way, way overstating things. This post is about two Scala annotations. If that's not a bug, is something like that first Scala annotation useful in D too? I don't really see any problem requiring a solution. If you're working on optimizations at that level, you ought to be comfortable examining the asm output for that and all the other stuff, too. Setting a store on just one aspect of switch implementations is a large mistake. The problem isn't the effect on optimization. The problem is that the semantics are insane. They are like nothing else in the language, and they don't make any sense. It's a very complicated feature: eg what happens if the case is a shared variable? Under what circumstances is a symbol treated as a variable, rather than a constant? As far as I know, no other language works anything like this. Either switch accepts only constants, or it accepts arbitrary expressions. Not this bizarre combination of both. Do you have a reference for this Java behaviour? I did a quick google, and everything I found indicates that case labels must be constants.
Re: New hash API: namespace
On 25/06/12 20:04, Jesse Phillips wrote: On Monday, 25 June 2012 at 16:09:43 UTC, Felix Hufnagel wrote: +1 for hashes into std.hash and cryptographic primitives into std.crypto and we should have a std.net (std.uri, std.socket, std.socketstream , std.net.curl, ...), std.io. for (Outbuffer, file, ) and probably std.database or something like that for (csv, json, xml, ...) I'd be for not being so flat. I reckon, follow biology. There's kingdom.phyllus.class.order.family.genus.species But in practice, that's far too clumsy. Instead, everyone just uses genus.species. And this works even though there are more than a million species. So I reckon two levels of modules is enough. More than that is clumsy. And, if you're not sure where something should be, because there are two or more equally valid alternatives, it should probably be a level closer to the root of the tree.
Re: LLVM IR influence on compiler debugging
On 29/06/12 08:04, bearophile wrote: This is a very easy to read article about the design of LLVM: http://www.drdobbs.com/architecture-and-design/the-design-of-llvm/240001128 That IR has a great effect on making it simpler to debug the compiler, I think this is important (and I think it partially explains why Clang was created so quickly): It's a good design, especially for optimisation tests. Although I can't see an immediate application of this for D. DMD's backend is nearly bug-free. (By which I mean, it has 100X fewer bugs than the front-end).
Re: Raw binary(to work without OS) in D
On 28/06/12 15:31, Jens Mueller wrote: Andrei Alexandrescu wrote: On 6/22/12 7:41 AM, Don Clugston wrote: I think the main thing that's still done in C is the floating point formatting. Would be great if a contributor could translate FP parsing and formatting code into D. Then we can use it in CTFE. I need it badly for some function tabulation code. I think formatting cannot be done such that it is CTFE-able. I tried implementing a less-inefficient version. As far as I can tell at some point you need to extract the significand and the exponent. This is done by some unsafe cast which is not allowed in CTFE. I don't know a way to do it in CTFE-compatible way. Jens Yeah, I think I will have to find a way of allowing it. But it's difficult to see a clean way of doing it.
Re: Raw binary(to work without OS) in D
On 28/06/12 17:00, Jens Mueller wrote: Andrei Alexandrescu wrote: On 6/28/12 10:07 AM, Roman D. Boiko wrote: On Thursday, 28 June 2012 at 14:04:37 UTC, Mehrdad wrote: I think just exposing them via .sig and .exp might be the way to go? sig is easy to confuse with sign .mantissa and .exp Letting the compiler define these properties is a solution. I thought Don is looking for something more general. But maybe this isn't needed here. Don't know. But using mantissa should be discouraged. I suggest calling them .significand and .exponent significand is preferred over mantissa by IEEE FP committee. I think it's fine to spell them out. There won't be much code using them anyway. Jens Yes, adding new properties would be the easiest way from a CTFE perspective; that way, they are endian-ness independent. It's a bit niche, but then again adding a special case for this in CTFE is niche as well. Maybe it would be the best approach. With naming, I'm included to agree, but the funny thing is that we have X.mant_dig as the number of digits in the significand. There's an oddity, though: the type of X.significand would be dependent on the type of X (and for the non-existent quadruple float, it would be non-existent ucent type!) Would it include the implicit bit of an 80-bit x87 real (the silly bit)?
Re: A little story
On 25/06/12 14:24, bearophile wrote: Dmitry Olshansky: Except for the fact, that someone has to implement it. I am not seeing one of the posts of this thread. So I'll answer here. The good thing regarding the run-time overflow integral tests is that they are already implemented and available as efficient compiler intrinsics in both GCC and LLVM back-ends. It's just a matter of using them (and introducing the compiler switch and some kind of pragma syntax). Bye, bearophile Bearophile, haven't you ever read that paper on integer overflow, which you keep posting to the newsgroup??? It clearly demonstrates that it is NOT POSSIBLE to implement integer overflow checking in a C-family language. Valid, correct, code which depends on integer overflow is very, very common (when overflow occurs, it's more likely to be correct, than incorrect). I don't think you could do it without introducing a no-overflow integer type. The compiler just doesn't have enough information.
Re: Raw binary(to work without OS) in D
On 22/06/12 10:08, Mehrdad wrote: On Friday, 22 June 2012 at 08:00:08 UTC, Dmitry Olshansky wrote: Then implement the ones you happen to actually need. Er, the question isn't WHAT to do, it's HOW. If you have any idea how to implement things like TLS, SEH, and the like, then PLEASE, share them! On Windows, all of the SEH code is in D. The C library isn't used any more. I think the main thing that's still done in C is the floating point formatting. The point I was trying to make was, though, that this information is not being shared with anyone. Which leads me to believe that whoever has this information doesn't want people to use it for D development...
Re: GDC review process.
On 20/06/12 16:37, Manu wrote: On 20 June 2012 17:15, Don Clugston d...@nospam.com mailto:d...@nospam.com wrote: On 20/06/12 13:22, Manu wrote: I find optimisers are very good at code simplification, assuming that you massage the code/expressions to neatly match any architectural quirks. I also appreciate that good x86 code is possibly the hardest architecture for an optimiser to get right... Optimizers improved enormously during the 80's and 90's, but the rate of improvement seems to have slowed. With x86, out-of-order execution has made it very easy to get reasonably good code, and much harder to achieve perfection. Still, Core i7 is much easier than Core2, since Intel removed one of the most complicated bottlenecks (on core2 and earlier there is a max 3 reads per cycle, of registers you haven't written to in the previous 3 cycles). Yeah okay, I can easily imagine the complexity for an x86 codegen. RISC architectures are so much more predictable. How do you define 'perfection'? Performance as measured on what particular machine? :) The theoretical limit for a particular architecture. Eg in BigInt, the most crucial functions an integer multiply in each loop iteration. Since the machine only has one integer multiply unit, it is impossible to do better than one multiply per cycle. If you've achieved that, it's perfect. If the processors are different enough you may also need a separate branch for different processors.
Re: How to break const
On 19/06/12 11:02, Iain Buclaw wrote: On 19 June 2012 09:18, Don Clugstond...@nospam.com wrote: So would I. Can you think of one? It was the best name I could come up with, given that the 'pure' was the keyword. We want a word that means 'no hidden state'. I thought that was what pure was for. :~) This page is interesting. http://en.wikipedia.org/wiki/Pure_function There's never any hidden state, even in a weakly pure function. So it satisfies rule 1. A weakly pure function may modify anything it can reach through the parameters, though. Does this violate rule 2? I guess that if you define all mutable arguments of a weakly pure function as being 'pass by reference', then even 'weakly pure' is pure according to that definition. The page states that according to that definition, the expressions which call the pure function are not pure. But again in the terms of that page, D has an Effect System which allow us to prove that a function is pure even though it has impure expressions in it. Wikipedia isn't very authoritative though. So I don't know -- although D 'pure' is very different to what FP people call 'pure', I'm no longer certain that we're abusing the term. After all, even this function isn't pure in the traditional FP view: int foo(int n) pure { int r = n*n; r += n; return r; }
Re: GDC review process.
On 19/06/12 20:19, Iain Buclaw wrote: Hi, Had round one of the code review process, so I'm going to post the main issues here that most affect D users / the platforms they want to run on / the compiler version they want to use. 1) D Inline Asm and naked function support is raising far too many alarm bells. So would just be easier to remove it and avoid all the other comments on why we need middle-end and backend headers in gdc. You seem to be conflating a couple of unrelated issues here. One is the calling convention. The other is inline asm. Comments in the thread about asm is mostly used for short things which get inlined leave me completely baffled, as it is completely wrong. There are two uses for asm, and they are very different: (1) Functionality. This happens when there are gaps in the language, and you get an abstraction inversion. You can address these with intrinsics. (2) Speed. High-speed, all-asm functions. These _always_ include a loop. You seem to be focusing on (1), but case (2) is completely different. Case (2) cannot be replaced with intrinsics. For example, you can't write asm code using MSVC intrinsics (because the compiler rewrites your code). Currently, D is the best way to write (2). It is much, much better than an external assembler.
Re: GDC review process.
On 20/06/12 03:01, Alex Rønne Petersen wrote: On 20-06-2012 02:58, Timon Gehr wrote: On 06/20/2012 02:04 AM, Alex Rønne Petersen wrote: On 20-06-2012 01:55, Timon Gehr wrote: On 06/20/2012 12:47 AM, Alex Rønne Petersen wrote: On 19-06-2012 23:52, Walter Bright wrote: On 6/19/2012 1:36 PM, bearophile wrote: No, but the idea was to allow D to innovate on calling conventions without disturbing code that needed to interface with C. The idea is nice, but ideas aren't enough. Where are the benchmarks that show a performance improvement over the C calling convention? And even if such improvement is present, is it worth it in the face of people that don't want to add it to GCC? GDC can certainly define its D calling convention to match GCC's. It's an implementation defined thing, not a language defined one. Then let's please rename it to the DMD ABI instead of calling it the D ABI and making it look like it's part of the language on the website. Further, D mangling rules should be separate from calling convention. IIRC currently, the calling convention is mangled into the symbol name. Do you want to remove this? Not that I can see from http://dlang.org/abi.html ? TypeFunction: CallConvention FuncAttrs Arguments ArgClose Type CallConvention: F // D U // C W // Windows V // Pascal R // C++ I see. I think it's a mistake to call that calling convention D. I'm not against removing it, but the description is highly misleading. And C++ calling convention doesn't make any sense. There is no such thing. On Windows, every vendor does it differently (even the ones who claim to be compatible with one another!).
Re: GDC review process.
On 20/06/12 00:55, Manu wrote: On 20 June 2012 01:07, Walter Bright newshou...@digitalmars.com mailto:newshou...@digitalmars.com wrote: On 6/19/2012 1:58 PM, Manu wrote: I find a thorough suite of architecture intrinsics are usually the fastest and cleanest way to the best possible code, although 'naked' may be handy in this circumstance too... Do a grep for naked across the druntime library sources. For example, its use in druntime/src/rt/alloca.d, where it is very much needed, as alloca() is one of those magic functions. I never argued against naked... I agree it's mandatory. Do a grep for asm across the druntime library sources. Can you justify all of that with some other scheme? I think almost all the blocks I just browsed through could be easily written with nothing more than the register alias feature I suggested, and perhaps a couple of opcode intrinsics. And as a bonus, they would also be readable. I can imagine cases where the optimiser would have more freedom too. Thinking more about the implications of removing the inline asm, what would REALLY roxors, would be a keyword to insist a variable is represented by a register, and by extension, to associate it with a specific register: This was a failure in C. Really? This is the missing link between mandatory asm blocks, and being able to do it in high level code with intrinsics. The 'register' keyword was similarly fail as 'inline'.. __forceinline was not fail, it is actually mandatory. I'd argue that __forceregister would be similarly useful in C aswell, but the real power would come from being able to specify the particular register to alias. This would almost entirely eliminate the usefulness of an inline assembler. Better yet, this could use the 'new' attribute syntax, which most agree will support arguments: @register(rsp) int x; Some C compilers did have such pseudo-register abilities. It was a failure in practice. Really? I've never seen that. What about it was fail? I really don't understand preferring all these rather convoluted enhancements to avoid something simple and straightforward like the inline assembler. The use of IA in the D runtime library, for example, has been quite successful. I agree, IA is useful and has been successful, but it has drawbacks too. * IA ruins optimisation around the IA block * IA doesn't inline well. intrinsics allow much greater opportunity for efficient integration into the calling context * most IA functions are small, and prime candidates for inlining (see points 1 and 2) You and I seem to be from different planets. I have almost never written as asm function which was suitable for inlining. Take a look at std.internal.math.biguintX86.d I do not know how to write that code without inline asm.
Re: GDC review process.
On 20/06/12 13:04, Manu wrote: On 20 June 2012 13:51, Don Clugston d...@nospam.com mailto:d...@nospam.com wrote: On 19/06/12 20:19, Iain Buclaw wrote: Hi, Had round one of the code review process, so I'm going to post the main issues here that most affect D users / the platforms they want to run on / the compiler version they want to use. 1) D Inline Asm and naked function support is raising far too many alarm bells. So would just be easier to remove it and avoid all the other comments on why we need middle-end and backend headers in gdc. You seem to be conflating a couple of unrelated issues here. One is the calling convention. The other is inline asm. Comments in the thread about asm is mostly used for short things which get inlined leave me completely baffled, as it is completely wrong. There are two uses for asm, and they are very different: (1) Functionality. This happens when there are gaps in the language, and you get an abstraction inversion. You can address these with intrinsics. (2) Speed. High-speed, all-asm functions. These _always_ include a loop. You seem to be focusing on (1), but case (2) is completely different. Case (2) cannot be replaced with intrinsics. For example, you can't write asm code using MSVC intrinsics (because the compiler rewrites your code). Currently, D is the best way to write (2). It is much, much better than an external assembler. Case 1 has no alternative to inline asm. I've thrown out some crazy ideas to think about (but nobody seems to like them). I still think it could be addressed though. Case 2; I'm not convinced. These such long functions are the type I'm generally interested in aswell, and have the most experience with. But in my experience, they're almost always best written with intrinsics. If they're small enough to be inlined, then you can't afford not to use intrinsics. If they are truly big functions, then you begin to sacrifice readability and maintain-ability, and certainly limit the number of programmers that can maintain the code. I don't agree with that. In the situations I'm used to, using intrinsics would not make it easier to read, and would definitely not make it easier to maintain. I find it inconceivable that somebody could understand the processor well enough to maintain the code, and yet not understand asm. I rarely fail to produce identical code with intrinsics to that which I would write with hand written asm. The flags are always the biggest challenge, as discussed prior in this thread. I think that could be addressed with better intrinsics. Again, look at std.internal.math.BiguintX86. There are many cases there where you can swap two instructions, and the code will still produce the correct result, but it will be 30% slower. I think that the SIMD case gives you a misleading impression, because on x86 they are very easy to schedule (they nearly all take the same number of cycles, etc). So it's not hard for the compiler to do a good job of it.
Re: GDC review process.
On 20/06/12 13:22, Manu wrote: On 20 June 2012 13:59, Don Clugston d...@nospam.com mailto:d...@nospam.com wrote: You and I seem to be from different planets. I have almost never written as asm function which was suitable for inlining. Take a look at std.internal.math.biguintX86.d I do not know how to write that code without inline asm. Interesting. I wish I could paste some counter-examples, but they're all proprietary _ I think they key detail here is where you stated, they _always_ include a loop. Is this because it's hard to manipulate the compiler into the correct interaction with the flags register? No. It's just because speed doesn't matter outside loops. A consequence of having the loop be inside the asm code, is that the parameter passing is much less significant for speed, and calling convention is the big I'd be interested to compare the compiled D code, and your hand written asm code, to see where exactly the optimiser goes wrong. It doesn't look like you're exploiting too many tricks (at a brief glance), it's just nice tight hand written code, which the optimiser should theoretically be able to get right... Theoretically, yes. In practice, DMD doesn't get anywhere near, and gcc isn't much better. I don't think there's any reason why they couldn't, but I don't have much hope that they will. As you say, the code looks fairly straightforward, but actually there are very many similar ways of writing the code, most of which are much slower. There are many bottlenecks you need to avoid. I was only able to get it to that speed by using the processor profiling registers. So, my original two uses for asm are actually: (1) when the language prevents you from accessing low-level functionality; and (2) when the optimizer isn't good enough. I find optimisers are very good at code simplification, assuming that you massage the code/expressions to neatly match any architectural quirks. I also appreciate that good x86 code is possibly the hardest architecture for an optimiser to get right... Optimizers improved enormously during the 80's and 90's, but the rate of improvement seems to have slowed. With x86, out-of-order execution has made it very easy to get reasonably good code, and much harder to achieve perfection. Still, Core i7 is much easier than Core2, since Intel removed one of the most complicated bottlenecks (on core2 and earlier there is a max 3 reads per cycle, of registers you haven't written to in the previous 3 cycles).
Re: GDC review process.
On 20/06/12 14:51, Manu wrote: On 20 June 2012 14:44, Don Clugston d...@nospam.com mailto:d...@nospam.com wrote: On 20/06/12 13:04, Manu wrote: On 20 June 2012 13:51, Don Clugston d...@nospam.com mailto:d...@nospam.com mailto:d...@nospam.com mailto:d...@nospam.com wrote: On 19/06/12 20:19, Iain Buclaw wrote: Hi, Had round one of the code review process, so I'm going to post the main issues here that most affect D users / the platforms they want to run on / the compiler version they want to use. 1) D Inline Asm and naked function support is raising far too many alarm bells. So would just be easier to remove it and avoid all the other comments on why we need middle-end and backend headers in gdc. You seem to be conflating a couple of unrelated issues here. One is the calling convention. The other is inline asm. Comments in the thread about asm is mostly used for short things which get inlined leave me completely baffled, as it is completely wrong. There are two uses for asm, and they are very different: (1) Functionality. This happens when there are gaps in the language, and you get an abstraction inversion. You can address these with intrinsics. (2) Speed. High-speed, all-asm functions. These _always_ include a loop. You seem to be focusing on (1), but case (2) is completely different. Case (2) cannot be replaced with intrinsics. For example, you can't write asm code using MSVC intrinsics (because the compiler rewrites your code). Currently, D is the best way to write (2). It is much, much better than an external assembler. Case 1 has no alternative to inline asm. I've thrown out some crazy ideas to think about (but nobody seems to like them). I still think it could be addressed though. Case 2; I'm not convinced. These such long functions are the type I'm generally interested in aswell, and have the most experience with. But in my experience, they're almost always best written with intrinsics. If they're small enough to be inlined, then you can't afford not to use intrinsics. If they are truly big functions, then you begin to sacrifice readability and maintain-ability, and certainly limit the number of programmers that can maintain the code. I don't agree with that. In the situations I'm used to, using intrinsics would not make it easier to read, and would definitely not make it easier to maintain. I find it inconceivable that somebody could understand the processor well enough to maintain the code, and yet not understand asm. These functions of yours are 100% asm, that's not really what I would usually call 'inline asm'. That's really just 'asm' :) I think you've just illustrated one of my key points actually; that is that you can't just insert small inline asm blocks within regular code, the optimiser can't deal with it in most cases, so inevitably, the entire function becomes asm from start to end. Personally I call it inline asm if I don't need to use a separate assembler. If you're using a different definition, then we don't actually disagree. I find I can typically produce equivalent code using carefully crafted intrinsics within regular C language structures. Also, often enough, the code outside the hot loop can be written in normal C for readability, since it barely affects performance, and trivial setup code will usually optimise perfectly anyway. You're correct that a person 'maintaining' such code, who doesn't have such a thorough understanding of the codegen may ruin it's perfectly tuned efficiency. This may be the case, but in a commercial coding environment, where a build MUST be delivered yesterday, the guy that understands it is on holiday, and you need to tweak the behaviour immediately, this is a much safer position to be in. This is a very real scenario. I can't afford to ignore this practical reality. OK, it sounds like your use case is a bit different. The kinds of things I deal with are I might have a go at compiling the regular D code tonight, and seeing if I can produce identical assembly. I haven't tried this so much with x86 as I have with RISC architectures, which have much more predictable codegen. I rarely fail to produce identical code with intrinsics to that which I would write with hand written asm. The flags are always the biggest challenge, as discussed prior
Re: How to break const
On 18/06/12 17:00, Artur Skawina wrote: On 06/18/12 16:41, deadalnix wrote: Le 18/06/2012 16:28, Artur Skawina a écrit : It's fine, if you view a delegate as opaque. No it isn't. You cannot ensure transitivity anywhere. This have obvious, and severe drawback for concurrent programing (implicit sharing is back) and GC performances (GC can eb crazy fast when it come to transitive immutable data, see OCaml's GC performances for instance). 'this' being const does not preclude accessing the object that 'this' points to via another, mutable, reference. Consider the alternative - you'd have to forbid storing any delegate with a non-const non-value argument inside any object. So how would you like to handle this? And, no, allowing only the cases that /can/ be statically checked is not ok - it would result in black magic - delegates would be accepted or not depending on the contents of the object (think templates and composition). And breaking const would then _still_ be possible and trivial. No, and your example don't demonstrate that in any way. Transitivity is maintained in the example below, because g isn't a member of s, and if it were, then the example would break at compile time. The word breaking is in quotes for a reason. Const is not an immutability guarantee. If you treat delegates as opaque then there's no practical difference between using them or accessing the data via another external reference. purity is another beast altogether. D's weak pure can help; I just don't like the redefinition of the term purity; another name for weak purity would be better. So would I. Can you think of one? It was the best name I could come up with, given that the 'pure' was the keyword. We want a word that means 'no hidden state'.
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 17/06/12 00:37, Walter Bright wrote: On 6/14/2012 1:03 AM, Don Clugston wrote: It is for debug builds. Iain's data indicates that it's only a few % of the time taken on semantic1(). Do you have data that shows otherwise? Nothing recent, it's mostly from my C++ compiler testing. But you argued in your blog that C++ parsing is inherently slow, and you've fixed those problems in the design of D. And as far as I can tell, you were extremely successful! Parsing in D is very, very fast. Yes, it is designed so you could just import a symbol table. It is done as source code, however, because it's trivial to implement. It has those nasty side-effects listed under (3) though. I don't think they're nasty or are side effects. They are new problems which people ask for solutions for. And they are far more difficult to solve than the original problem.
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 14/06/12 10:10, Jonathan M Davis wrote: On Thursday, June 14, 2012 10:03:05 Don Clugston wrote: On 13/06/12 16:29, Walter Bright wrote: On 6/13/2012 1:07 AM, Don Clugston wrote: On 12/06/12 18:46, Walter Bright wrote: On 6/12/2012 2:07 AM, timotheecour wrote: There's a current pull request to improve di file generation (https://github.com/D-Programming-Language/dmd/pull/945); I'd like to suggest further ideas. As far as I understand, di interface files try to achieve these conflicting goals: 1) speed up compilation by avoiding having to reparse large files over and over. 2) hide implementation details for proprietary reasons 3) still maintain source code in some form to allow inlining and CTFE 4) be human readable (4) was not a goal. A .di file could very well be a binary file, but making it look like D source enabled them to be loaded with no additional implementation work in the compiler. I don't understand (1) actually. For two reasons: (a) Is lexing + parsing really a significant part of the compilation time? Has anyone done some solid profiling? It is for debug builds. Iain's data indicates that it's only a few % of the time taken on semantic1(). Do you have data that shows otherwise? It seems to me, that slow parsing is a C++ problem which D already solved. If this is the case, is there any value at all to using .di files in druntime or Phobos other than in cases where we're specifically trying to hide implementation (e.g. with the GC)? Or do we still end up paying the semantic cost for importing the .d files such that using .di files would still help with compilation times? - Jonathan M Davis I don't think Phobos should use .di files at all. I don't think there are any cases where we want to conceal code. The performance benefit you would get is completely negligible. It doesn't even reduce the number of files that need to be loaded, just the length of each one. I think that, for example, improving the way that array literals are dealt with would have at least as much impact on compilation time. For the DMD backend, fixing up the treatment of comma expressions would have a much bigger impact than getting lexing and parsing time to zero. And we're well set up for parallel compilation. There's no shortage of things we can do to improve compilation time. Using di files for speed seems a bit like jettisoning the cargo to keep the ship afloat. It works but you only do it when you've got no other options.
Re: static array literal syntax request: auto x=[1,2,3]S;
On 10/06/12 23:43, Jonathan M Davis wrote: On Sunday, June 10, 2012 23:23:57 Mehrdad wrote: I honestly don't see the POINT of having a dynamic array literal. What's the point of making the literals dynamic? They should all be static, and only converted to dynamic if necessary from the context. But I really don't see the benefit of allocating them on the heap just because we can... perhaps someone can enlighten me? In the vast majority of cases where an array literal is used, it's assigned to a dynamic array. I doubt that very much. I know it's not true in my code, I use array literals almost exclusively for immutable values. Usually if you are initializing an array, where you will modify the elements later, you want all values to be the same. I argued that array literals should be immutable, just as string literals are. But I lost.
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 13/06/12 16:29, Walter Bright wrote: On 6/13/2012 1:07 AM, Don Clugston wrote: On 12/06/12 18:46, Walter Bright wrote: On 6/12/2012 2:07 AM, timotheecour wrote: There's a current pull request to improve di file generation (https://github.com/D-Programming-Language/dmd/pull/945); I'd like to suggest further ideas. As far as I understand, di interface files try to achieve these conflicting goals: 1) speed up compilation by avoiding having to reparse large files over and over. 2) hide implementation details for proprietary reasons 3) still maintain source code in some form to allow inlining and CTFE 4) be human readable (4) was not a goal. A .di file could very well be a binary file, but making it look like D source enabled them to be loaded with no additional implementation work in the compiler. I don't understand (1) actually. For two reasons: (a) Is lexing + parsing really a significant part of the compilation time? Has anyone done some solid profiling? It is for debug builds. Iain's data indicates that it's only a few % of the time taken on semantic1(). Do you have data that shows otherwise? It seems to me, that slow parsing is a C++ problem which D already solved. (b) Wasn't one of the goals of D's module system supposed to be that you could import a symbol table? Why not just implement that? Seems like that would be much faster than .di files can ever be. Yes, it is designed so you could just import a symbol table. It is done as source code, however, because it's trivial to implement. It has those nasty side-effects listed under (3) though.
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 12/06/12 18:46, Walter Bright wrote: On 6/12/2012 2:07 AM, timotheecour wrote: There's a current pull request to improve di file generation (https://github.com/D-Programming-Language/dmd/pull/945); I'd like to suggest further ideas. As far as I understand, di interface files try to achieve these conflicting goals: 1) speed up compilation by avoiding having to reparse large files over and over. 2) hide implementation details for proprietary reasons 3) still maintain source code in some form to allow inlining and CTFE 4) be human readable (4) was not a goal. A .di file could very well be a binary file, but making it look like D source enabled them to be loaded with no additional implementation work in the compiler. I don't understand (1) actually. For two reasons: (a) Is lexing + parsing really a significant part of the compilation time? Has anyone done some solid profiling? (b) Wasn't one of the goals of D's module system supposed to be that you could import a symbol table? Why not just implement that? Seems like that would be much faster than .di files can ever be.
Re: AST files instead of DI interface files for faster compilation and easier distribution
On 12/06/12 11:07, timotheecour wrote: There's a current pull request to improve di file generation (https://github.com/D-Programming-Language/dmd/pull/945); I'd like to suggest further ideas. As far as I understand, di interface files try to achieve these conflicting goals: 1) speed up compilation by avoiding having to reparse large files over and over. 2) hide implementation details for proprietary reasons 3) still maintain source code in some form to allow inlining and CTFE 4) be human readable Is that actually true? My recollection is that the original motivation was only goal (2), but I was fairly new to D at the time (2005). Here's the original post where it was implemented: http://www.digitalmars.com/d/archives/digitalmars/D/29883.html and it got partially merged into DMD 0.141 (Dec 4 2005), first usable in DMD0.142 Personally I believe that.di files are *totally* the wrong approach for goal (1). I don't think goal (1) and (2) have anything in common at all with each other, except that C tried to achieve both of them using header files. It's an OK solution for (1) in C, it's a failure in C++, and a complete failure in D. IMHO: If we want goal (1), we should try to achieve goal (1), and stop pretending its in any way related to goal (2).
Re: runtime hook for Crash on Error
On 05/06/12 17:44, Jonathan M Davis wrote: On Tuesday, June 05, 2012 13:57:14 Don Clugston wrote: On 05/06/12 09:07, Jonathan M Davis wrote: On Tuesday, June 05, 2012 08:53:16 Don Clugston wrote: On 04/06/12 21:29, Steven Schveighoffer wrote: On Mon, 04 Jun 2012 06:20:56 -0400, Don Clugstond...@nospam.com wrote: 1. There exist cases where you cannot know why the assert failed. 2. Therefore you never know why an assert failed. 3. Therefore it is not safe to unwind the stack from a nothrow function. Spot the fallacies. The fallacy in moving from 2 to 3 is more serious than the one from 1 to 2: this argument is not in any way dependent on the assert occuring in a nothrow function. Rather, it's an argument for not having AssertError at all. I'm not sure that is the issue here at all. What I see is that the unwinding of the stack is optional, based on the assumption that there's no right answer. However, there is an underlying driver for not unwinding the stack -- nothrow. If nothrow results in the compiler optimizing out whatever hooks a function needs to properly unwind itself (my limited understanding is that this helps performance), then there *is no choice*, you can't properly unwind the stack. -Steve No, this whole issue started because the compiler currently does do unwinding whenever it can. And Walter claimed that's a bug, and it should be explicitly disabled. It is, in my view, an absurd position. AFAIK not a single argument has been presented in favour of it. All arguments have been about you should never unwind Errors. It's quite clear that we cannot completely, correctly unwind the stack in the face of Errors. Well that's a motherhood statement. Obviously in the face of extreme memory corruption you can't guarantee *any* code is valid. The *main* reason why stack unwinding would not be possible is if nothrow intentionally omits stack unwinding code. It's not possible precisely because of nothrow. nothrow only means 'does not throw Exceptions'. It doesn't mean 'does not throw Errors'. Therefore, given: int foo() nothrow { ...} try { foo(); } catch (Error e) { ... } even though there are no throw statements inside foo(), the compiler is NOT permitted to remove the catch(Error), whereas it could remove catch(Exception). The problem is 'finally' clauses. Are they called only on Exception, or on Exception and Error? Regardless, I think that there are a number of people in this thread who are mistaken in how recoverable they think Errors and/or segfaults are, and they seem to be the ones pushing the hardest for full stack unwinding on the theory that they could somehow ensure safe recovery and a clean shutdown when an Error occurs, which is almost never possible, and certainly isn't possible in the general case. - Jonathan M Davis Well I'm pushing it because I implemented it (on Windows). I'm less knowledgeable about what happens on other systems, but know that on Windows, the whole system is far, far more robust than most people on this thread seem to think. I can't see *any* problem with executing catch(Error) clauses. I cannot envisage a situation where that can cause a problem. I really cannot. In many cases, it's probably fine, but if the program is in a bad enough state that an Error is thrown, then you can't know for sure that any particular such block will execute properly (memory corruption being the extreme case), and if it doesn't run correctly, then it could make things worse (e.g. writing invalid data to a file, corrupting that file). Also, if the stack is not unwound perfectly (as nothrow prevents), then the program's state will become increasingly invalid the farther that the program gets from the throw point, which will increase the chances of cleanup code functioning incorrectly, as any assumptions that they've made about the program state are increasingly likely to be wrong (as well as it being increasingly likely that the variables that they operate on no longer being valid). A lot of it comes down to worst case vs typical case. In the typical case, the code causing the Error is isolated enough and the code doing the cleanup is self-contained enough that trying to unwind the stack as much as possible will result in more correct behavior than skipping it all. But in the worst case, you can't rely on running any code being safe, because the state of the program is very much invalid, in which case, it's better to kill the program ASAP. Walter seems to subscribe to the approach that it's best to assume the worst case (e.g. that an assertion failure indicates horrible memory corruption), and always have Errors function that way, whereas others subscribe to the approach that things are almost never that bad, so we should just assume that they aren't, since skipping all of that cleanup causes other problems. I believe I now understand the root issue behind this dispute. Consider: if (x) throw new FileError; if (x) throw new
Re: runtime hook for Crash on Error
On 04/06/12 21:29, Steven Schveighoffer wrote: On Mon, 04 Jun 2012 06:20:56 -0400, Don Clugston d...@nospam.com wrote: 1. There exist cases where you cannot know why the assert failed. 2. Therefore you never know why an assert failed. 3. Therefore it is not safe to unwind the stack from a nothrow function. Spot the fallacies. The fallacy in moving from 2 to 3 is more serious than the one from 1 to 2: this argument is not in any way dependent on the assert occuring in a nothrow function. Rather, it's an argument for not having AssertError at all. I'm not sure that is the issue here at all. What I see is that the unwinding of the stack is optional, based on the assumption that there's no right answer. However, there is an underlying driver for not unwinding the stack -- nothrow. If nothrow results in the compiler optimizing out whatever hooks a function needs to properly unwind itself (my limited understanding is that this helps performance), then there *is no choice*, you can't properly unwind the stack. -Steve No, this whole issue started because the compiler currently does do unwinding whenever it can. And Walter claimed that's a bug, and it should be explicitly disabled. It is, in my view, an absurd position. AFAIK not a single argument has been presented in favour of it. All arguments have been about you should never unwind Errors.
Re: AST Macros?
On 04/06/12 20:46, Jacob Carlborg wrote: On 2012-06-04 10:03, Don Clugston wrote: AST macros were discussed informally on the day after the conference, and it quickly became clear that the proposed ones were nowhere near powerful enough. Since that time nobody has come up with another proposal, as far as I know. I think others have suggested doing something similar like Nemerle, Scala or Nimrod. Yes but only in very vague terms -- not in any more words than that. When I look at the Nimrod docs, it basically seems to be nothing more than expose the compiler internal data structures. Which is extremely easy to do but causes a heap of problems in the long term.
Re: runtime hook for Crash on Error
On 05/06/12 09:07, Jonathan M Davis wrote: On Tuesday, June 05, 2012 08:53:16 Don Clugston wrote: On 04/06/12 21:29, Steven Schveighoffer wrote: On Mon, 04 Jun 2012 06:20:56 -0400, Don Clugstond...@nospam.com wrote: 1. There exist cases where you cannot know why the assert failed. 2. Therefore you never know why an assert failed. 3. Therefore it is not safe to unwind the stack from a nothrow function. Spot the fallacies. The fallacy in moving from 2 to 3 is more serious than the one from 1 to 2: this argument is not in any way dependent on the assert occuring in a nothrow function. Rather, it's an argument for not having AssertError at all. I'm not sure that is the issue here at all. What I see is that the unwinding of the stack is optional, based on the assumption that there's no right answer. However, there is an underlying driver for not unwinding the stack -- nothrow. If nothrow results in the compiler optimizing out whatever hooks a function needs to properly unwind itself (my limited understanding is that this helps performance), then there *is no choice*, you can't properly unwind the stack. -Steve No, this whole issue started because the compiler currently does do unwinding whenever it can. And Walter claimed that's a bug, and it should be explicitly disabled. It is, in my view, an absurd position. AFAIK not a single argument has been presented in favour of it. All arguments have been about you should never unwind Errors. It's quite clear that we cannot completely, correctly unwind the stack in the face of Errors. Well that's a motherhood statement. Obviously in the face of extreme memory corruption you can't guarantee *any* code is valid. The *main* reason why stack unwinding would not be possible is if nothrow intentionally omits stack unwinding code. As such, no one should be relying on stack unwinding when an Error is thrown. This conclusion DOES NOT FOLLOW. And I am getting so sick of the number of times this fallacy has been repeated in this thread. These kinds of generalizations are completely invalid in a systems programming language. Regardless, I think that there are a number of people in this thread who are mistaken in how recoverable they think Errors and/or segfaults are, and they seem to be the ones pushing the hardest for full stack unwinding on the theory that they could somehow ensure safe recovery and a clean shutdown when an Error occurs, which is almost never possible, and certainly isn't possible in the general case. - Jonathan M Davis Well I'm pushing it because I implemented it (on Windows). I'm less knowledgeable about what happens on other systems, but know that on Windows, the whole system is far, far more robust than most people on this thread seem to think. I can't see *any* problem with executing catch(Error) clauses. I cannot envisage a situation where that can cause a problem. I really cannot. And catch(Exception) clauses won't be run, because of the exception chaining scheme we have implemented. The only difficult case is 'finally' clauses, which may be expecting an Exception.
Re: floats default to NaN... why?
On 14/04/12 16:52, F i L wrote: On Saturday, 14 April 2012 at 10:38:45 UTC, Silveri wrote: On Saturday, 14 April 2012 at 07:52:51 UTC, F i L wrote: On Saturday, 14 April 2012 at 06:43:11 UTC, Manfred Nowak wrote: F i L wrote: 4) use hardware signalling to overcome some of the limitations impressed by 3). 4) I have no idea what you just said... :) On Saturday, 14 April 2012 at 07:58:44 UTC, F i L wrote: That's interesting, but what effect does appending an invalid char to a valid one have? Does the resulting string end up being NaS (Not a String)? Cause if not, I'm not sure that's a fair comparison. The initialization values chosen are also determined by the underlying hardware implementation of the type. Signalling NANs (http://en.wikipedia.org/wiki/NaN#Signaling_NaN) can be used with floats because they are implemented by the CPU, but in the case of integers or strings their aren't really equivalent values. I'm sure the hardware can just as easily signal zeros. It can't.
Re: AST Macros?
On 01/06/12 21:37, Jacob Carlborg wrote: On 2012-06-01 17:47, Gor Gyolchanyan wrote: Where can I read more about Bartosz's race-free type system and if there are some specific ideas already, AST macros for D as well? AST macros have been mentioned in the newsgroups several times. There was a talk at the first D conference mentioning AST macros. This was before D2. http://d.puremagic.com/conference2007/speakers.html It's the talk by Walter Bright and Andrei Alexandrescu. It's probably in the second part. AST macros were discussed informally on the day after the conference, and it quickly became clear that the proposed ones were nowhere near powerful enough. Since that time nobody has come up with another proposal, as far as I know.
Re: [Proposal] Additional operator overloadings for multidimentional indexing and slicing
On 03/06/12 19:31, tn wrote: On Friday, 1 June 2012 at 01:57:36 UTC, kenji hara wrote: I'd like to propose a new language feature to D community. ... This patch is an additional enhancement of opDollar (issue 3474 and #442). Sounds awesome. However, the name opDollar should be changed to something like opSize, opLength, opEnd or almost anything else than the current name. opDollar is a pretty awful name but nobody could come up with something that is less awful. At least it is not confusing. Everybody instantly knows what it does. For built-in arrays $ is the length and the size, but that isn't generally true. Wish we had a better name, but opLength isn't it, and nor is opSize. opEnd might be the best of those three, but it kinda sounds like something to do with ranges.
Re: runtime hook for Crash on Error
On 01/06/12 12:26, Walter Bright wrote: On 6/1/2012 1:48 AM, Dmitry Olshansky wrote: On 01.06.2012 5:16, Walter Bright wrote: On 5/31/2012 3:22 AM, Dmitry Olshansky wrote: On 31.05.2012 13:06, deadalnix wrote: This is called failing gracefully. And this highly recommended, and you KNOW that the system will fail at some point. Exactly. + The point I tried to argue but it was apparently lost: doing stack unwinding and cleanup on most Errors (some Errors like stack overflow might not recoverable) is the best thing to do. This is all based on the assumption that the program is still in a valid state after an assert fail, and so any code executed after that and the data it relies on is in a workable state. This is a completely wrong assumption. To be frank a completely wrong assumption is flat-out exaggeration. The only problem that can make it completely wrong is memory corruption. Others just depend on specifics of system, e.g. wrong arithmetic in medical software == critical, arithmetic bug in refracted light color component in say 3-D game is no problem, just log it and recover. Or better - save game and then crash gracefully. Except that you do not know why the arithmetic turned out wrong - it could be the result of memory corruption. This argument seems to be: 1. There exist cases where you cannot know why the assert failed. 2. Therefore you never know why an assert failed. 3. Therefore it is not safe to unwind the stack from a nothrow function. Spot the fallacies. The fallacy in moving from 2 to 3 is more serious than the one from 1 to 2: this argument is not in any way dependent on the assert occuring in a nothrow function. Rather, it's an argument for not having AssertError at all.
Re: Exception/Error division in D
On 01/06/12 22:35, Walter Bright wrote: On 6/1/2012 11:14 AM, deadalnix wrote: We are talking about runing scope statement and finally when unwiding the stack, not trying to continue the execution of the program. Which will be running arbitrary code not anticipated by the assert failure, and code that is highly unlikely to be desirable for shutdown. Sorry, Walter, that's complete bollocks. try { assert(x == 2); } catch(AssertException e) { foo(); } is exactly equivalent to: version (release) {} else { if (x!=2) foo(); } Bad practice, sure. But it's not running arbitrary, unanticipated code.
Re: [Proposal] Additional operator overloadings for multidimentional indexing and slicing
On 04/06/12 15:38, bearophile wrote: David Nadlinger: Actually, I'd say its the other way round – opDollar rather corresponds to opDoubleEqualSign, as it simply describes the character used. I agree. It's the opposite of the semantic names of the original operator overloading set. You mean like the old opStar() (which meant deref), or like opBinary(+) ? g
Re: Pointer semantics in CTFE
On 30/05/12 17:33, Michel Fortin wrote: On 2012-05-30 14:44:37 +, Steven Schveighoffer schvei...@yahoo.com said: On Tue, 29 May 2012 13:35:12 -0400, Michel Fortin michel.for...@michelf.com wrote: Personally, I think it'd be much cleaner to go with some kind of magic function than trying to match the condition against a predefined pattern. Something like da.isSliceOf(a), which could do the usual pointer thing at runtime and call some sort of CTFE intrinsic at compile-time. That doesn't help when most code does not use this today. I.e. one of the main benefits of ctfe is that you don't *have* to write special code. But at the other end, there should be an easy to understand separation between what is supported by CTFE and what is not. Once you try to add special cases for some code patterns by adding heuristics, those heuristics now define the line and would have to become part of the language specification. More generally, the drawback of this kind of pattern recognition is that there's an infinite pool of equivalent patterns to recognize, and seemingly innocuous changes to a CTFEable function could break its CTFEablility if they happen to cross the invisible boundary. I'm just trying to point out the drawbacks of too clever heuristics. If such an heuristic is used, I think it should be limited in scope and well documented. Unfortunately, that means you'll still have to care about writing code in a way that fits the documented pattern. It'd be much easier to reason about CTFEability if the pattern had to be encapsulated in its own function. The heuristic is: one pointer comparison in each direction, connected by or ||. No restriction on the pointer expressions, except that they must have no side-effects. That covers most legitimate cases. The ones it doesn't cover are: - doing two interleaved isInside() comparisons: p1 = q1 s1 = r1 p2 q2 s2 r2 which needs to be rewritten as: (p1 = q1 p2 q2) (s1 = r1 s2 r2) - saving two one-side compares, and then not using them for _anything_ except an or || --- this is a fundamental limitation - calling two functions which each return a one-side-compare: bool cmp(void *a, void *b) { return ab); cmp(p1, q1) cmp(q2, p2) this one could actually be done, because it would only be legal to call such a function from an or ||. Implementation would be complicated though.
Re: [OT] Windows users: Are you happy with git?
On 30/05/12 21:49, Alex Rønne Petersen wrote: On 30-05-2012 21:46, Kagamin wrote: On Friday, 18 May 2012 at 07:58:26 UTC, Lars T. Kyllingstad wrote: were some concerns about using Git on Windows. People claimed that Git was a very Linux-centric tool, and that Windows support was buggy at best. Of course, git is a Linux-centric tool (Linus wrote it to be inherently unportable), hacked into windows environment and augmented with msys. You make it sound as if he was trying to hinder portability. He merely didn't care. Not the same thing. He expressed some very strong views to it. Aggression not ambivalence. I still can't avoid the feeling that if you're on Windows, you're a second-class citizen in the git world. BTW I found what the problem with my installation was: if you manage you to have two different git versions installed (I had git installed via cygwin, and later installed stand-alone MSYS git) then running one on a repository created by the other will corrupt various files in the repository, most notably the index file. It seems that git has no version numbers in its files. Instead, it silently corrupts them.
Re: Purity in D – new article
On 29/05/12 19:35, David Nadlinger wrote: On Tuesday, 29 May 2012 at 12:08:08 UTC, Don Clugston wrote: And to set the record straight -- the relaxed purity ideas were not my idea. I forget who first said them, but it wasn't me. I just championed them. Unfortunately, I don't quite remember either – was it Bruno Medeiros? In any case, if somebody can help my memory here, I'd be glad to give credit to the one who came up with the original proposal in the article as well. David The successful proposal, using weakly pure/strongly pure (Sep 21 2010): http://www.digitalmars.com/d/archives/digitalmars/D/Proposal_Relax_rules_for_pure_117735.html Its basically the same as this one by Bruno (Apr 29 2008), which uses partially pure and mentions an earlier post by me: http://www.digitalmars.com/d/archives/digitalmars/D/Idea_partially_pure_functions_70762.html#N70762 And the earliest reference I could find is by me (Apr 5 2008) where I called it an amoral function. http://www.digitalmars.com/d/archives/digitalmars/D/Grafting_Functional_Support_on_Top_of_an_Imperative_Language_69253.html The first compiler release with pure function attributes (though not implemented) was released in Apr 22, 2008 and the first with pure as a keyword was Jan 20 2008. So surely this is close to the original. So now I'm confused, maybe it *was* me after all! Then formalized by Bruno, and later championed by me?
Re: Pointer semantics in CTFE
On 29/05/12 16:20, Michel Fortin wrote: On 2012-05-29 13:29:35 +, Don Clugston d...@nospam.com said: On 27/05/12 02:45, Walter Bright wrote: You could implement it as simply comparing the addresses - you'd be no worse off than C is, and you would get the correct answer for pointers both in and out of the array without needing special cases. I think that's a no-go. Implementation-specific behaviour at runtime is bad enough, but at compile time, it's truly horrible. Consider that any change to unrelated code can change the results. Something that makes it really terrible is that the same function can be called in CTFE once before inlining, and once after. Good luck tracking that down. And at runtime, you have a debugger. Wouldn't it be possible to just catch the case where you compare two pointers not assigned from the same memory block and issue an error? Here's an idea: make each CTFE pointer some kind of struct with a pointer to the memory block and an offset. When comparing, if the memory block isn't the same, it's an error. If you add or subtract to a pointer, it'll still belong to the same memory block but with a different offset, thus it remains comparable. When dereferencing, you can make sure the pointer still points inside the block, assuming the block knows its length. Thats _exactly_ what it does right now.
Re: CTFE slower than expected
On 29/05/12 23:23, Philippe Sigaud wrote: On Tue, May 29, 2012 at 2:52 PM, Don Clugstond...@nospam.com wrote: Is there any way to improve it? Oh yeah. Orders of magnitude, easily. ! The slowness is not in any way inherent to CTFE. The experience will be completely different, once I have some time to work on it -- I know exactly how to do it. Did 2.058 or 2.059 see any new code for CTFE? Like the OP, I've the impression CTFE/mixins suddenly became far slower. I'm not complaining, I understand it's a difficult part of DMD, but I wondered if what I see is real or imaginary. The behaviour of __traits(allMembers) changed (it now returns an array of string literals) and I expect that to be a little bit slower. Compiling Phobos is now *much* slower than it used to be, due to changes in Phobos. (eg, import std.random; is unbelievably slow). As for CTFE, certain cases became faster (eg, repeated use of global array literals). But if you can pinpoint a case where CTFE itself became slower, I'd like to know.
Re: Exception/Error division in D
On 30/05/12 10:40, Jonathan M Davis wrote: On Wednesday, May 30, 2012 10:26:36 deadalnix wrote: The fact that error don't trigger scope and everything is nonsensial. If an Error is truly unrecoverable (as they're generally supposed to be), then what does it matter? Something fatal occured in your program, so it terminates. Because it's an Error, you can get a stack trace and report something before the program actually terminates, but continuing execution after an Error is considered to be truly _bad_ idea, so in general, why does it matter whether scope statements, finally blocks, or destructors get executed? It's only rarer cases where you're trying to do something like create a unit test framework on top of assert that you would need to catch an Error, and that's questionable enough as it is. In normal program execution, an error is fatal, so cleanup is irrelevant and even potentially dangerous, because your program is already in an invalid state. That's true for things like segfaults, but in the case of an AssertError, there's no reason to believe that cleanup would cause any damage. In fact, generally, the point of an AssertError is to prevent the program from entering an invalid state. And it's very valuable to log it properly.
Re: Pointer semantics in CTFE
On 30/05/12 01:47, Mehrdad wrote: Just a general note: going the make a special case for two comparisons route won't work if, for example, someone decides to use a lambda for comparing pointers. You mean effectively like: bool cmp(void *x, void *y) { return x y: } assert ( cmp(x, y) cmp(x, z) ); ? Yes, this is why it's a special case. I can imagine how that could be implemented in the current CTFE, I cannot see how it could be done reasonably with a JIT CTFE implementation. You'd have to have a special lamba for pointer inside a range rather than simple pointer comparisons. I'm suggesting that is pointer inside a range is a different primitive operation from comparison of two pointers to the same memory block. Even though C code typically uses the latter to implement the former, it's relying on undefined behaviour.
Re: Exception/Error division in D
On 30/05/12 12:59, Jonathan M Davis wrote: On Wednesday, May 30, 2012 11:32:00 Don Clugston wrote: On 30/05/12 10:40, Jonathan M Davis wrote: On Wednesday, May 30, 2012 10:26:36 deadalnix wrote: The fact that error don't trigger scope and everything is nonsensial. If an Error is truly unrecoverable (as they're generally supposed to be), then what does it matter? Something fatal occured in your program, so it terminates. Because it's an Error, you can get a stack trace and report something before the program actually terminates, but continuing execution after an Error is considered to be truly _bad_ idea, so in general, why does it matter whether scope statements, finally blocks, or destructors get executed? It's only rarer cases where you're trying to do something like create a unit test framework on top of assert that you would need to catch an Error, and that's questionable enough as it is. In normal program execution, an error is fatal, so cleanup is irrelevant and even potentially dangerous, because your program is already in an invalid state. That's true for things like segfaults, but in the case of an AssertError, there's no reason to believe that cleanup would cause any damage. In fact, generally, the point of an AssertError is to prevent the program from entering an invalid state. An assertion failure really isn't all that different from a segfault. By definition, if an assertion fails, the program is an invalid state, because the whole point of the assertion is to guarantee something about the program's state. There's a big difference. A segfault is a machine error. The integrity of the machine model has been violated, and the machine is in an out-of-control state. In particular, the stack may be corrupted, so stack unwinding may not be successful. But, in an assert error, the machine is completely intact; the error is at a higher level, which does not interfere with stack unwinding. Damage is possible only if you've written your destructors/finally code extremely poorly. Note that, unlike C++, it's OK to throw a new Error or Exception from inside a destructor. But with (say) a stack overflow, you don't necessarily know what code is being executed. It could do anything. Now, if a segfault occurs (particularly if it's caused by something other than a null pointer), the program is likely to be in a _worse_ state, but it's in an invalid state in either case. In neither case does it make any sense to try and recover, and in both cases, there's a definite risk in executing any further code - including cleanup code. Yes, the segfault is probably worse but not necessarily all that much worse. A logic error can be just as insidious to the state of a program as memory corruption, depending on what it is. I'm surprised by your response, I didn't think this was controversial. We could just as easily have said assert() throws an AssertException. (Or have two kinds of assert, one which is an Error and the other merely an Exception).
Re: Purity in D – new article
On 27/05/12 22:56, David Nadlinger wrote: Some of you might remember that I have been meaning to write a comprehensive introduction to design and use of purity for quite some while now – I finally got around to do so: http://klickverbot.at/blog/2012/05/purity-in-d/ Feedback and criticism of all kinds very welcome! David For the part about floating-point calculations: As this would be an impractical restriction, in D pure functions are allowed to read and write floating point flags + (ie, the floating point state is regarded as a variable implicitly passed to every pure function). And to set the record straight -- the relaxed purity ideas were not my idea. I forget who first said them, but it wasn't me. I just championed them.
Re: Add CTFE execute function
On 28/05/12 03:40, Chang Long wrote: On Saturday, 26 May 2012 at 15:56:38 UTC, Chang Long wrote: CTFE execute will be very useful on web develop, for example It is very hard to create a CTFE version template engine with rich feature. But we can use execute call to transe template file to d code string, then mixed it to application. The vibed project is very cool and I want to add my Jade template to this, but I can't find other way to do it. You can do a lot with import(filename); Maybe we also need a compiler option to enable this CTFE io operate because security. Let me make myself more clear, what I suggestion is something like this: mixin( std.process.execute(/usr/bin/template_engine template_file_path.htm) );
Re: CTFE slower than expected
On 29/05/12 12:25, Manu wrote: I've been trying to work out why my compile times have gone to hell recently. I have a lib, it takes 3.5 seconds to compile. I add one CTFE heavy module, it's not huge, certainly much smaller than the rest of the app, and it blows out to 18 seconds. I've done some experiments removing bits and pieces of code, I can isolate the bits that add seconds to the compile time, but the big offenders are one-line mixins which use CTFE fairly aggressively to generate the strings they mix in. Can anyone comment on CTFE as implemented? Why is it so slow? You really don't want to know. What it's actually doing is horrific. Bug 6498. The reason why it's still like that is that CTFE bugs have kept cropping up (mostly related to pointers and especially AAs), which have prevented me from doing anything on the performance issue. It's certainly not executing a lot of code. I can imagine executing the same routine in an interpreted language like lua would take milliseconds or less, not multiple seconds. What are the bottlenecks? It's was originally based on the const-folding code used by the optimizer. So most of the code was written with totally goals (that didn't include performance). Is there any way to improve it? Oh yeah. Orders of magnitude, easily. The slowness is not in any way inherent to CTFE. The experience will be completely different, once I have some time to work on it -- I know exactly how to do it.
Re: Pointer semantics in CTFE
On 27/05/12 02:45, Walter Bright wrote: On 5/26/2012 3:59 AM, Don wrote: Yes, that's what happens now. But that doesn't help the programmer. If it is inside, no problem, the expression is true. But if it is not inside, the expression is not false -- it's a compile-time error. Ok, I understand now what you meant. So you can't use it as a test for if it is inside the same object. I was confused about how memmove can work in C without relying on undefined behaviour. But I just read http://www.cplusplus.com/reference/clibrary/cstring/memcpy/ which defines it in terms of an intermediate buffer. So maybe, the current CTFE implementation is _exactly_ consistent with the C spec. If that's true, though, I find it pretty incredible that there is no way to find out if a pointers points a particular array, even if you have pointers to both the start and end of that array. (OK, I guess you can iterate from start to end, checking for equality, but .. bleah .. it's a terrible abstraction inversion). You could implement it as simply comparing the addresses - you'd be no worse off than C is, and you would get the correct answer for pointers both in and out of the array without needing special cases. I think that's a no-go. Implementation-specific behaviour at runtime is bad enough, but at compile time, it's truly horrible. Consider that any change to unrelated code can change the results. Something that makes it really terrible is that the same function can be called in CTFE once before inlining, and once after. Good luck tracking that down. And at runtime, you have a debugger. It's not hard to make it work in all cases of: one-sided-comparison one-sided-comparison one-sided-comparison || one-sided-comparison one-sided-comparision: ptr_expression RELOP ptr_expression ! one-sided-comparision RELOP: = = where ptr_expression is any expression of type pointer. And by all cases, I really mean all (the code for the four pointer expressions need not having anything in common). It's only when you allow other expressions to be present, that things get hairy.
Pointer semantics in CTFE
The current implementation of CTFE strictly enforces C pointer semantics. One of the restrictions is that you cannot perform ordering comparisons between unrelated pointers. This is important for repeatability: if it was permitted, the results would be arbitrary and might vary unpredictably with subtle changes in the code, or change between compiler releases. But, there's an interesting case from bug 7898: the 'inside' operation. If p and q are pointers to the same array, then (r = p r = q) is true if r points inside that array, and false if it does not. This seems to be a perfectly reasonable operation: it is completely repeatable and safe, regardless of what r points to. But there doesn't seem to be any way to rewrite it to avoid the disallowed comparisons. I could write code to allow this special case in CTFE. There's a bit of work to make sure that all the valid cases are detected, because there are quite a lot of ways to rewrite it, but it's not too terrible. But I dunno, I don't like this sort of thing much. Feels a bit clunky. OTOH it seems like necessary functionality, and I can't see any other way of doing it. Opinions?
Re: Visual D 0.3.32 maintenance release
On 13/05/12 21:28, Walter Bright wrote: On 5/13/2012 5:31 AM, Rainer Schuetze wrote: With the workflow of bugzilla/svn it was just copy and pasting the diff into the bug report. I understand it is easier on Walter's side, though. Yes, it is definitely easier on my side. But consider that the number of contributions to dmd has increased by at least a factor of 10 since we moved to github means that, in general, contributors find it easier, too. As I've said before -- that is true for DMD but not for Phobos. Rate of contributions to Phobos is basically the same as when it was in svn. Would be good to know why.
Re: forcing weak purity
On 24/05/12 02:26, Alex Rønne Petersen wrote: On 23-05-2012 19:16, deadalnix wrote: Le 23/05/2012 17:29, Don Clugston a écrit : There's a huge difference between a global collection *may* be performed from a pure function vs it *must* be possible to force a global collection from a pure function. Thank you ! I personally disagree that this should be a rationale to not allow the latter. D is a systems language and we really should stop trying to pretend that it isn't. There's a reason we have a core.memory module that lets us control the GC. This is all about not exposing quirks of the current implementation. The way it currently is, would get you to perform a gc before you enter the first pure function. After that, the only possible garbage to collect would have been generated from inside the pure function. And that should be very cheap to collect.
Re: pure functions calling impure functions at compile-time
On 23/05/12 11:41, bearophile wrote: Simen Kjaeraas: Should this be filed as a bug, or is the plan that only pure functions be ctfe-able? (or has someone already filed it, perhaps) It's already in Bugzilla, see issue 7994 and 6169. It's just happening because the purity checking is currently being done in a very unsophisticated way. But I think there is a semantic hole in some of the discussions about this problem. Is a future compile-time JIT allowed to perform purity-derived optimizations in CTFE? Some, definitely. Eg. foo(n) + foo(n) can be changed to 2*foo(n), where n is an integer, regardless of what foo does. It does need to be a bit conservative, but I think the issues aren't CTFE specific. Eg, something like this currently gives an assert at runtime: pure nothrow void check(int n) pure nothrow { assert(n == 4); } void main() { check(3); } even though check() can do nothing other than cause an error, it still cannot be optimized away. But you can get rid of all subsequent calls to it, because they'll produce the same error every time.
Re: forcing weak purity
On 23/05/12 07:05, Mehrdad wrote: We should make 'pure' mean strongly pure. For weakly pure, we could introduce the 'doped' keyword :-D No, the keyword should be more like @noglobal I wish people would stop using this weak purity / strong purity terminology, it's very unhelpful. (And it's my fault. I've created a monster!) There is absolutely no need for a keyword to mark (strong) purity, and weak purity isn't actually pure. The real question being asked is, do we need something for logical purity? Note that we need the same thing for caching. Or are the cases like this rare enough that we can just fake it with a cast?
Re: forcing weak purity
On 23/05/12 05:22, Steven Schveighoffer wrote: I have come across a dilemma. Alex Rønne Petersen has a pull request changing some things in the GC to pure. I think gc_collect() should be weak-pure, because it could technically run on any memory allocation (which is already allowed in pure functions), and it runs in a context that doesn't really affect execution of the pure function. So I think it should be able to be run inside a strong pure function. I am almost certain it should not. And I think this is quite important. A strongly pure function should be considered to have its own gc, and should not be able to collect any memory it did not allocate itself. Memory allocation from a pure function might trigger a gc cycle, but it would ONLY look at the memory allocated inside that pure function.
Re: forcing weak purity
On 23/05/12 15:56, Alex Rønne Petersen wrote: On 23-05-2012 15:17, Don Clugston wrote: On 23/05/12 05:22, Steven Schveighoffer wrote: I have come across a dilemma. Alex Rønne Petersen has a pull request changing some things in the GC to pure. I think gc_collect() should be weak-pure, because it could technically run on any memory allocation (which is already allowed in pure functions), and it runs in a context that doesn't really affect execution of the pure function. So I think it should be able to be run inside a strong pure function. I am almost certain it should not. And I think this is quite important. A strongly pure function should be considered to have its own gc, and should not be able to collect any memory it did not allocate itself. Memory allocation from a pure function might trigger a gc cycle, but it would ONLY look at the memory allocated inside that pure function. Implementing this on a per-function basis is not very realistic. Some programs have hundreds (if not thousands) of pure functions. No, it's not realistic for every function. But it's extremely easy for others. In particular, if you have a pure function which has no reference parameters, you just need a pointer to the last point a strongly pure function was entered. This partitions the heap into two parts. Each can be gc'd independently. And, in the non-pure part, nothing is happening. Once you've done a GC there, you NEVER need to do it again. Not to mention, we'd need some mechanism akin to critical regions to figure out when a thread is in a pure function during stop-the-world. Further, data allocated in a pure function f() in thread A must not be touched by a collection triggered by an allocation inside f() in thread B. It'd be a huge mess. Not so. It's impossible for anything outside of a strongly pure function to hold a pointer to memory allocated by the pure function. In my view, this is the single most interesting feature of purity. And, frankly, if my program dies from an OOME due to pure functions being unable to do full collection cycles, I'd just stop using pure permanently. It's not a very realistic approach to automatic memory management; at that point, manual memory management would work better. Of course. But I don't see how that's relevant. How the pure function actually obtains its memory is an implementation detail. There's a huge difference between a global collection *may* be performed from a pure function vs it *must* be possible to force a global collection from a pure function. The difficulty in expressing the latter is a simple consequence of the fact that it is intrinsically impure.
Re: Limit number of compiler error messages
On 20/05/12 00:38, cal wrote: Is there a way to limit the dmd compiler to outputting just the first few errors it comes across? No, but the intention of DMD is to generate only one error per bug in your code. If you are seeing a large number of useless errors, please report it in bugzilla. http://d.puremagic.com/issues/show_bug.cgi?id=8082 is a good example.
Re: Bug report severity
On 11/05/12 00:28, Mehrdad wrote: On Thursday, 10 May 2012 at 22:23:15 UTC, Stewart Gordon wrote: On 10/05/2012 23:12, Mehrdad wrote: How do you decide if something is 'critical', 'major', 'blocker', or just 'normal'? Is there a rule of thumb I could use? http://d.puremagic.com/issues/page.cgi?id=fields.html#bug_severity Stewart. Hmmm... thanks for the link. I'm having trouble understanding how to apply them, though. For example, why are these bugs critical? http://d.puremagic.com/issues/show_bug.cgi?id=5314 Because an error message with no clue of where it happened, is pretty much the same as a segfault. It's far more important than any other 'diagnostic' bug. http://d.puremagic.com/issues/show_bug.cgi?id=3445 Because this affects the documentation for all of Phobos. It has a huge impact. It's far more important than any other 'ddoc' bug. Are things like wrong error message or wrong documentation considered to be on par with ICEs? No, only error messages without line number. Like, I see an ICE like http://d.puremagic.com/issues/show_bug.cgi?id=6774 and I wonder why it's not blocker or at least critical... They have the 'ice' keyword which performs the same job. The severities are most useful for distinguishing when a bug has a very different importance to others in the same category.
Re: Lack of open source shown as negative part of D on Dr. Dobbs
On 10/05/12 11:02, Joseph Rushton Wakeling wrote: Assuming that LLVM is not an acceptable backend despite its permissive licence, and that the community can't buy out the code, I'd suggest again the idea of stabilizing the frontend and then synchronizing DMD, GDC and LDC updates, with all 3 endorsed as equally valid implementations of the reference standard. Yes. This is what we need to work towards.
Re: Does D have too many features?
On 09/05/12 10:16, Alex Rønne Petersen wrote: On 08-05-2012 23:48, Sean Kelly wrote: On May 8, 2012, at 2:31 PM, Jonathan M Davis wrote: We've previously discussed having _all_ of the C system call functions from the various OSes that we support being in druntime, and I very much think that that's the right way to go. Phobos and druntime then have whatever they need as for as standard C and system call functions go, and anyone who needs any which aren't wrapped by Phobos in some manner has them available to them. Anyone that doesn't want to use any of those C function directly, doesn't have to, but I don't see any reason to hide them just because someone doesn't want to use them in their code. If the problem is that certain C functions end up getting used a lot when they should have D wrappers of some kind which better encapsulate their functionality, then maybe we add the appropriate wrappers to Phobos. But that's a completely different issue. Hiding the C functions doesn't help us any. I personally use import core.stdc as an indicator that there may be some feature missing from Phobos. It's easily greppable, and easy to avoid using the routines. In fact, I think import core anything should be an exceptional case in a typical D application. Everything exposed in Druntime is for what I'd consider power users. Unsafe threads, runtime and GC hooks, platform API calls, etc. It's all there because the higher-level stuff needs it, but is really not intended for general use. I just hope none of it goes away. I make extensive use of many core.* modules. It makes sense to make truly internal stuff internal, but the standard C function declarations and OS system functions are _not_ internal to druntime. They're _very_ much external. druntime is just providing them because they're functionality which is core to the system that any D program is running on. Once upon a time, there was a D runtime library (unrelated to Druntime) that has no C library dependence at all. It was an interesting idea, but I don't know that there's any system that D targets which doesn't support C. *Is* there any system that doesn't support C? ;) There are plenty of systems that don't support C99 perfectly.
Re: is operator for structures?
On 09/05/12 16:13, bearophile wrote: Gor Gyolchanyan: Because the opBinary [...] Thank for your answer, but I don't carte of why the D compiler accepts that. I only care about the D compiler statically refusing that. Bye, bearophile I think you're asking for opBinary to be a keyword. If it were statically rejected, surely you'll also want to have: void opBinary(string xx, int x) {} rejected as well. Along with a multitude of other things.
Re: Why not all statement are expressions ?
On 07/05/12 19:06, deadalnix wrote: Hi, Working on D I noticed that some statement, notably assert, are expression of type void. Why not all statement (that are not expression already) are expression ? assert isn't a statement. It's an expression ( same as is() ). What makes you think it's a statement? The main use for a void expression is so that it can be used in a comma expression; this is why assert is an expression. The curious thing, which may be the source of the confusion, is that static assert() is a statement, while assert() is an expression. Maybe static assert should also be an expression rather than a statement?
Re: Does D have too many features?
On 08/05/12 09:56, Andrej Mitrovic wrote: On 4/30/12, Andrej Mitrovicandrej.mitrov...@gmail.com wrote: Personally my gripe with compilation times is that I get very used to having fast build times where I can go through an edit+compile+run cycle really fast, but after a while build times get slower Also since 2.059 error reporting is *completely* broken. I have to wait 5 seconds just to get this error message itself to print to the screen: http://pastebin.com/y93GEPAf 500 lines of errors even though only the first line is an actual error. What in the actual fuck are all those other error messages? The only problem was this line in a main file: CppGen gen; and CppGen was undefined because I've missed an import. And if I remove the only import left (std.range), I get much less garbage but I still get unrelated errors: main.d(80): Error: undefined identifier CppGen D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template std.conv.toImpl does not match any function template declaration D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template std.conv.toImpl cannot deduce template function from argument types !(string)(long) D:\DMD\dmd2\windows\bin\..\..\src\phobos\std\conv.d(244): Error: template instance toImpl!(string) errors instantiating template loader\gcc.d(167): Error: template instance std.conv.to!(string).to!(long) error instantiating 2.058 error reporting worked fine, I don't know what someone did to screw this up so massively. That bug was fixed in git not long after release. Unfortunately it seems that there are not enough people doing beta testing. As for why it happened -- previously the compiler used a hack to prevent the flood of error messages (and the hack didn't work properly in the case where errors were gagged, like in is(typeof()) ). Now it does it properly.
Re: Integer overflow and underflow semantics
On 05/05/12 06:57, Alex Rønne Petersen wrote: Hi, I don't think the language really makes it clear whether overflows and underflows are well-defined. Do we guarantee that for any integral type T, T.max + 1 == T.min and T.min - 1 == T.max? This is relevant in particular for GDC and LDC since they target a lot of weird architectures. I think the reason that C makes no guarantees, was because of ones-complement machines (which had become very rare even by 1970). Surely we can assume 2-s complement behaviour?
Re: Oddness with C binding
On 03/05/12 06:28, James Miller wrote: I'm writing bindings to XCB right now, and its mostly going smoothly. However I have encountered a very strange problem. This bit of code segfaults with DMD: auto connection = xcb_connect(null, null); auto setup = xcb_get_setup(connection); auto iter = xcb_setup_roots_iterator(setup); auto screen = iter.data; But it doesn't segfault with LDC2. This is odd to me because as far as I am aware LDC2 uses the same front end at DMD. This must mean that there is a bug in the dmd backend. I thought it could be related to const optimizations, but I removed all the const declarations from the appropriate C bindings and the same thing happened. I don't have the time to create a minimal test case for this, so I can't really file a bug report on it. I was also wondering what could cause this problem. I am using dmd 2.059 and the latest ldc from the arch repositories. -- James Miller The infamous bug 5570?
Re: How can D become adopted at my company?
On 30/04/12 01:03, Manu wrote: On 30 April 2012 01:24, Tove t...@fransson.se mailto:t...@fransson.se wrote: On Sunday, 29 April 2012 at 22:13:22 UTC, Manu wrote: Is it technically possible to have a precise GC clean up all unreferenced memory in one big pass? yes, but unless it's also moving/compacting... one would suffer memory fragmentation... so I would imagine TempAlloc is a better fit? In some cases I'm comfortable with that type of fragmentation (large regularly sized resources), although that leads me to a gaping hole in D's allocation system... OT, but still very important There is no way to request aligned memory. I can't even specify an alignment on a user type and expect it to be aligned if I create one on the stack, let alone the heap _ It seems I can request alignment for items within a struct, but I can't align the struct its self. In addition, a struct doesn't inherit the alignment of its aligned members, so the struct is allocated unaligned, and the aligned member fails its promise anyway. Bug 2278.
Re: Does D have too many features?
On 01/05/12 00:33, Timon Gehr wrote: On 04/30/2012 11:28 PM, bearophile wrote: Walter: The first thing to emphasize is that NONE of this will happen for D2. The emphasis on D2 is fixing implementation and toolchain issues. Breaking existing code is off the table unless we are pretty much forced to in order to fix some other more important issue. But you need to keep into account that D2 is still a not widely used language. So deprecating some things now will cause far less troubles than doing it in D3 some years from now. D2 - D3 will be full of breaking changes anyway. Otherwise there is no reason to add another major language version. What is this D3 thing As far as I can tell, 'D3' was invented by newcomers to the forums.
Re: Does D have too many features?
On 28/04/12 20:47, Walter Bright wrote: Andrei and I had a fun discussion last night about this question. The idea was which features in D are redundant and/or do not add significant value? A couple already agreed upon ones are typedef and the cfloat, cdouble and creal types. What's your list? Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse = About the NCEG operators -- the reason they're redundant is that you practically always want to treat NaN separately. I've tried _very_ hard to come up with uses for them, but without success. The thing I've used the most is: x != x which is a kind of built-in isNaN(x), but that can also be rewritten as: x != x Initially I though you'd do things like real func(real x) { // x must be non-NaN and in the range -x.infinity .. N if (x ! N) return real.nan; but even that isn't convincing, because if x is NaN you should be returning x, so that you preserve NaN payloads. I think I have used these guys more than anyone else, but I still haven't found a single use case that stands up to scrutiny.
Re: Does D have too many features?
On 03/05/12 16:13, Andrei Alexandrescu wrote: On 5/3/12 9:55 AM, Don Clugston wrote: On 28/04/12 20:47, Walter Bright wrote: Andrei and I had a fun discussion last night about this question. The idea was which features in D are redundant and/or do not add significant value? A couple already agreed upon ones are typedef and the cfloat, cdouble and creal types. What's your list? Other ones which were agreed to a long time ago were: * NCEG operators * built-in .sort and .reverse Good ones. In fact I even discounted them from this discussion because I'd already considered them gone. Walter agreed that I don't mention them in TDPL, with the intent to have them peter out. One good step right now would be to remove NCEG operators from the online documentation. Later on, we'll consider them an accept-invalid bug :o). Well, they are also used in druntime, in core.stdc.math BTW I *hate* that module, I don't know why it exists. Even worse, it seems to be growing -- people are adding more things to it. Practically everything in there has a better implementation in std.math.
Re: Does D have too many features?
On 29/04/12 20:08, Manu wrote: On 29 April 2012 18:50, Don nos...@nospam.com mailto:nos...@nospam.com wrote: On 28.04.2012 20:47, Walter Bright wrote: Andrei and I had a fun discussion last night about this question. The idea was which features in D are redundant and/or do not add significant value? A couple already agreed upon ones are typedef and the cfloat, cdouble and creal types. What's your list? * The operator, which does nothing except introduce bugs (It does NOT perform an unsigned shift). What does it do? I use this all over the place, I assumed it worked... maybe I have bugs? It works only for two types: int and long. For everything else, it is identical to So for short and byte, and in generic code, it's ALWAYS a bug.
Re: Does D have too many features?
On 30/04/12 05:45, H. S. Teoh wrote: On Sun, Apr 29, 2012 at 04:40:37PM +0200, Jacob Carlborg wrote: [...] * Do-while loops, how useful are those actually? I grepped through the DMD source once, looking for how often Walter uses do..while. The answer: exactly zero. OK, that got me all riled up about looping constructs, and now I'm provoked to rant: Since the advent of structured programming, looping constructs have always been somewhat b0rken. Yes they worked very well, they are clean, powerful, gets rid of almost all cases of needing goto's, etc.. But the point of a loop is that *the entry point does not always correspond with the exit point (where the loop condition is tested)*. The problem with both do-loops and while-loops is that they are just straitjacketed versions of a more general looping construct. Completely agree. Forth is one of the few languages which got it right. BEGIN cond WHILE ... REPEAT
Re: Does D have too many features?
On 30/04/12 12:27, Manu wrote: On 30 April 2012 10:32, Don Clugston d...@nospam.com mailto:d...@nospam.com wrote: On 29/04/12 20:08, Manu wrote: On 29 April 2012 18:50, Don nos...@nospam.com mailto:nos...@nospam.com mailto:nos...@nospam.com mailto:nos...@nospam.com wrote: On 28.04.2012 20:47, Walter Bright wrote: Andrei and I had a fun discussion last night about this question. The idea was which features in D are redundant and/or do not add significant value? A couple already agreed upon ones are typedef and the cfloat, cdouble and creal types. What's your list? * The operator, which does nothing except introduce bugs (It does NOT perform an unsigned shift). What does it do? I use this all over the place, I assumed it worked... maybe I have bugs? It works only for two types: int and long. For everything else, it is identical to So for short and byte, and in generic code, it's ALWAYS a bug. O_O Is that intentional? Or is it... a bug? I smiled when I saw in the language, I appreciate its presence. It's not necessary, but it cuts down on some ugly explicit casting (which theoretically makes generic code simpler). It's not a bug, it's a design flaw. The buggy behaviour is explicitly tested in the test suite. The problem is that the C promotion rules also apply, just as for and . But they are fundamentally incompatible with unsigned shift. So short and byte get promoted to int *by sign extension*, then the int gets an unsigned shift. Which means that the short or byte gets a signed shift instead of an unsigned one. I used to use in my code, because as you say, it is a nice idea, but after having a few bugs with short, and working out what the semantics actually were, I suddenly realized it was a landmine, and I removed every instance of it from my code. (cast(ulong)x) 3 is safer than x 3, unfortunately.
Re: What to do about default function arguments
On 26/04/12 05:44, Walter Bright wrote: A subtle but nasty problem - are default arguments part of the type, or part of the declaration? See http://d.puremagic.com/issues/show_bug.cgi?id=3866 Currently, they are both, which leads to the nasty behavior in the bug report. The problem centers around name mangling. If two types mangle the same, then they are the same type. But default arguments are not part of the mangled string. Hence the schizophrenic behavior. But if we make default arguments solely a part of the function declaration, then function pointers (and delegates) cannot have default arguments. (And maybe this isn't a bad thing?) I think it is a mistake to allow default arguments in function pointers and delegates (it's OK for delegate literals, there you have the declaration). I don't see how it can possibly work. If it's really a type, then given: void foo(int x = 2) {} void bar(int y = 3) {} then typeof(foo) should be: void function (int __param0 = 2) I don't see how we could justify having those types and not using them. But then, if you have: auto p = foo; // p has default parameter of 2 p = bar; // Should this work? I really don't think we want this. As I vaguely remember someone saying about the bug report, it looks like an attempt to have a pathetic special case of currying syntax sugar built into the language. But it isn't even as efficient as a library solution (if the construction of the default parameter is expensive, it will generate gobs of code every time the function parameter is called).
Re: How can D become adopted at my company?
On 25/04/12 17:38, Joseph Rushton Wakeling wrote: On 25/04/12 16:58, Kagamin wrote: On Tuesday, 24 April 2012 at 14:05:14 UTC, bearophile wrote: Python was widely used before Google support. And I think Haskell has enjoyed corporate support for a lot of time. And who's behind PHP? ... but importantly, Python and PHP (and Ruby, and Haskell, and others) were fully open source in their reference implementations from the get-go, or at least from very early on. This isn't just important in itself, but has a multiplicative impact with inclusion in the Linux distros, BSD's, etc. which make up the server infrastructure of the web. It also enables all sorts of 3rd-party suppliers who feel comfortable including the software in their hosting provision because they can be certain they won't in future suffer from the commercial constraints of a proprietary supplier. D's reference implementation _still_ isn't fully open source -- only the frontend -- and the available open source compilers lag behind the reference. rant open source is a horrible, duplicitous term. Really what you mean is the license is not GPL compatible. /rant Based on my understanding of the legal situation with Symantec, the backend CANNOT become GPL compatible. Stop using the word still, it will NEVER happen.
Re: What to do about default function arguments
On 26/04/12 11:28, Timon Gehr wrote: On 04/26/2012 10:51 AM, Don Clugston wrote: On 26/04/12 05:44, Walter Bright wrote: A subtle but nasty problem - are default arguments part of the type, or part of the declaration? See http://d.puremagic.com/issues/show_bug.cgi?id=3866 Currently, they are both, which leads to the nasty behavior in the bug report. The problem centers around name mangling. If two types mangle the same, then they are the same type. But default arguments are not part of the mangled string. Hence the schizophrenic behavior. But if we make default arguments solely a part of the function declaration, then function pointers (and delegates) cannot have default arguments. (And maybe this isn't a bad thing?) I think it is a mistake to allow default arguments in function pointers and delegates (it's OK for delegate literals, there you have the declaration). The parenthesised part is in conflict with your other statement. No it doesn't. A default argument is a delegate literal is part of the declaration, not part of the type.