content: -----------------------------------------------------------------------------
  --
  -- Module      :  JavaScript.Array
  -- Copyright   :  (c) Hamish Mackenzie
  -- License     :  MIT
  --
  -- Maintainer  :  Hamish Mackenzie <Hamish.K.Mackenzie@googlemail.com>
  --
  -- | Interface to JavaScript array
  --
  -----------------------------------------------------------------------------
  module JavaScript.Array
      ( SomeJSArray(..)
      , JSArray
      , MutableJSArray
      , create
      , length
      , lengthIO
      , null
      , fromList
      , fromListIO
      , toList
      , toListIO
      , index, (!)
      , read
      , write
      , append
      , push
      , pop
      , unshift
      , shift
      , reverse
      , take
      , takeIO
      , drop
      , dropIO
      , slice
      , sliceIO
      , freeze
      , unsafeFreeze
      , thaw
      , unsafeThaw
      ) where
  
  import Prelude hiding (length, drop, read, take, reverse, null)
  import Control.Monad (void)
  import Language.Javascript.JSaddle.Types
         (JSM, JSVal, SomeJSArray(..), JSArray,
          MutableJSArray, GHCJSPure(..))
  import Control.Lens.Operators ((^.))
  import Language.Javascript.JSaddle.Object (js2, js0, (<##), js1, js)
  import Language.Javascript.JSaddle.Value (valToNumber)
  import JavaScript.Array.Internal (create, fromList, fromListIO, toList, toListIO, index, read, push)
  
  length :: SomeJSArray m -> GHCJSPure Int
  length = GHCJSPure . lengthIO
  {-# INLINE length #-}
  
  lengthIO :: SomeJSArray m -> JSM Int
  lengthIO (SomeJSArray x) = round <$> (x ^. js "length" >>= valToNumber)
  {-# INLINE lengthIO #-}
  
  null :: SomeJSArray m -> GHCJSPure Bool
  null = GHCJSPure . fmap (== 0) . lengthIO
  {-# INLINE null #-}
  
  append :: SomeJSArray m -> SomeJSArray m -> JSM (SomeJSArray m1)
  append (SomeJSArray x) (SomeJSArray y) = SomeJSArray <$> x ^. js1 "concat" y
  {-# INLINE append #-}
  
  write :: Int -> JSVal -> MutableJSArray -> JSM ()
  write n e (SomeJSArray x) = void $ (x <## n) e
  {-# INLINE write #-}
  
  pop :: MutableJSArray -> JSM JSVal
  pop (SomeJSArray x) = x ^. js0 "pop"
  {-# INLINE pop #-}
  
  unshift :: JSVal -> MutableJSArray -> JSM ()
  unshift e (SomeJSArray x) = void $ x ^. js1 "unshift" e
  {-# INLINE unshift #-}
  
  shift :: MutableJSArray -> JSM JSVal
  shift (SomeJSArray x) = x ^. js0 "shift"
  {-# INLINE shift #-}
  
  reverse :: MutableJSArray -> JSM ()
  reverse (SomeJSArray x) = void $ x ^. js0 "reverse"
  {-# INLINE reverse #-}
  
  take :: Int -> SomeJSArray m -> GHCJSPure (SomeJSArray m1)
  take n = GHCJSPure . takeIO n
  {-# INLINE take #-}
  
  takeIO :: Int -> SomeJSArray m -> JSM (SomeJSArray m1)
  takeIO n (SomeJSArray x) = SomeJSArray <$> x ^. js2 "slice" (0::Int) n
  {-# INLINE takeIO #-}
  
  drop :: Int -> SomeJSArray m -> GHCJSPure (SomeJSArray m1)
  drop n = GHCJSPure . dropIO n
  {-# INLINE drop #-}
  
  dropIO :: Int -> SomeJSArray m -> JSM (SomeJSArray m1)
  dropIO n (SomeJSArray x) = SomeJSArray <$> x ^. js1 "slice1" n
  {-# INLINE dropIO #-}
  
  slice :: Int -> Int -> JSArray -> GHCJSPure (SomeJSArray m1)
  slice s n = GHCJSPure . sliceIO s n
  {-# INLINE slice #-}
  
  sliceIO :: Int -> Int -> JSArray -> JSM (SomeJSArray m1)
  sliceIO s n (SomeJSArray x) = SomeJSArray <$> x ^. js2 "slice" s n
  {-# INLINE sliceIO #-}
  
  freeze :: MutableJSArray -> JSM JSArray
  freeze (SomeJSArray x) = SomeJSArray <$> x ^. js1 "slice" (0::Int)
  {-# INLINE freeze #-}
  
  unsafeFreeze :: MutableJSArray -> JSM JSArray
  unsafeFreeze (SomeJSArray x) = pure (SomeJSArray x)
  {-# INLINE unsafeFreeze #-}
  
  thaw :: JSArray -> JSM MutableJSArray
  thaw (SomeJSArray x) = SomeJSArray <$> x ^. js1 "slice" (0::Int)
  {-# INLINE thaw #-}
  
  unsafeThaw :: JSArray -> JSM MutableJSArray
  unsafeThaw (SomeJSArray x) = pure (SomeJSArray x)
  {-# INLINE unsafeThaw #-}
  
  (!) :: JSArray -> Int -> GHCJSPure JSVal
  x ! n = GHCJSPure $ read n x
  {-# INLINE (!) #-}
  
  