mirror of
https://github.com/urbit/shrub.git
synced 2024-12-20 17:32:11 +03:00
Fixed a back-ref bug in my old jam, and got my fast jam to pass tests.
This commit is contained in:
parent
3c25a1bb6e
commit
d445c1cbb1
@ -21,7 +21,7 @@ import Data.Hashable (Hashable)
|
|||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
newtype Atom = MkAtom { unAtom :: Natural }
|
newtype Atom = MkAtom { unAtom :: Natural }
|
||||||
deriving newtype (Eq, Ord, Num, Bits, Enum, Real, Integral, Flat, Hashable)
|
deriving newtype (Eq, Ord, Num, Bits, Enum, Real, Integral, Flat, Hashable, NFData)
|
||||||
|
|
||||||
instance Show Atom where
|
instance Show Atom where
|
||||||
show (MkAtom a) = show a
|
show (MkAtom a) = show a
|
||||||
@ -109,6 +109,9 @@ instance IsAtom Integer where
|
|||||||
wordBitWidth# :: Word# -> Word#
|
wordBitWidth# :: Word# -> Word#
|
||||||
wordBitWidth# w = minusWord# 64## (clz# w)
|
wordBitWidth# w = minusWord# 64## (clz# w)
|
||||||
|
|
||||||
|
wordBitWidth :: Word -> Word
|
||||||
|
wordBitWidth (W# w) = W# (wordBitWidth# w)
|
||||||
|
|
||||||
bigNatBitWidth# :: BigNat -> Word#
|
bigNatBitWidth# :: BigNat -> Word#
|
||||||
bigNatBitWidth# nat =
|
bigNatBitWidth# nat =
|
||||||
lswBits `plusWord#` ((int2Word# lastIdx) `timesWord#` 64##)
|
lswBits `plusWord#` ((int2Word# lastIdx) `timesWord#` 64##)
|
||||||
@ -141,24 +144,30 @@ instance IsAtom Cursor where
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{-# INLINE slice #-}
|
||||||
slice :: (Atom, Atom) -> Atom -> Atom
|
slice :: (Atom, Atom) -> Atom -> Atom
|
||||||
slice (offset, size) buf =
|
slice (offset, size) buf =
|
||||||
fromSlice (Slice (fromAtom offset) (fromAtom size) buf)
|
fromSlice (Slice (fromAtom offset) (fromAtom size) buf)
|
||||||
|
|
||||||
|
{-# INLINE fromSlice #-}
|
||||||
fromSlice :: Slice -> Atom
|
fromSlice :: Slice -> Atom
|
||||||
fromSlice (Slice off wid buf) = mask .&. (shiftR buf off)
|
fromSlice (Slice off wid buf) = takeBits wid (shiftR buf off)
|
||||||
where mask = shiftL (MkAtom 1) wid - 1
|
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{-# INLINE takeBits #-}
|
||||||
takeBits :: Int -> Atom -> Atom
|
takeBits :: Int -> Atom -> Atom
|
||||||
takeBits wid buf = mask .&. buf
|
takeBits wid buf = buf .&. (shiftL (MkAtom 1) wid - 1)
|
||||||
where mask = shiftL (MkAtom 1) wid - 1
|
|
||||||
|
|
||||||
|
{-# INLINE takeBitsWord #-}
|
||||||
|
takeBitsWord :: Int -> Word -> Word
|
||||||
|
takeBitsWord wid wor = wor .&. (shiftL 1 wid - 1)
|
||||||
|
|
||||||
|
{-# INLINE bitIdx #-}
|
||||||
bitIdx :: Int -> Atom -> Bool
|
bitIdx :: Int -> Atom -> Bool
|
||||||
bitIdx idx buf = testBit buf idx
|
bitIdx idx buf = testBit buf idx
|
||||||
|
|
||||||
|
{-# INLINE bitConcat #-}
|
||||||
bitConcat :: Atom -> Atom -> Atom
|
bitConcat :: Atom -> Atom -> Atom
|
||||||
bitConcat x y = x .|. shiftL y (bitWidth x)
|
bitConcat x y = x .|. shiftL y (bitWidth x)
|
||||||
|
|
||||||
|
@ -15,6 +15,9 @@ import Test.Tasty.TH
|
|||||||
import Test.Tasty.QuickCheck as QC
|
import Test.Tasty.QuickCheck as QC
|
||||||
import Test.QuickCheck
|
import Test.QuickCheck
|
||||||
|
|
||||||
|
import qualified Data.Noun.Jam.Put as Fast
|
||||||
|
import qualified Data.Noun.Pill as Pill
|
||||||
|
|
||||||
|
|
||||||
-- Length-Encoded Atoms --------------------------------------------------------
|
-- Length-Encoded Atoms --------------------------------------------------------
|
||||||
|
|
||||||
@ -51,7 +54,7 @@ jam' = toAtom . fst . go 0 mempty
|
|||||||
where
|
where
|
||||||
insertNoun :: Noun -> Int -> Map Noun Int -> Map Noun Int
|
insertNoun :: Noun -> Int -> Map Noun Int -> Map Noun Int
|
||||||
insertNoun n i tbl = lookup n tbl
|
insertNoun n i tbl = lookup n tbl
|
||||||
& maybe tbl (const $ insertMap n i tbl)
|
& maybe (insertMap n i tbl) (const tbl)
|
||||||
|
|
||||||
go :: Int -> Map Noun Int -> Noun -> (Buf, Map Noun Int)
|
go :: Int -> Map Noun Int -> Noun -> (Buf, Map Noun Int)
|
||||||
go off oldTbl noun =
|
go off oldTbl noun =
|
||||||
@ -69,7 +72,7 @@ jam' = toAtom . fst . go 0 mempty
|
|||||||
(Nothing, Cell lef rit) ->
|
(Nothing, Cell lef rit) ->
|
||||||
(Buf (2+lSz+rSz) (xor 1 (shiftL (lRes .|. shiftL rRes lSz) 2)), rTbl)
|
(Buf (2+lSz+rSz) (xor 1 (shiftL (lRes .|. shiftL rRes lSz) 2)), rTbl)
|
||||||
where (Buf lSz lRes, lTbl) = go (off+2) tbl lef
|
where (Buf lSz lRes, lTbl) = go (off+2) tbl lef
|
||||||
(Buf rSz rRes, rTbl) = go (off+lSz) lTbl rit
|
(Buf rSz rRes, rTbl) = go (off+2+lSz) lTbl rit
|
||||||
|
|
||||||
cue' :: Atom -> Maybe Noun
|
cue' :: Atom -> Maybe Noun
|
||||||
cue' buf = view _2 <$> go mempty 0
|
cue' buf = view _2 <$> go mempty 0
|
||||||
@ -98,7 +101,7 @@ mat atm = Buf bufWid buffer
|
|||||||
where
|
where
|
||||||
atmWid = bitWidth atm
|
atmWid = bitWidth atm
|
||||||
preWid = bitWidth (toAtom atmWid)
|
preWid = bitWidth (toAtom atmWid)
|
||||||
bufWid = preWid + preWid + atmWid
|
bufWid = 2*preWid + atmWid
|
||||||
prefix = shiftL 1 preWid
|
prefix = shiftL 1 preWid
|
||||||
extras = takeBits (preWid-1) (toAtom atmWid)
|
extras = takeBits (preWid-1) (toAtom atmWid)
|
||||||
suffix = xor extras (shiftL atm (preWid-1))
|
suffix = xor extras (shiftL atm (preWid-1))
|
||||||
@ -114,9 +117,9 @@ rub slc@(Cursor idx buf) =
|
|||||||
prefix -> pure (Buf sz val)
|
prefix -> pure (Buf sz val)
|
||||||
where
|
where
|
||||||
widIdx = idx + 1 + prefix
|
widIdx = idx + 1 + prefix
|
||||||
width = fromSlice (Slice widIdx (prefix - 1) buf)
|
extra = fromSlice (Slice widIdx (prefix - 1) buf)
|
||||||
datIdx = widIdx + (prefix-1)
|
datIdx = widIdx + (prefix-1)
|
||||||
datWid = fromIntegral $ 2^(prefix-1) + width
|
datWid = fromIntegral $ extra + 2^(prefix-1)
|
||||||
sz = datWid + (2*prefix)
|
sz = datWid + (2*prefix)
|
||||||
val = fromSlice (Slice datIdx datWid buf)
|
val = fromSlice (Slice datIdx datWid buf)
|
||||||
|
|
||||||
@ -130,7 +133,7 @@ jam = toAtom . fst . go 0 mempty
|
|||||||
where
|
where
|
||||||
insertNoun :: Noun -> Int -> Map Noun Int -> Map Noun Int
|
insertNoun :: Noun -> Int -> Map Noun Int -> Map Noun Int
|
||||||
insertNoun n i tbl = lookup n tbl
|
insertNoun n i tbl = lookup n tbl
|
||||||
& maybe tbl (const $ insertMap n i tbl)
|
& maybe (insertMap n i tbl) (const tbl)
|
||||||
|
|
||||||
go :: Int -> Map Noun Int -> Noun -> (Buf, Map Noun Int)
|
go :: Int -> Map Noun Int -> Noun -> (Buf, Map Noun Int)
|
||||||
go off oldTbl noun =
|
go off oldTbl noun =
|
||||||
@ -148,7 +151,7 @@ jam = toAtom . fst . go 0 mempty
|
|||||||
(Nothing, Cell lef rit) ->
|
(Nothing, Cell lef rit) ->
|
||||||
(Buf (2+lSz+rSz) (xor 1 (shiftL (bitConcat lRes rRes) 2)), rTbl)
|
(Buf (2+lSz+rSz) (xor 1 (shiftL (bitConcat lRes rRes) 2)), rTbl)
|
||||||
where (Buf lSz lRes, lTbl) = go (off+2) tbl lef
|
where (Buf lSz lRes, lTbl) = go (off+2) tbl lef
|
||||||
(Buf rSz rRes, rTbl) = go (off+lSz) lTbl rit
|
(Buf rSz rRes, rTbl) = go (off+2+lSz) lTbl rit
|
||||||
|
|
||||||
leadingZeros :: Cursor -> Maybe Int
|
leadingZeros :: Cursor -> Maybe Int
|
||||||
leadingZeros (Cursor idx buf) = go 0
|
leadingZeros (Cursor idx buf) = go 0
|
||||||
@ -163,17 +166,15 @@ cue buf = view _2 <$> go mempty 0
|
|||||||
where
|
where
|
||||||
go :: Map Int Noun -> Int -> Maybe (Int, Noun, Map Int Noun)
|
go :: Map Int Noun -> Int -> Maybe (Int, Noun, Map Int Noun)
|
||||||
go tbl i =
|
go tbl i =
|
||||||
-- trace ("go-" <> show i)
|
|
||||||
case (bitIdx i buf, bitIdx (i+1) buf) of
|
case (bitIdx i buf, bitIdx (i+1) buf) of
|
||||||
(False, _ ) -> do Buf wid at <- rub (Cursor (i+1) buf)
|
(False, _ ) -> do Buf wid at <- rub (Cursor (i+1) buf)
|
||||||
let r = Atom at
|
let r = Atom at
|
||||||
pure (wid+1, r, insertMap i r tbl)
|
pure (1+wid, r, insertMap i r tbl)
|
||||||
(True, False ) -> do (lSz,lef,tbl) <- go tbl (i+2)
|
(True, False ) -> do (lSz,lef,tbl) <- go tbl (i+2)
|
||||||
(rSz,rit,tbl) <- go tbl (i+2+fromIntegral lSz)
|
(rSz,rit,tbl) <- go tbl (i+2+fromIntegral lSz)
|
||||||
let r = Cell lef rit
|
let r = Cell lef rit
|
||||||
pure (2+lSz+rSz, r, insertMap i r tbl)
|
pure (2+lSz+rSz, r, insertMap i r tbl)
|
||||||
(True, True ) -> do Buf wid at <- rub (Cursor (i+2) buf)
|
(True, True ) -> do Buf wid at <- rub (Cursor (i+2) buf)
|
||||||
-- traceM ("ref-" <> show at)
|
|
||||||
r <- lookup (fromIntegral at) tbl & \case
|
r <- lookup (fromIntegral at) tbl & \case
|
||||||
Nothing -> error ("bad-ref-" <> show at)
|
Nothing -> error ("bad-ref-" <> show at)
|
||||||
Just ix -> Just ix
|
Just ix -> Just ix
|
||||||
@ -182,6 +183,21 @@ cue buf = view _2 <$> go mempty 0
|
|||||||
|
|
||||||
-- Tests -----------------------------------------------------------------------
|
-- Tests -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
a12 = Atom 12
|
||||||
|
a36 = Atom 36
|
||||||
|
a9 = Atom 9
|
||||||
|
|
||||||
|
d12 = Cell a12 a12
|
||||||
|
q12 = Cell d12 d12
|
||||||
|
|
||||||
|
midleEx = Cell a36 $ Cell a9 $ Cell q12 q12
|
||||||
|
|
||||||
|
smallEx = Cell (Cell (Atom 14) (Atom 8))
|
||||||
|
$ Cell (Atom 15) (Atom 15)
|
||||||
|
|
||||||
|
smallEx2 = Cell (Cell (Atom 0) (Atom 0))
|
||||||
|
$ Cell (Atom 10) (Atom 10)
|
||||||
|
|
||||||
pills :: [Atom]
|
pills :: [Atom]
|
||||||
pills = [ 0x2, 0xc, 0x48, 0x29, 0xc9, 0x299
|
pills = [ 0x2, 0xc, 0x48, 0x29, 0xc9, 0x299
|
||||||
, 0x3170_c7c1, 0x93_c7c1, 0xa_72e0, 0x1bd5_b7dd_e080
|
, 0x3170_c7c1, 0x93_c7c1, 0xa_72e0, 0x1bd5_b7dd_e080
|
||||||
@ -193,6 +209,15 @@ cueTest = traverse cue pills
|
|||||||
jamTest :: Maybe [Atom]
|
jamTest :: Maybe [Atom]
|
||||||
jamTest = fmap jam <$> cueTest
|
jamTest = fmap jam <$> cueTest
|
||||||
|
|
||||||
|
prop_fastMatSlow :: Atom -> Bool
|
||||||
|
prop_fastMatSlow a = jam (Atom a) == Fast.jam (Atom a)
|
||||||
|
|
||||||
|
prop_fastJamSlow :: Noun -> Bool
|
||||||
|
prop_fastJamSlow n = jam n == Fast.jam n
|
||||||
|
|
||||||
|
prop_fastJam :: Noun -> Bool
|
||||||
|
prop_fastJam n = Just n == cue (Fast.jam n)
|
||||||
|
|
||||||
prop_jamCue :: Noun -> Bool
|
prop_jamCue :: Noun -> Bool
|
||||||
prop_jamCue n = Just n == cue (jam n)
|
prop_jamCue n = Just n == cue (jam n)
|
||||||
|
|
||||||
|
@ -7,16 +7,17 @@ import GHC.Prim
|
|||||||
import GHC.Natural
|
import GHC.Natural
|
||||||
import GHC.Integer.GMP.Internals
|
import GHC.Integer.GMP.Internals
|
||||||
|
|
||||||
import Control.Lens (view)
|
import Control.Lens (view, to, from, (&))
|
||||||
import Control.Monad (guard)
|
import Control.Monad (guard)
|
||||||
import Data.Bits (shiftL, shiftR, setBit, clearBit, (.|.), (.&.))
|
import Data.Bits (shiftL, shiftR, setBit, clearBit, (.|.), (.&.))
|
||||||
import Data.Map (Map)
|
import Data.Map (Map)
|
||||||
import Data.Noun.Atom (Atom(MkAtom), wordBitWidth#)
|
import Data.Noun.Atom ( Atom(MkAtom), wordBitWidth, wordBitWidth#
|
||||||
|
, atomBitWidth#, takeBitsWord )
|
||||||
import Data.Noun.Atom (toAtom, takeBits, bitWidth)
|
import Data.Noun.Atom (toAtom, takeBits, bitWidth)
|
||||||
import Data.Noun (Noun(Atom, Cell))
|
import Data.Noun (Noun(Atom, Cell))
|
||||||
import Data.Noun.Pill (bigNatWords)
|
import Data.Noun.Pill (bigNatWords, atomBS)
|
||||||
import Data.Vector.Primitive ((!))
|
import Data.Vector.Primitive ((!))
|
||||||
import Foreign.Marshal.Alloc (mallocBytes, free)
|
import Foreign.Marshal.Alloc (callocBytes, free)
|
||||||
import Foreign.Ptr (Ptr, castPtr, plusPtr, ptrToWordPtr)
|
import Foreign.Ptr (Ptr, castPtr, plusPtr, ptrToWordPtr)
|
||||||
import Foreign.Storable (peek, poke)
|
import Foreign.Storable (peek, poke)
|
||||||
import GHC.Int (Int(I#))
|
import GHC.Int (Int(I#))
|
||||||
@ -96,15 +97,16 @@ putS s = Put $ \tbl _ -> pure (PutResult s ())
|
|||||||
{-
|
{-
|
||||||
To write a bit:
|
To write a bit:
|
||||||
|
|
||||||
| reg |= 1 << regI
|
| reg |= 1 << off
|
||||||
| regI <- (regI + 1) % 64
|
| off <- (off + 1) % 64
|
||||||
| if (!regI):
|
| if (!off):
|
||||||
| buf[w++] <- reg
|
| buf[w++] <- reg
|
||||||
| reg <- 0
|
| reg <- 0
|
||||||
-}
|
-}
|
||||||
{-# INLINE writeBit #-}
|
{-# INLINE writeBit #-}
|
||||||
writeBit :: Bool -> Put ()
|
writeBit :: Bool -> Put ()
|
||||||
writeBit b = Put $ \tbl s@S{..} -> do
|
writeBit b = Put $ \tbl s@S{..} -> do
|
||||||
|
-- traceM ("writeBit: " <> show b)
|
||||||
let s' = s { reg = (if b then setBit else clearBit) reg off
|
let s' = s { reg = (if b then setBit else clearBit) reg off
|
||||||
, off = (off + 1) `mod` 64
|
, off = (off + 1) `mod` 64
|
||||||
, pos = pos + 1
|
, pos = pos + 1
|
||||||
@ -117,49 +119,60 @@ writeBit b = Put $ \tbl s@S{..} -> do
|
|||||||
{-
|
{-
|
||||||
To write a 64bit word:
|
To write a 64bit word:
|
||||||
|
|
||||||
| reg |= w << regI
|
| reg |= w << off
|
||||||
| buf[bufI++] = reg
|
| buf[bufI++] = reg
|
||||||
| reg = w >> (64 - regI)
|
| reg = w >> (64 - off)
|
||||||
-}
|
-}
|
||||||
{-# INLINE writeWord #-}
|
{-# INLINE writeWord #-}
|
||||||
writeWord :: Word -> Put ()
|
writeWord :: Word -> Put ()
|
||||||
writeWord wor = do
|
writeWord wor = do
|
||||||
|
-- traceM ("writeWord: " <> show wor)
|
||||||
S{..} <- getS
|
S{..} <- getS
|
||||||
setReg (reg .|. shiftL wor off)
|
setReg (reg .|. shiftL wor off)
|
||||||
flush
|
flush
|
||||||
setReg (shiftR wor (64 - off))
|
update \s -> s { pos = 64 + pos
|
||||||
|
, reg = shiftR wor (64 - off)
|
||||||
|
}
|
||||||
|
|
||||||
{-
|
{-
|
||||||
To write some bits (< 64) from a word:
|
To write some bits (< 64) from a word:
|
||||||
|
|
||||||
| reg |= wor << regI
|
| wor = takeBits(wid, wor)
|
||||||
| regI += wid
|
| reg = reg .|. (wor << off)
|
||||||
|
| off = (off + wid) % 64
|
||||||
|
|
|
|
||||||
| if (regI >= 64)
|
| if (off + wid >= 64)
|
||||||
| regI -= 64
|
|
||||||
| buf[w] = x
|
| buf[w] = x
|
||||||
| reg = wor >> (wid - regI)
|
| reg = wor >> (wid - off)
|
||||||
-}
|
-}
|
||||||
|
|
||||||
{-# INLINE writeBitsFromWord #-}
|
{-# INLINE writeBitsFromWord #-}
|
||||||
writeBitsFromWord :: Int -> Word -> Put ()
|
writeBitsFromWord :: Int -> Word -> Put ()
|
||||||
writeBitsFromWord wid wor = do
|
writeBitsFromWord wid wor = do
|
||||||
s <- getS
|
wor <- pure (takeBitsWord wid wor)
|
||||||
|
|
||||||
let s' = s { reg = reg s .|. shiftL wor (off s)
|
-- traceM ("writeBitsFromWord: " <> show wid <> ", " <> show wor)
|
||||||
, off = off s + wid
|
|
||||||
|
oldSt <- getS
|
||||||
|
|
||||||
|
let newSt = oldSt { reg = reg oldSt .|. shiftL wor (off oldSt)
|
||||||
|
, off = (off oldSt + wid) `mod` 64
|
||||||
|
, pos = fromIntegral wid + pos oldSt
|
||||||
}
|
}
|
||||||
|
|
||||||
if (off s' < 64)
|
putS newSt
|
||||||
then do putS s'
|
|
||||||
else do update (\s -> s { off = off s - 64 })
|
when (wid + off oldSt >= 64) $ do
|
||||||
flush
|
flush
|
||||||
setReg (shiftR wor (wid - off s'))
|
setReg (shiftR wor (wid - off newSt))
|
||||||
{-
|
{-
|
||||||
Write all of the the signficant bits of a direct atom.
|
Write all of the the signficant bits of a direct atom.
|
||||||
-}
|
-}
|
||||||
{-# INLINE writeAtomWord# #-}
|
{-# INLINE writeAtomWord# #-}
|
||||||
writeAtomWord# :: Word# -> Put ()
|
writeAtomWord# :: Word# -> Put ()
|
||||||
writeAtomWord# w = writeBitsFromWord (I# (word2Int# (wordBitWidth# w))) (W# w)
|
writeAtomWord# w = do
|
||||||
|
-- traceM "writeAtomWord"
|
||||||
|
writeBitsFromWord (I# (word2Int# (wordBitWidth# w))) (W# w)
|
||||||
|
|
||||||
{-# INLINE writeAtomWord #-}
|
{-# INLINE writeAtomWord #-}
|
||||||
writeAtomWord :: Word -> Put ()
|
writeAtomWord :: Word -> Put ()
|
||||||
@ -173,6 +186,7 @@ writeAtomWord (W# w) = writeAtomWord# w
|
|||||||
{-# INLINE writeAtomBigNat #-}
|
{-# INLINE writeAtomBigNat #-}
|
||||||
writeAtomBigNat :: BigNat -> Put ()
|
writeAtomBigNat :: BigNat -> Put ()
|
||||||
writeAtomBigNat (view bigNatWords -> words) = do
|
writeAtomBigNat (view bigNatWords -> words) = do
|
||||||
|
-- traceM "writeAtomBigNat"
|
||||||
let lastIdx = VP.length words - 1
|
let lastIdx = VP.length words - 1
|
||||||
for_ [0..(lastIdx-1)] \i ->
|
for_ [0..(lastIdx-1)] \i ->
|
||||||
writeWord (words ! i)
|
writeWord (words ! i)
|
||||||
@ -222,18 +236,23 @@ instance Monad Put where
|
|||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
doPut :: Word64 -> Put () -> ByteString
|
doPut :: Word -> Put () -> ByteString
|
||||||
doPut sz m =
|
doPut sz m =
|
||||||
unsafePerformIO $ do
|
unsafePerformIO $ do
|
||||||
tbl <- H.new
|
tbl <- H.new
|
||||||
buf <- mallocBytes (fromIntegral $ wordSz*8)
|
buf <- callocBytes (fromIntegral $ 4 * wordSz*8)
|
||||||
_ <- runPut m tbl (S buf 0 0 0)
|
_ <- runPut (m >> mbFlush) tbl (S buf 0 0 0)
|
||||||
BS.unsafePackCStringFinalizer (castPtr buf) byteSz (free buf)
|
BS.unsafePackCStringFinalizer (castPtr buf) (2*byteSz) (free buf)
|
||||||
where
|
where
|
||||||
wordSz = fromIntegral (sz `divUp` 64)
|
wordSz = fromIntegral (sz `divUp` 64)
|
||||||
byteSz = fromIntegral (sz `divUp` 8)
|
byteSz = fromIntegral (sz `divUp` 8)
|
||||||
divUp x y = (x `div` y) + (if x `mod` y == 0 then 0 else 1)
|
divUp x y = (x `div` y) + (if x `mod` y == 0 then 0 else 1)
|
||||||
|
|
||||||
|
mbFlush :: Put ()
|
||||||
|
mbFlush = do
|
||||||
|
shouldFlush <- (/= 0) . off <$> getS
|
||||||
|
when shouldFlush flush
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -242,32 +261,38 @@ doPut sz m =
|
|||||||
-}
|
-}
|
||||||
writeNoun :: Noun -> Put ()
|
writeNoun :: Noun -> Put ()
|
||||||
writeNoun n = do
|
writeNoun n = do
|
||||||
|
-- traceM "writeNoun"
|
||||||
|
|
||||||
p <- pos <$> getS
|
p <- pos <$> getS
|
||||||
mRef <- getRef n
|
mRef <- getRef n
|
||||||
|
|
||||||
case (mRef, n) of
|
case (mRef, n) of
|
||||||
(Nothing, Atom a) -> writeAtom a
|
(Nothing, Atom a) -> writeAtom a
|
||||||
(Nothing, Cell h t) -> writeCell h t
|
(Nothing, Cell h t) -> writeCell h t
|
||||||
(Just bk, Atom a) | a < toAtom bk -> writeAtom a
|
(Just bk, Atom a) | bitWidth a <= wordBitWidth bk -> writeAtom a
|
||||||
(Just bk, _) -> writeBackRef bk
|
(Just bk, _) -> writeBackRef bk
|
||||||
|
|
||||||
|
when (mRef == Nothing) $
|
||||||
insRef n p
|
insRef n p
|
||||||
|
|
||||||
{-# INLINE writeMat #-}
|
{-# INLINE writeMat #-}
|
||||||
writeMat :: Atom -> Put ()
|
writeMat :: Atom -> Put ()
|
||||||
|
writeMat 0 = do
|
||||||
|
-- traceM "writeMat: 0"
|
||||||
|
writeBit True
|
||||||
writeMat atm = do
|
writeMat atm = do
|
||||||
writeBitsFromWord (preWid+1) (shiftL (1 :: Word) preWid)
|
-- traceM ("writeMat: " <> show atm)
|
||||||
writeAtomBits extras
|
writeBitsFromWord (preWid+1) (shiftL 1 preWid)
|
||||||
|
writeBitsFromWord (preWid-1) atmWid
|
||||||
writeAtomBits atm
|
writeAtomBits atm
|
||||||
where
|
where
|
||||||
atmWid = bitWidth atm :: Atom
|
atmWid = bitWidth atm
|
||||||
preWid = bitWidth atmWid :: Int
|
preWid = fromIntegral (wordBitWidth atmWid)
|
||||||
prefix = shiftL (1 :: Word) (fromIntegral preWid)
|
|
||||||
extras = takeBits (preWid-1) (toAtom atmWid)
|
|
||||||
|
|
||||||
{-# INLINE writeCell #-}
|
{-# INLINE writeCell #-}
|
||||||
writeCell :: Noun -> Noun -> Put ()
|
writeCell :: Noun -> Noun -> Put ()
|
||||||
writeCell h t = do
|
writeCell h t = do
|
||||||
|
-- traceM "writeCell"
|
||||||
writeBit True
|
writeBit True
|
||||||
writeBit False
|
writeBit False
|
||||||
writeNoun h
|
writeNoun h
|
||||||
@ -276,12 +301,68 @@ writeCell h t = do
|
|||||||
{-# INLINE writeAtom #-}
|
{-# INLINE writeAtom #-}
|
||||||
writeAtom :: Atom -> Put ()
|
writeAtom :: Atom -> Put ()
|
||||||
writeAtom a = do
|
writeAtom a = do
|
||||||
|
-- traceM "writeAtom"
|
||||||
writeBit False
|
writeBit False
|
||||||
writeMat a
|
writeMat a
|
||||||
|
|
||||||
{-# INLINE writeBackRef #-}
|
{-# INLINE writeBackRef #-}
|
||||||
writeBackRef :: Word -> Put ()
|
writeBackRef :: Word -> Put ()
|
||||||
writeBackRef a = do
|
writeBackRef a = do
|
||||||
|
-- traceM ("writeBackRef: " <> show a)
|
||||||
writeBit True
|
writeBit True
|
||||||
writeBit True
|
writeBit True
|
||||||
writeMat (toAtom a)
|
writeMat (toAtom a)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
jamBS :: Noun -> ByteString
|
||||||
|
jamBS n = doPut (fst $ preJam n) (writeNoun n)
|
||||||
|
|
||||||
|
jam :: Noun -> Atom
|
||||||
|
jam = view (to jamBS . from atomBS)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
preJam :: Noun -> (Word, Map Noun Word)
|
||||||
|
preJam = go 0 mempty
|
||||||
|
where
|
||||||
|
insertNoun :: Noun -> Word -> Map Noun Word -> Map Noun Word
|
||||||
|
insertNoun n i tbl = lookup n tbl
|
||||||
|
& maybe (insertMap n i tbl) (const tbl)
|
||||||
|
|
||||||
|
go :: Word -> Map Noun Word -> Noun -> (Word, Map Noun Word)
|
||||||
|
go off oldTbl noun =
|
||||||
|
let tbl = insertNoun noun off oldTbl in
|
||||||
|
case lookup noun oldTbl of
|
||||||
|
Nothing ->
|
||||||
|
case noun of
|
||||||
|
Atom atm ->
|
||||||
|
(1 + W# (matSz# atm), tbl)
|
||||||
|
Cell l r ->
|
||||||
|
let (lSz, tbl') = go (2+off) tbl l in
|
||||||
|
let (rSz, tbl'') = go (2+off+lSz) tbl' r in
|
||||||
|
(2 + lSz + rSz, tbl'')
|
||||||
|
Just (W# ref) ->
|
||||||
|
let refSz = W# (wordBitWidth# ref) in
|
||||||
|
case noun of
|
||||||
|
Atom atm ->
|
||||||
|
let worSz = W# (matSz# atm) in
|
||||||
|
if worSz > refSz
|
||||||
|
then (2 + refSz, oldTbl)
|
||||||
|
else (1 + worSz, tbl)
|
||||||
|
Cell _ _ ->
|
||||||
|
(2 + refSz, oldTbl)
|
||||||
|
|
||||||
|
matSz# :: Atom -> Word#
|
||||||
|
matSz# 0 = 1##
|
||||||
|
matSz# a = preW `plusWord#` preW `plusWord#` atmW
|
||||||
|
where
|
||||||
|
atmW = atomBitWidth# a
|
||||||
|
preW = wordBitWidth# atmW
|
||||||
|
|
||||||
|
refSz# :: Word# -> Word#
|
||||||
|
refSz# w = 2## `plusWord#` (matSz# (MkAtom (NatS# w)))
|
||||||
|
|
||||||
|
nounSz# :: Noun -> Word#
|
||||||
|
nounSz# (Atom a) = 1## `plusWord#` (matSz# a)
|
||||||
|
nounSz# (Cell l r) = 2## `plusWord#` (nounSz# l) `plusWord#` (nounSz# r)
|
||||||
|
@ -25,7 +25,7 @@ module Data.Noun.Pill where
|
|||||||
import ClassyPrelude
|
import ClassyPrelude
|
||||||
import Data.Noun hiding (toList, fromList)
|
import Data.Noun hiding (toList, fromList)
|
||||||
import Data.Noun.Atom
|
import Data.Noun.Atom
|
||||||
import Data.Noun.Jam hiding (main)
|
-- import Data.Noun.Jam hiding (main)
|
||||||
import Data.Flat hiding (from, to)
|
import Data.Flat hiding (from, to)
|
||||||
import Control.Monad.Except
|
import Control.Monad.Except
|
||||||
import Control.Lens hiding (index, Index)
|
import Control.Lens hiding (index, Index)
|
||||||
@ -178,8 +178,8 @@ pillWords = iso toVec fromVec
|
|||||||
toVec = view (pillBS . to bsToWords)
|
toVec = view (pillBS . to bsToWords)
|
||||||
fromVec = view (to wordsToBytes . bytesBS . from pillBS)
|
fromVec = view (to wordsToBytes . bytesBS . from pillBS)
|
||||||
|
|
||||||
_CueBytes :: Prism' ByteString Noun
|
-- _CueBytes :: Prism' ByteString Noun
|
||||||
_CueBytes = from pillBS . from pill . _Cue
|
-- _CueBytes = from pillBS . from pill . _Cue
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -201,10 +201,13 @@ pill = iso toAtom fromPill
|
|||||||
toAtom = view (atomNat . natWords . from pillWords)
|
toAtom = view (atomNat . natWords . from pillWords)
|
||||||
fromPill = view (pillBS . to bsToWords . from natWords . from atomNat)
|
fromPill = view (pillBS . to bsToWords . from natWords . from atomNat)
|
||||||
|
|
||||||
|
atomBS :: Iso' Atom ByteString
|
||||||
|
atomBS = pill . pillBS
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
_Cue :: Prism' Atom Noun
|
-- _Cue :: Prism' Atom Noun
|
||||||
_Cue = prism' jam cue
|
-- _Cue = prism' jam cue
|
||||||
|
|
||||||
_Tall :: Flat a => Prism' ByteString a
|
_Tall :: Flat a => Prism' ByteString a
|
||||||
_Tall = prism' flat (eitherToMaybe . unflat)
|
_Tall = prism' flat (eitherToMaybe . unflat)
|
||||||
@ -221,8 +224,8 @@ loadPill = fmap Pill . readFile
|
|||||||
loadAtom :: FilePath -> IO Atom
|
loadAtom :: FilePath -> IO Atom
|
||||||
loadAtom = fmap (view $ from pillBS . from pill) . readFile
|
loadAtom = fmap (view $ from pillBS . from pill) . readFile
|
||||||
|
|
||||||
loadNoun :: FilePath -> IO (Maybe Noun)
|
-- loadNoun :: FilePath -> IO (Maybe Noun)
|
||||||
loadNoun = fmap (preview $ from pillBS . from pill . _Cue) . readFile
|
-- loadNoun = fmap (preview $ from pillBS . from pill . _Cue) . readFile
|
||||||
|
|
||||||
loadFlat :: Flat a => FilePath -> IO (Either Text a)
|
loadFlat :: Flat a => FilePath -> IO (Either Text a)
|
||||||
loadFlat = fmap (mapLeft tshow . unflat) . readFile
|
loadFlat = fmap (mapLeft tshow . unflat) . readFile
|
||||||
@ -235,8 +238,8 @@ dumpPill fp = writeFile fp . view pillBS
|
|||||||
dumpAtom :: FilePath -> Atom -> IO ()
|
dumpAtom :: FilePath -> Atom -> IO ()
|
||||||
dumpAtom fp = writeFile fp . view (pill . pillBS)
|
dumpAtom fp = writeFile fp . view (pill . pillBS)
|
||||||
|
|
||||||
dumpJam :: FilePath -> Noun -> IO ()
|
-- dumpJam :: FilePath -> Noun -> IO ()
|
||||||
dumpJam fp = writeFile fp . view (re _Cue . pill . pillBS)
|
-- dumpJam fp = writeFile fp . view (re _Cue . pill . pillBS)
|
||||||
|
|
||||||
dumpFlat :: Flat a => FilePath -> a -> IO ()
|
dumpFlat :: Flat a => FilePath -> a -> IO ()
|
||||||
dumpFlat fp = writeFile fp . flat
|
dumpFlat fp = writeFile fp . flat
|
||||||
@ -265,11 +268,11 @@ tryPackPill pf = do
|
|||||||
atm <- tryLoadPill pf
|
atm <- tryLoadPill pf
|
||||||
print $ length (atm ^. pill . pillBS)
|
print $ length (atm ^. pill . pillBS)
|
||||||
|
|
||||||
tryCuePill :: PillFile -> IO ()
|
-- tryCuePill :: PillFile -> IO ()
|
||||||
tryCuePill pill =
|
-- tryCuePill pill =
|
||||||
loadNoun (show pill) >>= \case Nothing -> print "nil"
|
-- loadNoun (show pill) >>= \case Nothing -> print "nil"
|
||||||
Just (Atom _) -> print "atom"
|
-- Just (Atom _) -> print "atom"
|
||||||
_ -> print "cell"
|
-- _ -> print "cell"
|
||||||
|
|
||||||
-- Tests -----------------------------------------------------------------------
|
-- Tests -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user