-- GENERATED by C->Haskell Compiler, version 0.16.4 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 a1 a2 =
  withObject a1 $ \a1' -> 
  withObject a2 $ \a2' -> 
  add'_ a1' a2' >>= \res ->
  stealObject res >>= \res' ->
  return (res')
{-# LINE 116 "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 122 "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 128 "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 134 "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 140 "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 146 "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 152 "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 166 "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 171 "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 176 "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 181 "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 187 "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 193 "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 199 "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 205 "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 211 "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 217 "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 223 "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 229 "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 235 "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 241 "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 247 "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 262 "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 268 "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 274 "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 280 "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 286 "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 291 "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 296 "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 302 "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"
  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 ()))))