clash-lang / clash-compiler

Haskell to VHDL/Verilog/SystemVerilog compiler
https://clash-lang.org/
Other
1.4k stars 147 forks source link

Improve ranges in error messages #2733

Closed DigitalBrains1 closed 3 days ago

DigitalBrains1 commented 3 weeks ago

We sometimes mention the valid range of an out-of-range input in error messages. However, if the range is actually empty, the message is rather garbled. Additionally, we sometimes format them like [upper bound..lower bound] which probably originates from the order of bit indices (highest indices on the left), but it might be confusing.

This PR changes the messages from:

>>> replaceBit 0 1 (0 :: BitVector 0)
*** Exception: replaceBit: 0 is out of range [-1..0]
[...]
>>> replaceBit 1 1 (0 :: BitVector 1)
*** Exception: replaceBit: 1 is out of range [0..0]
[...]
>>> replaceBit 6 0 (-5 :: Signed 6)
*** Exception: replaceBit: 6 is out of range [5..0]
[...]
>>> testBit (-5 :: Signed 6) 6
*** Exception: (!): 6 is out of range [5..0]
[...]
>>> checkedFromIntegral 1 :: Unsigned 0
*** Exception: Given integral 1 is out of bounds for target type. Bounds of target type are: [0..0].
[...]
>>> 1 :: Index 0
*** Exception: X: Clash.Sized.Index: result 1 is out of bounds: [0..-1]
[...]

to:

>>> replaceBit 0 1 (0 :: BitVector 0)
*** Exception: replaceBit: 0 is out of range <empty range>
[...]
>>> replaceBit 1 1 (0 :: BitVector 1)
*** Exception: replaceBit: 1 is out of range [0]
[...]
>>> replaceBit 6 0 (-5 :: Signed 6)
*** Exception: replaceBit: 6 is out of range [0..5]
[...]
>>> testBit (-5 :: Signed 6) 6
*** Exception: (!): 6 is out of range [0..5]
[...]
>>> checkedFromIntegral 1 :: Unsigned 0
*** Exception: Given integral 1 is out of bounds for target type. Bounds of target type are: [0].
[...]
>>>  1 :: Index 0
*** Exception: X: Clash.Sized.Index: result 1 is out of bounds: <empty range>
[...]

I also changed these:

>>> import qualified Data.Ix as Ix
>>> Ix.index @(Unsigned 8) (0,42) 43
*** Exception: Index 43 out of bounds (0, 42) ab
[...]
>>> Ix.index @(Signed 8) (0,42) 43
*** Exception: Index 43 out of bounds (0, 42) ab
[...]
>>> Ix.index @(Index 256) (0,42) 43
*** Exception: Index 43 out of bounds (0, 42)
[...]

to be the same as upstream:

>>> Ix.index @Int (0,42) 43
*** Exception: Ix{Int}.index: Index (43) out of range ((0,42))
>>> Ix.index @(Unsigned 8) (0,42) 43
*** Exception: Index (43) out of range ((0, 42))
CallStack (from HasCallStack):
  error, called at src/Clash/Sized/Internal/Unsigned.hs:797:19 in clash-prelude-1.9.0-inplace:Clash.Sized.Internal.Unsigned
[...etcetera...]

I'm not completely enamoured of the double parentheses, but I do love consistency (note we have a call stack though).

Still TODO: