Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DivideByZero exception has conflicting attributes #434

Open
coke opened this issue Jul 23, 2024 · 5 comments
Open

DivideByZero exception has conflicting attributes #434

coke opened this issue Jul 23, 2024 · 5 comments
Labels
language Changes to the Raku Programming Language

Comments

@coke
Copy link
Contributor

coke commented Jul 23, 2024

While roast only seems to check the type of the exception, current rakudo has 3 attributes:

  • numerator
  • using
  • details

Checking where the exception is thrown by rakudo, it seems to either be a numerator/using pair, the single attribute details, or nothing. We should be consistent in usage and probably select numerator and using, remove details, and ensure that wherever we throw the exception, we include the information.

Because there is no testing of these attributes in roast, we could do this as an implementation detail in existing rakudo, but I would recommend implementing it as a 6.e feature and then testing the attributes in roast for 6.e

@coke coke added the language Changes to the Raku Programming Language label Jul 23, 2024
@raiph
Copy link

raiph commented Jul 23, 2024

I'm on vacation, and can't yet give this full attention, but Raku's DBZ, successes, failures, DBZ exceptions, ....

@librasteve
Copy link

librasteve commented Jul 29, 2024

[please can you point to the source and I would be happy to try and grok the intent if I can]

for a long time IEEE P754 has given us valid values for the results of DBZ
these were provided to allow pipelined vector FPU ops to succeed (even if an interim result was Inf or NaN)
raku, uniquely [afaik], seeks to bridge this idea with Rats which can have a 0 denominator unless collapsed eg into a Str

following raiph's pointer to the docs on ZBRs, I see that this is OK:

say  <1/0>.Num;   # OUTPUT: «Inf␤» 
say <-1/0>.Num;   # OUTPUT: «-Inf␤» 
say  <0/0>.Num;   # OUTPUT: «NaN␤» 
say Inf.Rat.nude; # OUTPUT: «(1 0)␤» 

yet this is an error:

say <1/0>;
# Attempt to divide by zero when coercing Rational to Str in ...

my guess on the error attributes is:

  • numerator is the numerator
  • using is the denominator
  • details reveals the mechanism, such as
    • was the divide attempt in the CPU or the FPU
    • am I collapsing a Rat or reading across an extant FPU ±Inf
    • was the operation div, /, .Str (yes stringifying a Rat will try to print eg. a decimal)

@coke
Copy link
Contributor Author

coke commented Jul 29, 2024

You can find all the instances (though you'll have to look at the source because many of these are part of a multi-line invocation) with

$ cd rakudo
$ ack 'X::Numeric::DivideByZero' src

numerator is the numerator (only ever specified with using). using is typically the operator that was called (e.g. div). There's no need to specify the denominator... because it's 0.

details is just plain text describing the situation, e.g.:

  • when calling .$what on Rational
  • when coercing Rational to Str

There is nothing in the current usage of rakudo or roast that requires details over the numerator/using combo. Both of the examples above are easily translatable (esp. since using is just free text)

There is no tie in to the CPU/FPU operations here.

@lizmat
Copy link
Collaborator

lizmat commented Jul 29, 2024

s/ack/rak/ ?? :-)

@librasteve
Copy link

@coke thanks for clarifying my guess - looks like the info I guessed at is split between the using and details field (as you say no need for denominator - red face)

Based on this, I see no issue in keeping the fields as they are since both the using (ie the operator) and the details (ie when doing what) seem useful for debugging. The ZBRs are a quite thorny and unique(?) to raku so for me at least finding any extra hint is very valuable to work out what is happening.

On the FPU, apologies if I did not explain myself carefully, but the situation I wanted to clarify (at least to my own satisfaction) is that where this is a thing:

say  <1/0>.Num;   # OUTPUT: «Inf␤» 
say  <1/0>.Num.WHAT;   # OUTPUT: «(Num)␤» 

And this (although you can't make a string from it):

say  <1/0>.Num.Rat.WHAT;   # OUTPUT: «(Rat)␤» 

Then, from a raku coder POV a valid mental model is that this is a divide by zero "non-failure" aka a ZBR that is made by creating a Inf (ie. by coercing a ZBR to an IEEE P754 Inf in the FPU since Num s are doubles) and then coercing it back to a Rat which as a construct of Ints lives in the CPU.

And I can make the identical thing via an FPU overflow like this:

say 1.7976931348623157e309;  # OUTPUT: «Inf␤» 
say 1.7976931348623157e309 === <1/0>.Num; # OUTPUT: «True␤» 

My point is that when you have done a bunch of P754 coding then it is most natural to think of Inf (aka the result of a DBZ op) as a creature of the FPU. This is the design of raku Num and the cool thing is the "interop" between Num and Rat - but also a source of potential complexity around DBZ behaviours.

So, obviously this would work too:

say (1e0/0e0).Rat; # OUTPUT: «Attempt to divide 1 by zero using /␤»...

.oO Realises that raku still supports DBZ exceptions in the FPU. Probably have to monkey with the compiler directives to put FPU in the "don't raise exception" mode atm. Would be nice to have that control on the same footing as eg my $*RAT-OVERFLOW one day.

It took me a while to realise that this Failure is from an FPU exception so maybe the details field could mention that? At least if not for now, then maybe this is the kind of nuanced message that could be put in details in future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language Changes to the Raku Programming Language
Projects
None yet
Development

No branches or pull requests

4 participants