packages feed

cpython-3.1.0: CPython/Types/List.chs

-- 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/>.
-- 
{-# LANGUAGE ForeignFunctionInterface #-}
module CPython.Types.List
	( List
	, listType
	, toList
	, iterableToList
	, fromList
	, length
	, getItem
	, setItem
	, insert
	, append
	, getSlice
	, setSlice
	, sort
	, reverse
	, toTuple
	) where
import Prelude hiding (reverse, length)
import qualified Prelude as Prelude
import CPython.Internal hiding (new)
import qualified CPython.Types.Tuple as T

#include <hscpython-shim.h>

instance Concrete List where
	concreteType _ = listType

{# fun pure hscpython_PyList_Type as listType
	{} -> `Type' peekStaticObject* #}

toList :: [SomeObject] -> IO List
toList xs =
	mapWith withObject xs $ \ptrs ->
	withArrayLen ptrs $ \count array ->
	{# call hscpython_poke_list #} (fromIntegral count) array
	>>= stealObject

-- | Convert any object implementing the iterator protocol to a 'List'.
-- 
iterableToList :: Object iter => iter -> IO List
iterableToList iter = do
	raw <- callObjectRaw listType =<< T.toTuple [toObject iter]
	return $ unsafeCast raw

fromList :: List -> IO [SomeObject]
fromList py =
	withObject py $ \pyPtr ->
	({# call PyList_Size as ^ #} pyPtr >>=) $ \size ->
	let size' = fromIntegral size :: Int in
	withArray (replicate size' nullPtr) $ \ptrs ->
	{# call hscpython_peek_list #} pyPtr size ptrs >>
	peekArray size' ptrs >>= mapM peekObject

{# fun PyList_Size as length
	{ withObject* `List'
	} -> `Integer' checkIntReturn* #}

-- | Returns the object at a given position in the list. The position must be
-- positive; indexing from the end of the list is not supported. If the
-- position is out of bounds, throws an @IndexError@ exception.
-- 
{# fun PyList_GetItem as getItem
	{ withObject* `List'
	, fromIntegral `Integer'
	} -> `SomeObject' peekObject* #}

-- | Set the item at a given index.
-- 
setItem :: Object o => List -> Integer -> o -> IO ()
setItem self index x =
	withObject self $ \selfPtr ->
	withObject x $ \xPtr -> do
	incref xPtr
	{# call PyList_SetItem as ^ #} selfPtr (fromIntegral index) xPtr
	>>= checkStatusCode

-- | Inserts /item/ into the list in front of the given index. Throws an
-- exception if unsuccessful. Analogous to @list.insert(index, item)@.
-- 
{# fun PyList_Insert as insert
	`Object item' =>
	{ withObject* `List'
	, fromIntegral `Integer'
	, withObject* `item'
	} -> `()' checkStatusCode* #}

-- | Append /item/ to the end of th list. Throws an exception if unsuccessful.
-- Analogous to @list.append(item)@.
-- 
{# fun PyList_Append as append
	`Object item' =>
	{ withObject* `List'
	, withObject* `item'
	} -> `()' checkStatusCode* #}

-- | Return a list of the objects in list containing the objects between
-- the given indexes. Throws an exception if unsuccessful. Analogous to
-- @list[low:high]@. Negative indices, as when slicing from Python, are not
-- supported.
-- 
{# fun PyList_GetSlice as getSlice
	{ withObject* `List'
	, fromIntegral `Integer'
	, fromIntegral `Integer'
	} -> `List' stealObject* #}

-- | Sets the slice of a list between /low/ and /high/ to the contents of
-- a replacement list. Analogous to @list[low:high] = replacement@. The
-- replacement may be 'Nothing', indicating the assignment of an empty list
-- (slice deletion). Negative indices, as when slicing from Python, are not
-- supported.
-- 
setSlice
	:: List
	-> Integer -- ^ Low
	-> Integer -- ^ High
	-> Maybe List -- ^ Replacement
	-> IO ()
setSlice self low high items = let
	low' = fromIntegral low
	high' = fromIntegral high in
	withObject self $ \selfPtr ->
	maybeWith withObject items $ \itemsPtr -> do
	{# call PyList_SetSlice as ^ #} selfPtr low' high' itemsPtr
	>>= checkStatusCode

-- | Sort the items of a list in place. This is equivalent to @list.sort()@.
-- 
{# fun PyList_Sort as sort
	{ withObject* `List'
	} -> `()' checkStatusCode* #}

-- | Reverses the items of a list in place. This is equivalent to
-- @list.reverse()@.
-- 
{# fun PyList_Reverse as reverse
	{ withObject* `List'
	} -> `()' checkStatusCode* #}

-- | Return a new 'Tuple' containing the contents of a list; equivalent to
-- @tuple(list)@.
-- 
{# fun PyList_AsTuple as toTuple
	{ withObject* `List'
	} -> `Tuple' stealObject* #}