November 02, 2005
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
November 03, 2005
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.
November 03, 2005
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).
November 03, 2005
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.
November 03, 2005
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
November 03, 2005
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
November 05, 2005
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.
November 05, 2005
"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.


November 05, 2005
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)
November 06, 2005
"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.