-- GENERATED by C->Haskell Compiler, version 0.17.2 Crystal Seed, 24 Jan 2009 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "lib/CPython/Protocols/Number.chs" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE ExistentialQuantification #-}

-- Copyright (C) 2009 John Millikin <jmillikin@gmail.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.

module CPython.Protocols.Number
	( Number (..)
	, SomeNumber
	, castToNumber
	, add
	, subtract
	, multiply
	, floorDivide
	, trueDivide
	, remainder
	, divmod
	, power
	, negative
	, positive
	, absolute
	, invert
	, shiftL
	, shiftR
	, and
	, xor
	, or
	, inPlaceAdd
	, inPlaceSubtract
	, inPlaceMultiply
	, inPlaceFloorDivide
	, inPlaceTrueDivide
	, inPlaceRemainder
	, inPlacePower
	, inPlaceShiftL
	, inPlaceShiftR
	, inPlaceAnd
	, inPlaceXor
	, inPlaceOr
	, toInteger
	, toFloat
	, toBase
	) where



import           Prelude hiding (Integer, Float, subtract, and, or, toInteger)
import qualified Prelude as Prelude

import           CPython.Constants (none)
import           CPython.Internal hiding (xor, shiftR, shiftL)
import           CPython.Types.Complex (Complex)
import           CPython.Types.Float (Float)
import           CPython.Types.Integer (Integer)
import           CPython.Types.Set (Set, FrozenSet)
import           CPython.Types.Unicode (Unicode)

data SomeNumber = forall a. (Number a) => SomeNumber (ForeignPtr a)

class Object a => Number a where
	toNumber :: a -> SomeNumber

instance Object SomeNumber where
	toObject (SomeNumber x) = SomeObject x
	fromForeignPtr = SomeNumber

instance Number SomeNumber where
	toNumber = id

instance Number Integer where
	toNumber = unsafeCastToNumber

instance Number Float where
	toNumber = unsafeCastToNumber

instance Number Complex where
	toNumber = unsafeCastToNumber

-- lol wut
instance Number Set where
	toNumber = unsafeCastToNumber

instance Number FrozenSet where
	toNumber = unsafeCastToNumber

unsafeCastToNumber :: Object a => a -> SomeNumber
unsafeCastToNumber x = case toObject x of
	SomeObject ptr -> let
		ptr' = castForeignPtr ptr :: ForeignPtr SomeNumber
		in SomeNumber ptr'

castToNumber :: Object a => a -> IO (Maybe SomeNumber)
castToNumber obj =
	withObject obj $ \objPtr -> do
	isNumber <- fmap cToBool $ pyNumberCheck objPtr
	return $ if isNumber
		then Just $ unsafeCastToNumber obj
		else Nothing

add :: (Number a, Number b) => a -> b -> IO SomeNumber
add = c_add

-- c2hs won't accept functions named "add" any more, so have it generate
-- c_add and then wrap that manually.
c_add :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
c_add a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  c_add'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 121 "lib/CPython/Protocols/Number.chs" #-}


subtract :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
subtract a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  subtract'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 127 "lib/CPython/Protocols/Number.chs" #-}


multiply :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
multiply a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  multiply'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 133 "lib/CPython/Protocols/Number.chs" #-}


floorDivide :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
floorDivide a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  floorDivide'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 139 "lib/CPython/Protocols/Number.chs" #-}


trueDivide :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
trueDivide a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  trueDivide'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 145 "lib/CPython/Protocols/Number.chs" #-}


remainder :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
remainder a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  remainder'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 151 "lib/CPython/Protocols/Number.chs" #-}


divmod :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
divmod a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  divmod'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 157 "lib/CPython/Protocols/Number.chs" #-}


power :: (Number a, Number b, Number c) => a -> b -> Maybe c -> IO SomeNumber
power a b mc =
	withObject a $ \aPtr ->
	withObject b $ \bPtr ->
	maybe none (return . toObject) mc >>= \c ->
	withObject c $ \cPtr ->
	pyNumberPower aPtr bPtr cPtr
	>>= stealObject

negative :: Number a => (a) -> IO ((SomeNumber))
negative a1 =
  withObject a1 $ \a1' -> 
  negative'_ a1' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 171 "lib/CPython/Protocols/Number.chs" #-}


positive :: Number a => (a) -> IO ((SomeNumber))
positive a1 =
  withObject a1 $ \a1' -> 
  positive'_ a1' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 176 "lib/CPython/Protocols/Number.chs" #-}


absolute :: Number a => (a) -> IO ((SomeNumber))
absolute a1 =
  withObject a1 $ \a1' -> 
  absolute'_ a1' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 181 "lib/CPython/Protocols/Number.chs" #-}


invert :: Number a => (a) -> IO ((SomeNumber))
invert a1 =
  withObject a1 $ \a1' -> 
  invert'_ a1' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 186 "lib/CPython/Protocols/Number.chs" #-}


shiftL :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
shiftL a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  shiftL'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 192 "lib/CPython/Protocols/Number.chs" #-}


shiftR :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
shiftR a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  shiftR'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 198 "lib/CPython/Protocols/Number.chs" #-}


and :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
and a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  and'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 204 "lib/CPython/Protocols/Number.chs" #-}


xor :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
xor a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  xor'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 210 "lib/CPython/Protocols/Number.chs" #-}


or :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
or a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  or'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 216 "lib/CPython/Protocols/Number.chs" #-}


inPlaceAdd :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceAdd a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceAdd'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 222 "lib/CPython/Protocols/Number.chs" #-}


inPlaceSubtract :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceSubtract a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceSubtract'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 228 "lib/CPython/Protocols/Number.chs" #-}


inPlaceMultiply :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceMultiply a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceMultiply'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 234 "lib/CPython/Protocols/Number.chs" #-}


inPlaceFloorDivide :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceFloorDivide a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceFloorDivide'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 240 "lib/CPython/Protocols/Number.chs" #-}


inPlaceTrueDivide :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceTrueDivide a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceTrueDivide'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 246 "lib/CPython/Protocols/Number.chs" #-}


inPlaceRemainder :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceRemainder a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceRemainder'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 252 "lib/CPython/Protocols/Number.chs" #-}


inPlacePower ::(Number a, Number b, Number c) => a -> b -> Maybe c -> IO SomeNumber
inPlacePower a b mc =
	withObject a $ \aPtr ->
	withObject b $ \bPtr ->
	maybe none (return . toObject) mc >>= \c ->
	withObject c $ \cPtr ->
	pyNumberInPlacePower aPtr bPtr cPtr
	>>= stealObject

inPlaceShiftL :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceShiftL a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceShiftL'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 267 "lib/CPython/Protocols/Number.chs" #-}


inPlaceShiftR :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceShiftR a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceShiftR'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 273 "lib/CPython/Protocols/Number.chs" #-}


inPlaceAnd :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceAnd a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceAnd'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 279 "lib/CPython/Protocols/Number.chs" #-}


inPlaceXor :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceXor a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceXor'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 285 "lib/CPython/Protocols/Number.chs" #-}


inPlaceOr :: (Number a, Number b) => (a) -> (b) -> IO ((SomeNumber))
inPlaceOr a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  inPlaceOr'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 291 "lib/CPython/Protocols/Number.chs" #-}


toInteger :: Number a => (a) -> IO ((Integer))
toInteger a1 =
  withObject a1 $ \a1' -> 
  toInteger'_ a1' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 296 "lib/CPython/Protocols/Number.chs" #-}


toFloat :: Number a => (a) -> IO ((Float))
toFloat a1 =
  withObject a1 $ \a1' -> 
  toFloat'_ a1' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 301 "lib/CPython/Protocols/Number.chs" #-}


toBase :: Number a => (a) -> (Prelude.Integer) -> IO ((Unicode))
toBase a1 a2 =
  withObject a1 $ \a1' -> 
  let {a2' = fromIntegral a2} in 
  toBase'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')

{-# LINE 307 "lib/CPython/Protocols/Number.chs" #-}


foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Check"
  pyNumberCheck :: ((Ptr ()) -> (IO CInt))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Add"
  c_add'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Subtract"
  subtract'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Multiply"
  multiply'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_FloorDivide"
  floorDivide'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_TrueDivide"
  trueDivide'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Remainder"
  remainder'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Divmod"
  divmod'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Power"
  pyNumberPower :: ((Ptr ()) -> ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ())))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Negative"
  negative'_ :: ((Ptr ()) -> (IO (Ptr ())))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Positive"
  positive'_ :: ((Ptr ()) -> (IO (Ptr ())))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Absolute"
  absolute'_ :: ((Ptr ()) -> (IO (Ptr ())))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Invert"
  invert'_ :: ((Ptr ()) -> (IO (Ptr ())))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Lshift"
  shiftL'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Rshift"
  shiftR'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_And"
  and'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Xor"
  xor'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Or"
  or'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceAdd"
  inPlaceAdd'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceSubtract"
  inPlaceSubtract'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceMultiply"
  inPlaceMultiply'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceFloorDivide"
  inPlaceFloorDivide'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceTrueDivide"
  inPlaceTrueDivide'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceRemainder"
  inPlaceRemainder'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlacePower"
  pyNumberInPlacePower :: ((Ptr ()) -> ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ())))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceLshift"
  inPlaceShiftL'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceRshift"
  inPlaceShiftR'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceAnd"
  inPlaceAnd'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceXor"
  inPlaceXor'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_InPlaceOr"
  inPlaceOr'_ :: ((Ptr ()) -> ((Ptr ()) -> (IO (Ptr ()))))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Long"
  toInteger'_ :: ((Ptr ()) -> (IO (Ptr ())))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_Float"
  toFloat'_ :: ((Ptr ()) -> (IO (Ptr ())))

foreign import ccall safe "CPython/Protocols/Number.chs.h PyNumber_ToBase"
  toBase'_ :: ((Ptr ()) -> (CInt -> (IO (Ptr ()))))