packages feed

ddc-code-0.3.2.1: salt/primitive/Vector.dcs

-- | Vectors are arrays of unboxed values.
module Vector
imports {
        allocRaw     :: [r : Region]. Tag# -> Nat# -> Ptr# r Obj;
        payloadOfRaw :: [r : Region]. Ptr# r Obj -> Addr#;
} 
with letrec


-- Allocation -----------------------------------------------------------------
-- | Alloc a vector of the given length.
-- 
--   typedef struct
--   {  nat_t   length
--      uint8_t payload[] 
--   } Vector8
--
allocVector8 [r : Region] (length : Nat#) : Ptr# r Obj
 = do   
        -- total size of object payload.
        bytes   = add# [Nat#] (bytesNat# V#) length
        obj     = allocRaw [r] TAG0# bytes

        -- write the length field.
        payload = payloadOfRaw [r] obj
        write# [Nat#] payload 0# length

        -- zero fill vector
        fillVector8 [r] obj 0w8#

        obj


-- Projections ----------------------------------------------------------------
-- | Get the length of a vector.
lengthVector8 [r : Region] (obj : Ptr# r Obj) : Nat#
 = do   payload = payloadOfRaw [r] obj
        read# [Nat#] payload 0#


-- | Unsafely read a byte from a vector.
indexVector8 [r : Region] (obj : Ptr# r Obj) (index : Nat#) : Word8#
 = do   payload = payloadOfRaw [r] obj
        offset  = add# [Nat#] (bytesNat# V#) index
        read# [Word8#] payload offset 


-- Update ---------------------------------------------------------------------
-- | Unsafely write a byte into a vector.
updateVector8 
        [r : Region]
        (obj : Ptr# r Obj)
        (index : Nat#) (val : Word8#)
        : Void#
 = do   payload = payloadOfRaw [r] obj
        offset  = add# [Nat#] (bytesNat# V#) index
        write# [Word8#] payload offset val


-- Fill -----------------------------------------------------------------------
-- | Fill a vector with the given value.
fillVector8 
        [r : Region]
        (obj : Ptr# r Obj) (val : Word8#)
        : Void#
 = do   payload = payloadOfRaw [r] obj
        length  = read# [Nat#] payload 0#

        buf     = plusPtr# [r] [Word8#] (makePtr# [r] [Word8#] payload) (bytesNat# V#)
        max     = plusPtr# [r] [Word8#] buf length
        fillPtr8 [r] buf max val


-- | Fill a range of bytes with the given value.
fillPtr8 
        [r : Region] 
        (cur : Ptr# r Word8#) 
        (top : Ptr# r Word8#) (val : Word8#)
        : Void#
 = do   
        curAddr = takePtr# [r] [Word8#] cur
        topAddr = takePtr# [r] [Word8#] top
        case ge# [Addr#] curAddr topAddr of
         True#  -> V#
         False#  
          -> do poke# [r] [Word8#] cur 0# val
                next    = plusPtr# [r] [Word8#] cur 1#
                fillPtr8 [r] next top val


-- Copy -----------------------------------------------------------------------
-- | Copy a vector into a fresh buffer.
copyVector8 
        [r1 r2 : Region]
        (vec1 : Ptr# r1 Obj)
        : Ptr# r2 Obj
 = do   
        len     = lengthVector8 [r1] vec1
        vec2    = allocVector8  [r2] len

        src     = plusPtr# [r1] [Word8#]
                        (makePtr#  [r1] [Word8#] (payloadOfRaw [r1] vec1))
                        (bytesNat# V#)

        dst     = plusPtr# [r2] [Word8#]
                        (makePtr#  [r2] [Word8#] (payloadOfRaw [r2] vec2))
                        (bytesNat# V#)

        copyPtr8 [:r1 r2:] 0# len src dst
        vec2


copyPtr8
        [r1 r2 : Region]
        (offset : Nat#)
        (length : Nat#)
        (src : Ptr# r1 Word8#)
        (dst : Ptr# r2 Word8#)
        : Void#
 = do   
        case gt# [Nat#] offset length of
         True#   -> V#
         False#
          -> do x1       = peek# [r1] [Word8#] src offset
                poke# [r2] [Word8#] dst offset x1
                
                copyPtr8 [:r1 r2:] 
                        (add# [Nat#] offset 1#)
                        length src dst