on 05ceebb help sign in
12 files changed+129−213
since splitsnapshots
unifiedsplit
bench/Main.hs+1−2 flake.lock+3−3 flake.nix+1−1 package.yaml−2 src/Nock.hs+4−4 src/Nock/Cue.hs−98 src/Nock/Jam.hs+111−88 src/Nock/Jets.hs+1−2 src/Nock/Types.hs+1−6 stack.yaml+1−1 stack.yaml.lock+4−4 tests/Main.hs+2−2
bench/Main.hs+1−2
@@ -10,7 +10,6 @@ import Nock.Parser (noun)
1010import System.FilePath.Posix
1111import System.Process.Typed
1212import Test.Tasty.Golden (findByExtension)
13−import Effectful
1413
1514main :: IO ()
1615main = do
@@ -23,5 +22,5 @@ main = do
2322 $ proc "urbit" ["eval"]
2423 & setStdin (byteStringInput hoon)
2524 & setStderr nullStream
26− pure $ bench (takeBaseName hoonFile) $ nf (runPureEff . tar) $ cell (atom 0) nock
25+ pure $ bench (takeBaseName hoonFile) $ nf tar $ cell (atom 0) nock
2726 defaultMain benchmarks
flake.lock+3−3
@@ -19,11 +19,11 @@
1919 },
2020 "nixpkgs": {
2121 "locked": {
22− "lastModified": 1746141548,
23− "narHash": "sha256-IgBWhX7A2oJmZFIrpRuMnw5RAufVnfvOgHWgIdds+hc=",
22+ "lastModified": 1737062831,
23+ "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=",
2424 "owner": "NixOS",
2525 "repo": "nixpkgs",
26− "rev": "f02fddb8acef29a8b32f10a335d44828d7825b78",
26+ "rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c",
2727 "type": "github"
2828 },
2929 "original": {
flake.nix+1−1
@@ -8,7 +8,7 @@
88 let
99 supportedSystems =
1010 [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" ];
11− compilerVersion = "984";
11+ compilerVersion = "966";
1212 in flake-utils.lib.eachSystem supportedSystems (system:
1313 let pkgs = import nixpkgs { inherit system; };
1414 in {
package.yaml−2
@@ -22,7 +22,6 @@ dependencies:
2222 - unordered-containers
2323 - murmur3
2424 - file-embed
25− - mtl
2625library:
2726 source-dirs: src
2827
@@ -36,7 +35,6 @@ benchmarks:
3635 main: bench/Main.hs
3736
3837 dependencies:
39− - effectful
4038 - tasty
4139 - nock
4240ghc-options: >
src/Nock.hs+4−4
@@ -43,8 +43,8 @@ lus ~(Atom nat _) = atom $ case nat of
4343 (# l, c #) -> NB (bigNatFromWord2# (int2Word# c) l)
4444 (NB n) -> NB (bigNatAddWord# n 1##)
4545
46−tis :: Noun -> Noun -> Eff es Noun
47−tis lhs rhs = pure $ if lhs == rhs then sig else one
46+tis :: (SEL.State EqualityCache :> es, IOE :> es) => Noun -> Noun -> Eff es Noun
47+tis lhs rhs = nounEq lhs rhs <&> \eq -> if eq then sig else one
4848
4949fas# :: Word# -> Noun -> Noun
5050fas# lhs rhs =
@@ -84,10 +84,10 @@ hax n b c =
8484 then hax a (cell (fas (n - 1) c) b) c
8585 else hax a (cell b (fas (n + 1) c)) c
8686
87−tar :: Noun -> Eff es Noun
87+tar :: (SEL.State EqualityCache :> es, IOE :> es) => Noun -> Eff es Noun
8888tar ~(Cell subject ~(Cell a b _) _) = tar' a b subject
8989
90−tar' :: Noun -> Noun -> Noun -> Eff es Noun
90+tar' :: (SEL.State EqualityCache :> es, IOE :> es) => Noun -> Noun -> Noun -> Eff es Noun
9191tar' b c subject = case b of
9292 Cell x y _ -> case c of
9393 ~(Cell l k _) -> cell <$> tar' x y subject <*> tar' l k subject
src/Nock/Cue.hsdeleted−98
@@ -1,98 +0,0 @@
1−module Nock.Cue (cue, rub) where
2−
3−import Control.Monad.Trans.Class
4−import Control.Monad.Trans.State
5−import Data.Binary.Bits.BitOrder
6−import Data.Binary.Bits.Get
7−import Data.Binary.Get (runGet)
8−import Data.Bits
9−import Data.ByteString.Lazy (ByteString)
10−import Data.Map (Map)
11−import Data.Map qualified as M
12−import GHC.Base (Int (..), Word (..), Word#, int2Word#, minusWord#, or#, shiftL#, word2Int#)
13−import GHC.Num
14−import Nock.Types
15−
16−type BitParser = StateT (Int, Map Int Noun) BitGet
17−
18−parseBit# :: BitParser Int
19−parseBit# = do
20− (counter, m) <- get
21− b <- lift getBool#
22− put (counter + 1, m)
23− pure b
24−
25−parseBits# :: Word# -> BitParser Natural
26−parseBits# 0## = pure 0
27−parseBits# n = do
28− I# b <- parseBit#
29− rest <- parseBits# (n `minusWord#` 1##)
30− pure $ (rest `shiftL` 1) `naturalOr` NS (int2Word# b)
31−
32−getOffset :: BitParser Int
33−getOffset = fst <$> get
34−
35−getMapping :: BitParser (Map Int Noun)
36−getMapping = snd <$> get
37−
38−putMapping :: Map Int Noun -> BitParser ()
39−putMapping m = do
40− (offset, _) <- get
41− put (offset, m)
42−
43−cue :: ByteString -> Noun
44−cue = runGet (runBitGet . withBitOrder LL . flip evalStateT (0, M.empty) $ cue')
45−
46−cue' :: BitParser Noun
47−cue' = do
48− offset <- getOffset
49− I# isNotAtom <- parseBit#
50− case isNotAtom of
51− 0# -> do
52− a' <- rub'
53− let a = atom a'
54− m <- getMapping
55− putMapping $ M.insert offset a m
56− pure a
57− _ -> do
58− I# isRef <- parseBit#
59− case isRef of
60− 0# -> do
61− x <- cue'
62− y <- cue'
63− let c = cell x y
64− m <- getMapping
65− putMapping $ M.insert offset c m
66− pure c
67− _ -> do
68− ref <- rub'
69− let ref# = case ref of
70− NS w -> I# (word2Int# w)
71− _ -> undefined
72− m <- getMapping
73− case M.lookup ref# m of
74− Nothing -> undefined
75− Just a -> pure a
76−
77−rub :: ByteString -> Natural
78−rub = runGet (runBitGet . withBitOrder LL . flip evalStateT (0, M.empty) $ rub')
79−
80−rub' :: BitParser Natural
81−rub' = do
82− parseBit# >>= \case
83− I# 0# -> do
84− W# lengthOfLength <- countZeros 0
85− lengthBits <- parseBits# lengthOfLength
86− let lengthBits# = case lengthBits of
87− NS w -> w
88− _ -> undefined
89− let lent = lengthBits# `or#` (1## `shiftL#` word2Int# lengthOfLength)
90− parseBits# lent
91− _ -> pure 0
92−
93−countZeros :: Word -> BitParser Word
94−countZeros n = do
95− I# b <- parseBit#
96− case b of
97− 0# -> countZeros (n + 1)
98− _ -> pure n
src/Nock/Jam.hs+111−88
@@ -1,118 +1,136 @@
1−{-# LANGUAGE NoMonomorphismRestriction #-}
1+module Nock.Jam (jam, cue, mat, rub) where
22
3−module Nock.Jam (jam, mat) where
4−
5−import Control.Monad.Identity
6−import Control.Monad.State.Strict (MonadState (..))
73import Control.Monad.Trans.Class
8−import Control.Monad.Trans.State hiding (get, put)
4+import Control.Monad.Trans.State
95import Data.Binary.Bits.BitOrder
10−import Data.Binary.Bits.Put qualified as Put
6+import Data.Binary.Bits.Get
7+import Data.Binary.Bits.Put
8+import Data.Binary.Get (runGet)
119import Data.Binary.Put (runPut)
1210import Data.Bits
1311import Data.ByteString.Lazy (ByteString)
14−import Data.Map.Strict (Map)
15−import Data.Map.Strict qualified as M
16−import GHC.Base (Word (..), Word#, int2Word#, isTrue#, leWord#, plusWord#, timesWord#)
17−import GHC.Int (Int (..))
12+import Data.Map (Map)
13+import Data.Map qualified as M
14+import GHC.Base (Int (..), Word (..), Word#, int2Word#, minusWord#, or#, plusWord#, shiftL#, word2Int#)
1815import GHC.Num
16+import Nock
1917import Nock.Types
2018
21−type BitPrinterM = StateT (Natural, Map Noun Natural) Put.BitPut
22−
23−class (MonadState (Natural, Map Noun Natural) m) => BitPrinter m where
24− putBit# :: (BitPrinter m) => Word# -> m ()
25− putBool :: Bool -> m ()
26−
27−instance BitPrinter (StateT (Natural, Map Noun Natural) Identity) where
28− putBit# _ = do
29− (counter, m) <- get
30− put (counter + 1, m)
31− putBool _ = do
32− (counter, m) <- get
33− put (counter + 1, m)
34−
35−instance BitPrinter BitPrinterM where
36− putBit# w = do
37− (counter, m) <- get
38− lift $ Put.putBool# w
39− put (counter + 1, m)
40− putBool b = do
41− (counter, m) <- get
42− lift $ Put.putBool b
43− put (counter + 1, m)
44−
45−getOffset :: (BitPrinter m) => m Natural
19+type BitParser = StateT (Int, Map Int Noun) BitGet
20+
21+parseBit# :: BitParser Int
22+parseBit# = do
23+ (counter, m) <- get
24+ b <- lift getBool#
25+ put (counter + 1, m)
26+ pure b
27+
28+parseBits# :: Word# -> BitParser Natural
29+parseBits# 0## = pure 0
30+parseBits# n = do
31+ I# b <- parseBit#
32+ rest <- parseBits# (n `minusWord#` 1##)
33+ pure $ (rest `shiftL` 1) `naturalOr` NS (int2Word# b)
34+
35+getOffset :: BitParser Int
4636getOffset = fst <$> get
4737
48−getMapping :: (BitPrinter m) => m (Map Noun Natural)
38+getMapping :: BitParser (Map Int Noun)
4939getMapping = snd <$> get
5040
51−putMapping :: (BitPrinter m) => Noun -> Natural -> m ()
52−putMapping idx n = do
53− (offset, m) <- get
54− put (offset, M.insert idx n m)
41+putMapping :: Map Int Noun -> BitParser ()
42+putMapping m = do
43+ (offset, _) <- get
44+ put (offset, m)
5545
56−jam :: Noun -> ByteString
57−jam n = runPut . Put.runBitPut . withBitOrder LL . flip evalStateT (0, M.empty) $ jam' n
46+cue :: ByteString -> Noun
47+cue = runGet (runBitGet . withBitOrder LL . flip evalStateT (0, M.empty) $ cue')
5848
59−jam' :: (BitPrinter m) => Noun -> m ()
60−jam' n = do
49+cue' :: BitParser Noun
50+cue' = do
6151 offset <- getOffset
62− mapping <- getMapping
63− case M.lookup n mapping of
64− Nothing -> do
65− putMapping n offset
66− case n of
67− (Atom a _) -> do
68− putBit# 0##
69− mat' a
70− (Cell lhs rhs _) -> do
71− putBit# 1##
72− putBit# 0##
73− jam' lhs
74− jam' rhs
75− Just ref -> do
76− case n of
77− Cell {} -> do
78− putBit# 1##
79− putBit# 1##
80− mat' ref
81− (Atom a _) -> do
82− if isTrue# (matSize a `leWord#` matSize ref)
83− then do
84− putBit# 0##
85− mat' a
86− else do
87− putBit# 1##
88− putBit# 1##
89− mat' ref
52+ I# isNotAtom <- parseBit#
53+ case isNotAtom of
54+ 0# -> do
55+ a' <- rub'
56+ let a = atom a'
57+ m <- getMapping
58+ putMapping $ M.insert offset a m
59+ pure a
60+ _ -> do
61+ I# isRef <- parseBit#
62+ case isRef of
63+ 0# -> do
64+ x <- cue'
65+ y <- cue'
66+ let c = cell x y
67+ m <- getMapping
68+ putMapping $ M.insert offset c m
69+ pure c
70+ _ -> do
71+ ref <- rub'
72+ let ref# = case ref of
73+ NS w -> I# (word2Int# w)
74+ _ -> undefined
75+ m <- getMapping
76+ case M.lookup ref# m of
77+ Nothing -> undefined
78+ Just a -> pure a
79+
80+jam :: Noun -> ByteString
81+jam n = runPut . runBitPut . withBitOrder LL $ jam' n
82+
83+jam' :: Noun -> BitPut ()
84+jam' (Atom n _) = do
85+ putBool# 0##
86+ mat' n
87+jam' (Cell lhs rhs _) = do
88+ putBool# 1##
89+ putBool# 0##
90+ jam' lhs
91+ jam' rhs
9092
9193mat :: Natural -> ByteString
92−mat n = runPut . Put.runBitPut . withBitOrder LL . flip evalStateT (0, M.empty) $ mat' n
94+mat n = runPut . runBitPut . withBitOrder LL $ mat' n
9395
94−mat' :: (BitPrinter m) => Natural -> m ()
95−mat' 0 = putBit# 1##
96+mat' :: Natural -> BitPut ()
97+mat' 0 = putBool# 1##
9698mat' n = do
9799 let bitsLength = countBits# n
98100 lengthBits = init $ numToBits (W# bitsLength)
99− putBit# 0##
101+ putBool# 0##
100102 putBits $ replicate (length lengthBits) False
101− putBit# 1##
103+ putBool# 1##
102104 putBits lengthBits
103105 putNumToBits# n
104106
105−matSize :: Natural -> Word#
106−matSize 0 = 1##
107−matSize n =
108− let bitsLength = countBits# n
109− !(I# lengthBits) = length $ init $ numToBits (W# bitsLength)
110− in 2## `plusWord#` (int2Word# lengthBits `timesWord#` 2##) `plusWord#` bitsLength
111−
112−putBits :: (BitPrinter m) => [Bool] -> m ()
107+putBits :: [Bool] -> BitPut ()
113108putBits [] = pure ()
114109putBits (x : xs) = putBool x >> putBits xs
115110
111+rub :: ByteString -> Natural
112+rub = runGet (runBitGet . withBitOrder LL . flip evalStateT (0, M.empty) $ rub')
113+
114+rub' :: BitParser Natural
115+rub' = do
116+ parseBit# >>= \case
117+ I# 0# -> do
118+ W# lengthOfLength <- countZeros 0
119+ lengthBits <- parseBits# lengthOfLength
120+ let lengthBits# = case lengthBits of
121+ NS w -> w
122+ _ -> undefined
123+ let lent = lengthBits# `or#` (1## `shiftL#` word2Int# lengthOfLength)
124+ parseBits# lent
125+ _ -> pure 0
126+
127+countZeros :: Word -> BitParser Word
128+countZeros n = do
129+ I# b <- parseBit#
130+ case b of
131+ 0# -> countZeros (n + 1)
132+ _ -> pure n
133+
116134numToBits :: (Bits a, Integral a) => a -> [Bool]
117135numToBits n | n <= 0 = []
118136numToBits n = ((n .&. 1) == 1) : numToBits (shiftR n 1)
@@ -121,8 +139,13 @@ countBits# :: Natural -> Word#
121139countBits# (NS 0##) = 0##
122140countBits# n = 1## `plusWord#` countBits# (n `naturalShiftR#` 1##)
123141
124−putNumToBits# :: (BitPrinter m) => Natural -> m ()
142+putNumToBits# :: Natural -> BitPut ()
125143putNumToBits# (NS 0##) = pure ()
126144putNumToBits# n = case n .&. 1 of
127− NS w -> putBit# w >> putNumToBits# (n `naturalShiftR#` 1##)
145+ NS w -> putBool# w >> putNumToBits# (n `naturalShiftR#` 1##)
128146 _ -> undefined
147+
148+-- ((n .&. 1) == 1) : numToBits (shiftR n 1)
149+
150+bitsToNum :: (Bits a, Integral a) => [Bool] -> a
151+bitsToNum = foldr (\b acc -> shiftL acc 1 .|. if b then 1 else 0) 0
src/Nock/Jets.hs+1−2
@@ -5,8 +5,7 @@ module Nock.Jets (add, dec, decJam, decNoun) where
55import Data.ByteString (ByteString)
66import Data.ByteString.Lazy qualified as BSL
77import Data.FileEmbed (embedFileRelative)
8−import Nock.Cue
9−import Nock.Jam
8+import Nock.Jam (cue)
109import Nock.Parser qualified
1110import Nock.Types
1211
src/Nock/Types.hs+1−6
@@ -13,6 +13,7 @@ module Nock.Types
1313 )
1414where
1515
16+import Control.Applicative
1617import Control.DeepSeq
1718import Data.ByteString (ByteString)
1819import Data.ByteString.Short
@@ -89,12 +90,6 @@ instance Eq Noun where
8990 (Atom a _) == (Atom b _) = a == b
9091 _ == _ = False
9192
92−instance Ord Noun where
93− Atom {} <= Cell {} = True
94− Cell {} <= Atom {} = False
95− Atom n _ <= Atom m _ = n <= m
96− Cell a b _ <= Cell c d _ = (a, b) <= (c, d)
97−
9893instance Arbitrary Noun where
9994 arbitrary =
10095 oneof
stack.yaml+1−1
@@ -23,7 +23,7 @@ nix:
2323#
2424# resolver: ./custom-snapshot.yaml
2525# resolver: https://example.com/snapshots/2018-01-01.yaml
26−resolver: lts-23.21
26+resolver: lts-22.43
2727
2828# User packages to be built.
2929# Various formats can be used as shown in the example below.
stack.yaml.lock+4−4
@@ -17,7 +17,7 @@ packages:
1717 git: https://github.com/ilyakooo0/binary-bits
1818snapshots:
1919- completed:
20− sha256: f4a61482dcad21151331bf84ec85bee9be43965f143791fa4bb202ac1e443e1b
21− size: 683833
22− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/23/21.yaml
23− original: lts-23.21
20+ sha256: 08bd13ce621b41a8f5e51456b38d5b46d7783ce114a50ab604d6bbab0d002146
21+ size: 720271
22+ url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/22/43.yaml
23+ original: lts-22.43
tests/Main.hs+2−2
@@ -7,16 +7,16 @@ import Data.Text.Lazy.Encoding as TL
77import Effectful
88import Effectful.State.Static.Local qualified as SEL
99import Nock
10−import Nock.Cue
1110import Nock.Jam
1211import Nock.Jets
1312import Nock.Parser qualified
13+import Nock.Printer
1414import Nock.Types
1515import System.FilePath.Posix
1616import System.Process.Typed
1717import Test.Tasty
1818import Test.Tasty.Golden
19−import Test.Tasty.HUnit (testCase, (@?=))
19+import Test.Tasty.HUnit (assertEqual, testCase, (@=?), (@?=))
2020import Test.Tasty.QuickCheck
2121
2222main :: IO ()