@@ -13,6 +13,7 @@ module Python.Inline.Literal
1313import Control.Exception
1414import Control.Monad
1515import Control.Monad.IO.Class
16+ import Control.Monad.Trans.Class
1617import Control.Monad.Trans.Cont
1718import Data.Int
1819import Data.Word
@@ -28,6 +29,7 @@ import Language.C.Inline.Unsafe qualified as CU
2829import Python.Types
2930import Python.Internal.Types
3031import Python.Internal.Eval
32+ import Python.Internal.Util
3133
3234
3335----------------------------------------------------------------
@@ -163,6 +165,38 @@ instance FromPy Bool where
163165 1 -> pure $ Just True
164166 _ -> pure $ Nothing
165167
168+ instance (ToPy a , ToPy b ) => ToPy (a ,b ) where
169+ basicToPy (a,b) = do
170+ p_a <- basicToPy a
171+ p_b <- basicToPy b
172+ Py [CU. exp | PyObject* { PyTuple_Pack(2, $(PyObject* p_a), $(PyObject* p_b)) } |]
173+
174+ instance (FromPy a , FromPy b ) => FromPy (a ,b ) where
175+ basicFromPy p_tup = evalContT $ do
176+ -- Unpack 2-tuple.
177+ p_args <- withPyAllocaArray 2
178+ unpack_ok <- liftIO [CU. exp | int {
179+ inline_py_unpack_iterable($(PyObject *p_tup), 2, $(PyObject **p_args))
180+ }|]
181+ -- We may want to extract exception to haskell side later
182+ liftIO [CU. exp | void { PyErr_Clear() } |]
183+ when (unpack_ok /= 0 ) $ abort $ pure Nothing
184+ -- Unpack 2-elements
185+ lift $ do
186+ p_a <- liftIO $ peekElemOff p_args 0
187+ p_b <- liftIO $ peekElemOff p_args 1
188+ let parse = basicFromPy p_a >>= \ case
189+ Nothing -> pure Nothing
190+ Just a -> basicFromPy p_b >>= \ case
191+ Nothing -> pure Nothing
192+ Just b -> pure $ Just (a,b)
193+ fini = liftIO [CU. block | void {
194+ Py_XDECREF( $(PyObject* p_a) );
195+ Py_XDECREF( $(PyObject* p_b) );
196+ } |]
197+ parse `finallyPy` fini
198+
199+
166200
167201----------------------------------------------------------------
168202-- Functions marshalling
0 commit comments