File: Cast.hs

package info (click to toggle)
haskell-basement 0.0.16-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,048 kB
  • sloc: haskell: 11,336; ansic: 63; makefile: 5
file content (149 lines) | stat: -rw-r--r-- 4,631 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
{-# LANGUAGE ConstraintKinds       #-}
{-# LANGUAGE CPP                   #-}
{-# LANGUAGE FlexibleInstances     #-}
{-# LANGUAGE DefaultSignatures     #-}
{-# LANGUAGE MagicHash             #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeOperators         #-}
-- |
-- Module      : Basement.Cast
-- License     : BSD-style
-- Maintainer  : Haskell Foundation
--
module Basement.Cast
    ( Cast(..)
    ) where

#include "MachDeps.h"

import qualified Basement.Block.Base as Block
import           Basement.Compat.Base
import           Basement.Compat.Natural
import           Basement.Compat.Primitive
import           Basement.Numerical.Number
import           Basement.Numerical.Conversion
import           Basement.PrimType

import           Data.Proxy (Proxy(..))

import           GHC.Int
import           GHC.Prim
import           GHC.Types
import           GHC.ST
import           GHC.Word

-- | `Cast` an object of type a to b.
--
-- Do not add instance of this class if the source type is not of the same
-- size of the destination type. Also keep in mind this is casting a value
-- of a given type into a destination type. The value won't be changed to
-- fit the destination represention.
--
-- If you wish to convert a value of a given type into another type, look at
-- `From` and `TryFrom`.
--
-- @
-- cast (-10 :: Int) :: Word === 18446744073709551606
-- @
--
class Cast source destination where
    cast :: source -> destination

    default cast :: ( PrimType source
                    , PrimType destination
                    , PrimSize source ~ PrimSize destination
                    )
                 => source -> destination
    cast a = runST $ do
        mba <- Block.new 1
        Block.unsafeWrite mba 0 a
        Block.unsafeRead (Block.unsafeRecast mba) 0

instance Cast Int8  Word8 where
    cast (I8# i) = W8# (wordToWord8# (int2Word# (int8ToInt# i)))
instance Cast Int16 Word16 where
    cast (I16# i) = W16# (wordToWord16# (int2Word# (int16ToInt# i)))
instance Cast Int32 Word32 where
    cast (I32# i) = W32# (wordToWord32# (int2Word# (int32ToInt# i)))
instance Cast Int64 Word64 where
    cast = int64ToWord64
instance Cast Int   Word where
    cast (I# i) = W# (int2Word# i)

instance Cast Word8  Int8 where
    cast (W8# i) = I8# (intToInt8# (word2Int# (word8ToWord# i)))
instance Cast Word16 Int16 where
    cast (W16# i) = I16# (intToInt16# (word2Int# (word16ToWord# i)))
instance Cast Word32 Int32 where
    cast (W32# i) = I32# (intToInt32# (word2Int# (word32ToWord# i)))
instance Cast Word64 Int64 where
    cast = word64ToInt64
instance Cast Word   Int where
    cast (W# w) = I# (word2Int# w)

#if WORD_SIZE_IN_BITS == 64
#if __GLASGOW_HASKELL__ >= 904
instance Cast Word   Word64 where
    cast (W# w) = W64# (wordToWord64# w)
instance Cast Word64 Word where
    cast (W64# w) = W# (GHC.Prim.word64ToWord# w)

instance Cast Word   Int64 where
    cast (W# w) = I64# (intToInt64# (word2Int# w))
instance Cast Int64  Word where
    cast (I64# i) = W# (int2Word# (int64ToInt# i))

instance Cast Int    Int64 where
    cast (I# i) = I64# (intToInt64# i)
instance Cast Int64  Int where
    cast (I64# i) = I# (int64ToInt# i)

instance Cast Int    Word64 where
    cast (I# i) = W64# (wordToWord64# (int2Word# i))
instance Cast Word64 Int where
    cast (W64# w) = I# (word2Int# (GHC.Prim.word64ToWord# w))
#else
instance Cast Word   Word64 where
    cast (W# w) = W64# w
instance Cast Word64 Word where
    cast (W64# w) = W# w

instance Cast Word   Int64 where
    cast (W# w) = I64# (word2Int# w)
instance Cast Int64  Word where
    cast (I64# i) = W# (int2Word# i)

instance Cast Int    Int64 where
    cast (I# i) = I64# i
instance Cast Int64  Int where
    cast (I64# i) = I# i

instance Cast Int    Word64 where
    cast (I# i) = W64# (int2Word# i)
instance Cast Word64 Int where
    cast (W64# w) = I# (word2Int# w)
#endif
#else
instance Cast Word   Word32 where
    cast (W# w) = W32# (wordToWord32# w)
instance Cast Word32 Word where
    cast (W32# w) = W# (word32ToWord# w)

instance Cast Word   Int32 where
    cast (W# w) = I32# (intToInt32# (word2Int# w))
instance Cast Int32  Word where
    cast (I32# i) = W# (int2Word# (int32ToInt# i))

instance Cast Int    Int32 where
    cast (I# i) = I32# (intToInt32# i)
instance Cast Int32  Int where
    cast (I32# i) = I# (int32ToInt# i)

instance Cast Int    Word32 where
    cast (I# i) = W32# (wordToWord32# (int2Word# i))
instance Cast Word32 Int where
    cast (W32# w) = I# (word2Int# (word32ToWord# w))
#endif

instance Cast (Block.Block a) (Block.Block Word8) where
    cast (Block.Block ba) = Block.Block ba