{-|
  Copyright   :  (C) 2012-2016, University of Twente,
                     2016     , Myrtle Software Ltd,
                     2017     , Google Inc.,
                     2021     , QBayLogic B.V.
  License     :  BSD2 (see the file LICENSE)
  Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>

  Term Literal
-}

{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Clash.Core.Literal
  ( Literal (..)
  ) where

import Control.DeepSeq                        (NFData (..))
import Data.Binary                            (Binary)
import Data.Hashable                          (Hashable)
import Data.Primitive.ByteArray               (ByteArray)
import Data.Primitive.ByteArray.Extra         ()
import Data.Word                              (Word32, Word64)
import GHC.Generics                           (Generic)

{-
Note [Storage of floating point in Literal]
-------------------------------------------

GHC stores literals of 'Float' and 'Double' as 'Rational'. However, unlike
GHC, we also need to store transfinite "literals". We need to preserve all
information there is in a specific code word representing a floating point
value.

Storing them as 'Float' and 'Double' here introduces issues with 'Eq' and
'Hashable'. 0.0 == -0.0, and NaN compares unequal to everything including
itself.

Also unlike GHC, we already assume that 'Float' is single-precision IEEE-754,
and 'Double' is double-precision IEEE-754. So we can store them as 'Word32'
and 'Word64' and get the 'Eq' and hashing properties we require.
-}

-- | Term Literal
data Literal
  = IntegerLiteral  !Integer
  | IntLiteral      !Integer
  | WordLiteral     !Integer
  | Int64Literal    !Integer
  | Word64Literal   !Integer
  | StringLiteral   !String
  | FloatLiteral    !Word32
  | DoubleLiteral   !Word64
  | CharLiteral     !Char
  | NaturalLiteral  !Integer
  | ByteArrayLiteral !ByteArray
  deriving (Literal -> Literal -> Bool
(Literal -> Literal -> Bool)
-> (Literal -> Literal -> Bool) -> Eq Literal
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Literal -> Literal -> Bool
$c/= :: Literal -> Literal -> Bool
== :: Literal -> Literal -> Bool
$c== :: Literal -> Literal -> Bool
Eq,Eq Literal
Eq Literal
-> (Literal -> Literal -> Ordering)
-> (Literal -> Literal -> Bool)
-> (Literal -> Literal -> Bool)
-> (Literal -> Literal -> Bool)
-> (Literal -> Literal -> Bool)
-> (Literal -> Literal -> Literal)
-> (Literal -> Literal -> Literal)
-> Ord Literal
Literal -> Literal -> Bool
Literal -> Literal -> Ordering
Literal -> Literal -> Literal
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Literal -> Literal -> Literal
$cmin :: Literal -> Literal -> Literal
max :: Literal -> Literal -> Literal
$cmax :: Literal -> Literal -> Literal
>= :: Literal -> Literal -> Bool
$c>= :: Literal -> Literal -> Bool
> :: Literal -> Literal -> Bool
$c> :: Literal -> Literal -> Bool
<= :: Literal -> Literal -> Bool
$c<= :: Literal -> Literal -> Bool
< :: Literal -> Literal -> Bool
$c< :: Literal -> Literal -> Bool
compare :: Literal -> Literal -> Ordering
$ccompare :: Literal -> Literal -> Ordering
$cp1Ord :: Eq Literal
Ord,Int -> Literal -> ShowS
[Literal] -> ShowS
Literal -> String
(Int -> Literal -> ShowS)
-> (Literal -> String) -> ([Literal] -> ShowS) -> Show Literal
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Literal] -> ShowS
$cshowList :: [Literal] -> ShowS
show :: Literal -> String
$cshow :: Literal -> String
showsPrec :: Int -> Literal -> ShowS
$cshowsPrec :: Int -> Literal -> ShowS
Show,(forall x. Literal -> Rep Literal x)
-> (forall x. Rep Literal x -> Literal) -> Generic Literal
forall x. Rep Literal x -> Literal
forall x. Literal -> Rep Literal x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Literal x -> Literal
$cfrom :: forall x. Literal -> Rep Literal x
Generic,Literal -> ()
(Literal -> ()) -> NFData Literal
forall a. (a -> ()) -> NFData a
rnf :: Literal -> ()
$crnf :: Literal -> ()
NFData,Eq Literal
Eq Literal
-> (Int -> Literal -> Int) -> (Literal -> Int) -> Hashable Literal
Int -> Literal -> Int
Literal -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Literal -> Int
$chash :: Literal -> Int
hashWithSalt :: Int -> Literal -> Int
$chashWithSalt :: Int -> Literal -> Int
$cp1Hashable :: Eq Literal
Hashable,Get Literal
[Literal] -> Put
Literal -> Put
(Literal -> Put)
-> Get Literal -> ([Literal] -> Put) -> Binary Literal
forall t. (t -> Put) -> Get t -> ([t] -> Put) -> Binary t
putList :: [Literal] -> Put
$cputList :: [Literal] -> Put
get :: Get Literal
$cget :: Get Literal
put :: Literal -> Put
$cput :: Literal -> Put
Binary)