-- This corresponds to src/comp/IntegerUtil.hs in bsc.
module Language.Bluespec.IntegerUtil
  ( integerFormat
  , integerFormatPref
  , integerToString
  ) where

import Language.Bluespec.Prelude

integerFormat :: Integer -> Integer -> Integer -> String
integerFormat :: Integer -> Integer -> Integer -> String
integerFormat Integer
width Integer
base Integer
value =
        if Integer
value Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 then
                Char
'-' Char -> String -> String
forall a. a -> [a] -> [a]
: Integer -> Integer -> Integer -> String
integerFormat Integer
width Integer
base (-Integer
value)
        else
                let s :: String
s = Int -> Integer -> String
integerToString (Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
base) Integer
value
                    l :: Int
l = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s
                    w :: Int
w = Integer -> Int
forall a. Num a => Integer -> a
fromInteger Integer
width
                    pad :: String
pad = if Int
l Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
w then Int -> Char -> String
forall a. Int -> a -> [a]
replicate (Int
wInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
l) Char
'0' else String
""
                in  String
pad String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s

integerFormatPref :: Integer -> Integer -> Integer -> String
integerFormatPref :: Integer -> Integer -> Integer -> String
integerFormatPref Integer
width  Integer
2 Integer
value = String
"0b" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> Integer -> Integer -> String
integerFormat Integer
width  Integer
2 Integer
value
integerFormatPref Integer
width  Integer
8 Integer
value = String
"0o" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> Integer -> Integer -> String
integerFormat Integer
width  Integer
8 Integer
value
integerFormatPref Integer
width Integer
10 Integer
value =         Integer -> Integer -> Integer -> String
integerFormat Integer
width Integer
10 Integer
value
integerFormatPref Integer
width Integer
16 Integer
value = String
"0x" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Integer -> Integer -> Integer -> String
integerFormat Integer
width Integer
16 Integer
value
-- otherwise, use decimal
integerFormatPref Integer
width  Integer
_ Integer
value = Integer -> Integer -> Integer -> String
integerFormatPref Integer
width Integer
10 Integer
value

integerToString :: Int -> Integer -> String
integerToString :: Int -> Integer -> String
integerToString Int
b Integer
i | Int
b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2      =  String -> String
forall a. HasCallStack => String -> a
error String
"integerToString: base must be >= 2"
                    | Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0      =  Char
'-' Char -> String -> String
forall a. a -> [a] -> [a]
: Integer -> Integer -> String -> String
showIntBase (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
b) (Integer -> Integer
forall a. Num a => a -> a
negate Integer
i) String
""
                    | Bool
otherwise  =  Integer -> Integer -> String -> String
showIntBase (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
b) Integer
i String
""

-- mostly duplicates the function in the Prelude from the Haskell 98 Report
showIntBase :: Integer -> Integer -> String -> String
showIntBase :: Integer -> Integer -> String -> String
showIntBase Integer
b Integer
n String
r | Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0 = String -> String
forall a. HasCallStack => String -> a
error String
"Numeric.showInt: can't show negative numbers"
                  | Bool
otherwise =
                      let (Integer
n',Integer
d) = Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
quotRem Integer
n Integer
b
                          r' :: String
r'     = Integer -> Char
forall {a} {a}. (Integral a, Enum a) => a -> a
digit Integer
d Char -> String -> String
forall a. a -> [a] -> [a]
: String
r
                          digit :: a -> a
digit a
d' | a
d' a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
10     =  Int -> a
forall a. Enum a => Int -> a
toEnum (Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
'0' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
d')
                                   | Bool
otherwise   =  Int -> a
forall a. Enum a => Int -> a
toEnum (Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
'A' Int -> Int -> Int
forall a. Num a => a -> a -> a
+ a -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
d' Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
10)
                      in  if Integer
n' Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 then String
r' else Integer -> Integer -> String -> String
showIntBase Integer
b Integer
n' String
r'