on master help sign in
Remove support for GHC 8.4.*
09ed99dAdithya Kumar
.circleci/config.yml+2−2
@@ -409,8 +409,8 @@ workflows:
409 #- cabal-ghc-8_0_2:
409 #- cabal-ghc-8_0_2:
410 # name: GHC 8.0.2 + no-test + no-bench + no-docs
410 # name: GHC 8.0.2 + no-test + no-bench + no-docs
411 #- cabal-ghc-7.10.3
411 #- cabal-ghc-7.10.3
412− - cabal-ghcjs-8_4:
412+ # - cabal-ghcjs-8_4:
413− name: GHCJS 8.4 + no-test + no-docs
413+ # name: GHCJS 8.4 + no-test + no-docs
414 #- stack-ghc-8.4
414 #- stack-ghc-8.4
415 #- stack-ghc-8.2
415 #- stack-ghc-8.2
416 #- coveralls-ghc-8.2.2
416 #- coveralls-ghc-8.2.2
.github/workflows/haskell.yml−7
@@ -157,13 +157,6 @@ jobs:
157 cabal_project: cabal.project
157 cabal_project: cabal.project
158 cabal_build_options: "--flag debug --flag -opt"
158 cabal_build_options: "--flag debug --flag -opt"
159 ignore_error: false
159 ignore_error: false
160− - name: 8.4.4-sdist
161− ghc_version: 8.4.4
162− runner: ubuntu-latest
163− build: cabal
164− cabal_version: 3.6.2.0
165− cabal_project: cabal.project
166− ignore_error: false
167
160
168 steps:
161 steps:
169 - uses: actions/checkout@v2
162 - uses: actions/checkout@v2
core/src/Streamly/Internal/Data/Unboxed.hs−122
@@ -113,128 +113,6 @@ unpin arr@(MutableByteArray marr#) =
113-- The Unboxed type class
113-- The Unboxed type class
114--------------------------------------------------------------------------------
114--------------------------------------------------------------------------------
115
115
116−#if !MIN_VERSION_base(4,12,0)
117−
118−#define SIZEOF_HSCHAR_PRIMITIVE 4#
119−#define SIZEOF_HSINT_PRIMITIVE 8#
120−#define SIZEOF_HSWORD_PRIMITIVE 8#
121−#define SIZEOF_WORD8_PRIMITIVE 1#
122−#define SIZEOF_WORD32_PRIMITIVE 4#
123−#define SIZEOF_WORD64_PRIMITIVE 8#
124−#define SIZEOF_HSDOUBLE_PRIMITIVE 8#
125−#define SIZEOF_INT32_PRIMITIVE 4#
126−#define SIZEOF_INT64_PRIMITIVE 8#
127−
128−#ifdef __GHCJS__
129−#define WORD64TYP Word64#
130−#else
131−#define WORD64TYP Word#
132−#endif
133−
134−#ifdef __GHCJS__
135−#define INT64TYP Int64#
136−#else
137−#define INT64TYP Int#
138−#endif
139−
140−{-# INLINE readWord8ArrayAsWideChar# #-}
141−readWord8ArrayAsWideChar# ::
142− MutableByteArray# d -> Int# -> State# d -> (# State# d, Char# #)
143−readWord8ArrayAsWideChar# arr# i# =
144− readWideCharArray# arr# (quotInt# i# SIZEOF_HSCHAR_PRIMITIVE)
145−
146−{-# INLINE writeWord8ArrayAsWideChar# #-}
147−writeWord8ArrayAsWideChar# ::
148− MutableByteArray# d -> Int# -> Char# -> State# d -> State# d
149−writeWord8ArrayAsWideChar# arr# i# =
150− writeWideCharArray# arr# (quotInt# i# SIZEOF_HSCHAR_PRIMITIVE)
151−
152−{-# INLINE readWord8ArrayAsInt# #-}
153−readWord8ArrayAsInt# ::
154− MutableByteArray# d -> Int# -> State# d -> (# State# d, Int# #)
155−readWord8ArrayAsInt# arr# i# =
156− readIntArray# arr# (quotInt# i# SIZEOF_HSINT_PRIMITIVE)
157−
158−{-# INLINE writeWord8ArrayAsInt# #-}
159−writeWord8ArrayAsInt# ::
160− MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
161−writeWord8ArrayAsInt# arr# i# =
162− writeIntArray# arr# (quotInt# i# SIZEOF_HSINT_PRIMITIVE)
163−
164−{-# INLINE readWord8ArrayAsInt32# #-}
165−readWord8ArrayAsInt32# ::
166− MutableByteArray# d -> Int# -> State# d -> (# State# d, Int# #)
167−readWord8ArrayAsInt32# arr# i# =
168− readInt32Array# arr# (quotInt# i# SIZEOF_INT32_PRIMITIVE)
169−
170−{-# INLINE writeWord8ArrayAsInt32# #-}
171−writeWord8ArrayAsInt32# ::
172− MutableByteArray# d -> Int# -> Int# -> State# d -> State# d
173−writeWord8ArrayAsInt32# arr# i# =
174− writeInt32Array# arr# (quotInt# i# SIZEOF_INT32_PRIMITIVE)
175−
176−{-# INLINE readWord8ArrayAsInt64# #-}
177−readWord8ArrayAsInt64# ::
178− MutableByteArray# d -> Int# -> State# d -> (# State# d, INT64TYP #)
179−readWord8ArrayAsInt64# arr# i# =
180− readInt64Array# arr# (quotInt# i# SIZEOF_INT64_PRIMITIVE)
181−
182−{-# INLINE writeWord8ArrayAsInt64# #-}
183−writeWord8ArrayAsInt64# ::
184− MutableByteArray# d -> Int# -> INT64TYP -> State# d -> State# d
185−writeWord8ArrayAsInt64# arr# i# =
186− writeInt64Array# arr# (quotInt# i# SIZEOF_INT64_PRIMITIVE)
187−
188−{-# INLINE readWord8ArrayAsWord# #-}
189−readWord8ArrayAsWord# ::
190− MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
191−readWord8ArrayAsWord# arr# i# =
192− readWordArray# arr# (quotInt# i# SIZEOF_HSWORD_PRIMITIVE)
193−
194−{-# INLINE writeWord8ArrayAsWord# #-}
195−writeWord8ArrayAsWord# ::
196− MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
197−writeWord8ArrayAsWord# arr# i# =
198− writeWordArray# arr# (quotInt# i# SIZEOF_HSWORD_PRIMITIVE)
199−
200−{-# INLINE readWord8ArrayAsWord32# #-}
201−readWord8ArrayAsWord32# ::
202− MutableByteArray# d -> Int# -> State# d -> (# State# d, Word# #)
203−readWord8ArrayAsWord32# arr# i# =
204− readWord32Array# arr# (quotInt# i# SIZEOF_WORD32_PRIMITIVE)
205−
206−{-# INLINE writeWord8ArrayAsWord32# #-}
207−writeWord8ArrayAsWord32# ::
208− MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
209−writeWord8ArrayAsWord32# arr# i# =
210− writeWord32Array# arr# (quotInt# i# SIZEOF_WORD32_PRIMITIVE)
211−
212−{-# INLINE readWord8ArrayAsWord64# #-}
213−readWord8ArrayAsWord64# ::
214− MutableByteArray# d -> Int# -> State# d -> (# State# d, WORD64TYP #)
215−readWord8ArrayAsWord64# arr# i# =
216− readWord64Array# arr# (quotInt# i# SIZEOF_WORD64_PRIMITIVE)
217−
218−{-# INLINE writeWord8ArrayAsWord64# #-}
219−writeWord8ArrayAsWord64# ::
220− MutableByteArray# d -> Int# -> WORD64TYP -> State# d -> State# d
221−writeWord8ArrayAsWord64# arr# i# =
222− writeWord64Array# arr# (quotInt# i# SIZEOF_WORD64_PRIMITIVE)
223−
224−{-# INLINE readWord8ArrayAsDouble# #-}
225−readWord8ArrayAsDouble# ::
226− MutableByteArray# d -> Int# -> State# d -> (# State# d, Double# #)
227−readWord8ArrayAsDouble# arr# i# =
228− readDoubleArray# arr# (quotInt# i# SIZEOF_HSDOUBLE_PRIMITIVE)
229−
230−{-# INLINE writeWord8ArrayAsDouble# #-}
231−writeWord8ArrayAsDouble# ::
232− MutableByteArray# d -> Int# -> Double# -> State# d -> State# d
233−writeWord8ArrayAsDouble# arr# i# =
234− writeDoubleArray# arr# (quotInt# i# SIZEOF_HSDOUBLE_PRIMITIVE)
235−
236−#endif
237−
238-- In theory we could convert a type to and from a byte stream and use that
116-- In theory we could convert a type to and from a byte stream and use that
239-- to implement boxing, unboxing. But that would be inefficient. This type
117-- to implement boxing, unboxing. But that would be inefficient. This type
240-- class allows each primitive type to have its own specific efficient
118-- class allows each primitive type to have its own specific efficient
docs/User/ProjectRelated/Changelog.md+1
@@ -3,6 +3,7 @@
3<!-- See rendered changelog at https://streamly.composewell.com -->
3<!-- See rendered changelog at https://streamly.composewell.com -->
4## Unreleased
4## Unreleased
5
5
6+* Remove support for GHC 8.4.*
6* The unboxed arrays now require `Unbox` instance along with `Storable` for the
7* The unboxed arrays now require `Unbox` instance along with `Storable` for the
7 stored type. The `Unbox` typeclass can be found in `Streamly.Data.Unbox`.
8 stored type. The `Unbox` typeclass can be found in `Streamly.Data.Unbox`.
8* New modules for unboxed mutable & unboxed immutable arrays are added.
9* New modules for unboxed mutable & unboxed immutable arrays are added.
src/Streamly/Internal/Data/SVar/Dispatch.hs−3
@@ -46,9 +46,6 @@ import Control.Monad (when, void)
46import Control.Monad.IO.Class (MonadIO(liftIO))
46import Control.Monad.IO.Class (MonadIO(liftIO))
47import Data.Maybe (fromJust, fromMaybe)
47import Data.Maybe (fromJust, fromMaybe)
48import Data.IORef (IORef, modifyIORef, newIORef, readIORef, writeIORef)
48import Data.IORef (IORef, modifyIORef, newIORef, readIORef, writeIORef)
49−#if __GLASGOW_HASKELL__ < 804
50−import Data.Semigroup ((<>))
51−#endif
52import Streamly.Internal.Control.Concurrent (MonadAsync, askRunInIO)
49import Streamly.Internal.Control.Concurrent (MonadAsync, askRunInIO)
53import Streamly.Internal.Control.ForkLifted (doFork)
50import Streamly.Internal.Control.ForkLifted (doFork)
54import Streamly.Internal.Data.Atomics
51import Streamly.Internal.Data.Atomics
src/Streamly/Internal/Data/Stream/Async/Channel/Dispatcher.hs−3
@@ -44,9 +44,6 @@ import Control.Monad (when, void)
44import Control.Monad.IO.Class (MonadIO(liftIO))
44import Control.Monad.IO.Class (MonadIO(liftIO))
45import Data.Maybe (fromJust, fromMaybe)
45import Data.Maybe (fromJust, fromMaybe)
46import Data.IORef (IORef, modifyIORef, newIORef, readIORef, writeIORef)
46import Data.IORef (IORef, modifyIORef, newIORef, readIORef, writeIORef)
47−#if __GLASGOW_HASKELL__ < 804
48−import Data.Semigroup ((<>))
49−#endif
50import Streamly.Internal.Control.ForkLifted (doFork)
47import Streamly.Internal.Control.ForkLifted (doFork)
51import Streamly.Internal.Data.Atomics
48import Streamly.Internal.Data.Atomics
52 (atomicModifyIORefCAS, atomicModifyIORefCAS_, writeBarrier,
49 (atomicModifyIORefCAS, atomicModifyIORefCAS_, writeBarrier,
src/Streamly/Internal/Data/Stream/IsStream/Type.hs−2
@@ -152,13 +152,11 @@ infixr 5 |:
152--
152--
153-- @since 0.8.0
153-- @since 0.8.0
154class
154class
155−#if __GLASGOW_HASKELL__ >= 806
156 ( forall m a. MonadAsync m => Semigroup (t m a)
155 ( forall m a. MonadAsync m => Semigroup (t m a)
157 , forall m a. MonadAsync m => Monoid (t m a)
156 , forall m a. MonadAsync m => Monoid (t m a)
158 , forall m. Monad m => Functor (t m)
157 , forall m. Monad m => Functor (t m)
159 , forall m. MonadAsync m => Applicative (t m)
158 , forall m. MonadAsync m => Applicative (t m)
160 ) =>
159 ) =>
161−#endif
162 IsStream t where
160 IsStream t where
163 toStream :: t m a -> K.Stream m a
161 toStream :: t m a -> K.Stream m a
164 fromStream :: K.Stream m a -> t m a
162 fromStream :: K.Stream m a -> t m a
src/Streamly/Internal/FileSystem/FDIO.hs−5
@@ -57,13 +57,8 @@ isNonBlocking fd = fdIsNonBlocking fd /= 0
57
57
58-- "poll"s the fd for data to become available or timeout
58-- "poll"s the fd for data to become available or timeout
59-- See cbits/inputReady.c in base package
59-- See cbits/inputReady.c in base package
60−#if __GLASGOW_HASKELL__ >= 804
61foreign import ccall unsafe "fdReady"
60foreign import ccall unsafe "fdReady"
62 unsafe_fdReady :: CInt -> CBool -> Int64 -> CBool -> IO CInt
61 unsafe_fdReady :: CInt -> CBool -> Int64 -> CBool -> IO CInt
63−#else
64−foreign import ccall safe "fdReady"
65− unsafe_fdReady :: CInt -> CInt -> CInt -> CInt -> IO CInt
66−#endif
67
62
68writeNonBlocking :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
63writeNonBlocking :: String -> FD -> Ptr Word8 -> Int -> CSize -> IO CInt
69writeNonBlocking loc !fd !buf !off !len
64writeNonBlocking loc !fd !buf !off !len
streamly.cabal+1−2
@@ -31,8 +31,7 @@ homepage: https://streamly.composewell.com
31bug-reports: https://github.com/composewell/streamly/issues
31bug-reports: https://github.com/composewell/streamly/issues
32license: BSD-3-Clause
32license: BSD-3-Clause
33license-file: LICENSE
33license-file: LICENSE
34−tested-with: GHC==8.4.4
34+tested-with: GHC==8.6.5
35− , GHC==8.6.5
36 , GHC==8.8.4
35 , GHC==8.8.4
37 , GHC==8.10.7
36 , GHC==8.10.7
38 , GHC==9.0.2
37 , GHC==9.0.2
test/Streamly/Test/Data/Unfold.hs−6
@@ -410,8 +410,6 @@ enumerateFromThenToSmallUnit =
410 in testUnfold unf (f :: (), th, to) $
410 in testUnfold unf (f :: (), th, to) $
411 Prelude.take 1 $ Prelude.enumFromThenTo f th to
411 Prelude.take 1 $ Prelude.enumFromThenTo f th to
412
412
413−
414−#if MIN_VERSION_base(4,12,0)
415enumerateFromFractional :: Property
413enumerateFromFractional :: Property
416enumerateFromFractional =
414enumerateFromFractional =
417 property
415 property
@@ -443,8 +441,6 @@ enumerateFromToFractional =
443 let unf = UF.enumerateFromToFractional
441 let unf = UF.enumerateFromToFractional
444 in testUnfold unf (f :: Double, t) [f..(t :: Double)]
442 in testUnfold unf (f :: Double, t) [f..(t :: Double)]
445
443
446−#endif
447−
448-------------------------------------------------------------------------------
444-------------------------------------------------------------------------------
449-- Stream transformation
445-- Stream transformation
450-------------------------------------------------------------------------------
446-------------------------------------------------------------------------------
@@ -651,12 +647,10 @@ testGeneration =
651 prop "enumerateFromToSmallBool" enumerateFromToSmallBool
647 prop "enumerateFromToSmallBool" enumerateFromToSmallBool
652 prop "enumerateFromThenToSmallBool" enumerateFromThenToSmallBool
648 prop "enumerateFromThenToSmallBool" enumerateFromThenToSmallBool
653
649
654−#if MIN_VERSION_base(4,12,0)
655 prop "enumerateFromFractional" enumerateFromFractional
650 prop "enumerateFromFractional" enumerateFromFractional
656 prop "enumerateFromThenFractional" enumerateFromThenFractional
651 prop "enumerateFromThenFractional" enumerateFromThenFractional
657 prop "enumerateFromToFractional" enumerateFromToFractional
652 prop "enumerateFromToFractional" enumerateFromToFractional
658 prop "enumerateFromThenToFractional" enumerateFromThenToFractional
653 prop "enumerateFromThenToFractional" enumerateFromThenToFractional
659−#endif
660
654
661testTransformation :: Spec
655testTransformation :: Spec
662testTransformation =
656testTransformation =
test/Streamly/Test/Prelude/Serial.hs−2
@@ -555,10 +555,8 @@ main = hspec
555 serialOps $ prop "serially replicateM" . constructWithReplicateM
555 serialOps $ prop "serially replicateM" . constructWithReplicateM
556 serialOps $ prop "serially intFromThenTo" .
556 serialOps $ prop "serially intFromThenTo" .
557 constructWithIntFromThenTo
557 constructWithIntFromThenTo
558−#if __GLASGOW_HASKELL__ >= 806
559 serialOps $ prop "serially DoubleFromThenTo" .
558 serialOps $ prop "serially DoubleFromThenTo" .
560 constructWithDoubleFromThenTo
559 constructWithDoubleFromThenTo
561−#endif
562 serialOps $ prop "serially iterate" . constructWithIterate
560 serialOps $ prop "serially iterate" . constructWithIterate
563 -- XXX test for all types of streams
561 -- XXX test for all types of streams
564 serialOps $ prop "serially iterateM" . constructWithIterateM
562 serialOps $ prop "serially iterateM" . constructWithIterateM
test/lib/Streamly/Test/Prelude/Common.hs+7−39
@@ -15,9 +15,7 @@ module Streamly.Test.Prelude.Common
15 , constructWithReplicate
15 , constructWithReplicate
16 , constructWithReplicateM
16 , constructWithReplicateM
17 , constructWithIntFromThenTo
17 , constructWithIntFromThenTo
18−#if __GLASGOW_HASKELL__ >= 806
19 , constructWithDoubleFromThenTo
18 , constructWithDoubleFromThenTo
20−#endif
21 , constructWithIterate
19 , constructWithIterate
22 , constructWithIterateM
20 , constructWithIterateM
23 , constructWithEnumerate
21 , constructWithEnumerate
@@ -221,7 +219,6 @@ constructWithRepeatM = constructWithLenM stream list
221 stream n = S.take n $ S.repeatM (return 1)
219 stream n = S.take n $ S.repeatM (return 1)
222 list n = return $ replicate n 1
220 list n = return $ replicate n 1
223
221
224−#if __GLASGOW_HASKELL__ >= 806
225-- XXX try very small steps close to 0
222-- XXX try very small steps close to 0
226constructWithDoubleFromThenTo
223constructWithDoubleFromThenTo
227 :: IsStream t
224 :: IsStream t
@@ -235,7 +232,6 @@ constructWithDoubleFromThenTo op l =
235 let list len = take len [from,next..to]
232 let list len = take len [from,next..to]
236 stream len = S.take len $ S.enumerateFromThenTo from next to
233 stream len = S.take len $ S.enumerateFromThenTo from next to
237 in constructWithLen stream list op l
234 in constructWithLen stream list op l
238−#endif
239
235
240constructWithIterate ::
236constructWithIterate ::
241 IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
237 IsStream t => (t IO Int -> SerialT IO Int) -> Word8 -> Property
@@ -396,11 +392,7 @@ constructWithUnfoldr listT op len =
396 else Just (seed, seed + 1)
392 else Just (seed, seed + 1)
397
393
398constructWithFromPure ::
394constructWithFromPure ::
399− (IsStream t
400−#if __GLASGOW_HASKELL__ < 806
401− , Monoid (t IO Int)
395+ (IsStream t, Monoid (t IO Int))
402−#endif
403− )
404 => ([Int] -> [Int])
396 => ([Int] -> [Int])
405 -> (t IO Int -> SerialT IO Int)
397 -> (t IO Int -> SerialT IO Int)
406 -> Word8
398 -> Word8
@@ -416,11 +408,7 @@ constructWithFromPure listT op len =
416 listEquals (==) (listT strm) list
408 listEquals (==) (listT strm) list
417
409
418constructWithFromEffect ::
410constructWithFromEffect ::
419− (IsStream t
420−#if __GLASGOW_HASKELL__ < 806
421− , Monoid (t IO Int)
411+ (IsStream t, Monoid (t IO Int))
422−#endif
423− )
424 => ([Int] -> [Int])
412 => ([Int] -> [Int])
425 -> (t IO Int -> SerialT IO Int)
413 -> (t IO Int -> SerialT IO Int)
426 -> Word8
414 -> Word8
@@ -1033,11 +1021,7 @@ foldFromList constr op eq = transformFromList constr eq id op
1033
1021
1034-- XXX concatenate streams of multiple elements rather than single elements
1022-- XXX concatenate streams of multiple elements rather than single elements
1035semigroupOps
1023semigroupOps
1036− :: (IsStream t
1037−#if __GLASGOW_HASKELL__ < 804
1038− , Semigroup (t IO Int)
1039−#endif
1040− , Monoid (t IO Int))
1024+ :: (IsStream t, Monoid (t IO Int))
1041 => String
1025 => String
1042 -> ([Int] -> [Int] -> Bool)
1026 -> ([Int] -> [Int] -> Bool)
1043 -> (t IO Int -> SerialT IO Int)
1027 -> (t IO Int -> SerialT IO Int)
@@ -1469,11 +1453,7 @@ bracketPartialStreamProp t vec =
1469#endif
1453#endif
1470
1454
1471bracketExceptionProp ::
1455bracketExceptionProp ::
1472− (IsStream t, MonadThrow (t IO)
1456+ (IsStream t, MonadThrow (t IO), Semigroup (t IO Int))
1473−#if __GLASGOW_HASKELL__ < 806
1474− , Semigroup (t IO Int)
1475−#endif
1476− )
1477 => (t IO Int -> SerialT IO Int)
1457 => (t IO Int -> SerialT IO Int)
1478 -> Property
1458 -> Property
1479bracketExceptionProp t =
1459bracketExceptionProp t =
@@ -1560,11 +1540,7 @@ finallyPartialStreamProp t vec =
1560#endif
1540#endif
1561
1541
1562finallyExceptionProp ::
1542finallyExceptionProp ::
1563− (IsStream t, MonadThrow (t IO)
1543+ (IsStream t, MonadThrow (t IO), Semigroup (t IO Int))
1564−#if __GLASGOW_HASKELL__ < 806
1565− , Semigroup (t IO Int)
1566−#endif
1567− )
1568 => (t IO Int -> SerialT IO Int)
1544 => (t IO Int -> SerialT IO Int)
1569 -> Property
1545 -> Property
1570finallyExceptionProp t =
1546finallyExceptionProp t =
@@ -1582,11 +1558,7 @@ finallyExceptionProp t =
1582 assert $ refValue == 1
1558 assert $ refValue == 1
1583
1559
1584onExceptionProp ::
1560onExceptionProp ::
1585− (IsStream t, MonadThrow (t IO)
1561+ (IsStream t, MonadThrow (t IO), Semigroup (t IO Int))
1586−#if __GLASGOW_HASKELL__ < 806
1587− , Semigroup (t IO Int)
1588−#endif
1589− )
1590 => (t IO Int -> SerialT IO Int)
1562 => (t IO Int -> SerialT IO Int)
1591 -> Property
1563 -> Property
1592onExceptionProp t =
1564onExceptionProp t =
@@ -1620,11 +1592,7 @@ handleProp t vec =
1620 assert $ res == vec ++ [0] ++ vec
1592 assert $ res == vec ++ [0] ++ vec
1621
1593
1622exceptionOps ::
1594exceptionOps ::
1623− (IsStream t, MonadThrow (t IO)
1595+ (IsStream t, MonadThrow (t IO), Semigroup (t IO Int))
1624−#if __GLASGOW_HASKELL__ < 806
1625− , Semigroup (t IO Int)
1626−#endif
1627− )
1628 => String
1596 => String
1629 -> (t IO Int -> SerialT IO Int)
1597 -> (t IO Int -> SerialT IO Int)
1630 -> Spec
1598 -> Spec