99{-# Language FlexibleInstances #-}
1010{-# Language FunctionalDependencies #-}
1111{-# Language GADTs #-}
12+ {-# Language KindSignatures #-}
1213{-# Language LambdaCase #-}
1314{-# LANGUAGE OverloadedStrings #-}
1415{-# LANGUAGE ScopedTypeVariables #-}
1718{-# Language ViewPatterns #-}
1819
1920-- required to not warn about IsVector usage.
20- {-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
21+ {-# OPTIONS_GHC -fno-warn-redundant-constraints -fplugin-opt=LiquidHaskell:--skip-module=False #-}
22+ {-@ LIQUID " --exact-data-cons" @- } -- needed to have LH accept specs in module HExp
23+ {- @ LIQUID "--prune-unsorted" @-}
2124module Language.R. Literal
25+ {-
2226 ( -- * Literals conversion
2327 Literal(..)
2428 , toPairList
@@ -33,16 +37,20 @@ module Language.R.Literal
3337 , mkProtectedSEXPVectorIO
3438 -- * Internal
3539 , funToSEXP
36- ) where
40+ ) -} where
3741
3842import Control.Memory. Region
3943import Control.Monad.R. Class
4044import qualified Data.Vector. SEXP as SVector
4145import qualified Data.Vector.SEXP. Mutable as SMVector
46+ import qualified Data.Vector.SEXP. Mutable as Mutable -- Needed to help LH name resolution
47+ import Foreign. C -- Needed to help LH name resolution
4248import qualified Foreign. R as R
43- import qualified Foreign.R.Internal as R (somesexp )
44- import Foreign.R.Type ( IsVector , SSEXPTYPE )
45- import Foreign.R ( SEXP , SomeSEXP (.. ) )
49+ import Foreign.R. Type ( IsVector )
50+ import Foreign.R.Type. Singletons (SSEXPTYPE )
51+ import Foreign. R ( SEXP )
52+ import GHC. ForeignPtr -- Needed to help LH name resolution
53+ import GHC. ST -- Needed to help LH name resolution
4654import Internal. Error
4755import {-# SOURCE #-} Language.R. Internal (r1)
4856import Language.R. Globals (nilValue)
@@ -67,84 +75,98 @@ import qualified GHC.Foreign as GHC
6775import GHC.IO.Encoding. UTF8
6876import System.IO. Unsafe ( unsafePerformIO )
6977
78+ {- @ measure Language.R.Literal.literalRType :: a -> R.SEXPTYPE @-}
79+
7080-- | Values that can be converted to 'SEXP'.
71- class SingI ty => Literal a ty | a -> ty where
81+ class SingI ty => Literal a (ty : : R. SEXPTYPE ) | a -> ty where
7282 -- | Internal function for converting a literal to a 'SEXP' value. You
7383 -- probably want to be using 'mkSEXP' instead.
74- mkSEXPIO :: a -> IO (SEXP V ty )
75- fromSEXP :: SEXP s ty -> a
84+ {- @ mkSEXPIO :: x:a -> IO (TSEXP V (literalRType x)) @-}
85+ mkSEXPIO :: a -> IO (SEXP V )
86+ {- @ fromSEXP :: s:SEXP s -> {v:a | literalRType v == typeOf s} @-}
87+ fromSEXP :: SEXP s -> a
88+
89+ {- @ literalRType :: x:a -> {v:R.SEXPTYPE | v == literalRType x } @-}
90+ literalRType :: a -> R. SEXPTYPE
7691
77- default mkSEXPIO :: (IsVector ty , Literal [a ] ty ) => a -> IO (SEXP V ty )
92+ {-
93+ default mkSEXPIO :: (IsVector ty, Literal [a] ty) => a -> IO (SEXP V)
7894 mkSEXPIO x = mkSEXPIO [x]
7995
80- default fromSEXP :: (IsVector ty , Literal [a ] ty ) => SEXP s ty -> a
96+ default fromSEXP :: (IsVector ty, Literal [a] ty) => SEXP s -> a
8197 fromSEXP (fromSEXP -> [x]) = x
8298 fromSEXP _ = failure "fromSEXP" "Not a singleton vector."
99+ -}
83100
84101-- | Create a SEXP value and protect it in current region
85- mkSEXP :: (Literal a b , MonadR m ) => a -> m (SEXP (Region m ) b )
86- mkSEXP x = acquire =<< io (mkSEXPIO x)
87-
88- -- | Like 'fromSEXP', but with no static type satefy. Performs a dynamic
89- -- (i.e. at runtime) check instead.
90- fromSomeSEXP :: forall s a form . (Literal a form ) => R. SomeSEXP s -> a
91- fromSomeSEXP = fromSEXP . R. cast (sing :: Sing form )
102+ {- @ assume mkSEXP :: x:a -> m (TSEXP (Region m) (literalRType x)) @-}
103+ mkSEXP :: (Literal a b , MonadR m ) => a -> m (SEXP (Region m ))
104+ mkSEXP x = io (mkSEXPIO x) >>= \ a -> acquire a
92105
93106-- | Like 'fromSomeSEXP', but behaves like the @as.*@ family of functions
94107-- in R, by performing a best effort conversion to the target form (e.g. rounds
95108-- reals to integers, etc) for atomic types.
96- dynSEXP :: forall a s ty . (Literal a ty ) => SomeSEXP s -> a
97- dynSEXP ( SomeSEXP sx) =
98- fromSomeSEXP $ unsafePerformIO $ case fromSing (sing :: SSEXPTYPE ty ) of
109+ dynSEXP :: forall a s ty . (Literal a ty ) => SEXP s -> a
110+ dynSEXP sx =
111+ fromSEXP $ unsafePerformIO $ case fromSing (sing :: SSEXPTYPE ty ) of
99112 R. Char -> r1 " as.character" sx
100113 R. Int -> r1 " as.integer" sx
101114 R. Real -> r1 " as.double" sx
102115 R. Complex -> r1 " as.complex" sx
103116 R. Logical -> r1 " as.logical" sx
104117 R. Raw -> r1 " as.raw" sx
105- _ -> return $ SomeSEXP $ R. release sx
118+ _ -> return $ R. release sx
106119
107120{-# NOINLINE mkSEXPVector #-}
108- mkSEXPVector :: (Storable (SVector. ElemRep s a ), IsVector a )
109- => SSEXPTYPE a
110- -> [IO (SVector. ElemRep s a )]
111- -> SEXP s a
121+ {- @ mkSEXPVector :: vt:VSEXPTYPE s a -> [IO a] -> TSEXP s (vstypeOf vt) @-}
122+ mkSEXPVector :: Storable a
123+ => SVector. VSEXPTYPE s a
124+ -> [IO a ]
125+ -> SEXP s
112126mkSEXPVector ty allocators = unsafePerformIO $ mkSEXPVectorIO ty allocators
113127
114- mkSEXPVectorIO :: (Storable (SVector. ElemRep s a ), IsVector a )
115- => SSEXPTYPE a
116- -> [IO (SVector. ElemRep s a )]
117- -> IO (SEXP s a )
128+ {- @ assume mkSEXPVectorIO :: vt:VSEXPTYPE s a -> [IO a] -> IO (TSEXP s (vstypeOf vt)) @-}
129+ {- @ ignore mkSEXPVectorIO @-}
130+ mkSEXPVectorIO :: Storable a
131+ => SVector. VSEXPTYPE s a
132+ -> [IO a ]
133+ -> IO (SEXP s )
118134mkSEXPVectorIO ty allocators =
119- R. withProtected (R. allocVector ty $ length allocators) $ \ vec -> do
135+ R. withProtected (R. allocVector ( SVector. vstypeOf ty) $ length allocators) $ \ vec -> do
120136 let ptr = castPtr $ R. unsafeSEXPToVectorPtr vec
121137 zipWithM_ (\ i -> (>>= pokeElemOff ptr i)) [0 .. ] allocators
122138 return vec
123139
124140{-# NOINLINE mkProtectedSEXPVector #-}
125- mkProtectedSEXPVector :: IsVector b
126- => SSEXPTYPE b
127- -> [SEXP s a ]
128- -> SEXP s b
141+ {- @
142+ mkProtectedSEXPVector :: vt:VSEXPTYPE s a -> [SEXP s] -> TSEXP s (vstypeOf vt)
143+ @-}
144+ mkProtectedSEXPVector :: SVector. VSEXPTYPE s a
145+ -> [SEXP s ]
146+ -> SEXP s
129147mkProtectedSEXPVector ty xs = unsafePerformIO $ mkProtectedSEXPVectorIO ty xs
130148
131- mkProtectedSEXPVectorIO :: IsVector b
132- => SSEXPTYPE b
133- -> [SEXP s a ]
134- -> IO (SEXP s b )
149+ {- @
150+ assume mkProtectedSEXPVectorIO :: vt:VSEXPTYPE s a -> [SEXP s] -> IO (TSEXP s (vstypeOf vt))
151+ ignore mkProtectedSEXPVectorIO
152+ @-}
153+ mkProtectedSEXPVectorIO :: SVector. VSEXPTYPE s a
154+ -> [SEXP s ]
155+ -> IO (SEXP s )
135156mkProtectedSEXPVectorIO ty xs = do
136157 mapM_ (void . R. protect) xs
137- z <- R. withProtected (R. allocVector ty $ length xs) $ \ vec -> do
158+ z <- R. withProtected (R. allocVector ( SVector. vstypeOf ty) $ length xs) $ \ vec -> do
138159 let ptr = castPtr $ R. unsafeSEXPToVectorPtr vec
139160 zipWithM_ (pokeElemOff ptr) [0 .. ] xs
140161 return vec
141162 R. unprotect (length xs)
142163 return z
143164
144165instance Literal [R. Logical ] 'R.Logical where
145- mkSEXPIO = mkSEXPVectorIO sing . map return
166+ mkSEXPIO = mkSEXPVectorIO (fromSing sing) . map return
146167 fromSEXP (hexp -> Logical v) = SVector. toList v
147168
169+ {-
148170instance Literal [Int32] 'R.Int where
149171 mkSEXPIO = mkSEXPVectorIO sing . map return
150172 fromSEXP (hexp -> Int v) = SVector.toList v
@@ -256,7 +278,7 @@ instance (NFData a, Literal a la) => HFunWrap (R s a) (IO R.SEXP0) where
256278
257279instance (Literal a la, HFunWrap b wb)
258280 => HFunWrap (a -> b) (R.SEXP0 -> wb) where
259- hFunWrap f a = hFunWrap $ f $! fromSEXP (R. cast sing ( R. somesexp a) :: SEXP s la )
281+ hFunWrap f a = hFunWrap $ f $! fromSEXP (R.SEXP a :: SEXP s la)
260282
261283foreign import ccall "missing_r.h funPtrToSEXP" funPtrToSEXP
262284 :: FunPtr a -> IO (SEXP s 'R.ExtPtr)
@@ -265,3 +287,4 @@ funToSEXP :: HFunWrap a b => (b -> IO (FunPtr b)) -> a -> IO (SEXP s 'R.ExtPtr)
265287funToSEXP w x = funPtrToSEXP =<< w (hFunWrap x)
266288
267289$(thWrapperLiterals 3 12)
290+ -}
0 commit comments