{-# LANGUAGE CPP #-}
module Foreign.Hoppy.Generator.Std.Vector (
Options (..),
defaultOptions,
Contents (..),
instantiate,
instantiate',
toExports,
) where
import Control.Monad (forM_, when)
#if !MIN_VERSION_base(4,8,0)
import Data.Monoid (mconcat)
#endif
import Foreign.Hoppy.Generator.Language.Haskell (
HsTypeSide (HsHsSide),
addImports,
cppTypeToHsTypeAndUse,
indent,
ln,
prettyPrint,
sayLn,
saysLn,
)
import Foreign.Hoppy.Generator.Spec
import Foreign.Hoppy.Generator.Spec.Class (
Class,
MethodApplicability (MConst),
makeClass,
makeFnMethod,
mkConstMethod,
mkConstMethod',
mkCtor,
mkMethod,
mkMethod',
toHsDataTypeName,
toHsClassEntityName,
)
import Foreign.Hoppy.Generator.Std (ValueConversion (ConvertPtr, ConvertValue))
import Foreign.Hoppy.Generator.Std.Iterator
import Foreign.Hoppy.Generator.Types
import Foreign.Hoppy.Generator.Version (CppVersion (Cpp2011), activeCppVersion, collect, just, test)
data Options = Options
{ optVectorClassFeatures :: [ClassFeature]
, optValueConversion :: Maybe ValueConversion
}
defaultOptions :: Options
defaultOptions = Options [] Nothing
data Contents = Contents
{ c_vector :: Class
, c_iterator :: Class
, c_constIterator :: Class
}
instantiate :: String -> Type -> Reqs -> Contents
instantiate vectorName t tReqs = instantiate' vectorName t tReqs defaultOptions
instantiate' :: String -> Type -> Reqs -> Options -> Contents
instantiate' vectorName t tReqs opts =
let reqs = mconcat [tReqs, reqInclude $ includeStd "vector"]
iteratorName = vectorName ++ "Iterator"
constIteratorName = vectorName ++ "ConstIterator"
vector =
(case optValueConversion opts of
Nothing -> id
Just conversion -> addAddendumHaskell $ makeAddendum conversion) $
addReqs reqs $
classAddFeatures (Assignable : Copyable : optVectorClassFeatures opts) $
makeClass (ident1T "std" "vector" [t]) (Just $ toExtName vectorName) [] $
collect
[ just $ mkCtor "new" np
, just $ mkMethod' "at" "at" [sizeT] $ refT t
, just $ mkConstMethod' "at" "atConst" [sizeT] $ refT $ constT t
, just $ mkMethod' "back" "back" np $ refT t
, just $ mkConstMethod' "back" "backConst" np $ refT $ constT t
, just $ mkMethod' "begin" "begin" np $ toGcT $ objT iterator
, just $ mkConstMethod' "begin" "beginConst" np $ toGcT $ objT constIterator
, just $ mkConstMethod "capacity" np sizeT
, just $ mkMethod "clear" np voidT
, just $ mkConstMethod "empty" np boolT
, just $ mkMethod' "end" "end" np $ toGcT $ objT iterator
, just $ mkConstMethod' "end" "endConst" np $ toGcT $ objT constIterator
, just $ mkMethod' "erase" "erase" [objT iterator] voidT
, just $ mkMethod' "erase" "eraseRange" [objT iterator, objT iterator] voidT
, just $ mkMethod' "front" "front" np $ refT t
, just $ mkConstMethod' "front" "frontConst" np $ refT $ constT t
, just $ mkMethod "insert" [objT iterator, t] $ toGcT $ objT iterator
, just $ mkConstMethod' "max_size" "maxSize" np sizeT
, just $ mkMethod' "pop_back" "popBack" np voidT
, just $ mkMethod' "push_back" "pushBack" [t] voidT
, just $ mkMethod "reserve" [sizeT] voidT
, just $ mkMethod' "resize" "resize" [sizeT] voidT
, just $ mkMethod' "resize" "resizeWith" [sizeT, t] voidT
, test (activeCppVersion >= Cpp2011) $ mkMethod' "shrink_to_fit" "shrinkToFit" np voidT
, just $ mkConstMethod "size" np sizeT
, just $ mkMethod "swap" [refT $ objT vector] voidT
]
iterator =
addReqs reqs $
makeRandomIterator Mutable (Just t) ptrdiffT $
makeClass (identT' [("std", Nothing), ("vector", Just [t]), ("iterator", Nothing)])
(Just $ toExtName iteratorName) [] []
constIterator =
addReqs reqs $
makeRandomIterator Constant (Just t) ptrdiffT $
makeClass (identT' [("std", Nothing), ("vector", Just [t]), ("const_iterator", Nothing)])
(Just $ toExtName constIteratorName) []
[ mkCtor "newFromNonconst" [objT iterator]
, makeFnMethod (ident2 "hoppy" "iterator" "deconst") "deconst" MConst Nonpure
[objT constIterator, refT $ objT vector] $ toGcT $ objT iterator
]
makeAddendum conversion = do
addImports $ mconcat [hsImports "Prelude" ["($)", "(-)"],
hsImportForPrelude,
hsImportForRuntime]
when (conversion == ConvertValue) $
addImports $ hsImport1 "Control.Monad" "(<=<)"
forM_ [Const, Nonconst] $ \cst -> do
hsDataTypeName <- toHsDataTypeName cst vector
hsValueType <-
cppTypeToHsTypeAndUse HsHsSide $
(case conversion of
ConvertPtr -> ptrT
ConvertValue -> id) $
case cst of
Const -> constT t
Nonconst -> t
ln
saysLn ["instance HoppyFHR.HasContents ", hsDataTypeName,
" (", prettyPrint hsValueType, ") where"]
indent $ do
sayLn "toContents this' = do"
indent $ do
vectorAt <- toHsClassEntityName vector $ case cst of
Const -> "atConst"
Nonconst -> "at"
vectorSize <- toHsClassEntityName vector "size"
saysLn ["size' <- ", vectorSize, " this'"]
saysLn ["HoppyP.mapM (",
case conversion of
ConvertPtr -> ""
ConvertValue -> "HoppyFHR.decode <=< ",
vectorAt, " this') [0..size'-1]"]
when (cst == Nonconst) $ do
ln
saysLn ["instance HoppyFHR.FromContents ", hsDataTypeName,
" (", prettyPrint hsValueType, ") where"]
indent $ do
sayLn "fromContents values' = do"
indent $ do
vectorNew <- toHsClassEntityName vector "new"
vectorPushBack <- toHsClassEntityName vector "pushBack"
vectorReserve <- toHsClassEntityName vector "reserve"
saysLn ["vector' <- ", vectorNew]
saysLn [vectorReserve, " vector' $ HoppyFHR.coerceIntegral $ HoppyP.length values'"]
saysLn ["HoppyP.mapM_ (", vectorPushBack, " vector') values'"]
sayLn "HoppyP.return vector'"
in Contents
{ c_vector = vector
, c_iterator = iterator
, c_constIterator = constIterator
}
toExports :: Contents -> [Export]
toExports m = map (Export . ($ m)) [c_vector, c_iterator, c_constIterator]