@@ -26,13 +26,24 @@ module Data.Syntax.Combinator
2626 sepBy,
2727 sepBy1,
2828
29+ -- * Arrowized combinators.
30+ takeArr,
31+
2932 -- * Vectors.
3033 vecNSepBy,
3134 ivecNSepBy,
3235 vec,
3336 vecSepBy,
3437 ivec,
35− ivecSepBy
38+ ivecSepBy,
39+
40+ -- * Unboxed vectors.
41+ uvecNSepBy,
42+ uivecNSepBy,
43+ uvec,
44+ uvecSepBy,
45+ uivec,
46+ uivecSepBy
3647 ) where
3748
3849import Control.Category
@@ -40,10 +51,11 @@ import Control.Category.Structures
4051import Control.Lens
4152import Control.Lens.SemiIso
4253import Control.SIArrow
54+import qualified Data.MonoTraversable as Seq
4355import Data.Syntax
44−import Data.Vector (Vector)
4556import qualified Data.Vector as V
46−import Prelude hiding (id, (.))
57+import qualified Data.Vector.Unboxed as VU
58+import Prelude hiding (id, (.), take)
4759
4860-- | One or zero occurences of @f@.
4961optional :: SIArrow cat => cat () a -> cat () (Maybe a)
@@ -81,17 +93,22 @@ sepBy v s = sepBy1 v s /+/ sipure _Empty
8193sepBy1 :: SIArrow cat => cat () a -> cat () () -> cat () [a]
8294sepBy1 v s = _Cons /$/ v /*/ (s */ sepBy1 v s /+/ sipure _Empty)
8395
96+-- | A string of given length.
97+takeArr :: Syntax syn => syn Int (Seq syn)
98+takeArr = sibind $ iso (\n -> constant n #>> take n)
99+ (\s -> constant (Seq.olength s) #>> take (Seq.olength s))
100+
84101-- | Constant size vector with separators.
85102--
86103-- @vecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
87−vecNSepBy :: Syntax syn => Int -> syn () a -> syn () () -> syn () (Vector a)
104+vecNSepBy :: Syntax syn => Int -> syn () a -> syn () () -> syn () (V.Vector a)
88105vecNSepBy n e sep = ivecNSepBy n (unit ^>> second e) sep
89106
90107-- | Constant size vector with separators and index-aware elements.
91108--
92109-- @ivecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
93110-- Each element gets its index and should output a value and the index unchanged.
94−ivecNSepBy :: Syntax syn => Int -> syn Int (Int, a) -> syn () () -> syn () (Vector a)
111+ivecNSepBy :: Syntax syn => Int -> syn Int (Int, a) -> syn () () -> syn () (V.Vector a)
95112ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
96113 where
97114 el k | k < n - 1 = unit ^>> e *** sep >># unit
@@ -100,27 +117,74 @@ ivecNSepBy n e sep = ivecN n $ sibind $ iso el (el . fst)
100117-- | Runtime sized vector. The size can depend on the result of some computation.
101118--
102119-- @vec e@ describes a vector with elements @e@.
103−vec :: Syntax syn => syn () a -> syn Int (Vector a)
120+vec :: Syntax syn => syn () a -> syn Int (V.Vector a)
104121vec e = vecSepBy e (siarr id)
105122
106123-- | Runtime sized vector with separators. The size can depend on the result of some
107124-- computation.
108125--
109126-- @vecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
110−vecSepBy :: Syntax syn => syn () a -> syn () () -> syn Int (Vector a)
127+vecSepBy :: Syntax syn => syn () a -> syn () () -> syn Int (V.Vector a)
111128vecSepBy e sep = ivecSepBy (unit ^>> second e) sep
112129
113130-- | Runtime sized vector with index-aware elements. The size can depend on the result
114131-- of some computation.
115132--
116133-- @ivec e@ describes a vector with elements @e@.
117−ivec :: Syntax syn => syn Int (Int, a) -> syn Int (Vector a)
134+ivec :: Syntax syn => syn Int (Int, a) -> syn Int (V.Vector a)
118135ivec e = ivecSepBy e (siarr id)
119136
120137-- | Runtime sized vector with index-aware elements and separators. The size can depend
121138-- on the result of some computation.
122139--
123140-- @ivecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
124−ivecSepBy :: Syntax syn => syn Int (Int, a) -> syn () () -> syn Int (Vector a)
141+ivecSepBy :: Syntax syn => syn Int (Int, a) -> syn () () -> syn Int (V.Vector a)
125142ivecSepBy e sep = sibind $ iso (\n -> constant n #>> ivecNSepBy n e sep)
126143 (\v -> constant (V.length v) #>> ivecNSepBy (V.length v) e sep)
144+
145+-- | Constant size unboxed vector with separators.
146+--
147+-- @uvecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
148+uvecNSepBy :: (Syntax syn, VU.Unbox a) => Int -> syn () a -> syn () () -> syn () (VU.Vector a)
149+uvecNSepBy n e sep = uivecNSepBy n (unit ^>> second e) sep
150+
151+-- | Constant size unboxed vector with separators and index-aware elements.
152+--
153+-- @uivecNSepBy n e sep@ describes a size @n@ vector with elements @e@ separated by @sep@.
154+-- Each element gets its index and should output a value and the index unchanged.
155+uivecNSepBy :: (Syntax syn, VU.Unbox a) => Int -> syn Int (Int, a)
156+ -> syn () () -> syn () (VU.Vector a)
157+uivecNSepBy n e sep = uivecN n $ sibind $ iso el (el . fst)
158+ where
159+ el k | k < n - 1 = unit ^>> e *** sep >># unit
160+ | otherwise = e
161+
162+-- | Runtime sized unboxed vector. The size can depend on the result of some computation.
163+--
164+-- @uvec e@ describes a vector with elements @e@.
165+uvec :: (Syntax syn, VU.Unbox a) => syn () a -> syn Int (VU.Vector a)
166+uvec e = uvecSepBy e (siarr id)
167+
168+-- | Runtime sized unboxed vector with separators. The size can depend on the result of some
169+-- computation.
170+--
171+-- @uvecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
172+uvecSepBy :: (Syntax syn, VU.Unbox a) => syn () a -> syn () () -> syn Int (VU.Vector a)
173+uvecSepBy e sep = uivecSepBy (unit ^>> second e) sep
174+
175+-- | Runtime sized unboxed vector with index-aware elements. The size can depend on the result
176+-- of some computation.
177+--
178+-- @uivec e@ describes a vector with elements @e@.
179+uivec :: (Syntax syn, VU.Unbox a) => syn Int (Int, a) -> syn Int (VU.Vector a)
180+uivec e = uivecSepBy e (siarr id)
181+
182+-- | Runtime sized unboxed vector with index-aware elements and separators. The size can depend
183+-- on the result of some computation.
184+--
185+-- @uivecSepBy e sep@ describes a vector with elements @e@ separated by @sep@.
186+uivecSepBy :: (Syntax syn, VU.Unbox a) => syn Int (Int, a)
187+ -> syn () () -> syn Int (VU.Vector a)
188+uivecSepBy e sep = sibind $ iso (\n -> constant n #>> uivecNSepBy n e sep)
189+ (\v -> constant (VU.length v)
190+ #>> uivecNSepBy (VU.length v) e sep)