www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - DMD 0.137 release

reply "Walter Bright" <newshound digitalmars.com> writes:
A couple of oft-requested features.

http://www.digitalmars.com/d/changelog.html
Oct 24 2005
next sibling parent Sean Kelly <sean f4.ca> writes:
In article <djjpa0$1o9n$2 digitaldaemon.com>, Walter Bright says...
A couple of oft-requested features.
Very nice! Sean
Oct 24 2005
prev sibling next sibling parent reply Vathix <chris dprogramming.com> writes:
On Mon, 24 Oct 2005 19:02:00 -0400, Walter Bright  
<newshound digitalmars.com> wrote:

 A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html
On http://www.digitalmars.com/d/declaration.html#AutoDeclaration that anchor does not seem to exist and I can not find the word inference.
Oct 24 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Vathix" <chris dprogramming.com> wrote in message
news:op.sy6bxz0dl2lsvj esi...
 On http://www.digitalmars.com/d/declaration.html#AutoDeclaration that
 anchor does not seem to exist and I can not find the word inference.
I hadn't posted the updated doc yet. It's there now.
Oct 24 2005
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter Bright wrote:
 "Vathix" <chris dprogramming.com> wrote in message
 news:op.sy6bxz0dl2lsvj esi...
 
On http://www.digitalmars.com/d/declaration.html#AutoDeclaration that
anchor does not seem to exist and I can not find the word inference.
I hadn't posted the updated doc yet. It's there now.
Cool, Implicit Type Inference! However, I think that the problems with overloading the "auto" keyword to declare it are made obvious by the special case you had to define with classes. That's sure to bite people with strange, subtle bugs. Plus, such special cases make templates harder to write. Say you were defining a mixin where it would be useful to have both: template Foo(alias func) { auto foo = func(); // drat, can't use both implicit types and auto } void main() { Foo(myFunc); ...stuff... }
Oct 25 2005
parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Russ Lewis wrote:
 
 Cool, Implicit Type Inference!
 
I agree.
 However, I think that the problems with overloading the "auto" keyword 
 to declare it are made obvious by the special case you had to define 
 with classes.  That's sure to bite people with strange, subtle bugs. 
 Plus, such special cases make templates harder to write.  Say you were 
 defining a mixin where it would be useful to have both:
 
 template Foo(alias func) {
   auto foo = func();  // drat, can't use both implicit types and auto
 }
 
 void main() {
   Foo(myFunc);
   ...stuff...
 }
And i also agree. This way you cannot have auto objects with type inference and it is a problem. Couldn't another keywoard be added for type inference? Many have been suggested (autotype, var, ...).
Oct 25 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Ivan Senji" <ivan.senji_REMOVE_ _THIS__gmail.com> wrote in message
news:djlqvi$2tn$1 digitaldaemon.com...
 And i also agree. This way you cannot have auto objects with type
 inference and it is a problem. Couldn't another keywoard be added for
 type inference? Many have been suggested (autotype, var, ...).
I've tried to stay away from 'var', it reminds me of Pascal too much <g>. Anyhow, I've thought about this problem a lot, and there is an answer for it that is simple and consistent. It's just a bit of work to implement :-(.
Oct 25 2005
next sibling parent reply "Uwe Salomon" <post uwesalomon.de> writes:
 And i also agree. This way you cannot have auto objects with type
 inference and it is a problem. Couldn't another keywoard be added for
 type inference? Many have been suggested (autotype, var, ...).
I've tried to stay away from 'var', it reminds me of Pascal too much <g>. Anyhow, I've thought about this problem a lot, and there is an answer for it that is simple and consistent. It's just a bit of work to implement :-(.
Huh? Could you please explain that briefly? I am currently writing a compiler myself, and i thought a lot about this problem. Declarations and expressions can look very similar at the beginning, and it requires a lot of lookahead for the parser to decide between the two (which is annoying, as the lexer is more difficult then). I fumbled around with "var" and friends, too, but it looks so annoying if you have to write it everywhere. Associative arrays in the current syntax are sometimes simply undistinguishable from static arrays without context knowledge (so the D language is not 100% context-free), as in: char[something] x; To decide if x is a static or associative array, you need to know whether "something" is a type or a constant. I have not found a nice solution for this problem yet (things like char[type something] look rather disgusting). By the way, this problem is quite similar to the C cast syntax (where the parser is also unable to decide between type and expression). Ciao uwe
Oct 25 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Uwe Salomon" <post uwesalomon.de> wrote in message
news:op.sy7vgtpb6yjbe6 sandmann.maerchenwald.net...
 Huh? Could you please explain that briefly? I am currently writing a
 compiler myself, and i thought a lot about this problem. Declarations and
 expressions can look very similar at the beginning, and it requires a lot
 of lookahead for the parser to decide between the two (which is annoying,
 as the lexer is more difficult then). I fumbled around with "var" and
 friends, too, but it looks so annoying if you have to write it everywhere.
Yes, I've (obviously) run into the same problems. It's not an LALR(1) grammar (one token lookahead), but doing LALR(1) would have compromised the look & feel I was trying to achieve. So arbitrary lookahead (LALR(n)) is needed. (A nit: it isn't a lexer problem, it's a parsing problem.) The lexer was designed from the start so that arbitrary lookahead is easy to do.
 Associative arrays in the current syntax are sometimes simply
 undistinguishable from static arrays without context knowledge (so the D
 language is not 100% context-free), as in:

 char[something] x;

 To decide if x is a static or associative array, you need to know whether
 "something" is a type or a constant. I have not found a nice solution for
 this problem yet (things like char[type something] look rather
 disgusting). By the way, this problem is quite similar to the C cast
 syntax (where the parser is also unable to decide between type and
 expression).
This isn't a big problem to deal with, because the resulting parse tree is the same whether it turns out to be a static array or an associative array. The D parser just creates it as an associative array. If the identifier turns out during semantic analysis not to be a type, but an expression, the type is rewritten as a static array. Since the parse tree remains the same, I believe it technically is a context-free grammar.
Oct 25 2005
parent Dave <Dave_member pathlink.com> writes:
In article <djmgi7$1jtr$2 digitaldaemon.com>, Walter Bright says...
"Uwe Salomon" <post uwesalomon.de> wrote in message
news:op.sy7vgtpb6yjbe6 sandmann.maerchenwald.net...
 Huh? Could you please explain that briefly? I am currently writing a
 compiler myself, and i thought a lot about this problem. Declarations and
 expressions can look very similar at the beginning, and it requires a lot
 of lookahead for the parser to decide between the two (which is annoying,
 as the lexer is more difficult then). I fumbled around with "var" and
 friends, too, but it looks so annoying if you have to write it everywhere.
Yes, I've (obviously) run into the same problems. It's not an LALR(1) grammar (one token lookahead), but doing LALR(1) would have compromised the look & feel I was trying to achieve. So arbitrary lookahead (LALR(n)) is needed. (A nit: it isn't a lexer problem, it's a parsing problem.) The lexer was designed from the start so that arbitrary lookahead is easy to do.
 Associative arrays in the current syntax are sometimes simply
 undistinguishable from static arrays without context knowledge (so the D
 language is not 100% context-free), as in:

 char[something] x;

 To decide if x is a static or associative array, you need to know whether
 "something" is a type or a constant. I have not found a nice solution for
 this problem yet (things like char[type something] look rather
 disgusting). By the way, this problem is quite similar to the C cast
 syntax (where the parser is also unable to decide between type and
 expression).
This isn't a big problem to deal with, because the resulting parse tree is the same whether it turns out to be a static array or an associative array. The D parser just creates it as an associative array. If the identifier turns out during semantic analysis not to be a type, but an expression, the type is rewritten as a static array. Since the parse tree remains the same, I believe it technically is a context-free grammar.
FWIW, I've been playing around with this code recently and it is a beauty to behold how it all comes together (and runs damn fast as well!).
Oct 25 2005
prev sibling parent reply Sai <Sai_member pathlink.com> writes:
Is the answer for it is to use a new keyword or to make the compiler smarter ?
Just curious 
:D
Sai


In article <djlsi7$4u4$1 digitaldaemon.com>, Walter Bright says...
"Ivan Senji" <ivan.senji_REMOVE_ _THIS__gmail.com> wrote in message
news:djlqvi$2tn$1 digitaldaemon.com...
 And i also agree. This way you cannot have auto objects with type
 inference and it is a problem. Couldn't another keywoard be added for
 type inference? Many have been suggested (autotype, var, ...).
I've tried to stay away from 'var', it reminds me of Pascal too much <g>. Anyhow, I've thought about this problem a lot, and there is an answer for it that is simple and consistent. It's just a bit of work to implement :-(.
Oct 25 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Sai" <Sai_member pathlink.com> wrote in message
news:djm1oj$p58$1 digitaldaemon.com...
 Is the answer for it is to use a new keyword or to make the compiler
smarter ? It's implementing class objects on the stack with the: classname(constructor arguments) syntax. Then, an RAII class object would be: auto c = classname(arguments); and a non-RAII class object would be: auto c = new classname(arguments); and the old RAII syntax would be supported as: auto classname c = new classname(arguments); and eventually deprecated.
Oct 25 2005
next sibling parent reply "Dave" <Dave_member pathlink.com> writes:
"Walter Bright" <newshound digitalmars.com> wrote in message 
news:djmgi6$1jtr$1 digitaldaemon.com...
 "Sai" <Sai_member pathlink.com> wrote in message
 news:djm1oj$p58$1 digitaldaemon.com...
 Is the answer for it is to use a new keyword or to make the compiler
smarter ? It's implementing class objects on the stack with the: classname(constructor arguments) syntax. Then, an RAII class object would be: auto c = classname(arguments); and a non-RAII class object would be: auto c = new classname(arguments);
Hot damn!
 and the old RAII syntax would be supported as:

    auto classname c = new classname(arguments);

 and eventually deprecated.

 
Oct 25 2005
parent "Walter Bright" <newshound digitalmars.com> writes:
"Dave" <Dave_member pathlink.com> wrote in message
news:djmm80$1sm8$1 digitaldaemon.com...
 Hot damn!
It's still a bit low down on the priority list, though.
Oct 25 2005
prev sibling next sibling parent reply Carlos Santander <csantander619 gmail.com> writes:
Walter Bright escribió:
 "Sai" <Sai_member pathlink.com> wrote in message
 news:djm1oj$p58$1 digitaldaemon.com...
 
Is the answer for it is to use a new keyword or to make the compiler
smarter ? It's implementing class objects on the stack with the: classname(constructor arguments) syntax. Then, an RAII class object would be: auto c = classname(arguments);
Regarding this case, what's gonna happen if "static classname.opCall(whatever)" has been defined?
 and a non-RAII class object would be:
 
     auto c = new classname(arguments);
 
 and the old RAII syntax would be supported as:
 
     auto classname c = new classname(arguments);
 
 and eventually deprecated.
 
 
-- Carlos Santander Bernal
Oct 25 2005
parent "Lionello Lunesu" <lio remove.lunesu.com> writes:
"Carlos Santander" <csantander619 gmail.com> wrote in message 
news:djmpd1$25oa$1 digitaldaemon.com...
 Walter Bright escribió:
 "Sai" <Sai_member pathlink.com> wrote in message
 news:djm1oj$p58$1 digitaldaemon.com...

Is the answer for it is to use a new keyword or to make the compiler
smarter ? It's implementing class objects on the stack with the: classname(constructor arguments) syntax. Then, an RAII class object would be: auto c = classname(arguments);
Regarding this case, what's gonna happen if "static classname.opCall(whatever)" has been defined?
I'm not really sure, but I guess you'll need an instance of a class for opCall to apply; there's no ambiguity here since the (..) applies to the class name. If I understood his comments correclty, Walter's not going to support classname c(arguments) for class construction. L.
Oct 27 2005
prev sibling next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Walter Bright wrote:
 Then, an RAII class object would be:
 
     auto c = classname(arguments);
 
 and a non-RAII class object would be:
 
     auto c = new classname(arguments);
Are you serious? This would make code very unreadable. Having keywords with multiple meanings is bad enough, but when the context looks as similar as in this case then things will get confusing very quickly. IMHO the non-RAII keyword should be something different. I think many alternatives have already been proposed, but I'd like to add one. Not sure what this would mean for parsability, but I like how this looks: ... c = new classname(arguments); I.e. a new "..." keyword that represents an inferred type. Looks as if something was left out, which is exactly how it is. Hauke
Oct 26 2005
next sibling parent reply Hauke Duden <H.NS.Duden gmx.net> writes:
Hauke Duden wrote:
 Walter Bright wrote:
 
 Then, an RAII class object would be:

     auto c = classname(arguments);

 and a non-RAII class object would be:

     auto c = new classname(arguments);
Are you serious? This would make code very unreadable. Having keywords with multiple meanings is bad enough, but when the context looks as similar as in this case then things will get confusing very quickly. IMHO the non-RAII keyword should be something different.
I just realized that maybe I misunderstood your plans. Do you mean that "auto" will only be used to represent a type and will not be directly connected to RAII anymore? I.e. would I also be able to create a RAII object like this? classname c = classname(arguments) In that case it would be easier to understand the concepts. However, readability would still suffer because auto c = classname(arguments); and auto c = new classname(arguments); look so similar. It would be really nice if the lines would look more different because the automatic destruction of c is such an important fact to realize. What about a C++ style syntax plus a keyword to make parsing easier? local classname c(arguments) Hauke
Oct 26 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
news:djnhiv$1833$1 digitaldaemon.com...
 I just realized that maybe I misunderstood your plans. Do you mean that
 "auto" will only be used to represent a type and will not be directly
 connected to RAII anymore? I.e. would I also be able to create a RAII
 object like this?

 classname c = classname(arguments)
Yes.
 In that case it would be easier to understand the concepts. However,
 readability would still suffer because

 auto c = classname(arguments);

 and

 auto c = new classname(arguments);

 look so similar. It would be really nice if the lines would look more
 different because the automatic destruction of c is such an important
 fact to realize.
I think it makes logical sense, one expects new to allocate on the heap, and non-new to allocate on the stack.
 What about a C++ style syntax plus a keyword to make parsing easier?

 local classname c(arguments)
The "function style" constructors in C++ declarations cause a lot of ambiguity problems. Parsing of the auto c = classname(args) is easy. The work comes in keeping careful track of when to insert the destructors.
Oct 26 2005
parent Sean Kelly <sean f4.ca> writes:
In article <djodvq$2nvh$2 digitaldaemon.com>, Walter Bright says...
"Hauke Duden" <H.NS.Duden gmx.net> wrote in message
 What about a C++ style syntax plus a keyword to make parsing easier?

 local classname c(arguments)
The "function style" constructors in C++ declarations cause a lot of ambiguity problems. Parsing of the auto c = classname(args) is easy. The work comes in keeping careful track of when to insert the destructors.
I very much agree. Unless function prototypes become illegal in D I would very much prefer to use a non-ambiguous class construction syntax. The C++ method can cause all sorts of subtle errors, and I've yet to meet a programmer who routinely constructs classes in a way that prevents them: MyClass c( (p1), p2, p3 ); The above doesn't seem natural and looks a bit odd. I also don't like that C++ baically offers two different ways to construct types: T t(val); T t = T(val); While the optimizer can make these effectively equivalent, the rules surrounding the need for a copy ctor and assignment operator in C++ are not particularly intuitive, and a lot of that has to do with the need to support both construction formats. Sean
Oct 26 2005
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <djnghp$13ob$1 digitaldaemon.com>, Hauke Duden says...
Walter Bright wrote:
 Then, an RAII class object would be:
 
     auto c = classname(arguments);
 
 and a non-RAII class object would be:
 
     auto c = new classname(arguments);
Are you serious? This would make code very unreadable. Having keywords with multiple meanings is bad enough, but when the context looks as similar as in this case then things will get confusing very quickly.
I think Walter's example is of an auto typed class declaration. You would also be able to instantiate a class like so: classname c = classname(arguments); classname c = new classname(arguments); At the same time, the old RAII meaning of auto would be deprecated, as it's no longer needed if you can allocate classes on the stack.
IMHO the non-RAII keyword should be something different. I think many 
alternatives have already been proposed, but I'd like to add one. Not 
sure what this would mean for parsability, but I like how this looks:

... c = new classname(arguments);

I.e. a new "..." keyword that represents an inferred type. Looks as if 
something was left out, which is exactly how it is.
I'm not sure I like it--it reminds me too much of implicitly declared variables in other languages. It could also lead to subtle errors: int myValue; myvalue = 5; With a token like 'auto' the programmer is able to explicitly declare which expressions are declarations. Sean
Oct 26 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <djo5n4$2cqp$1 digitaldaemon.com>, Sean Kelly says...
classname c = classname(arguments);
classname c = new classname(arguments);
Oops, I meant: classname c = classname(arguments); classname* c = new classname(arguments); What would be ideal is if this syntax applied to all D types: int x = int(5); int* x = new int(5); etc. This makes instantiation easier to accomplish in template code as the syntax is consistent. I'm not certain whether the ambiguity with opCall will be a problem however, as it's essentially a matter of overload resolution. So long as static opCall functions and class ctors don't have the same parameter list I don't think the compiler will complain. Sean
Oct 26 2005
parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Sean Kelly wrote:
 In article <djo5n4$2cqp$1 digitaldaemon.com>, Sean Kelly says...
 
classname c = classname(arguments);
classname c = new classname(arguments);
Oops, I meant: classname c = classname(arguments); classname* c = new classname(arguments);
I hope not. Just as we all got used to objects-are-references this would break everything.
 What would be ideal is if this syntax applied to all D types:
 
With this i agree, but value types and reference types are different and they should be treated different (at least it is that way, for example, templates but new returning a pointer is returning to C++ and i don't like it.
 int x = int(5);
 int* x = new int(5);
 
 etc.  This makes instantiation easier to accomplish in template code as the
 syntax is consistent.  I'm not certain whether the ambiguity with opCall will
be
 a problem however, as it's essentially a matter of overload resolution.  So
long
 as static opCall functions and class ctors don't have the same parameter list I
 don't think the compiler will complain.
 
 
 Sean
 
 
Oct 27 2005
parent Sean Kelly <sean f4.ca> writes:
In article <djrata$jac$1 digitaldaemon.com>, Ivan Senji says...
Sean Kelly wrote:
 In article <djo5n4$2cqp$1 digitaldaemon.com>, Sean Kelly says...
 
classname c = classname(arguments);
classname c = new classname(arguments);
Oops, I meant: classname c = classname(arguments); classname* c = new classname(arguments);
I hope not. Just as we all got used to objects-are-references this would break everything.
Yes, but it would do so very obviously and be quite simple to fix, since value semantics don't exist for classes right now.
 What would be ideal is if this syntax applied to all D types:
 
With this i agree, but value types and reference types are different and they should be treated different (at least it is that way, for example, templates but new returning a pointer is returning to C++ and i don't like it.
As I said in my other post, I'm not sure whether return by value will work with the existing handle semantics. And without return by value, this would be little more than in-language support for alloca(), which is not sufficient to solve the problems normally handled by stack-based UDTs. That said, true value semantics for stack-based classes raises a bunch of other issues as well--such as the need for copy ctors and the like--which may well turn out to be a big can of worms. I know that Walter is also (understandably) not particularly fond of this aspect of C++, so I plan to Wait and See insofar as this particular feature is concerned. I very much like the idea of stack-based classes, but I think the design will require some care to get right. And I certainly do not expect this to be a direct port of the features as they exist in C++ :-) Sean
Oct 27 2005
prev sibling next sibling parent reply Vathix <chris dprogramming.com> writes:
On Tue, 25 Oct 2005 19:15:12 -0400, Walter Bright  
<newshound digitalmars.com> wrote:

 "Sai" <Sai_member pathlink.com> wrote in message
 news:djm1oj$p58$1 digitaldaemon.com...
 Is the answer for it is to use a new keyword or to make the compiler
smarter ? It's implementing class objects on the stack with the: classname(constructor arguments) syntax. Then, an RAII class object would be: auto c = classname(arguments); and a non-RAII class object would be: auto c = new classname(arguments); and the old RAII syntax would be supported as: auto classname c = new classname(arguments); and eventually deprecated.
I like it. Only problem I can think of is conflicts if the class has a static opCall. Perhaps classes should not have them (but they're very handy for structs/unions). This extra code in the compiler to support it could possibly be hacked in by adding an internal, implicit static opCall to all classes, which are translated to RAII constructors when invoked from an initializer ;)
Oct 26 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Vathix" <chris dprogramming.com> wrote in message
news:op.sy8x7py7l2lsvj esi...
 I like it. Only problem I can think of is conflicts if the class has a
 static opCall. Perhaps classes should not have them
I'm hard pressed to see the point of them for classes anyway.
 (but they're very
 handy for structs/unions). This extra code in the compiler to support it
 could possibly be hacked in by adding an internal, implicit static opCall
 to all classes, which are translated to RAII constructors when invoked
  from an initializer ;)
There's more work to get all the details ironed out, but that is where I want to go. It's needed because there are a certain class of problems D doesn't work well without.
Oct 26 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <djodvq$2nvh$3 digitaldaemon.com>, Walter Bright says...
There's more work to get all the details ironed out, but that is where I
want to go. It's needed because there are a certain class of problems D
doesn't work well without.
I'm glad to hear it :) This is the only real syntax-level issue I have with D, and it's a relief to know that it will be addressed at some point. Sean
Oct 26 2005
parent reply Sean Kelly <sean f4.ca> writes:
Sean Kelly wrote:
 In article <djodvq$2nvh$3 digitaldaemon.com>, Walter Bright says...
 
There's more work to get all the details ironed out, but that is where I
want to go. It's needed because there are a certain class of problems D
doesn't work well without.
I'm glad to hear it :) This is the only real syntax-level issue I have with D, and it's a relief to know that it will be addressed at some point.
Oh, one more question, is there any chance that this will allow static object composition as well? ie. class C {} class D { C c = C(); } Not a big deal, but it would be nice if the entire class could avoid the use of new rather than just the outer instantiation. The syntax seems a bit weird for this purpose (as the above doesn't allow for c to be constructed in D's ctor), but perhaps there's a way to clarify it somehow? Sean
Nov 02 2005
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Sean Kelly wrote:
 Oh, one more question, is there any chance that this will allow static 
 object composition as well?  ie.
 
 class C {}
 class D { C c = C(); }
 
 Not a big deal, but it would be nice if the entire class could avoid the 
 use of new rather than just the outer instantiation.  The syntax seems a 
 bit weird for this purpose (as the above doesn't allow for c to be 
 constructed in D's ctor), but perhaps there's a way to clarify it somehow?
I also think that it would be a good idea to handle static object composition with the same syntax as classes on the stack. In either case, we are really declaring a class-value variable rather than a class-reference variable.
Nov 02 2005
parent reply Sean Kelly <sean f4.ca> writes:
Russ Lewis wrote:
 
 I also think that it would be a good idea to handle static object 
 composition with the same syntax as classes on the stack.  In either 
 case, we are really declaring a class-value variable rather than a 
 class-reference variable.
Technically, it's a class reference to a stack instance as this change would not provide value semantics for classes. The distinction is clear when considering this: class C {} class D { C c; this() { c = C(); } this( int x ) { c = new C(); } } This is completely legal with the proposed semantics and would result in c referring to an invalid location if the default ctor is called. Currently, we can use placement new to fake static composition: class E { C c; ubyte[C.sizeof] buf; this() { c = new (&buf[0]) C(); } } (I'm just guessing at syntax here as I haven't actually tried this) but this raises alignment issues and such that a language-supported method does not have. Sean
Nov 02 2005
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Sean Kelly wrote:
 Russ Lewis wrote:
 
 I also think that it would be a good idea to handle static object 
 composition with the same syntax as classes on the stack.  In either 
 case, we are really declaring a class-value variable rather than a 
 class-reference variable.
Technically, it's a class reference to a stack instance as this change would not provide value semantics for classes. The distinction is clear when considering this: class C {} class D { C c; this() { c = C(); } this( int x ) { c = new C(); } } This is completely legal with the proposed semantics and would result in c referring to an invalid location if the default ctor is called. Currently, we can use placement new to fake static composition: class E { C c; ubyte[C.sizeof] buf; this() { c = new (&buf[0]) C(); } } (I'm just guessing at syntax here as I haven't actually tried this) but this raises alignment issues and such that a language-supported method does not have.
It's a hack on top of a hack on top of a hack. And it's all because we wanted to save typing * characters for our class variables. (sigh)
Nov 02 2005
parent reply Sean Kelly <sean f4.ca> writes:
Russ Lewis wrote:
 
 It's a hack on top of a hack on top of a hack.  And it's all because we 
 wanted to save typing * characters for our class variables.  (sigh)
I used to feel this way, but I'm coming around. Adding the pointer qualifier to heap-based classes has the unfortunate consequence of requiring value semantics for their stack-based equivalent. And while I do believe that user-defined value types can be quite useful in some circumstances, I think they also tend to be misused and are prone to creating code that is difficult to read. So long as the language has sufficient support for higher maths and such built-in (the complex type, vector ops, etc), I don't see a pressing need for value semantics in D. I think it's important to note that D differs fundamentally from C++ in that it does impose language-level restrictions in an attempt to reduce the amount of unreadable code and other sheer nastiness that is common in C++. But it also provides a lot of features C++ doesn't--built into the language--to eliminate the need for such nasty code in the first place. This definately fosters a different programming style than C++, but given the vast bulk of horrible C++ code I've encountered I think that's probably a good thing. Sean
Nov 02 2005
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Sean Kelly wrote:
 Russ Lewis wrote:
 
 It's a hack on top of a hack on top of a hack.  And it's all because 
 we wanted to save typing * characters for our class variables.  (sigh)
I used to feel this way, but I'm coming around. Adding the pointer qualifier to heap-based classes has the unfortunate consequence of requiring value semantics for their stack-based equivalent. And while I do believe that user-defined value types can be quite useful in some circumstances, I think they also tend to be misused and are prone to creating code that is difficult to read. So long as the language has sufficient support for higher maths and such built-in (the complex type, vector ops, etc), I don't see a pressing need for value semantics in D. I think it's important to note that D differs fundamentally from C++ in that it does impose language-level restrictions in an attempt to reduce the amount of unreadable code and other sheer nastiness that is common in C++. But it also provides a lot of features C++ doesn't--built into the language--to eliminate the need for such nasty code in the first place. This definately fosters a different programming style than C++, but given the vast bulk of horrible C++ code I've encountered I think that's probably a good thing.
Changing the syntax doesn't require you to change the functionality, just the syntax. I'm actually pretty happy about the development of the language over time. IMHO, it was a good idea to discard class-value variables at the start of development. We all argued out whether or not they were *really* necessary. Eventually, we came to the conclusion that they were, so they were implemented, but with restrictions. That same process could have happened quite easliy even if we were typing * characters. Granted, there would be a lot more flame wars about why we didn't have "basic" features. Ick.
Nov 02 2005
parent Sean Kelly <sean f4.ca> writes:
Russ Lewis wrote:
 
 Changing the syntax doesn't require you to change the functionality, 
 just the syntax.  I'm actually pretty happy about the development of the 
 language over time.  IMHO, it was a good idea to discard class-value 
 variables at the start of development.  We all argued out whether or not 
 they were *really* necessary.  Eventually, we came to the conclusion 
 that they were, so they were implemented, but with restrictions.  That 
 same process could have happened quite easliy even if we were typing * 
 characters.
True enough. It would just be a tad weird if class variables always needed to be declared as pointers and the non-pointer syntax wasn't supported. Though I grant that it would be more consistent from a syntax perspective. I can see this potentially causing problems with template code that specializes on pointer types: template fn(T : T*) { fn( T* val ) { T temp = *val; // illegal if T is a class type ... } }
 Granted, there would be a lot more flame wars about why we didn't have 
 "basic" features.  Ick.
Yup. Sean
Nov 02 2005
prev sibling next sibling parent reply Dave <Dave_member pathlink.com> writes:
In article <djodvq$2nvh$3 digitaldaemon.com>, Walter Bright says...
"Vathix" <chris dprogramming.com> wrote in message
news:op.sy8x7py7l2lsvj esi...
 I like it. Only problem I can think of is conflicts if the class has a
 static opCall. Perhaps classes should not have them
I'm hard pressed to see the point of them for classes anyway.
 (but they're very
 handy for structs/unions). This extra code in the compiler to support it
 could possibly be hacked in by adding an internal, implicit static opCall
 to all classes, which are translated to RAII constructors when invoked
  from an initializer ;)
There's more work to get all the details ironed out, but that is where I want to go. It's needed because there are a certain class of problems D doesn't work well without.
Could we do stuff like this (w/o the new/delete member overrides)?: ;--- -import std.c.stdlib, std.stdio; - -void main() -{ - // imagine 'f' is constructed like: - // auto f = Foo(100); - Foo f = new(std.c.stdlib.alloca(Foo.classinfo.init.length)) Foo(100); - for(int i = 0; i < 100; i++) - { - f.x *= i + 1; - writefln(f.x); - Foo f2 = foo(f); - writefln(f2.x,"\n"); - } -} - -Foo foo(Foo f) -{ - f.x *= 3.14159; - return f; -} - -class Foo -{ - double x; - this(double x) - { - this.x = x; - } - new(uint sz, void *p) - { - return p; - } - delete(void* p) - { - assert(0); - } -} Thanks, - Dave
Oct 26 2005
next sibling parent Dave <Dave_member pathlink.com> writes:
Geesh - see code correction below..

In article <djoku3$2v3p$1 digitaldaemon.com>, Dave says...
In article <djodvq$2nvh$3 digitaldaemon.com>, Walter Bright says...
There's more work to get all the details ironed out, but that is where I
want to go. It's needed because there are a certain class of problems D
doesn't work well without.
Could we do stuff like this (w/o the new/delete member overrides)?: ;--- -import std.c.stdlib, std.stdio; - -void main() -{ - // imagine 'f' is constructed like: - // auto f = Foo(100); - Foo f = new(std.c.stdlib.alloca(Foo.classinfo.init.length)) Foo(100); - for(int i = 0; i < 100; i++) - { - f.x *= i + 1; - writefln(f.x); - Foo f2 = foo(f); - writefln(f2.x,"\n"); - } -} -
-Foo foo(Foo f) -{ - // imagine 'f2' is constructed like: - // Foo f2 = Foo(10); - Foo f2 = new(alloca(Foo.classinfo.init.length)) Foo(10); - f2.x *= f.x * 3.14159; - return f2; -} What I meant to ask is will we be able to return stack allocated class instances from functions?
-
-class Foo
-{
-    double x;
-    this(double x)
-    {
-        this.x = x;
-    }
-    new(uint sz, void *p)
-    {
-	return p;
-    }
-    delete(void* p)
-    {
-	assert(0);
-    }
-}

Thanks,

- Dave
Oct 26 2005
prev sibling parent "Walter Bright" <newshound digitalmars.com> writes:
"Dave" <Dave_member pathlink.com> wrote in message
news:djoku3$2v3p$1 digitaldaemon.com...
 Could we do stuff like this (w/o the new/delete member overrides)?:
Yes.
Oct 27 2005
prev sibling parent "Garett Bass" <garettbass studiotekne.com> writes:
Please don't kill opCall for classes, it makes for great factory method 
syntax :)  If you're leaning that way, maybe only allow static opCall for 
abstract classes?


"Walter Bright" <newshound digitalmars.com> wrote in message 
news:djodvq$2nvh$3 digitaldaemon.com...
 "Vathix" <chris dprogramming.com> wrote in message
 news:op.sy8x7py7l2lsvj esi...
 I like it. Only problem I can think of is conflicts if the class has a
 static opCall. Perhaps classes should not have them
I'm hard pressed to see the point of them for classes anyway.
 (but they're very
 handy for structs/unions). This extra code in the compiler to support it
 could possibly be hacked in by adding an internal, implicit static opCall
 to all classes, which are translated to RAII constructors when invoked
  from an initializer ;)
There's more work to get all the details ironed out, but that is where I want to go. It's needed because there are a certain class of problems D doesn't work well without.
Oct 31 2005
prev sibling parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Walter Bright wrote:
 "Sai" <Sai_member pathlink.com> wrote in message
 news:djm1oj$p58$1 digitaldaemon.com...
 
Is the answer for it is to use a new keyword or to make the compiler
smarter ? It's implementing class objects on the stack with the: classname(constructor arguments) syntax. Then, an RAII class object would be: auto c = classname(arguments); and a non-RAII class object would be: auto c = new classname(arguments); and the old RAII syntax would be supported as: auto classname c = new classname(arguments); and eventually deprecated.
First of all, kudos on this great feature! But I must say I too don't like having auto (type) share the same name as the unrelated (RAII) auto. Not only it has now that pratical problem of not being able to declare an "auto auto" object, but conceptually as well I don't think it's good to have two keywords with the same name who do quite different things. (remeber C's static ... ugh :P ) Now, as for possible alternative solutions, I don't like that proposed one either. Doesn't read that well, and it still has the homonymous keywords. How about having autoraii be just an alternative to new. Something like: Foo foo = autonew Foo(arguments); possibly with a different shorter name than autonew, like anew, or snew. And an autotype autoraii object would be: auto foo = anew Foo(arguments); Incidently, and I mean incidently, it would allow anonymous autoraii objects, and consequently would allow easier work with blocks/scopes. Something like: // prints: { anew HtmlHtml(); // <html> { anew HtmlHead(); // <head> HtmlTitle("History"); // <title>History</title> } // </head> { anew HtmlBody(); // <body> HtmlComment("HI"); // <!-- HI --> HtmlHeader("Header"); // <h1>Header</h1> { anew HtmlParagraph(); // <p> HtmlText("paragraph"); // paragraph } // </p> } // </body> } // </html> Interesting at least, but this whole issue needs to be thought about more. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Oct 26 2005
next sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Bruno Medeiros" <daiphoenixNO SPAMlycos.com> wrote in message
news:djnlj6$1nbv$1 digitaldaemon.com...
 But I must say I too don't like having auto (type) share the same name
 as the unrelated (RAII) auto. Not only it has now that pratical problem
 of not being able to declare an "auto auto" object, but conceptually as
 well I don't think it's good to have two keywords with the same name who
 do quite different things. (remeber C's static ... ugh :P )
But I think it is completely related! All 'auto' declarations will be destroyed when they go out of scope. Remember that class declarations only give references to class objects, not class objects themselves. So, class(args) creates a stack class object, which is destroyed when it goes out of scope. new class(args) creates one on the heap, which is not.
Oct 26 2005
next sibling parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Walter Bright wrote:
 "Bruno Medeiros" <daiphoenixNO SPAMlycos.com> wrote in message
 news:djnlj6$1nbv$1 digitaldaemon.com...
 
But I must say I too don't like having auto (type) share the same name
as the unrelated (RAII) auto. Not only it has now that pratical problem
of not being able to declare an "auto auto" object, but conceptually as
well I don't think it's good to have two keywords with the same name who
do quite different things. (remeber C's static ... ugh :P )
But I think it is completely related! All 'auto' declarations will be destroyed when they go out of scope. Remember that class declarations only give references to class objects, not class objects themselves. So, class(args) creates a stack class object, which is destroyed when it goes out of scope. new class(args) creates one on the heap, which is not.
Whoa, you lost me there. Are you talking about the current DMD.127 situation, or your alternative proposal? It seems you are talking about your new proposal, however that (quoted) comment of mine was relative to the current DMD.127 situation. I'm still kinda lost because the following statement will be false nomatter what situation you were refering to: "All 'auto' declarations will be destroyed when they go out of scope." (I assume "'auto' declaration" is any with a 'auto' keyword in there) There is an error or misunderstanding here somewhere. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Oct 26 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Bruno Medeiros" <daiphoenixNO SPAMlycos.com> wrote in message
news:djosi1$5b9$1 digitaldaemon.com...
 Whoa, you lost me there. Are you talking about the current DMD.127
 situation,
The current version is 0.137 <g>
 or your alternative proposal? It seems you are talking about
 your new proposal, however that (quoted) comment of mine was relative to
 the current DMD.127 situation.
 I'm still kinda lost because the following statement will be false
 nomatter what situation you were refering to: "All 'auto' declarations
 will be destroyed when they go out of scope." (I assume "'auto'
 declaration" is any with a 'auto' keyword in there)
 There is an error or misunderstanding here somewhere.
The statement will remain true, and that's because class declarations are only for *references* to a class, not instances. The auto reference will always go away at the end of the scope. Whether the instance does or not depends on if it is on the class or the stack. The way the initializer is written determines if it is a stack or a heap instance.
Oct 27 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...
The statement will remain true, and that's because class declarations are
only for *references* to a class, not instances. The auto reference will
always go away at the end of the scope. Whether the instance does or not
depends on if it is on the class or the stack. The way the initializer is
written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way? Would such a design support returning classes by value? ie. MyClass getInstance() { MyClass c = MyClass(); return c; } From what you're saying, this sounds like it would produce undefined behavior. And in large function calls, this could be an easy mistake to make. Why omit the need for pointer semantics for heap-based classes? I'd think it would offer a degree of checking that the handle-based syntax doesn't: MyClass* getInstance() { MyClass c = MyClass(); return c; // error: cannot convert MyClass to MyClass* } Sean
Oct 27 2005
next sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Sean Kelly wrote:
 In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...
 
The statement will remain true, and that's because class declarations are
only for *references* to a class, not instances. The auto reference will
always go away at the end of the scope. Whether the instance does or not
depends on if it is on the class or the stack. The way the initializer is
written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way? Would such a design support returning classes by value? ie. MyClass getInstance() { MyClass c = MyClass(); return c; } From what you're saying, this sounds like it would produce undefined behavior.
As it would in C++, at the end of scope c is dead.
 And in large function calls, this could be an easy mistake to make.  Why omit
Indeed.
 the need for pointer semantics for heap-based classes?  I'd think it would
offer
 a degree of checking that the handle-based syntax doesn't:
 
 MyClass* getInstance() {
 MyClass c = MyClass();
 return c; // error: cannot convert MyClass to MyClass*
 }
 
Yuck. With stack based class objects we are getting big bunch of problems with returning destructed objects. Is it really a good idea to have stack-based classes? We have lived without them for a long time in D. And although i can see that they have some advantages (like speed) but it looks to me they bring big problems to the language.
 
 Sean
 
 
Oct 27 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <djrbo0$lkk$1 digitaldaemon.com>, Ivan Senji says...
With stack based class objects we are getting big bunch of problems with 
returning destructed objects. Is it really a good idea to have 
stack-based classes? We have lived without them for a long time in D.
And although i can see that they have some advantages (like speed) but 
it looks to me they bring big problems to the language.
I very much agree. But as Walter said, there is a certain class of problems that require stack-based behavior to be easily solvable. I think a careful, explicit use of handles might resolve this in some instances, but as Regan's smart pointer example shows, this is not particularly natural in D and is very prone to programmer error. I believe there must be a more elegant way to implement value semantics than how they are handled in C++, perhaps this is mostly a matter of finding it. Sean
Oct 27 2005
parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Sean Kelly wrote:
 In article <djrbo0$lkk$1 digitaldaemon.com>, Ivan Senji says...
 
With stack based class objects we are getting big bunch of problems with 
returning destructed objects. Is it really a good idea to have 
stack-based classes? We have lived without them for a long time in D.
And although i can see that they have some advantages (like speed) but 
it looks to me they bring big problems to the language.
I very much agree. But as Walter said, there is a certain class of problems that require stack-based behavior to be easily solvable. I think a careful, explicit use of handles might resolve this in some instances, but as Regan's smart pointer example shows, this is not particularly natural in D and is very prone to programmer error. I believe there must be a more elegant way to implement value semantics than how they are handled in C++, perhaps this is mostly a matter of finding it.
And we know just the man to find them :)
 
 Sean
 
 
Oct 27 2005
prev sibling next sibling parent reply Dave <Dave_member pathlink.com> writes:
In article <djrbo0$lkk$1 digitaldaemon.com>, Ivan Senji says...
Sean Kelly wrote:
 In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...
 
The statement will remain true, and that's because class declarations are
only for *references* to a class, not instances. The auto reference will
always go away at the end of the scope. Whether the instance does or not
depends on if it is on the class or the stack. The way the initializer is
written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way? Would such a design support returning classes by value? ie. MyClass getInstance() { MyClass c = MyClass(); return c; } From what you're saying, this sounds like it would produce undefined behavior.
As it would in C++, at the end of scope c is dead.
Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour although it can hide bugs that seem like it <g> I think the prev. poster was just asking (as I did earlier with an example) if Walter has some magic that would allow this? Like how stack allocated D structs are returned by value (shallow copy of heap members), which D can usually get away with because of the GC.
 And in large function calls, this could be an easy mistake to make.  Why omit
Indeed.
 the need for pointer semantics for heap-based classes?  I'd think it would
offer
 a degree of checking that the handle-based syntax doesn't:
 
 MyClass* getInstance() {
 MyClass c = MyClass();
 return c; // error: cannot convert MyClass to MyClass*
 }
 
Yuck. With stack based class objects we are getting big bunch of problems with returning destructed objects. Is it really a good idea to have stack-based classes? We have lived without them for a long time in D. And although i can see that they have some advantages (like speed) but it looks to me they bring big problems to the language.
 
 Sean
 
 
Oct 27 2005
parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Dave wrote:
 In article <djrbo0$lkk$1 digitaldaemon.com>, Ivan Senji says...
As it would in C++, at the end of scope c is dead.
Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour although it can hide bugs that seem like it <g>
Copy ctor? D doesn't hava a copy ctor. c is a reference to a location on the stack, and when you exit the method and the objects is destroyed you really shouldn't be using that memory location. Can hide bugs? It is a bug.
 I think the prev. poster was just asking (as I did earlier with an example) if
 Walter has some magic that would allow this? Like how stack allocated D structs
 are returned by value (shallow copy of heap members), which D can usually get
 away with because of the GC.
Only Walter knows. But structs are very different from classes.
 ...
Oct 27 2005
parent reply Dave <Dave_member pathlink.com> writes:
In article <djsf79$r5t$1 digitaldaemon.com>, Ivan Senji says...
Dave wrote:
 In article <djrbo0$lkk$1 digitaldaemon.com>, Ivan Senji says...
As it would in C++, at the end of scope c is dead.
Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour although it can hide bugs that seem like it <g>
Copy ctor? D doesn't hava a copy ctor. c is a reference to a location on the stack, and when you exit the method and the objects is destroyed you really shouldn't be using that memory location.
Ok - how's this: "Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour /in C++/ although it can hide bugs that seem like it <g>" Since my reply was right after you mentioned C++ I thought it would be clear that the reference was to C++.
Can hide bugs? It is a bug.

 I think the prev. poster was just asking (as I did earlier with an example) if
 Walter has some magic that would allow this? Like how stack allocated D structs
 are returned by value (shallow copy of heap members), which D can usually get
 away with because of the GC.
Only Walter knows. But structs are very different from classes.
 ...
Oct 28 2005
parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Dave wrote:
 In article <djsf79$r5t$1 digitaldaemon.com>, Ivan Senji says...
 
Dave wrote:

In article <djrbo0$lkk$1 digitaldaemon.com>, Ivan Senji says...

As it would in C++, at the end of scope c is dead.
Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour although it can hide bugs that seem like it <g>
Copy ctor? D doesn't hava a copy ctor. c is a reference to a location on the stack, and when you exit the method and the objects is destroyed you really shouldn't be using that memory location.
Ok - how's this: "Yes, 'c' is dead, but before that the copy ctor is called (implicit or explicit) and that temporary copy is returned; so it really isn't undefined behaviour /in C++/ although it can hide bugs that seem like it <g>" Since my reply was right after you mentioned C++ I thought it would be clear that the reference was to C++.
Sorry, my mistake :) But the program segment in question i see as this code in C++: MyClass* getInstance() { MyClass c(); return &c; } And we can agree that this is not good code.
 
Can hide bugs? It is a bug.


I think the prev. poster was just asking (as I did earlier with an example) if
Walter has some magic that would allow this? Like how stack allocated D structs
are returned by value (shallow copy of heap members), which D can usually get
away with because of the GC.
Only Walter knows. But structs are very different from classes.
...
Oct 28 2005
prev sibling parent Hauke Duden <H.NS.Duden gmx.net> writes:
Ivan Senji wrote:
 Yuck.
 With stack based class objects we are getting big bunch of problems with 
 returning destructed objects. Is it really a good idea to have 
 stack-based classes? We have lived without them for a long time in D.
 And although i can see that they have some advantages (like speed) but 
 it looks to me they bring big problems to the language.
I think the most important use of stack based objects is if you want something to automatically happen when the scope is left. For example (using pseudo-syntax to avoid the confusion of "auto"): { local MutexLock l=MutexLock(myMutex); ...stuff // automatically release mutex } Having this ability can be invaluable for preventing bugs that are very hard to find. The solution for preventing dangling references for stack based objects would be to make "stack-based" a type modifier without implicit conversion to non-stack-based types. For example: local MutexLock l=MutexLock(myMutex); MutexLock x=l; // error because x is not a stack-reference. local MutexLock y=l; // ok. Note that y cannot become a dangling // reference because it is either in the same // scope as l or in an inner scope. So y always // goes out of scope before l. MutexLock x=cast(local MutexLock)l; //ok? should be allowed IMHO Stack references should only be allowed as local variables and function parameters. Everything else would lead to dangling references. Note that implicit conversion from non-stack reference to stack reference is not a problem. I just realized that such a type modifier would also solve another common programming problem. You often have methods with arguments that should only be used during the execution of the method. I.e. you do not want a reference to the argument to be stored and used again later, possibly because the object might be in an invalid state at that time. Having a "local" type modifier could help to enforce this. If the function argument is "local" then it can only be stored in other local variables of that function. So it is impossible for the implementor of the method to accidently access the object again after the function returns. Hauke
Oct 29 2005
prev sibling next sibling parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...
 The statement will remain true, and that's because class declarations  
 are
 only for *references* to a class, not instances. The auto reference will
 always go away at the end of the scope. Whether the instance does or not
 depends on if it is on the class or the stack. The way the initializer  
 is
 written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way? Would such a design support returning classes by value? ie. MyClass getInstance() { MyClass c = MyClass(); return c; } From what you're saying, this sounds like it would produce undefined behavior.
Why can't this simply be detected at compile time? Regan
Oct 27 2005
next sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Regan Heath wrote:
 On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 
 In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...

 The statement will remain true, and that's because class 
 declarations  are
 only for *references* to a class, not instances. The auto reference will
 always go away at the end of the scope. Whether the instance does or not
 depends on if it is on the class or the stack. The way the 
 initializer  is
 written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way? Would such a design support returning classes by value? ie. MyClass getInstance() { MyClass c = MyClass(); return c; } From what you're saying, this sounds like it would produce undefined behavior.
Why can't this simply be detected at compile time?
The simple example can allways be complicated: MyClass getInstance() { MyClass c = MyClass(); ...a lot of code MyClass a = c; ...a lot of code return a; } I don't think it would be possible for the compiler to track all that is going on with references to stack allocated objects. What if you had in the method above: MyClass c = MyClass(); ...a lot of code MyClass a; if(somecondition) { a = c; } else { a = new MyClass(); } return a; In this case the code is sometimes legal and sometimes not. No easy solution in sight.
 Regan
Oct 27 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 27 Oct 2005 23:24:42 +0200, Ivan Senji  
<ivan.senji_REMOVE_ _THIS__gmail.com> wrote:
 Regan Heath wrote:
 On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:

 In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...

 The statement will remain true, and that's because class  
 declarations  are
 only for *references* to a class, not instances. The auto reference  
 will
 always go away at the end of the scope. Whether the instance does or  
 not
 depends on if it is on the class or the stack. The way the  
 initializer  is
 written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way? Would such a design support returning classes by value? ie. MyClass getInstance() { MyClass c = MyClass(); return c; } From what you're saying, this sounds like it would produce undefined behavior.
Why can't this simply be detected at compile time?
The simple example can allways be complicated: MyClass getInstance() { MyClass c = MyClass(); ...a lot of code MyClass a = c; ...a lot of code return a; } I don't think it would be possible for the compiler to track all that is going on with references to stack allocated objects. What if you had in the method above: MyClass c = MyClass(); ...a lot of code MyClass a; if(somecondition) { a = c; } else { a = new MyClass(); } return a; In this case the code is sometimes legal and sometimes not. No easy solution in sight.
If the actual instance is flagged as being stack based then you simply error when a reference is returned that references a stack based instance. You don't actually need to track anything, except that the instance itself is stack based, which you have to track anyway because you're going to destroy it at the end of scope, right? Regan
Oct 27 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <opszbqebii23k2f5 nrage.netwin.co.nz>, Regan Heath says...
If the actual instance is flagged as being stack based then you simply  
error when a reference is returned that references a stack based instance.  
You don't actually need to track anything, except that the instance itself  
is stack based, which you have to track anyway because you're going to  
destroy it at the end of scope, right?
If it's on the stack, no explicit tracking is needed. It will be destroyed automatically as a part of the stack unwinding process when the function exits. Though if the class has a dtor then some tracking is indeed necessary. Either way, this is something that happens at run time, not compile time. Though I suppose an AssertError is better than attempting to access released memory. Sean
Oct 27 2005
parent "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 27 Oct 2005 22:13:02 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 In article <opszbqebii23k2f5 nrage.netwin.co.nz>, Regan Heath says...
 If the actual instance is flagged as being stack based then you simply
 error when a reference is returned that references a stack based  
 instance.
 You don't actually need to track anything, except that the instance  
 itself
 is stack based, which you have to track anyway because you're going to
 destroy it at the end of scope, right?
If it's on the stack, no explicit tracking is needed. It will be destroyed automatically as a part of the stack unwinding process when the function exits. Though if the class has a dtor then some tracking is indeed necessary. Either way, this is something that happens at run time, not compile time.
So the compiler can't flag a reference as referencing a local stack object at compile time, and error if it's returned? It would have to copy the flag on assignments and so on, but it's _possible_ right? It's more work for the compiler, but at least it's done at compile time and not runtime.
 Though I
 suppose an AssertError is better than attempting to access released  
 memory.
Most things are. Regan
Oct 27 2005
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <opszbo89dr23k2f5 nrage.netwin.co.nz>, Regan Heath says...
On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 Interesting.  So the variable would be declared the same either way?   
 Would such
 a design support returning classes by value?  ie.

 MyClass getInstance() {
 MyClass c = MyClass();
 return c;
 }

 From what you're saying, this sounds like it would produce undefined  
 behavior.
Why can't this simply be detected at compile time?
I think it could be for simple cases, but I'm not sure the compiler could catch all such errors. Though perhaps partial detection is sufficient... Sean
Oct 27 2005
parent reply "Regan Heath" <regan netwin.co.nz> writes:
On Thu, 27 Oct 2005 21:30:12 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 In article <opszbo89dr23k2f5 nrage.netwin.co.nz>, Regan Heath says...
 On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 Interesting.  So the variable would be declared the same either way?
 Would such
 a design support returning classes by value?  ie.

 MyClass getInstance() {
 MyClass c = MyClass();
 return c;
 }

 From what you're saying, this sounds like it would produce undefined
 behavior.
Why can't this simply be detected at compile time?
I think it could be for simple cases, but I'm not sure the compiler could catch all such errors. Though perhaps partial detection is sufficient...
Why not? Surely you just flag the actual instance as stack based and then error whenever someone returns a reference to a stack based instance? Regan
Oct 27 2005
parent Dave <Dave_member pathlink.com> writes:
In article <opszbqbmzg23k2f5 nrage.netwin.co.nz>, Regan Heath says...
On Thu, 27 Oct 2005 21:30:12 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 In article <opszbo89dr23k2f5 nrage.netwin.co.nz>, Regan Heath says...
 On Thu, 27 Oct 2005 19:48:41 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:
 Interesting.  So the variable would be declared the same either way?
 Would such
 a design support returning classes by value?  ie.

 MyClass getInstance() {
 MyClass c = MyClass();
 return c;
 }

 From what you're saying, this sounds like it would produce undefined
 behavior.
Why can't this simply be detected at compile time?
I think it could be for simple cases, but I'm not sure the compiler could catch all such errors. Though perhaps partial detection is sufficient...
Why not? Surely you just flag the actual instance as stack based and then error whenever someone returns a reference to a stack based instance? Regan
I think you're right - this should be do-able at compile time as long as the assignments are direct and not through pointers to references, etc. And even then the semantic optimizer in the reference compiler will remove cases like this (this 'optimizer' is run no matter which compiler flags are used): MyClass c1 = new MyClass; MyClass c2 = *&c1; // optimized to c2 = c1;
Oct 27 2005
prev sibling next sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message
news:djraup$jeb$1 digitaldaemon.com...
 In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...
The statement will remain true, and that's because class declarations are
only for *references* to a class, not instances. The auto reference will
always go away at the end of the scope. Whether the instance does or not
depends on if it is on the class or the stack. The way the initializer is
written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way?
Would such
 a design support returning classes by value?  ie.

 MyClass getInstance() {
 MyClass c = MyClass();
 return c;
 }
Returning references to stack variables is wrong, wrong, wrong <g>.
 From what you're saying, this sounds like it would produce undefined
behavior.
 And in large function calls, this could be an easy mistake to make.  Why
omit
 the need for pointer semantics for heap-based classes?  I'd think it would
offer
 a degree of checking that the handle-based syntax doesn't:

 MyClass* getInstance() {
 MyClass c = MyClass();
 return c; // error: cannot convert MyClass to MyClass*
 }
It's not an improvement, the same errors are possible. Those errors are just as possible in C++, too.
Oct 27 2005
parent reply Dave <Dave_member pathlink.com> writes:
In article <djrt8q$2o2o$1 digitaldaemon.com>, Walter Bright says...
"Sean Kelly" <sean f4.ca> wrote in message
news:djraup$jeb$1 digitaldaemon.com...
 In article <djr50f$4pr$3 digitaldaemon.com>, Walter Bright says...
The statement will remain true, and that's because class declarations are
only for *references* to a class, not instances. The auto reference will
always go away at the end of the scope. Whether the instance does or not
depends on if it is on the class or the stack. The way the initializer is
written determines if it is a stack or a heap instance.
Interesting. So the variable would be declared the same either way?
Would such
 a design support returning classes by value?  ie.

 MyClass getInstance() {
 MyClass c = MyClass();
 return c;
 }
Returning references to stack variables is wrong, wrong, wrong <g>.
What happens with structs now? They are copied by value, but are not deep copied. In D this is usually fine w/o big problems because of the GC - as long as the programmer remembers that pointers and ref. types will refer to the same chunk of memory unless reassigned: void main() { S s = foo(); printf("%d\n",s.c.i); } struct S { C c; } class C { int i; } S foo() { S s; s.c = new C; s.c.i = 10; return s; } So, for stack alloc. classes (excluding RAII), couldn't an implicit shallow copy be made into a temporary returned on the stack, and then the reference to that assigned in the new scope? From there the semantics for stack allocated class objects with pointer and ref. members would be consistent with returning structs by value.
 From what you're saying, this sounds like it would produce undefined
behavior.
 And in large function calls, this could be an easy mistake to make.  Why
omit
 the need for pointer semantics for heap-based classes?  I'd think it would
offer
 a degree of checking that the handle-based syntax doesn't:

 MyClass* getInstance() {
 MyClass c = MyClass();
 return c; // error: cannot convert MyClass to MyClass*
 }
It's not an improvement, the same errors are possible. Those errors are just as possible in C++, too.
Oct 27 2005
parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Dave wrote:
 So, for stack alloc. classes (excluding RAII), couldn't an ...
Walter has said this here before: stack allocated classes/objects and RAII classes/objects are *the same*. There is no stack allocated classes/objects that are not RAII.
 In article <djrt8q$2o2o$1 digitaldaemon.com>, Walter Bright says...
"Sean Kelly" <sean f4.ca> wrote in message
Would such

a design support returning classes by value?  ie.

MyClass getInstance() {
MyClass c = MyClass();
return c;
}
Returning references to stack variables is wrong, wrong, wrong <g>.
"Would such a design support returning classes by value?" Why did everyone suddenly started talking about implementind value semantics for classes? It has nothing to do with the current design/issue (which is RAII and auto-type). Just because the new RAII proposal has a syntax similiar to C++'s value objects, it doesn't mean they are anywhere near the same.
 What happens with structs now? They are copied by value, but are not deep
 copied. ...
What follows is a reply to also some other comments in others posts: Structs have value semantics because they are structs, *not because* they are stack allocated. Thus just because we have stack allocated objects (RAII) doesn't mean they should have value semantics as well! D's objects follow a reference model (all of them), and any discussion regarding that, is off-topic for this thread. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Oct 28 2005
next sibling parent Sean Kelly <sean f4.ca> writes:
In article <djssee$1b40$1 digitaldaemon.com>, Bruno Medeiros says...
"Would such a design support returning classes by value?"
Why did everyone suddenly started talking about implementind value 
semantics for classes? It has nothing to do with the current 
design/issue (which is RAII and auto-type). Just because the new RAII 
proposal has a syntax similiar to C++'s value objects, it doesn't mean 
they are anywhere near the same.
I asked mostly because the two go hand-in-hand and I wanted to be sure I understood what Walter was proposing. I've given this issue some thought however, and I think Walter is right for avoiding value semantics for classes with this change. I can't think of a way around the need for a copy ctor and assignment operator support, and smart pointers also typically require an overloaded -> operator, which would be an overloaded dot operator in D (a horrifying idea IMO). I have also seen arguments that shared_ptr does not offer deterministic destruction so it's really more like a poor man's GC in most cases--the real strength of shared_ptr lies in its ability to execute arbitrary code on destruction, which we can do easily enough with auto classes accepting a delegate. I've realized that most times I want stack-based classes it's either because I want scope-specific RAII or because I want to avoid the use of heap allocation for one reason or another, and Walter's proposal provides this. I personally don't believe that D has this now because alloca() is a nonstandard C extension, and is therefore nonportable (it's also done at runtime, which is unnecessary in most cases). The semantic issue makes sense in this light because classes will never be value types, unlike all other types in D. So long as the new construction method is extended to work for all types (besides struct), I'll be quite happy: T v = T(val); T v = new T(val); (assume this is template code so T is actually a pointer type for non-class values) And if not, I'll stick to using template wrappers for this stuff :p Sean
Oct 28 2005
prev sibling parent reply Dave <Dave_member pathlink.com> writes:
In article <djssee$1b40$1 digitaldaemon.com>, Bruno Medeiros says...
Dave wrote:
 So, for stack alloc. classes (excluding RAII), couldn't an ...
Walter has said this here before: stack allocated classes/objects and RAII classes/objects are *the same*. There is no stack allocated classes/objects that are not RAII.
 In article <djrt8q$2o2o$1 digitaldaemon.com>, Walter Bright says...
"Sean Kelly" <sean f4.ca> wrote in message
Would such

a design support returning classes by value?  ie.

MyClass getInstance() {
MyClass c = MyClass();
return c;
}
Returning references to stack variables is wrong, wrong, wrong <g>.
"Would such a design support returning classes by value?" Why did everyone suddenly started talking about implementind value semantics for classes? It has nothing to do with the current design/issue (which is RAII and auto-type). Just because the new RAII proposal has a syntax similiar to C++'s value objects, it doesn't mean they are anywhere near the same.
 What happens with structs now? They are copied by value, but are not deep
 copied. ...
What follows is a reply to also some other comments in others posts: Structs have value semantics because they are structs, *not because* they are stack allocated. Thus just because we have stack allocated
Yep, but classes having value semantics was not necessarily what I was implying.
objects (RAII) doesn't mean they should have value semantics as well!
I'm not really asking for value semantics, I'm asking /if/ classes allocated on the stack can be returned 'safely' in a defined way, and I suggested a way to implement it that would basically allow the same syntax whether or not a class object was heap or stack allocated.
D's objects follow a reference model (all of them), and any discussion 
No, they don't - structs can be considered 'objects' as can any native type - especially when you consider the implications of the current design on generic programming techniques. For example, for many algorithms you would have to develop two sets of templates or use compiler conditionals like static if everywhere to support both class and struct 'objects' with the same template declarations. That is not what I'd like to call 'generic' programming.
regarding that, is off-topic for this thread.
Huh? Asking whether or not the new syntax that Walter put out here and has been recently discussed (and replied to) would let us return class objects allocated on the stack is completely within the context of this discussion since it was not real clear whether or not RAII and/or class object stack allocation would require 'auto' declaration or not.
-- 
Bruno Medeiros - CS/E student
"Certain aspects of D are a pathway to many abilities some consider to 
be... unnatural."
Oct 28 2005
parent Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Dave wrote:
 In article <djssee$1b40$1 digitaldaemon.com>, Bruno Medeiros says...
 
Dave wrote:

So, for stack alloc. classes (excluding RAII), couldn't an ...
Walter has said this here before: stack allocated classes/objects and RAII classes/objects are *the same*. There is no stack allocated classes/objects that are not RAII.
In article <djrt8q$2o2o$1 digitaldaemon.com>, Walter Bright says...

"Sean Kelly" <sean f4.ca> wrote in message
Would such


a design support returning classes by value?  ie.

MyClass getInstance() {
MyClass c = MyClass();
return c;
}
Returning references to stack variables is wrong, wrong, wrong <g>.
"Would such a design support returning classes by value?" Why did everyone suddenly started talking about implementind value semantics for classes? It has nothing to do with the current design/issue (which is RAII and auto-type). Just because the new RAII proposal has a syntax similiar to C++'s value objects, it doesn't mean they are anywhere near the same.
What happens with structs now? They are copied by value, but are not deep
copied. ...
What follows is a reply to also some other comments in others posts: Structs have value semantics because they are structs, *not because* they are stack allocated. Thus just because we have stack allocated
Yep, but classes having value semantics was not necessarily what I was implying.
Ah then, that changes things.
 
objects (RAII) doesn't mean they should have value semantics as well!
I'm not really asking for value semantics, I'm asking /if/ classes allocated on the stack can be returned 'safely' in a defined way, and I suggested a way to implement it that would basically allow the same syntax whether or not a class object was heap or stack allocated.
D's objects follow a reference model (all of them), and any discussion 
No, they don't - structs can be considered 'objects' as can any native type - especially when you consider the implications of the current design on generic programming techniques. For example, for many algorithms you would have to develop two sets of templates or use compiler conditionals like static if everywhere to support both class and struct 'objects' with the same template declarations. That is not what I'd like to call 'generic' programming.
I wasn't saying that structs should have value semantics. Just that they now have value semantics, and that it wasn't because they were stack allocated.
 
regarding that, is off-topic for this thread.
Huh? Asking whether or not the new syntax that Walter put out here and has been recently discussed (and replied to) would let us return class objects allocated on the stack is completely within the context of this discussion since it was not real clear whether or not RAII and/or class object stack allocation would require 'auto' declaration or not.
Yes, in that case (since you weren't talking about value-semantics), it is relevant. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Oct 29 2005
prev sibling parent Niko Korhonen <niktheblak hotmail.com> writes:
Sean Kelly wrote:
 From what you're saying, this sounds like it would produce undefined behavior.
 And in large function calls, this could be an easy mistake to make.  Why omit
 the need for pointer semantics for heap-based classes?  I'd think it would
offer
 a degree of checking that the handle-based syntax doesn't:
 
 MyClass* getInstance() {
 MyClass c = MyClass();
 return c; // error: cannot convert MyClass to MyClass*
 }
...and by that time D's metamorphosis into C++ will be complete. -- Niko Korhonen SW Developer
Oct 30 2005
prev sibling parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Walter Bright wrote:
 "Bruno Medeiros" <daiphoenixNO SPAMlycos.com> wrote in message
 news:djnlj6$1nbv$1 digitaldaemon.com...
 
But I must say I too don't like having auto (type) share the same name
as the unrelated (RAII) auto. Not only it has now that pratical problem
of not being able to declare an "auto auto" object, but conceptually as
well I don't think it's good to have two keywords with the same name who
do quite different things. (remeber C's static ... ugh :P )
But I think it is completely related! All 'auto' declarations will be destroyed when they go out of scope. Remember that class declarations only give references to class objects, not class objects themselves. So, class(args) creates a stack class object, which is destroyed when it goes out of scope. new class(args) creates one on the heap, which is not.
Ok, I've re-read this statement after your other explanation. I still find some things to be in error. In "All 'auto' declarations will be destroyed when they go out of scope", I read "destroyed" as refering to the object of the declaration (the instance), not the reference of course. The reference, being a local pointer, is obviously allocated on stack and is destroyed at the end of the scope. I would have to be seriously out-of-place/unknowledgeable to think otherwise. So, "All 'auto' declarations will be destroyed when they go out of scope" is false, since by "'auto' declarations" one should interpret as the objects created (instances), not the references. Namely, here are two auto declarations, taken from the docs, where the statement is false on the first one: auto c = new C(); // c is not RAII , is auto-typed auto C d = new C(); // c is RAII, is not auto-typed Also, This goes back to my original post, and clarifies what I meant by having the keyword 'auto' have two different meanings. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Oct 27 2005
parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Bruno Medeiros wrote:
 
 auto c = new C();   // c is not RAII , is auto-typed
 auto C d = new C(); // c is RAII, is not auto-typed
 
Shouldn't it be: type c = new type(args); //type not infered, no RAII auto c = new type(args); //type infered, no RAII type c = type(args); //type not infered, RAII auto c = type(args); //type infered, RAII At least this is what i figured out it should be, so: auto means type is infered, no new means RAII.
 Also, This goes back to my original post, and clarifies what I meant by 
 having the keyword 'auto' have two different meanings.
 
Oct 27 2005
parent reply Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Ivan Senji wrote:
 Bruno Medeiros wrote:
 
 auto c = new C();   // c is not RAII , is auto-typed
 auto C d = new C(); // c is RAII, is not auto-typed
Shouldn't it be: type c = new type(args); //type not infered, no RAII auto c = new type(args); //type infered, no RAII type c = type(args); //type not infered, RAII auto c = type(args); //type infered, RAII At least this is what i figured out it should be, so: auto means type is infered, no new means RAII.
No it shouldn't be. I said before (here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.announce/1771 ) that I was talking about the current DMD.137 situation in that post, not Walter's new proposal. -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Oct 28 2005
parent Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Bruno Medeiros wrote:
 Ivan Senji wrote:
 
 Bruno Medeiros wrote:

 auto c = new C();   // c is not RAII , is auto-typed
 auto C d = new C(); // c is RAII, is not auto-typed
Shouldn't it be: type c = new type(args); //type not infered, no RAII auto c = new type(args); //type infered, no RAII type c = type(args); //type not infered, RAII auto c = type(args); //type infered, RAII At least this is what i figured out it should be, so: auto means type is infered, no new means RAII.
No it shouldn't be. I said before (here: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.announce/1771 ) that I was talking about the current DMD.137 situation in that post, not Walter's new proposal.
Sorry, i really was tired when reading these posts :)
 
Oct 28 2005
prev sibling parent Bruno Medeiros <daiphoenixNO SPAMlycos.com> writes:
Bruno Medeiros wrote:
 Walter Bright wrote:
 It's implementing class objects on the stack with the:
     classname(constructor arguments)
 syntax. Then, an RAII class object would be:

     auto c = classname(arguments);

 and a non-RAII class object would be:

     auto c = new classname(arguments);

 and the old RAII syntax would be supported as:

     auto classname c = new classname(arguments);

 and eventually deprecated.
...
 
 Now, as for possible alternative solutions, I don't like that proposed 
 one either. Doesn't read that well, and it still has the homonymous 
 keywords.
 
I want to withdraw this opinion. I don't think I understood the new proposal correctly the first time. It seems to me this is a good alternative, even better than my similar 'autonew/snew' one. For the sake of no misundertansdings, I mean this: auto foo = Foo(arguments); // auto-type, RAII auto foo = new Foo(arguments); // auto-type, non-RAII (heap/GC) Foo foo = Foo(arguments); // explicit type, RAII Foo foo = new Foo(arguments); // explicit type, non-RAII (heap/GC) -- Bruno Medeiros - CS/E student "Certain aspects of D are a pathway to many abilities some consider to be... unnatural."
Oct 29 2005
prev sibling next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <djjpa0$1o9n$2 digitaldaemon.com>, Walter Bright says...
A couple of oft-requested features.
I'm running into an odd error with typeof. I have this line in std.c.stddef: alias typeof(int.sizeof) size_t; and have this in object.d: public import std.c.stddef; When I try to compile stddef I get this error: C:\bin\dmd\src\ares\std\c>dmd -c stddef.d stddef.d(10): size of type typeof(4) is not known When I move the alias into object.d however, the error goes away. This pattern worked fine when I was using version blocks to define the size_t alias, so it's something to do with typeof. Any ideas? Sean
Oct 24 2005
parent "Walter Bright" <newshound digitalmars.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message
news:djjrin$1q93$1 digitaldaemon.com...
 When I try to compile stddef I get this error:

 C:\bin\dmd\src\ares\std\c>dmd -c stddef.d
 stddef.d(10): size of type typeof(4) is not known

 When I move the alias into object.d however, the error goes away.  This
pattern
 worked fine when I was using version blocks to define the size_t alias, so
it's
 something to do with typeof.  Any ideas?
I can't reproduce the error.
Oct 25 2005
prev sibling next sibling parent reply "John Reimer" <terminal.node gmail.com> writes:
Yay!

"extern(linkage) for nested functions now works."

Thanks, Walter!  I thought you had all but forgotten this one.

- John

"Walter Bright" <newshound digitalmars.com> wrote in message 
news:djjpa0$1o9n$2 digitaldaemon.com...
A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html


 
Oct 25 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"John Reimer" <terminal.node gmail.com> wrote in message
news:djlrjv$3pl$1 digitaldaemon.com...
 Yay!

 "extern(linkage) for nested functions now works."

 Thanks, Walter!  I thought you had all but forgotten this one.
I just kept getting distracted onto other things. Sorry it took so long.
Oct 25 2005
parent reply "John Reimer" <terminal.node gmail.com> writes:
"Walter Bright" <newshound digitalmars.com> wrote in message 
news:djlu50$agr$1 digitaldaemon.com...
 "John Reimer" <terminal.node gmail.com> wrote in message
 news:djlrjv$3pl$1 digitaldaemon.com...
 Yay!

 "extern(linkage) for nested functions now works."

 Thanks, Walter!  I thought you had all but forgotten this one.
I just kept getting distracted onto other things. Sorry it took so long.
No problem! You certainly have plenty to distract you. :-) One note, though. It won't work in it's current form. Having the ability to apply extern(linkage) for nested functions is primarily useful for OS callback methods; but as implemented right now, this is not possible because the nested functions are seen solely as /delegates/ not /function pointers/. See the following: module callback; extern(Windows) alias int function(int,int) UPDATE_EVENT_W; // Simulate external win32 call extern(Windows) int extfunction( UPDATE_EVENT_W func ) { // do nothing auto fw = func; return 1; } void init( UPDATE_EVENT_W fc ) { extern(Windows) int func1( int a, int b ) { if (fc !is null) fc( a, b ); } extfunction( &func1 ); } That code produces the following compile message: callback.d(20): function callback.extfunction (int(Windows *)(int, int)) does not match argument types (int de legate(int a, int b)) callback.d(20): cannot implicitly convert expression (&func1) of type int delegate(int a, int b) to int(Window s *)(int, int) Is it possible to fix this? Also it appears that extern(Linkage) {} still won't work and defining function literals with a linkage attribute is also impossible. Thanks! -John
Oct 26 2005
parent reply Sean Kelly <sean f4.ca> writes:
In article <djoo2b$lv$1 digitaldaemon.com>, John Reimer says...
One note, though.  It won't work in it's current form.  Having the ability 
to apply extern(linkage) for nested functions is primarily useful for OS 
callback methods; but as implemented right now, this is not possible because 
the nested functions are seen solely as /delegates/ not /function pointers/. 
Try this:
void init( UPDATE_EVENT_W fc )
{
 extern(Windows) int func1( int a, int b )
static extern(Windows) int func1( int a, int b ) Sean
Oct 26 2005
parent reply John Reimer <John_member pathlink.com> writes:
In article <djopo5$29m$1 digitaldaemon.com>, Sean Kelly says...
In article <djoo2b$lv$1 digitaldaemon.com>, John Reimer says...
One note, though.  It won't work in it's current form.  Having the ability 
to apply extern(linkage) for nested functions is primarily useful for OS 
callback methods; but as implemented right now, this is not possible because 
the nested functions are seen solely as /delegates/ not /function pointers/. 
Try this:
void init( UPDATE_EVENT_W fc )
{
 extern(Windows) int func1( int a, int b )
static extern(Windows) int func1( int a, int b ) Sean
I tried that already and numerous other combinations. Nothing worked. Did you actually get that to work? -JJR
Oct 26 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
In article <djp8g4$fj9$1 digitaldaemon.com>, John Reimer says...
I tried that already and numerous other combinations.  Nothing worked.

Did you actually get that to work?
I didn't try it. I know that 'static' is supposed to make local delegates into nonlocal functions and figured it was worth a shot. I'll try to find some time to mess with it tomorrow. Sean
Oct 26 2005
parent John Reimer <John_member pathlink.com> writes:
In article <djpppq$12v6$1 digitaldaemon.com>, Sean Kelly says...
In article <djp8g4$fj9$1 digitaldaemon.com>, John Reimer says...
I tried that already and numerous other combinations.  Nothing worked.

Did you actually get that to work?
I didn't try it. I know that 'static' is supposed to make local delegates into nonlocal functions and figured it was worth a shot. I'll try to find some time to mess with it tomorrow. Sean
Um actually, you are correct. The problem arose elsewhere. Static is required and makes complete sense; it just won't work in the context I gave. The reason it won't work is because I was silly enough to try to access the init() functions stack variable from within the nested func1. Clearly, that stack variable fc will only last the life of the init function. Once that's run the nested function won't be accessing a vaild variable making func1 completely illegal to submit as a callback. Therefore adding static would work only if I don't try to access the init() variables. I'm afraid I was not thinking. My original idea was to encase an external function of normal D linkage (perhaps even a delegate) within a windows linkage callback that could be submitted to win32 function. My method obviously was invalid. In conclusion, adding static does the trick for func1() as long as init() stack variables aren't referenced. -JJR
Oct 27 2005
prev sibling parent "Walter Bright" <newshound digitalmars.com> writes:
"John Reimer" <John_member pathlink.com> wrote in message
news:djp8g4$fj9$1 digitaldaemon.com...
 In article <djopo5$29m$1 digitaldaemon.com>, Sean Kelly says...
In article <djoo2b$lv$1 digitaldaemon.com>, John Reimer says...
One note, though.  It won't work in it's current form.  Having the
ability
to apply extern(linkage) for nested functions is primarily useful for OS
callback methods; but as implemented right now, this is not possible
because
the nested functions are seen solely as /delegates/ not /function
pointers/.
Try this:

void init( UPDATE_EVENT_W fc )
{
 extern(Windows) int func1( int a, int b )
static extern(Windows) int func1( int a, int b ) Sean
I tried that already and numerous other combinations. Nothing worked. Did you actually get that to work?
Yes, but it's: extern (Windows) static int func1(int a, int b) ...
Oct 27 2005
prev sibling next sibling parent reply Carlos Santander <csantander619 gmail.com> writes:
Walter Bright escribió:
 A couple of oft-requested features.
 
 http://www.digitalmars.com/d/changelog.html
 
 
 
I really like the auto type declaration, but I'd like to suggest something slightly related: can't static strings be of type char[] instead of static char[length]? The problem is that this doesn't work: auto str = "hi"; str = "hello"; -- Carlos Santander Bernal
Oct 25 2005
next sibling parent "Walter Bright" <newshound digitalmars.com> writes:
"Carlos Santander" <csantander619 gmail.com> wrote in message
news:djmpd4$25oa$2 digitaldaemon.com...
 I really like the auto type declaration, but I'd like to suggest something
 slightly related: can't static strings be of type char[] instead of static
 char[length]? The problem is that this doesn't work:

 auto str = "hi";
 str = "hello";
I hear you, but it's easier to go from a static array to a dynamic array, but not vice versa. So I think making it a static array type is better.
Oct 25 2005
prev sibling parent reply Vathix <chris dprogramming.com> writes:
On Tue, 25 Oct 2005 22:19:25 -0400, Carlos Santander  
<csantander619 gmail.com> wrote:

 Walter Bright escribió:
 A couple of oft-requested features.
  http://www.digitalmars.com/d/changelog.html
I really like the auto type declaration, but I'd like to suggest something slightly related: can't static strings be of type char[] instead of static char[length]? The problem is that this doesn't work: auto str = "hi"; str = "hello";
auto str = "hi"[]; str = "hello";
Oct 25 2005
parent "Walter Bright" <newshound digitalmars.com> writes:
"Vathix" <chris dprogramming.com> wrote in message
news:op.sy8mfjbxl2lsvj esi...
 On Tue, 25 Oct 2005 22:19:25 -0400, Carlos Santander
 <csantander619 gmail.com> wrote:
 I really like the auto type declaration, but I'd like to suggest
 something slightly related: can't static strings be of type char[]
 instead of static char[length]? The problem is that this doesn't work:

 auto str = "hi";
 str = "hello";
auto str = "hi"[]; str = "hello";
I had missed that. Thanks for pointing it out.
Oct 25 2005
prev sibling next sibling parent reply "John C" <johnch_atms hotmail.com> writes:
"Walter Bright" <newshound digitalmars.com> wrote in message 
news:djjpa0$1o9n$2 digitaldaemon.com...
A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html
Superb. By introducing local type inference now, D is ahead of the while yet, and Java probably never. Coincidentally (or maybe not), "auto" also happens to be the proposed C++ syntax.
Oct 26 2005
next sibling parent "Walter Bright" <newshound digitalmars.com> writes:
"John C" <johnch_atms hotmail.com> wrote in message
news:djnapn$d2b$1 digitaldaemon.com...
 Superb. By introducing local type inference now, D is ahead of the

long
 while yet, and Java probably never.

 Coincidentally (or maybe not), "auto" also happens to be the proposed C++
 syntax.
It's auto for the same reason, "auto" is an old C keyword used for local stack variables, and this presses it into service.
Oct 26 2005
prev sibling parent reply renox <renosky free.fr> writes:
John C wrote:
 "Walter Bright" <newshound digitalmars.com> wrote in message 
 news:djjpa0$1o9n$2 digitaldaemon.com...
 
A couple of oft-requested features.

http://www.digitalmars.com/d/changelog.html
Superb. By introducing local type inference now, D is ahead of the while yet, and Java probably never. Coincidentally (or maybe not), "auto" also happens to be the proposed C++ syntax.
Just to add a 'dissenting view' Limbo (a relatively unknown language for Plan9 that I've never used but just read it's nifty syntax) had type inference for a long time.. Anyway I applaud the type inference for D which IMHO will have a profound impact on code's readability. The reuse of auto word for both type inferencing and RAII seems a bit strange, IMHO ':=' as in Limbo is the best (as it's the shortest: having nearly invisible variable declaration is a good thing, especially since in D you can't have two declaration of the same variable in a function which prevent abuse), var is nice too (it's used in Scala). Regards, Renaud. PS: Hoping that it won't be considered as trolling but I tend to think than Limbo's variable declaration syntax is more readable than D: x : int; // declares x to be of type int x : int = 5; //declares x to be of type int and initialize it to 5. x := 8; //declares x to be to the type of 8: int and initialize it to 8. This Pascal-like syntax is a bit verbose sometimes but very readable: x : array[10] of int; The advantage is that declaration and utilisation are made in the same order, contrary to D. Of course it isn't C-like, but while C has strong points some parts like its syntax to declare variable, switch/case with default fall-through, ';' instead of '{}' for empty loop/if/while (took me two days to find a bug caused by this one time), octal which starts with 0 instead of 0o are not very good..
Nov 13 2005
parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
renox wrote:
 John C wrote:
 
 Just to add a 'dissenting view' Limbo (a relatively unknown language for 
 Plan9 that I've never used but just read it's nifty syntax) had type 
 inference for a long time..
 
 Anyway I applaud the type inference for D which IMHO will have a 
 profound impact on code's readability.
I think so too.
 The reuse of auto word for both type inferencing and RAII seems a bit 
 strange, IMHO ':=' as in Limbo is the best (as it's the shortest: having 
 nearly invisible variable declaration is a good thing, especially since 
 in D you can't have two declaration of the same variable in a function 
 which prevent abuse), var is nice too (it's used in Scala).
 
 Regards,
 Renaud.
 
 PS: Hoping that it won't be considered as trolling but I tend to think 
 than Limbo's variable declaration syntax is more readable than D:
 
More readable to a compiler definitelly because there is no ambiguity in this syntax, but more readable to humans is a discutable thing.
 x : int; // declares x to be of type int
 x : int = 5; //declares x to be of type int and initialize it to 5.
 x := 8; //declares x to be to the type of 8: int and initialize it to 8.

 This Pascal-like syntax is a bit verbose sometimes but very readable:
 x : array[10] of int;
 
 The advantage is that declaration and utilisation are made in the same 
 order, contrary to D.
 Of course it isn't C-like, but while C has strong points some parts like 
  its syntax to declare variable, switch/case with default fall-through, 
 ';' instead of '{}' for empty loop/if/while (took me two days to find a 
 bug caused by this one time), octal which starts with 0 instead of 0o 
 are not very good..
Nov 13 2005
parent renox <renosky free.fr> writes:
Ivan Senji wrote:

 renox wrote:
 
 John C wrote:

 Just to add a 'dissenting view' Limbo (a relatively unknown language 
 for Plan9 that I've never used but just read it's nifty syntax) had 
 type inference for a long time..

 Anyway I applaud the type inference for D which IMHO will have a 
 profound impact on code's readability.
I think so too.
 The reuse of auto word for both type inferencing and RAII seems a bit 
 strange, IMHO ':=' as in Limbo is the best (as it's the shortest: 
 having nearly invisible variable declaration is a good thing, 
 especially since in D you can't have two declaration of the same 
 variable in a function which prevent abuse), var is nice too (it's 
 used in Scala).

 Regards,
 Renaud.

 PS: Hoping that it won't be considered as trolling but I tend to think 
 than Limbo's variable declaration syntax is more readable than D:
More readable to a compiler definitelly because there is no ambiguity in this syntax, but more readable to humans is a discutable thing.
Of course, as everything is, but I've used mostly C (that I like for small programs) / C++ (that I dislike very much) and still I find Limbo's syntax for variable declaration *very nice* to read (better than C, C++ and also better than D sorry).. Not that it matters to D: its syntax is definitely good enough for me. Regards, Renaud Hebert.
 x : int; // declares x to be of type int
 x : int = 5; //declares x to be of type int and initialize it to 5.
 x := 8; //declares x to be to the type of 8: int and initialize it to 8.

 This Pascal-like syntax is a bit verbose sometimes but very readable:
 x : array[10] of int;

 The advantage is that declaration and utilisation are made in the same 
 order, contrary to D.
 Of course it isn't C-like, but while C has strong points some parts 
 like  its syntax to declare variable, switch/case with default 
 fall-through, ';' instead of '{}' for empty loop/if/while (took me two 
 days to find a bug caused by this one time), octal which starts with 0 
 instead of 0o are not very good..
Nov 13 2005
prev sibling next sibling parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Walter Bright wrote:
 A couple of oft-requested features.
 
 http://www.digitalmars.com/d/changelog.html
Now that you're working on the compiler once again, is there any chance of an answer about these any time soon? http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/28426 http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/28449 Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Oct 26 2005
prev sibling next sibling parent reply pragma <pragma_member pathlink.com> writes:
In article <djjpa0$1o9n$2 digitaldaemon.com>, Walter Bright says...
A couple of oft-requested features.

http://www.digitalmars.com/d/changelog.html
Walter, I think others have brought this up, but there's a problem with overloading the use of 'auto' in this way. If one wants to have both RAII *and* auto-type capabilities in the same statement, it can't be done since they both use the same keyword. Might I propose moving the RAII aspect of auto out to a new keyword? How about "raii"? // code listed including your proposal for stack-allocation, for completeness auto a = new classname(); // auto-type, heap alloc auto b = classname(); // auto-type, stack alloc raii c = new classname(); // RAII, heap alloc raii d = classname(); // RAII, stack alloc auto raii e = new classname(); // auto-type, RAII, heap alloc auto raii f = classname(); // auto-type, RAII, stack alloc Also, others have mentioned a possible ambiguity with "static opCall()" and your proposal for stack-allocation. What are your thoughts on using a keyword in place of 'new' to signify stack-allocation? - EricAnderton at yahoo
Oct 26 2005
next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
pragma wrote:
 In article <djjpa0$1o9n$2 digitaldaemon.com>, Walter Bright says...
 A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html
Walter, I think others have brought this up, but there's a problem with overloading the use of 'auto' in this way. If one wants to have both RAII *and* auto-type capabilities in the same statement, it can't be done since they both use the same keyword.
<snip> You've got me wondering what practical use this auto-type facility has. Just syntactic sugar for typeof(4u) y = 4u; ? Stewart. -- -----BEGIN GEEK CODE BLOCK----- Version: 3.1 GCS/M d- s:- C++ a->--- UB P+ L E W++ N+++ o K- w++ O? M V? PS- PE- Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y ------END GEEK CODE BLOCK------ My e-mail is valid but not my primary mailbox. Please keep replies on the 'group where everyone may benefit.
Oct 26 2005
parent reply "John C" <johnch_atms hotmail.com> writes:
"Stewart Gordon" <smjg_1998 yahoo.com> wrote in message 
news:djohp1$2rnq$1 digitaldaemon.com...
 pragma wrote:
 In article <djjpa0$1o9n$2 digitaldaemon.com>, Walter Bright says...
 A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html
Walter, I think others have brought this up, but there's a problem with overloading the use of 'auto' in this way. If one wants to have both RAII *and* auto-type capabilities in the same statement, it can't be done since they both use the same keyword.
<snip> You've got me wondering what practical use this auto-type facility has. Just syntactic sugar for typeof(4u) y = 4u; ?
If it spares one from having to write the type twice -- first for the declaration, then for the initialisation -- then I think it's a welcome addition. And while it may not seem a huge deal, already I have saved time by cutting down on errors made keying in template and delegate declarations. For example, I'm often unsure which of these two is correct because the way one declares and initialises a delegate differs: delegate int(char[]) d = delegate int(char[] s) { ... }; or int delegate(char[]) d = delegate int(char[] s) { ... }; And I won't find out that the first is incorrect until I compile. But using auto I'll not have to fix and recompile: auto d = delegate int(char[] s) { ... }; Plus if I change the signature of the delegate, I need do it only in one place. I know some will disagree, but I also think this is more readable. John.
 Stewart.

 -- 
 -----BEGIN GEEK CODE BLOCK-----
 Version: 3.1
 GCS/M d- s:- C++  a->--- UB  P+ L E  W++  N+++ o K-  w++  O? M V? PS- PE- 
 Y? PGP- t- 5? X? R b DI? D G e++>++++ h-- r-- !y
 ------END GEEK CODE BLOCK------

 My e-mail is valid but not my primary mailbox.  Please keep replies on the 
 'group where everyone may benefit. 
Oct 26 2005
parent "Walter Bright" <newshound digitalmars.com> writes:
"John C" <johnch_atms hotmail.com> wrote in message
news:djokmm$2upu$1 digitaldaemon.com...
 Plus if I change the signature of the delegate, I need do it only in one
 place. I know some will disagree, but I also think this is more readable.
Right. This reduces the need for typedef's. It can also reduce bugs that happen when one changes the types in components of an initializer, but fail to correct all the uses of those components, yet with implicit conversions the error may get hidden.
Oct 27 2005
prev sibling parent "Walter Bright" <newshound digitalmars.com> writes:
"pragma" <pragma_member pathlink.com> wrote in message
news:djo2np$2995$1 digitaldaemon.com...
 I think others have brought this up, but there's a problem with
overloading the
 use of 'auto' in this way.  If one wants to have both RAII *and* auto-type
 capabilities in the same statement, it can't be done since they both use
the
 same keyword.
No, there isn't a conflict. Auto *always* makes it RAII. The initializer is another matter, though. If it's 'new', it's not RAII, if it's not 'new', it is not. There is no need at all for heap allocated objects to be RAII.
 Also, others have mentioned a possible ambiguity with "static opCall()"
and your
 proposal for stack-allocation.
I know, that has to be worked out.
 What are your thoughts on using a keyword in
 place of 'new' to signify stack-allocation?
I don't believe it's necessary.
Oct 26 2005
prev sibling next sibling parent reply Kyle Furlong <kylefurlong gmail.com> writes:
Walter Bright wrote:
 A couple of oft-requested features.
 
 http://www.digitalmars.com/d/changelog.html
 
 
 
Would the new auto declaration permit a "mode" where ALL declarations are implicitly auto? e.g. <code> x = 1; // x is int and has value 1 x = 2; // x is assigned 1 x = 1u; // Compile Error? x = new AnotherObject(); // Compile Error: x is int o1 = new MyObject(1); // o1 is MyObject o2 = new MyObject(2); // o2 is MyObject o1 = o2; // okay o1 = new AnotherObject(); // Compile Error: o1 is MyObject ao = new AnotherObject(); // okay o2 = ao; // Compile Error: o2 is MyObject </code> What could be broken in this? Well, obviously there is the issue that you cant declare a new local variable with the same name as a variable in an outer scope. Then there case where conversions are possible is another area. Another is the cases where the complier cant determine the type of the rvalue. I dont know if there are any cases of this though. Another question is is this desirable syntax? I think if you are going to use the auto type declaration, then yes it is, saves 4 keystrokes per declaration.
Oct 27 2005
next sibling parent Kyle Furlong <kylefurlong gmail.com> writes:
Kyle Furlong wrote:
 Walter Bright wrote:
 
 A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html
Would the new auto declaration permit a "mode" where ALL declarations are implicitly auto? e.g. <code> x = 1; // x is int and has value 1 x = 2; // x is assigned 1
This line should read: x = 2; // x is assigned 2
 x = 1u;              // Compile Error?
 x = new AnotherObject();     // Compile Error: x is int
 
 o1 = new MyObject(1);        // o1 is MyObject
 o2 = new MyObject(2);        // o2 is MyObject
 o1 = o2;            // okay
 o1 = new AnotherObject();    // Compile Error: o1 is MyObject
 ao = new AnotherObject();    // okay
 o2 = ao;            // Compile Error: o2 is MyObject
 
 </code>
 
 What could be broken in this? Well, obviously there is the issue that 
 you cant declare a new local variable with the same name as a variable 
 in an outer scope. Then there case where conversions are possible is 
 another area. Another is the cases where the complier cant determine the 
 type of the rvalue. I dont know if there are any cases of this though.
 
 Another question is is this desirable syntax? I think if you are going 
 to use the auto type declaration, then yes it is, saves 4 keystrokes per 
 declaration.
Oct 27 2005
prev sibling parent reply Ivan Senji <ivan.senji_REMOVE_ _THIS__gmail.com> writes:
Kyle Furlong wrote:
 Walter Bright wrote:
 
 A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html
Would the new auto declaration permit a "mode" where ALL declarations are implicitly auto? e.g. <code> x = 1; // x is int and has value 1 x = 2; // x is assigned 1 x = 1u; // Compile Error? x = new AnotherObject(); // Compile Error: x is int o1 = new MyObject(1); // o1 is MyObject o2 = new MyObject(2); // o2 is MyObject o1 = o2; // okay o1 = new AnotherObject(); // Compile Error: o1 is MyObject ao = new AnotherObject(); // okay o2 = ao; // Compile Error: o2 is MyObject </code> What could be broken in this? Well, obviously there is the issue that you cant declare a new local variable with the same name as a variable in an outer scope. Then there case where conversions are possible is another area. Another is the cases where the complier cant determine the type of the rvalue. I dont know if there are any cases of this though. Another question is is this desirable syntax? I think if you are going to use the auto type declaration, then yes it is, saves 4 keystrokes per declaration.
Syntax is great with auto because it simplifies things alot, but for x=1; to be a declaration would be a big mistake, i never liked those languages, things like that cause bugs that are really hard to find if you for example misspell something, or if you later need to find the places in code where you declare new objects it is imposible.
Oct 27 2005
parent "Walter Bright" <newshound digitalmars.com> writes:
"Ivan Senji" <ivan.senji_REMOVE_ _THIS__gmail.com> wrote in message
news:djsfm9$rr8$1 digitaldaemon.com...
 Syntax is great with auto because it simplifies things alot, but for
 x=1; to be a declaration would be a big mistake, i never liked those
 languages, things like that cause bugs that are really hard to find if
 you for example misspell something, or if you later need to find the
 places in code where you declare new objects it is imposible.
You're right. Declarations that have the same syntax as expressions or other statements lead to the classic "DO10I" bug.
Oct 28 2005
prev sibling next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
Walter Bright wrote:
 A couple of oft-requested features.
 
 http://www.digitalmars.com/d/changelog.html
 
 
 
Can we have a new warning for use of potentially uninitialized variable? I know this might cause problems with current code relying on D's default initialization values. Anyway, I have a mathematical model which makes exclusive use of the double floating-point type, and doubles are initialized to NaN in D by default. Consequently, propogating NaNs through the calculation makes it hard to track down where the first NaN came from - hence, which variable in particular was forgotten to be initialized. There are a lot of variables in this model, and debugging is not easy since it is running under Excel (from VBA) as an external Win32 DLL, so no printf tricks will track the guy down unfortunately. Anyway, I think my point still stands. Use of uninitialized variable warning, please? Or perhaps a way to trap usage of a NaN in a calculation and break into the debugger - THAT would make debugging MUCH faster, i.e. use SNANs instead of QNANs (signaling/noisy vs. quiet).
Oct 28 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"James Dunne" <james.jdunne gmail.com> wrote in message
news:djtfg6$1u2s$1 digitaldaemon.com...
 Can we have a new warning for use of potentially uninitialized variable?
   I know this might cause problems with current code relying on D's
 default initialization values.
As you say, that kinda undermines a lot of the way D is oriented.
 Anyway, I have a mathematical model which makes exclusive use of the
 double floating-point type, and doubles are initialized to NaN in D by
 default.  Consequently, propogating NaNs through the calculation makes
 it hard to track down where the first NaN came from - hence, which
 variable in particular was forgotten to be initialized.

 There are a lot of variables in this model, and debugging is not easy
 since it is running under Excel (from VBA) as an external Win32 DLL, so
 no printf tricks will track the guy down unfortunately.
When I needed to use printf in a DLL with no console, I'd have the printf write to a file. That worked well.
 Anyway, I think my point still stands.  Use of uninitialized variable
 warning, please?  Or perhaps a way to trap usage of a NaN in a
 calculation and break into the debugger - THAT would make debugging MUCH
 faster, i.e. use SNANs instead of QNANs (signaling/noisy vs. quiet).
Some strategically placed assert(!isnan(x)) expressions should help.
Oct 28 2005
parent reply James Dunne <james.jdunne gmail.com> writes:
In article <djtk8t$22lg$2 digitaldaemon.com>, Walter Bright says...
"James Dunne" <james.jdunne gmail.com> wrote in message
news:djtfg6$1u2s$1 digitaldaemon.com...
 Can we have a new warning for use of potentially uninitialized variable?
   I know this might cause problems with current code relying on D's
 default initialization values.
As you say, that kinda undermines a lot of the way D is oriented.
Well, I think the case is exceptional for IEEE floating point types in D. If I assume correctly, you've initialized them to _quiet_ NaNs so that it'd be easy to detect when they are used in their "uninitialized" state. Since the IEEE spec defines that no _signaling_ NaN will be produced by any floating point operation, and that SNaNs are strictly for assignment purposes, it seems logical to initialize floating point values to signaling NaNs instead of quiet NaNs. I'm sure you're well aware of this, and perhaps it might have been a minor oversight. However, if there was some conscious decision made as whether to use QNaNs over SNaNs I'd be interested to hear some reasoning. FWIW, I'm not that well read on the topic of the IEEE standard, but I did do my homework! =) I came across 'rumors', if you will, that supporting signaling NaNs is tough to do in implementation because I guess the spec is unclear on specific details of implementation and certain usage cases.
 Anyway, I have a mathematical model which makes exclusive use of the
 double floating-point type, and doubles are initialized to NaN in D by
 default.  Consequently, propogating NaNs through the calculation makes
 it hard to track down where the first NaN came from - hence, which
 variable in particular was forgotten to be initialized.

 There are a lot of variables in this model, and debugging is not easy
 since it is running under Excel (from VBA) as an external Win32 DLL, so
 no printf tricks will track the guy down unfortunately.
When I needed to use printf in a DLL with no console, I'd have the printf write to a file. That worked well.
Thought of doing that, yes...
 Anyway, I think my point still stands.  Use of uninitialized variable
 warning, please?  Or perhaps a way to trap usage of a NaN in a
 calculation and break into the debugger - THAT would make debugging MUCH
 faster, i.e. use SNANs instead of QNANs (signaling/noisy vs. quiet).
Some strategically placed assert(!isnan(x)) expressions should help.
Yes, but hopefully catching a floating-point exception from usage of a signaling NaN would track it down even better... ? Regards, James Dunne
Oct 28 2005
next sibling parent Georg Wrede <georg.wrede nospam.org> writes:
James Dunne wrote:

 Well, I think the case is exceptional for IEEE floating point types
 in D.  If I assume correctly, you've initialized them to _quiet_ NaNs
 so that it'd be easy to detect when they are used in their
 "uninitialized" state.  
 Since the IEEE spec defines that no
 _signaling_ NaN will be produced by any floating point operation, and
 that SNaNs are strictly for assignment purposes, it seems logical to
 initialize floating point values to signaling NaNs instead of quiet
 NaNs.
Precisely! I too missed the distinction when I last year studied NANs. For some embarrassing oversight, I never stopped to figure out exactly why there are two distinct NANs in the first place. (I guess I just vaguely assumed that it'd give more ways for the application programmer to deal with them.) Even though we have "printf debugging", this would save a considerable amount of time. And while QNANs would be propagated, SNANs should at least cause an error whenever they are stumbled upon. (This includes code that never expects to see them.)
Oct 29 2005
prev sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"James Dunne" <james.jdunne gmail.com> wrote in message
news:djun8f$1ht$1 digitaldaemon.com...
 Well, I think the case is exceptional for IEEE floating point types in D.
If I
 assume correctly, you've initialized them to _quiet_ NaNs so that it'd be
easy
 to detect when they are used in their "uninitialized" state.  Since the
IEEE
 spec defines that no _signaling_ NaN will be produced by any floating
point
 operation, and that SNaNs are strictly for assignment purposes, it seems
logical
 to initialize floating point values to signaling NaNs instead of quiet
NaNs.
 I'm sure you're well aware of this, and perhaps it might have been a minor
 oversight.  However, if there was some conscious decision made as whether
to use
 QNaNs over SNaNs I'd be interested to hear some reasoning.
I essentially gave up on the SNAN/QNAN distinction because it was too often unsupported.
 FWIW, I'm not that well read on the topic of the IEEE standard, but I did
do my
 homework! =)  I came across 'rumors', if you will, that supporting
signaling
 NaNs is tough to do in implementation because I guess the spec is unclear
on
 specific details of implementation and certain usage cases.
It isn't hard to do the implementation. The hard thing is that too much software out there ignores the distinction, and nearly all documentation makes no distinction. It's just too frustrating.
When I needed to use printf in a DLL with no console, I'd have the printf
write to a file. That worked well.
Thought of doing that, yes...
 Anyway, I think my point still stands.  Use of uninitialized variable
 warning, please?  Or perhaps a way to trap usage of a NaN in a
 calculation and break into the debugger - THAT would make debugging
MUCH
 faster, i.e. use SNANs instead of QNANs (signaling/noisy vs. quiet).
Some strategically placed assert(!isnan(x)) expressions should help.
Yes, but hopefully catching a floating-point exception from usage of a
signaling
 NaN would track it down even better... ?
No, all the signal does is set a flag FE_EXCEPT. Not too useful.
Oct 29 2005
parent reply Georg Wrede <georg.wrede nospam.org> writes:
Walter Bright wrote:
 It isn't hard to do the implementation. The hard thing is that too
 much software out there ignores the distinction, and nearly all
 documentation makes no distinction. It's just too frustrating.
...
 NaN would track it down even better... ?
No, all the signal does is set a flag FE_EXCEPT. Not too useful.
Hmm. Seems to me inserting tests for FE_EXCEPT and then throwing wouldn't bee too hard? Of course it would slow non-release floating point code significantly, but I don't see that as a major problem. Granted, if we use bad (non-D) libraries, then we're out of luck, but the point here is to make it easy to write robust floating point libraries in D. As well as robust applications. Somehow I can't help feeling this should be easier to implement than bounds checking. Or then I've misunderstood something. :-)
Oct 29 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Georg Wrede" <georg.wrede nospam.org> wrote in message
news:4363EFF5.20203 nospam.org...
 No, all the signal does is set a flag FE_EXCEPT. Not too useful.
Hmm. Seems to me inserting tests for FE_EXCEPT and then throwing wouldn't bee too hard? Of course it would slow non-release floating point code significantly, but I don't see that as a major problem.
No, it wouldn't be too hard. But it wouldn't be any easier than doing assert(!isnan(x));
 Granted, if we use bad (non-D) libraries, then we're out of luck, but
 the point here is to make it easy to write robust floating point
 libraries in D. As well as robust applications.

 Somehow I can't help feeling this should be easier to implement than
 bounds checking. Or then I've misunderstood something. :-)
Oct 30 2005
next sibling parent Georg Wrede <georg.wrede nospam.org> writes:
Walter Bright wrote:
 "Georg Wrede" <georg.wrede nospam.org> wrote in message
 news:4363EFF5.20203 nospam.org...
 
No, all the signal does is set a flag FE_EXCEPT. Not too useful.
Hmm. Seems to me inserting tests for FE_EXCEPT and then throwing wouldn't bee too hard? Of course it would slow non-release floating point code significantly, but I don't see that as a major problem.
No, it wouldn't be too hard. But it wouldn't be any easier than doing assert(!isnan(x));
So, the bright boy from the plains asks the weathered seaman "we'd need a power winch at this point on the deck" and the seaman answers "you'd only need it late in the afternoon when everybody is drunk, or at night in the storm when everybody is too exhausted to think clearly". I step back.
Granted, if we use bad (non-D) libraries, then we're out of luck, but
the point here is to make it easy to write robust floating point
libraries in D. As well as robust applications.

Somehow I can't help feeling this should be easier to implement than
bounds checking. Or then I've misunderstood something. :-)
Oct 30 2005
prev sibling parent reply James Dunne <james.jdunne gmail.com> writes:
Walter Bright wrote:
 "Georg Wrede" <georg.wrede nospam.org> wrote in message
 news:4363EFF5.20203 nospam.org...
 
No, all the signal does is set a flag FE_EXCEPT. Not too useful.
Hmm. Seems to me inserting tests for FE_EXCEPT and then throwing wouldn't bee too hard? Of course it would slow non-release floating point code significantly, but I don't see that as a major problem.
No, it wouldn't be too hard. But it wouldn't be any easier than doing assert(!isnan(x));
That'd get real ugly, real quick. Especially when you have complex lines of code that are using vectors of doubles with operator overloads. Granted, the assert statement could go in the vector's operator overloads, but still the problem remains for complex lines of floating-point calculations... Let me fabricate an example from a line of my code: debug { assert(!isnan(a)); assert(!isnan(b)); assert(!isnan(c)); assert(!isnan(d)); assert(!isnan(e)); assert(!isnan(f)); } T = (a * b + c*d + (a * (e - b) + (e - c) * d) / f) * (1.0 / (a + d)); (the variable names have been changed to protect intellectual property and to disguise any actual meaning of the calculation) Anyway, this is just one of a few hundred lines of calculations in the model, and requiring that block of 6 assert lines to be called before each line (worst-case scenario of course) is a bit overwhelming. In reality, you'd only have to check the inputs as they come into the function with a nice contract - but to be honest, I never have used DbC and completely forget that they exist. The way I see it, there are 2 possible solutions here: 1) Have compiler throw in assert(!isnan(x)) statements automatically under debug build (possibly with additional compiler switch) before each floating-point operation 2) Switch default QNaN initialization to SNaN and check FE_EXCEPT flag after each floating-point operation to throw a FloatingPointException (again under debug build possibly with additional compiler switch) Are you sure that FE_EXCEPT flag is the only thing that happens when a SNaN is hit? Isn't there a hardware interrupt tied in somewhere for this sort of thing? Throwing up a flag is nice and all, but quite useless if it must be checked explicitly after each floating-point operation... I think the implicit assert statement is a good option if the hardware end seems to fall apart. It'd be no worse than implicit array bounds checking. And like George said, it's only in debug mode. It would certainly lighten the load from the programmer off to the compiler.
 
Granted, if we use bad (non-D) libraries, then we're out of luck, but
the point here is to make it easy to write robust floating point
libraries in D. As well as robust applications.

Somehow I can't help feeling this should be easier to implement than
bounds checking. Or then I've misunderstood something. :-)
Oct 31 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
James Dunne wrote:
 
 Are you sure that FE_EXCEPT flag is the only thing that happens when a 
 SNaN is hit?  Isn't there a hardware interrupt tied in somewhere for 
 this sort of thing?  Throwing up a flag is nice and all, but quite 
 useless if it must be checked explicitly after each floating-point 
 operation...
The C standard says that floating point exceptions should be handled in a similar fashion to exceptions raised by arithmetic exceptions, thus any traps the system supports should be called by feraiseexcept. I know the Sun compiler can be set to behave this way, and I believe it can be turned off by specifying that quiet NaNs should be used (fuzzy on the details, I only saw mention of all this in their header files). I'm not sure how much granularity might be useful, but it would probably no be terribly difficult to provide a mask that indicates which exceptions should throw/signal and which should not. I'll check the IA-32 docs and see if I can find some more info on this. My experience with floating point at this level is very limited. Sean
Oct 31 2005
parent reply Sean Kelly <sean f4.ca> writes:
It turns out that x86 does define a set of floating point exceptions, 
and these are handled just like divide by zero and such.  At a glance, I 
think exception handling support for this could be built into Phobos, 
likely by modifying internal/deh.c.  I need to read up a bit on 
structured exception handling, but I'll play with this a bit and see 
what I can work out.  I don't know offhand if it will conflict with how 
the DM C library handles floating point exceptions though, perhaps 
Walter can tell us?


Sean
Oct 31 2005
parent James Dunne <james.jdunne gmail.com> writes:
Sean Kelly wrote:
 It turns out that x86 does define a set of floating point exceptions, 
 and these are handled just like divide by zero and such.  At a glance, I 
 think exception handling support for this could be built into Phobos, 
 likely by modifying internal/deh.c.  I need to read up a bit on 
 structured exception handling, but I'll play with this a bit and see 
 what I can work out.  I don't know offhand if it will conflict with how 
 the DM C library handles floating point exceptions though, perhaps 
 Walter can tell us?
 
 
 Sean
Exactly! Setting the signaling NaN to raise an exception should *NOT* adversely affect any previously existing code, unless such code *explicitly* makes use of signaling NaNs. Most uses of NaNs are quiet. This is why the distinction exists. If the signaling NaN is not set to raise an exception, then there is effectively no difference between signaling and quiet NaNs (aside from simply setting the FE_INVALID flag, but even that is rarely checked).
Nov 03 2005
prev sibling parent reply "Walter Bright" <newshound digitalmars.com> writes:
"James Dunne" <james.jdunne gmail.com> wrote in message
news:dk5ncl$1hp0$1 digitaldaemon.com...
 That'd get real ugly, real quick.  Especially when you have complex
 lines of code that are using vectors of doubles with operator overloads.
   Granted, the assert statement could go in the vector's operator
 overloads, but still the problem remains for complex lines of
 floating-point calculations...  Let me fabricate an example from a line
 of my code:

 debug {
 assert(!isnan(a));
 assert(!isnan(b));
 assert(!isnan(c));
 assert(!isnan(d));
 assert(!isnan(e));
 assert(!isnan(f));
 }
 T = (a * b + c*d + (a * (e - b) + (e - c) * d) / f) * (1.0 / (a + d));

 (the variable names have been changed to protect intellectual property
 and to disguise any actual meaning of the calculation)
What I'd to is just add: assert(!isnan(T)). Then, only if it trips, would I worry about which one it is.
 Anyway, this is just one of a few hundred lines of calculations in the
 model, and requiring that block of 6 assert lines to be called before
 each line (worst-case scenario of course) is a bit overwhelming.  In
 reality, you'd only have to check the inputs as they come into the
 function with a nice contract - but to be honest, I never have used DbC
 and completely forget that they exist.

 The way I see it, there are 2 possible solutions here:

 1) Have compiler throw in assert(!isnan(x)) statements automatically
 under debug build (possibly with additional compiler switch) before each
 floating-point operation
NaN is a useful value in its own right, especially when doing data collection. You don't want to throw out your entire data set because of a few known bad values (such as data from a space probe, or data from a camera with a few stuck pixels). You only want to know if your output is affected by those bad values. NaN fits the bill perfectly. (In digital electronics, one normally deals with True, False, and Don't Know. NaN corresponds to the Don't Know state.) Implementing "nans-are-bugs" would preclude D from being useful for a significant problem space.
 2) Switch default QNaN initialization to SNaN and check FE_EXCEPT flag
 after each floating-point operation to throw a FloatingPointException
 (again under debug build possibly with additional compiler switch)

 Are you sure that FE_EXCEPT flag is the only thing that happens when a
 SNaN is hit?
Yes (actually, it's FE_INVALID). A qnan does not set FE_INVALID.
 Isn't there a hardware interrupt tied in somewhere for
 this sort of thing?  Throwing up a flag is nice and all, but quite
 useless if it must be checked explicitly after each floating-point
 operation...
It's possible to configure the hardware to do that. I don't know if such is supported by Win32 or Linux, though. I'd also caution against it, because all sorts of floating point code will start failing, as that isn't expected behavior.
Nov 01 2005
next sibling parent reply Sean Kelly <sean f4.ca> writes:
Walter Bright wrote:
 
 NaN is a useful value in its own right, especially when doing data
 collection. You don't want to throw out your entire data set because of a
 few known bad values (such as data from a space probe, or data from a camera
 with a few stuck pixels). You only want to know if your output is affected
 by those bad values. NaN fits the bill perfectly. (In digital electronics,
 one normally deals with True, False, and Don't Know. NaN corresponds to the
 Don't Know state.) Implementing "nans-are-bugs" would preclude D from being
 useful for a significant problem space.
I agree. Were this to be implemented it should be purely optional. I've never felt the need for this feature myself, but if it's not too hard to do, perhaps it could be a compile or run-time option?
Isn't there a hardware interrupt tied in somewhere for
this sort of thing?  Throwing up a flag is nice and all, but quite
useless if it must be checked explicitly after each floating-point
operation...
It's possible to configure the hardware to do that. I don't know if such is supported by Win32 or Linux, though. I'd also caution against it, because all sorts of floating point code will start failing, as that isn't expected behavior.
Win32 supports at least some of the FP exceptions through SEH, but divide by zero was the only one I saw listed in the Win32 docs that seemed particularly useful and D already supports that one. I couldn't say whether Linux supports this, but I imagine it does. Sean
Nov 01 2005
parent "Walter Bright" <newshound digitalmars.com> writes:
"Sean Kelly" <sean f4.ca> wrote in message
news:dk914a$1afm$1 digitaldaemon.com...
 Walter Bright wrote:
 NaN is a useful value in its own right, especially when doing data
 collection. You don't want to throw out your entire data set because of
a
 few known bad values (such as data from a space probe, or data from a
camera
 with a few stuck pixels). You only want to know if your output is
affected
 by those bad values. NaN fits the bill perfectly. (In digital
electronics,
 one normally deals with True, False, and Don't Know. NaN corresponds to
the
 Don't Know state.) Implementing "nans-are-bugs" would preclude D from
being
 useful for a significant problem space.
I agree. Were this to be implemented it should be purely optional. I've never felt the need for this feature myself, but if it's not too hard to do, perhaps it could be a compile or run-time option?
C and C++ are loaded up with compiler switches that change the meaning of the language. I really want to do my best to avoid this. In the end, it does the users a disservice because they can't rely on consistent semantics.
Nov 01 2005
prev sibling next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
Walter Bright wrote:
 "James Dunne" <james.jdunne gmail.com> wrote in message
 news:dk5ncl$1hp0$1 digitaldaemon.com...
 
That'd get real ugly, real quick.  Especially when you have complex
lines of code that are using vectors of doubles with operator overloads.
  Granted, the assert statement could go in the vector's operator
overloads, but still the problem remains for complex lines of
floating-point calculations...  Let me fabricate an example from a line
of my code:

debug {
assert(!isnan(a));
assert(!isnan(b));
assert(!isnan(c));
assert(!isnan(d));
assert(!isnan(e));
assert(!isnan(f));
}
T = (a * b + c*d + (a * (e - b) + (e - c) * d) / f) * (1.0 / (a + d));

(the variable names have been changed to protect intellectual property
and to disguise any actual meaning of the calculation)
What I'd to is just add: assert(!isnan(T)). Then, only if it trips, would I worry about which one it is.
Anyway, this is just one of a few hundred lines of calculations in the
model, and requiring that block of 6 assert lines to be called before
each line (worst-case scenario of course) is a bit overwhelming.  In
reality, you'd only have to check the inputs as they come into the
function with a nice contract - but to be honest, I never have used DbC
and completely forget that they exist.

The way I see it, there are 2 possible solutions here:

1) Have compiler throw in assert(!isnan(x)) statements automatically
under debug build (possibly with additional compiler switch) before each
floating-point operation
NaN is a useful value in its own right, especially when doing data collection. You don't want to throw out your entire data set because of a few known bad values (such as data from a space probe, or data from a camera with a few stuck pixels). You only want to know if your output is affected by those bad values. NaN fits the bill perfectly. (In digital electronics, one normally deals with True, False, and Don't Know. NaN corresponds to the Don't Know state.) Implementing "nans-are-bugs" would preclude D from being useful for a significant problem space.
2) Switch default QNaN initialization to SNaN and check FE_EXCEPT flag
after each floating-point operation to throw a FloatingPointException
(again under debug build possibly with additional compiler switch)

Are you sure that FE_EXCEPT flag is the only thing that happens when a
SNaN is hit?
Yes (actually, it's FE_INVALID). A qnan does not set FE_INVALID.
Isn't there a hardware interrupt tied in somewhere for
this sort of thing?  Throwing up a flag is nice and all, but quite
useless if it must be checked explicitly after each floating-point
operation...
It's possible to configure the hardware to do that. I don't know if such is supported by Win32 or Linux, though. I'd also caution against it, because all sorts of floating point code will start failing, as that isn't expected behavior.
How can I catch an assert from a DLL using WinDbg? From what I've seen, WinDbg doesn't break on D's exceptions, unless they're serious enough like an Access Violation.
Nov 03 2005
parent Sean Kelly <sean f4.ca> writes:
James Dunne wrote:
 
 How can I catch an assert from a DLL using WinDbg?  From what I've seen, 
 WinDbg doesn't break on D's exceptions, unless they're serious enough 
 like an Access Violation.
I think you either need to override the assert handler or put a breakpoint there (Ares makes it easy to do this). Do a search in phobos/internal for "_d_assert." The easiest thing is just to add a divide by zero or an asm { int 3; } statement. Sean
Nov 03 2005
prev sibling parent reply Georg Wrede <georg.wrede nospam.org> writes:
Walter Bright wrote:
 "James Dunne" <james.jdunne gmail.com> 

 Isn't there a hardware interrupt tied in somewhere for this sort of
 thing?  Throwing up a flag is nice and all, but quite useless if it
 must be checked explicitly after each floating-point operation...
It's possible to configure the hardware to do that. I don't know if such is supported by Win32 or Linux, though. I'd also caution against it, because all sorts of floating point code will start failing, as that isn't expected behavior.
I don't understand the problem. Suppose my code wants to use a hardware interrupt with FPU ops. Then, first my code sets up a handler, then turns on the interrupt. Now, if an interrupt occurs, then my code gets executed. Any other code running simultaneously on the (windows or linux) machine, gets the FPU flags set its own way whenever a process switch takes place. Therefore, the other code is oblivious of my FPU interrupt settings, right? So, we're back to if I use sloppy 3rd party libraries from my D code, and they choke on SNANs. But then, my handler gets executed anyway, which is what I'd want all along. And any new process starting on the machine gets the FPU reset, flags and all. So, I still don't see the problem. Additionally, how my code uses the FPU should not interest the OS, right? If I crap up my calculations, as long as I have installed the interrupt handler, nothing disturbs anybody else. Unless of course, Windows _prevents_ me from doing that, or deliberately interferes. But even I am not paranoid enough to really suspect that.
Nov 03 2005
next sibling parent Sean Kelly <sean f4.ca> writes:
Georg Wrede wrote:
 Walter Bright wrote:
 
 "James Dunne" <james.jdunne gmail.com>

 Isn't there a hardware interrupt tied in somewhere for this sort of
 thing?  Throwing up a flag is nice and all, but quite useless if it
 must be checked explicitly after each floating-point operation...
It's possible to configure the hardware to do that. I don't know if such is supported by Win32 or Linux, though. I'd also caution against it, because all sorts of floating point code will start failing, as that isn't expected behavior.
I don't understand the problem. Suppose my code wants to use a hardware interrupt with FPU ops. Then, first my code sets up a handler, then turns on the interrupt. Now, if an interrupt occurs, then my code gets executed.
I think the issue is that this is something that is supposed to be done through the OS rather than setting hardware traps directly--see the IA-32 docs on floating point exceptions for more information. But you're right about the behavior.
 Any other code running simultaneously on the (windows or linux) machine, 
 gets the FPU flags set its own way whenever a process switch takes 
 place. Therefore, the other code is oblivious of my FPU interrupt 
 settings, right?
Yes.
 Additionally, how my code uses the FPU should not interest the OS, 
 right? If I crap up my calculations, as long as I have installed the 
 interrupt handler, nothing disturbs anybody else.
It's just like a divide by zero error (which is also a hardware exception) The only thing that happens is that the OS halts your app, often triggering a debugger if one is active. Sean
Nov 03 2005
prev sibling parent "Walter Bright" <newshound digitalmars.com> writes:
"Georg Wrede" <georg.wrede nospam.org> wrote in message
news:436A5D7A.4020102 nospam.org...
 So, we're back to if I use sloppy 3rd party libraries from my D code,
 and they choke on SNANs. But then, my handler gets executed anyway,
 which is what I'd want all along.
I wouldn't call it sloppy, because SNANs have simply (and unfortunately) not been endorsed by the standards that matter, and so code doesn't take the difference between SNAN and QNAN into account. This includes C, and D is supposed to conform to the C ABI.
Nov 06 2005
prev sibling parent reply Burton Radons <burton-radons smocky.com> writes:
Walter Bright wrote:
 A couple of oft-requested features.
 
 http://www.digitalmars.com/d/changelog.html
Scoping access rights broke: class A { class B { protected this () { } } } int main () { new A.B (); return 0; } This fails compilation in Linux with "class f.A.B member this is not accessible". It worked before.
Nov 04 2005
parent reply "Walter Bright" <newshound digitalmars.com> writes:
"Burton Radons" <burton-radons smocky.com> wrote in message
news:dkgtc4$4oi$1 digitaldaemon.com...
 Walter Bright wrote:
 A couple of oft-requested features.

 http://www.digitalmars.com/d/changelog.html
Scoping access rights broke: class A { class B { protected this () { } } } int main () { new A.B (); return 0; } This fails compilation in Linux with "class f.A.B member this is not accessible". It worked before.
I believe the compiler is correct, as protected means that only derived classes can access it. main() is not a member of a class derived from B, so it cannot create an instance of B, because B's constructor is protected.
Nov 05 2005
parent reply Burton Radons <burton-radons smocky.com> writes:
Walter Bright wrote:
 "Burton Radons" <burton-radons smocky.com> wrote in message
 news:dkgtc4$4oi$1 digitaldaemon.com...
 
Walter Bright wrote:

A couple of oft-requested features.

http://www.digitalmars.com/d/changelog.html
Scoping access rights broke: class A { class B { protected this () { } } } int main () { new A.B (); return 0; } This fails compilation in Linux with "class f.A.B member this is not accessible". It worked before.
I believe the compiler is correct, as protected means that only derived classes can access it. main() is not a member of a class derived from B, so it cannot create an instance of B, because B's constructor is protected.
You forget your language. :) Private and protected members are accessible throughout the module they've been declared in: "Private means that only members of the enclosing class can access the member, or members and functions in the same module as the enclosing class. Private members cannot be overridden. ... Protected means that only members of the enclosing class or any classes derived from that class, or members and functions in the same module as the enclosing class, can access the member." (http://www.digitalmars.com/d/attribute.html under Protection Attribute)
Nov 05 2005
parent "Walter Bright" <newshound digitalmars.com> writes:
"Burton Radons" <burton-radons smocky.com> wrote in message news:dkil5i$1o40
 You forget your language.  :)  Private and protected members are
 accessible throughout the module they've been declared in:
You're right. I'll fix the bug.
Nov 06 2005