PageRenderTime 123ms CodeModel.GetById 69ms RepoModel.GetById 0ms app.codeStats 1ms

/std/src/Foreign/Hoppy/Generator/Std/List.hs

https://gitlab.com/lingnan/hoppy
Haskell | 242 lines | 185 code | 18 blank | 39 comment | 4 complexity | ae4ef0666199199f3c2d18e2698a8d7a MD5 | raw file
  1. -- This file is part of Hoppy.
  2. --
  3. -- Copyright 2015-2016 Bryan Gardiner <bog@khumba.net>
  4. --
  5. -- Licensed under the Apache License, Version 2.0 (the "License");
  6. -- you may not use this file except in compliance with the License.
  7. -- You may obtain a copy of the License at
  8. --
  9. -- http://www.apache.org/licenses/LICENSE-2.0
  10. --
  11. -- Unless required by applicable law or agreed to in writing, software
  12. -- distributed under the License is distributed on an "AS IS" BASIS,
  13. -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. -- See the License for the specific language governing permissions and
  15. -- limitations under the License.
  16. {-# LANGUAGE CPP #-}
  17. -- | Bindings for @std::list@.
  18. module Foreign.Hoppy.Generator.Std.List (
  19. Options (..),
  20. defaultOptions,
  21. Contents (..),
  22. instantiate,
  23. instantiate',
  24. toExports,
  25. ) where
  26. import Control.Monad (forM_, when)
  27. #if !MIN_VERSION_base(4,8,0)
  28. import Data.Monoid (mconcat)
  29. #endif
  30. import Foreign.Hoppy.Generator.Language.Haskell (
  31. HsTypeSide (HsHsSide),
  32. addImports,
  33. cppTypeToHsTypeAndUse,
  34. indent,
  35. ln,
  36. prettyPrint,
  37. sayLn,
  38. saysLn,
  39. toHsDataTypeName,
  40. toHsClassEntityName,
  41. )
  42. import Foreign.Hoppy.Generator.Spec
  43. import Foreign.Hoppy.Generator.Spec.ClassFeature (
  44. ClassFeature (Assignable, Comparable, Copyable, Equatable),
  45. classAddFeatures,
  46. )
  47. import Foreign.Hoppy.Generator.Std (ValueConversion (ConvertPtr, ConvertValue))
  48. import Foreign.Hoppy.Generator.Std.Iterator
  49. import Foreign.Hoppy.Generator.Types
  50. import Foreign.Hoppy.Generator.Version (collect, just, test)
  51. -- | Options for instantiating the list classes.
  52. data Options = Options
  53. { optListClassFeatures :: [ClassFeature]
  54. -- ^ Additional features to add to the @std::list@ class. Lists are always
  55. -- 'Assignable' and 'Copyable', but you may want to add 'Equatable' and
  56. -- 'Comparable' if your value type supports those.
  57. , optValueConversion :: Maybe ValueConversion
  58. }
  59. -- | The default options have no additional 'ClassFeature's.
  60. defaultOptions :: Options
  61. defaultOptions = Options [] Nothing
  62. -- | A set of instantiated list classes.
  63. data Contents = Contents
  64. { c_list :: Class -- ^ @std::list\<T>@
  65. , c_iterator :: Class -- ^ @std::list\<T>::iterator@
  66. , c_constIterator :: Class -- ^ @std::list\<T>::const_iterator@
  67. }
  68. -- | @instantiate className t tReqs@ creates a set of bindings for an
  69. -- instantiation of @std::list@ and associated types (e.g. iterators). In the
  70. -- result, the 'c_list' class has an external name of @className@, and the
  71. -- iterator classes are further suffixed with @\"Iterator\"@ and
  72. -- @\"ConstIterator\"@ respectively.
  73. instantiate :: String -> Type -> Reqs -> Contents
  74. instantiate listName t tReqs = instantiate' listName t tReqs defaultOptions
  75. -- | 'instantiate' with additional options.
  76. instantiate' :: String -> Type -> Reqs -> Options -> Contents
  77. instantiate' listName t tReqs opts =
  78. let reqs = mconcat [tReqs, reqInclude $ includeStd "list"]
  79. iteratorName = listName ++ "Iterator"
  80. constIteratorName = listName ++ "ConstIterator"
  81. features = Assignable : Copyable : optListClassFeatures opts
  82. list =
  83. (case optValueConversion opts of
  84. Nothing -> id
  85. Just conversion -> addAddendumHaskell $ makeAddendum conversion) $
  86. addReqs reqs $
  87. classAddFeatures features $
  88. makeClass (ident1T "std" "list" [t]) (Just $ toExtName listName) [] $
  89. collect
  90. [ just $ mkCtor "new" []
  91. , just $ mkMethod' "back" "back" [] $ refT t
  92. , just $ mkConstMethod' "back" "backConst" [] $ refT $ constT t
  93. , just $ mkMethod' "begin" "begin" [] $ toGcT $ objT iterator
  94. , just $ mkConstMethod' "begin" "beginConst" [] $ toGcT $ objT constIterator
  95. , just $ mkMethod "clear" [] voidT
  96. , just $ mkConstMethod "empty" [] boolT
  97. , just $ mkMethod' "end" "end" [] $ toGcT $ objT iterator
  98. , just $ mkConstMethod' "end" "endConst" [] $ toGcT $ objT constIterator
  99. , just $ mkMethod' "erase" "erase" [objT iterator] voidT
  100. , just $ mkMethod' "erase" "eraseRange" [objT iterator, objT iterator] voidT
  101. , just $ mkMethod' "front" "front" [] $ refT t
  102. , just $ mkConstMethod' "front" "frontConst" [] $ refT $ constT t
  103. , just $ mkMethod "insert" [objT iterator, t] $ toGcT $ objT iterator
  104. , just $ mkConstMethod' "max_size" "maxSize" [] sizeT
  105. , test (elem Comparable features) $ mkMethod "merge" [refT $ objT list] voidT
  106. -- TODO merge(list&, Comparator)
  107. , just $ mkMethod' "pop_back" "popBack" [] voidT
  108. , just $ mkMethod' "pop_front" "popFront" [] voidT
  109. , just $ mkMethod' "push_back" "pushBack" [t] voidT
  110. , just $ mkMethod' "push_front" "pushFront" [t] voidT
  111. , test (elem Equatable features) $ mkMethod "remove" [t] voidT
  112. -- TODO remove_if(UnaryPredicate)
  113. , just $ mkMethod' "resize" "resize" [sizeT] voidT
  114. , just $ mkMethod' "resize" "resizeWith" [sizeT, t] voidT
  115. , just $ mkMethod "reverse" [] voidT
  116. , just $ mkConstMethod "size" [] sizeT
  117. , test (elem Comparable features) $ mkMethod "sort" [] voidT
  118. -- TODO sort(Comparator)
  119. , just $ mkMethod' "splice" "spliceAll" [objT iterator, refT $ objT list] voidT
  120. , just $ mkMethod' "splice" "spliceOne"
  121. [objT iterator, refT $ objT list, objT iterator] voidT
  122. , just $ mkMethod' "splice" "spliceRange"
  123. [objT iterator, refT $ objT list, objT iterator, objT iterator] voidT
  124. , just $ mkMethod "swap" [refT $ objT list] voidT
  125. , test (Equatable `elem` features) $ mkMethod "unique" [] voidT
  126. -- TODO unique(BinaryPredicate)
  127. ]
  128. iterator =
  129. addReqs reqs $
  130. makeBidirectionalIterator Mutable (Just t) $
  131. makeClass (identT' [("std", Nothing), ("list", Just [t]), ("iterator", Nothing)])
  132. (Just $ toExtName iteratorName) [] []
  133. constIterator =
  134. addReqs reqs $
  135. makeBidirectionalIterator Constant (Just t) $
  136. makeClass (identT' [("std", Nothing), ("list", Just [t]), ("const_iterator", Nothing)])
  137. (Just $ toExtName constIteratorName)
  138. []
  139. [ mkCtor "newFromConst" [objT iterator]
  140. , makeFnMethod (ident2 "hoppy" "iterator" "deconst") "deconst" MConst Nonpure
  141. [objT constIterator, refT $ objT list] $ toGcT $ objT iterator
  142. ]
  143. -- The addendum for the list class contains HasContents and FromContents
  144. -- instances.
  145. makeAddendum conversion = do
  146. addImports $ mconcat [hsImport1 "Prelude" "($)",
  147. hsImportForPrelude,
  148. hsImportForRuntime]
  149. when (conversion == ConvertValue) $
  150. addImports $ hsImport1 "Prelude" "(=<<)"
  151. forM_ [Const, Nonconst] $ \cst -> do
  152. hsDataTypeName <- toHsDataTypeName cst list
  153. hsValueType <-
  154. cppTypeToHsTypeAndUse HsHsSide $
  155. (case conversion of
  156. ConvertPtr -> ptrT
  157. ConvertValue -> id) $
  158. case cst of
  159. Const -> constT t
  160. Nonconst -> t
  161. -- Generate const and nonconst HasContents instances.
  162. ln
  163. saysLn ["instance HoppyFHR.HasContents ", hsDataTypeName,
  164. " (", prettyPrint hsValueType, ") where"]
  165. indent $ do
  166. sayLn "toContents this' = do"
  167. indent $ do
  168. listEmpty <- toHsClassEntityName list "empty"
  169. listBegin <- toHsClassEntityName list $ case cst of
  170. Const -> "beginConst"
  171. Nonconst -> "begin"
  172. listEnd <- toHsClassEntityName list $ case cst of
  173. Const -> "endConst"
  174. Nonconst -> "end"
  175. let iter = case cst of
  176. Const -> constIterator
  177. Nonconst -> iterator
  178. iterEq <- toHsClassEntityName iter OpEq
  179. iterGet <- toHsClassEntityName iter $ case cst of
  180. Const -> "getConst"
  181. Nonconst -> "get"
  182. iterPrev <- toHsClassEntityName iter "prev"
  183. saysLn ["empty' <- ", listEmpty, " this'"]
  184. sayLn "if empty' then HoppyP.return [] else do"
  185. indent $ do
  186. saysLn ["begin' <- ", listBegin, " this'"]
  187. saysLn ["iter' <- ", listEnd, " this'"]
  188. sayLn "go' iter' begin' []"
  189. sayLn "where"
  190. indent $ do
  191. sayLn "go' iter' begin' acc' = do"
  192. indent $ do
  193. saysLn ["stop' <- ", iterEq, " iter' begin'"]
  194. sayLn "if stop' then HoppyP.return acc' else do"
  195. indent $ do
  196. saysLn ["_ <- ", iterPrev, " iter'"]
  197. saysLn ["value' <- ",
  198. case conversion of
  199. ConvertPtr -> ""
  200. ConvertValue -> "HoppyFHR.decode =<< ",
  201. iterGet, " iter'"]
  202. sayLn "go' iter' begin' $ value':acc'"
  203. -- Only generate a nonconst FromContents instance.
  204. when (cst == Nonconst) $ do
  205. ln
  206. saysLn ["instance HoppyFHR.FromContents ", hsDataTypeName,
  207. " (", prettyPrint hsValueType, ") where"]
  208. indent $ do
  209. sayLn "fromContents values' = do"
  210. indent $ do
  211. listNew <- toHsClassEntityName list "new"
  212. listPushBack <- toHsClassEntityName list "pushBack"
  213. saysLn ["list' <- ", listNew]
  214. saysLn ["HoppyP.mapM_ (", listPushBack, " list') values'"]
  215. sayLn "HoppyP.return list'"
  216. in Contents
  217. { c_list = list
  218. , c_iterator = iterator
  219. , c_constIterator = constIterator
  220. }
  221. -- | Converts an instantiation into a list of exports to be included in a
  222. -- module.
  223. toExports :: Contents -> [Export]
  224. toExports m = map (ExportClass . ($ m)) [c_list, c_iterator, c_constIterator]