1 /* -----------------------------------------------------------------------------
2 * $Id: CTypes.h,v 1.1 2001/01/11 17:25:58 simonmar Exp $
4 * Dirty CPP hackery for CTypes/CTypesISO
6 * (c) The FFI task force, 2000
7 * -------------------------------------------------------------------------- */
11 /* As long as there is no automatic derivation of classes for newtypes we resort
12 to extremely dirty cpp-hackery. :-P Some care has to be taken when the
13 macros below are modified, otherwise the layout rule will bite you. */
15 /* A hacked version for GHC follows the Haskell 98 version... */
16 #ifndef __GLASGOW_HASKELL__
18 #define NUMERIC_TYPE(T,C,S,B) \
19 newtype T = T B deriving (Eq, Ord) ; \
24 INSTANCE_TYPEABLE(T,C,S) ;
26 #define INTEGRAL_TYPE(T,C,S,B) \
27 NUMERIC_TYPE(T,C,S,B) ; \
28 INSTANCE_BOUNDED(T) ; \
30 INSTANCE_INTEGRAL(T) ; \
33 #define FLOATING_TYPE(T,C,S,B) \
34 NUMERIC_TYPE(T,C,S,B) ; \
36 INSTANCE_FRACTIONAL(T) ; \
37 INSTANCE_FLOATING(T) ; \
38 INSTANCE_REALFRAC(T) ; \
41 #define INSTANCE_READ(T) \
42 instance Read T where { \
43 readsPrec p s = fakeMap (\(x, t) -> (T x, t)) (readsPrec p s) }
45 #define INSTANCE_SHOW(T) \
46 instance Show T where { \
47 showsPrec p (T x) = showsPrec p x }
49 #define INSTANCE_NUM(T) \
50 instance Num T where { \
51 (T i) + (T j) = T (i + j) ; \
52 (T i) - (T j) = T (i - j) ; \
53 (T i) * (T j) = T (i * j) ; \
54 negate (T i) = T (negate i) ; \
55 abs (T i) = T (abs i) ; \
56 signum (T i) = T (signum i) ; \
57 fromInteger x = T (fromInteger x) }
59 #define INSTANCE_TYPEABLE(T,C,S) \
62 instance Typeable T where { \
63 typeOf _ = mkAppTy C [] }
65 #define INSTANCE_STORABLE(T) \
66 instance Storable T where { \
67 sizeOf (T x) = sizeOf x ; \
68 alignment (T x) = alignment x ; \
69 peekElemOff a i = liftM T (peekElemOff a i) ; \
70 pokeElemOff a i (T x) = pokeElemOff a i x }
72 #define INSTANCE_BOUNDED(T) \
73 instance Bounded T where { \
74 minBound = T minBound ; \
75 maxBound = T maxBound }
77 #define INSTANCE_ENUM(T) \
78 instance Enum T where { \
79 succ (T i) = T (succ i) ; \
80 pred (T i) = T (pred i) ; \
81 toEnum x = T (toEnum x) ; \
82 fromEnum (T i) = fromEnum i ; \
83 enumFrom (T i) = fakeMap T (enumFrom i) ; \
84 enumFromThen (T i) (T j) = fakeMap T (enumFromThen i j) ; \
85 enumFromTo (T i) (T j) = fakeMap T (enumFromTo i j) ; \
86 enumFromThenTo (T i) (T j) (T k) = fakeMap T (enumFromThenTo i j k) }
88 #define INSTANCE_REAL(T) \
89 instance Real T where { \
90 toRational (T i) = toRational i }
92 #define INSTANCE_INTEGRAL(T) \
93 instance Integral T where { \
94 (T i) `quot` (T j) = T (i `quot` j) ; \
95 (T i) `rem` (T j) = T (i `rem` j) ; \
96 (T i) `div` (T j) = T (i `div` j) ; \
97 (T i) `mod` (T j) = T (i `mod` j) ; \
98 (T i) `quotRem` (T j) = let (q,r) = i `quotRem` j in (T q, T r) ; \
99 (T i) `divMod` (T j) = let (d,m) = i `divMod` j in (T d, T m) ; \
100 toInteger (T i) = toInteger i ; \
101 toInt (T i) = toInt i }
103 #define INSTANCE_BITS(T) \
104 instance Bits T where { \
105 (T x) .&. (T y) = T (x .&. y) ; \
106 (T x) .|. (T y) = T (x .|. y) ; \
107 (T x) `xor` (T y) = T (x `xor` y) ; \
108 complement (T x) = T (complement x) ; \
109 shift (T x) n = T (shift x n) ; \
110 rotate (T x) n = T (rotate x n) ; \
111 bit n = T (bit n) ; \
112 setBit (T x) n = T (setBit x n) ; \
113 clearBit (T x) n = T (clearBit x n) ; \
114 complementBit (T x) n = T (complementBit x n) ; \
115 testBit (T x) n = testBit x n ; \
116 bitSize (T x) = bitSize x ; \
117 isSigned (T x) = isSigned x }
119 #define INSTANCE_FRACTIONAL(T) \
120 instance Fractional T where { \
121 (T x) / (T y) = T (x / y) ; \
122 recip (T x) = T (recip x) ; \
123 fromRational r = T (fromRational r) }
125 #define INSTANCE_FLOATING(T) \
126 instance Floating T where { \
128 exp (T x) = T (exp x) ; \
129 log (T x) = T (log x) ; \
130 sqrt (T x) = T (sqrt x) ; \
131 (T x) ** (T y) = T (x ** y) ; \
132 (T x) `logBase` (T y) = T (x `logBase` y) ; \
133 sin (T x) = T (sin x) ; \
134 cos (T x) = T (cos x) ; \
135 tan (T x) = T (tan x) ; \
136 asin (T x) = T (asin x) ; \
137 acos (T x) = T (acos x) ; \
138 atan (T x) = T (atan x) ; \
139 sinh (T x) = T (sinh x) ; \
140 cosh (T x) = T (cosh x) ; \
141 tanh (T x) = T (tanh x) ; \
142 asinh (T x) = T (asinh x) ; \
143 acosh (T x) = T (acosh x) ; \
144 atanh (T x) = T (atanh x) }
146 #define INSTANCE_REALFRAC(T) \
147 instance RealFrac T where { \
148 properFraction (T x) = let (m,y) = properFraction x in (m, T y) ; \
149 truncate (T x) = truncate x ; \
150 round (T x) = round x ; \
151 ceiling (T x) = ceiling x ; \
152 floor (T x) = floor x }
154 #define INSTANCE_REALFLOAT(T) \
155 instance RealFloat T where { \
156 floatRadix (T x) = floatRadix x ; \
157 floatDigits (T x) = floatDigits x ; \
158 floatRange (T x) = floatRange x ; \
159 decodeFloat (T x) = decodeFloat x ; \
160 encodeFloat m n = T (encodeFloat m n) ; \
161 exponent (T x) = exponent x ; \
162 significand (T x) = T (significand x) ; \
163 scaleFloat n (T x) = T (scaleFloat n x) ; \
164 isNaN (T x) = isNaN x ; \
165 isInfinite (T x) = isInfinite x ; \
166 isDenormalized (T x) = isDenormalized x ; \
167 isNegativeZero (T x) = isNegativeZero x ; \
168 isIEEE (T x) = isIEEE x ; \
169 (T x) `atan2` (T y) = T (x `atan2` y) }
171 #else /* __GLASGOW_HASKELL__ */
173 /* On GHC, we just cast the type of each method to the underlying
174 * type. This means that GHC only needs to generate the dictionary
175 * for each instance, rather than a new function for each method (the
176 * simplifier currently isn't clever enough to reduce a method that
177 * simply deconstructs a newtype and calls the underlying method into
178 * an indirection to the underlying method, so that's what we're doing
182 #define NUMERIC_TYPE(T,C,S,B) \
185 INSTANCE_ORD(T,B) ; \
186 INSTANCE_NUM(T,B) ; \
187 INSTANCE_READ(T,B) ; \
188 INSTANCE_SHOW(T,B) ; \
191 #define INTEGRAL_TYPE(T,C,S,B) \
192 NUMERIC_TYPE(T,C,S,B) ; \
193 INSTANCE_BOUNDED(T,B) ; \
194 INSTANCE_REAL(T,B) ; \
195 INSTANCE_INTEGRAL(T,B) ; \
198 #define FLOATING_TYPE(T,C,S,B) \
199 NUMERIC_TYPE(T,C,S,B) ; \
200 INSTANCE_REAL(T,B) ; \
201 INSTANCE_FRACTIONAL(T,B) ; \
202 INSTANCE_FLOATING(T,B) ; \
203 INSTANCE_REALFRAC(T) ; \
204 INSTANCE_REALFLOAT(T,B)
206 #define INSTANCE_EQ(T,B) \
207 instance Eq T where { \
208 (==) = unsafeCoerce# ((==) :: B -> B -> Bool); \
209 (/=) = unsafeCoerce# ((/=) :: B -> B -> Bool); }
211 #define INSTANCE_ORD(T,B) \
212 instance Ord T where { \
213 compare = unsafeCoerce# (compare :: B -> B -> Ordering); \
214 (<) = unsafeCoerce# ((<) :: B -> B -> Bool); \
215 (<=) = unsafeCoerce# ((<=) :: B -> B -> Bool); \
216 (>=) = unsafeCoerce# ((>=) :: B -> B -> Bool); \
217 (>) = unsafeCoerce# ((>) :: B -> B -> Bool); \
218 max = unsafeCoerce# (max :: B -> B -> B); \
219 min = unsafeCoerce# (min :: B -> B -> B); }
221 #define INSTANCE_READ(T,B) \
222 instance Read T where { \
223 readsPrec = unsafeCoerce# (readsPrec :: Int -> ReadS B); \
224 readList = unsafeCoerce# (readList :: ReadS [B]); }
226 #define INSTANCE_SHOW(T,B) \
227 instance Show T where { \
228 showsPrec = unsafeCoerce# (showsPrec :: Int -> B -> ShowS); \
229 show = unsafeCoerce# (show :: B -> String); \
230 showList = unsafeCoerce# (showList :: [B] -> ShowS); }
232 #define INSTANCE_NUM(T,B) \
233 instance Num T where { \
234 (+) = unsafeCoerce# ((+) :: B -> B -> B); \
235 (-) = unsafeCoerce# ((-) :: B -> B -> B); \
236 (*) = unsafeCoerce# ((*) :: B -> B -> B); \
237 negate = unsafeCoerce# (negate :: B -> B); \
238 abs = unsafeCoerce# (abs :: B -> B); \
239 signum = unsafeCoerce# (signum :: B -> B); \
240 fromInteger = unsafeCoerce# (fromInteger :: Integer -> B); \
241 fromInt = unsafeCoerce# (fromInt :: Int -> B) }
243 #define INSTANCE_STORABLE(T,B) \
244 instance Storable T where { \
245 sizeOf = unsafeCoerce# (sizeOf :: B -> Int); \
246 alignment = unsafeCoerce# (alignment :: B -> Int); \
247 peekElemOff = unsafeCoerce# (peekElemOff :: Ptr B -> Int -> IO B); \
248 pokeElemOff = unsafeCoerce# (pokeElemOff :: Ptr B -> Int -> B -> IO B); }
250 #define INSTANCE_BOUNDED(T,B) \
251 instance Bounded T where { \
252 minBound = T minBound ; \
253 maxBound = T maxBound }
255 #define INSTANCE_ENUM(T,B) \
256 instance Enum T where { \
257 succ = unsafeCoerce# (succ :: B -> B); \
258 pred = unsafeCoerce# (pred :: B -> B); \
259 toEnum = unsafeCoerce# (toEnum :: Int -> B); \
260 fromEnum = unsafeCoerce# (fromEnum :: B -> Int); \
261 enumFrom = unsafeCoerce# (enumFrom :: B -> [B]); \
262 enumFromThen = unsafeCoerce# (enumFromThen :: B -> B -> [B]); \
263 enumFromTo = unsafeCoerce# (enumFromTo :: B -> B -> [B]); \
264 enumFromThenTo = unsafeCoerce# (enumFromThenTo :: B -> B -> B -> [B]);}
266 #define INSTANCE_REAL(T,B) \
267 instance Real T where { \
268 toRational = unsafeCoerce# (toRational :: B -> Rational) }
270 #define INSTANCE_INTEGRAL(T,B) \
271 instance Integral T where { \
272 quot = unsafeCoerce# (quot:: B -> B -> B); \
273 rem = unsafeCoerce# (rem:: B -> B -> B); \
274 div = unsafeCoerce# (div:: B -> B -> B); \
275 mod = unsafeCoerce# (mod:: B -> B -> B); \
276 quotRem = unsafeCoerce# (quotRem:: B -> B -> (B,B)); \
277 divMod = unsafeCoerce# (divMod:: B -> B -> (B,B)); \
278 toInteger = unsafeCoerce# (toInteger:: B -> Integer); \
279 toInt = unsafeCoerce# (toInt:: B -> Int); }
281 #define INSTANCE_BITS(T,B) \
282 instance Bits T where { \
283 (.&.) = unsafeCoerce# ((.&.) :: B -> B -> B); \
284 (.|.) = unsafeCoerce# ((.|.) :: B -> B -> B); \
285 xor = unsafeCoerce# (xor:: B -> B -> B); \
286 complement = unsafeCoerce# (complement:: B -> B); \
287 shift = unsafeCoerce# (shift:: B -> Int -> B); \
288 rotate = unsafeCoerce# (rotate:: B -> Int -> B); \
289 bit = unsafeCoerce# (bit:: Int -> B); \
290 setBit = unsafeCoerce# (setBit:: B -> Int -> B); \
291 clearBit = unsafeCoerce# (clearBit:: B -> Int -> B); \
292 complementBit = unsafeCoerce# (complementBit:: B -> Int -> B); \
293 testBit = unsafeCoerce# (testBit:: B -> Int -> Bool); \
294 bitSize = unsafeCoerce# (bitSize:: B -> Int); \
295 isSigned = unsafeCoerce# (isSigned:: B -> Bool); }
297 #define INSTANCE_FRACTIONAL(T,B) \
298 instance Fractional T where { \
299 (/) = unsafeCoerce# ((/) :: B -> B -> B); \
300 recip = unsafeCoerce# (recip :: B -> B); \
301 fromRational = unsafeCoerce# (fromRational :: Rational -> B); }
303 #define INSTANCE_FLOATING(T,B) \
304 instance Floating T where { \
305 pi = unsafeCoerce# (pi :: B); \
306 exp = unsafeCoerce# (exp :: B -> B); \
307 log = unsafeCoerce# (log :: B -> B); \
308 sqrt = unsafeCoerce# (sqrt :: B -> B); \
309 (**) = unsafeCoerce# ((**) :: B -> B -> B); \
310 logBase = unsafeCoerce# (logBase :: B -> B -> B); \
311 sin = unsafeCoerce# (sin :: B -> B); \
312 cos = unsafeCoerce# (cos :: B -> B); \
313 tan = unsafeCoerce# (tan :: B -> B); \
314 asin = unsafeCoerce# (asin :: B -> B); \
315 acos = unsafeCoerce# (acos :: B -> B); \
316 atan = unsafeCoerce# (atan :: B -> B); \
317 sinh = unsafeCoerce# (sinh :: B -> B); \
318 cosh = unsafeCoerce# (cosh :: B -> B); \
319 tanh = unsafeCoerce# (tanh :: B -> B); \
320 asinh = unsafeCoerce# (asinh :: B -> B); \
321 acosh = unsafeCoerce# (acosh :: B -> B); \
322 atanh = unsafeCoerce# (atanh :: B -> B); }
324 /* The coerce trick doesn't work for RealFrac, these methods are
325 * polymorphic and overloaded.
327 #define INSTANCE_REALFRAC(T) \
328 instance RealFrac T where { \
329 properFraction (T x) = let (m,y) = properFraction x in (m, T y) ; \
330 truncate (T x) = truncate x ; \
331 round (T x) = round x ; \
332 ceiling (T x) = ceiling x ; \
333 floor (T x) = floor x }
335 #define INSTANCE_REALFLOAT(T,B) \
336 instance RealFloat T where { \
337 floatRadix = unsafeCoerce# (floatRadix :: B -> Integer); \
338 floatDigits = unsafeCoerce# (floatDigits :: B -> Int); \
339 floatRange = unsafeCoerce# (floatRange :: B -> (Int,Int)); \
340 decodeFloat = unsafeCoerce# (decodeFloat :: B -> (Integer,Int)); \
341 encodeFloat = unsafeCoerce# (encodeFloat :: Integer -> Int -> B); \
342 exponent = unsafeCoerce# (exponent :: B -> Int); \
343 significand = unsafeCoerce# (significand :: B -> B); \
344 scaleFloat = unsafeCoerce# (scaleFloat :: Int -> B -> B); \
345 isNaN = unsafeCoerce# (isNaN :: B -> Bool); \
346 isInfinite = unsafeCoerce# (isInfinite :: B -> Bool); \
347 isDenormalized = unsafeCoerce# (isDenormalized :: B -> Bool); \
348 isNegativeZero = unsafeCoerce# (isNegativeZero :: B -> Bool); \
349 isIEEE = unsafeCoerce# (isIEEE :: B -> Bool); \
350 atan2 = unsafeCoerce# (atan2 :: B -> B -> B); }
352 #endif /* __GLASGOW_HASKELL__ */