on master help sign in
commit1655064ac497069877d9e0b33b333f0ab1fd2f66 authoriko <mail@iko.soy> dateTue 21 Jan 2025, 03:33 (2 years ago) parent58116b1
14 files changed+184−77
flake.lock+59 flake.nix+24 package.yaml+3 src/Nock.hs+38−33 src/Nock/Jam.hs+1 src/Nock/Types.hs+45−33 stack.yaml+1−2 stack.yaml.lock+4−5 tests/Main.hs+4−1 tests/golden/add-nock.nock tests/golden/add.nock+1−1 tests/golden/dec.nock+1−1 tests/golden/mul.hoon+2−1 tests/golden/mul.nock+1
flake.locknew file+59
@@ -0,0 +1,59 @@
1+{
2+ "nodes": {
3+ "flake-utils": {
4+ "inputs": {
5+ "systems": "systems"
6+ },
7+ "locked": {
8+ "lastModified": 1731533236,
9+ "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
10+ "owner": "numtide",
11+ "repo": "flake-utils",
12+ "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
13+ "type": "github"
14+ },
15+ "original": {
16+ "id": "flake-utils",
17+ "type": "indirect"
18+ }
19+ },
20+ "nixpkgs": {
21+ "locked": {
22+ "lastModified": 1737062831,
23+ "narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=",
24+ "owner": "NixOS",
25+ "repo": "nixpkgs",
26+ "rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c",
27+ "type": "github"
28+ },
29+ "original": {
30+ "id": "nixpkgs",
31+ "ref": "nixos-unstable",
32+ "type": "indirect"
33+ }
34+ },
35+ "root": {
36+ "inputs": {
37+ "flake-utils": "flake-utils",
38+ "nixpkgs": "nixpkgs"
39+ }
40+ },
41+ "systems": {
42+ "locked": {
43+ "lastModified": 1681028828,
44+ "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
45+ "owner": "nix-systems",
46+ "repo": "default",
47+ "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
48+ "type": "github"
49+ },
50+ "original": {
51+ "owner": "nix-systems",
52+ "repo": "default",
53+ "type": "github"
54+ }
55+ }
56+ },
57+ "root": "root",
58+ "version": 7
59+}
flake.nixnew file+24
@@ -0,0 +1,24 @@
1+{
2+ inputs = {
3+ nixpkgs.url = "nixpkgs/nixos-unstable";
4+ flake-utils.url = "flake-utils";
5+ };
6+
7+ outputs = { self, flake-utils, nixpkgs }:
8+ let
9+ supportedSystems =
10+ [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" "aarch64-linux" ];
11+ compilerVersion = "966";
12+ in flake-utils.lib.eachSystem supportedSystems (system:
13+ let pkgs = import nixpkgs { inherit system; };
14+ in {
15+ devShells.default = pkgs.mkShell {
16+ buildInputs = with pkgs; [
17+ haskell.compiler."ghc${compilerVersion}"
18+ (pkgs.haskell-language-server.override {
19+ supportedGhcVersions = [ compilerVersion ];
20+ })
21+ ];
22+ };
23+ });
24+}
package.yaml+3
@@ -18,6 +18,8 @@ dependencies:
1818 - gauge
1919 - filepath
2020 - deepseq
21+ - effectful
22+ - unordered-containers
2123library:
2224 source-dirs: src
2325
@@ -85,3 +87,4 @@ tests:
8587 - nock
8688 - tasty-hspec
8789 - hspec
90+ - effectful
src/Nock.hs+38−33
@@ -1,19 +1,13 @@
11{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
22
3−module Nock (tar, hax, fas, cell, atom, Annotation (..), Noun, RawNoun (..)) where
3+module Nock (tar, hax, fas, cell, atom, Annotation (..), Noun) where
44
5−import Control.DeepSeq (NFData, force)
65import Data.Bits
7−import Data.Hashable
8−import Data.Text.Lazy qualified as TL
9−import Data.Text.Lazy.Builder qualified as TLB
10−import Data.Text.Lazy.Builder.Int qualified as TLB
11−import Debug.Trace
6+import Data.Functor ((<&>))
7+import Effectful
8+import Effectful.State.Static.Local qualified as SEL
129import GHC.Base
13−import GHC.Conc (par)
14−import GHC.Generics (Generic)
1510import GHC.Num
16−import Nock.Jets
1711import Nock.Types
1812
1913sig :: Noun
@@ -44,8 +38,8 @@ wut Atom {} = one
4438lus :: Noun -> Noun
4539lus ~(Atom nat _) = atom (nat + 1)
4640
47−tis :: Noun -> Noun -> Noun
48−tis lhs rhs = if hashEq lhs rhs then sig else one
41+tis :: (SEL.State EqualityCache :> es, IOE :> es) => Noun -> Noun -> Eff es Noun
42+tis lhs rhs = nounEq lhs rhs <&> \eq -> if eq then sig else one
4943
5044fasWord :: Word# -> Noun -> Noun
5145fasWord lhs rhs =
@@ -70,7 +64,6 @@ fas n rhs =
7064 else fas 2 rest
7165
7266haxWord :: Word# -> Noun -> Noun -> Noun
73−haxWord _ _ tree | traceShow tree False = undefined
7467haxWord 1## newValue _ = newValue
7568haxWord place newValue ~(Cell lhs rhs _) =
7669 let a = uncheckedShiftRL# place 1#
@@ -78,48 +71,60 @@ haxWord place newValue ~(Cell lhs rhs _) =
7871 1## -> cell (haxWord a newValue lhs) rhs
7972 _ -> cell lhs (haxWord a newValue rhs)
8073
74+hax :: Natural -> Noun -> Noun -> Noun
75+hax (NS n) b c = haxWord n b c
8176hax n b c =
8277 let a = unsafeShiftR n 1
8378 in case n of
8479 1 -> b
8580 _ | testBit n 0 -> hax a (cell (fas (n - 1) c) b) c
8681 _ -> hax a (cell b (fas (n + 1) c)) c
87−tar :: Noun -> Noun
82+
83+tar :: (SEL.State EqualityCache :> es, IOE :> es) => Noun -> Eff es Noun
8884tar ~(Cell subject ~(Cell a b _) _) = tar' a b subject
8985
90−tar' :: Noun -> Noun -> Noun -> Noun
86+tar' :: (SEL.State EqualityCache :> es, IOE :> es) => Noun -> Noun -> Noun -> Eff es Noun
9187tar' b c subject = case b of
9288 Cell x y _ -> case c of
93− ~(Cell l k _) -> cell (tar' x y subject) (tar' l k subject)
89+ ~(Cell l k _) -> cell <$> tar' x y subject <*> tar' l k subject
9490 Atom (NB _) _ -> undefined
9591 Atom (NS n) _ -> case n of
9692 0## -> case c of
97− ~(Atom nat _) -> fas nat subject
98− 1## -> c
93+ ~(Atom nat _) -> pure $ fas nat subject
94+ 1## -> pure c
9995 3## -> case c of
100− ~(Cell l k _) -> wut $ tar' l k subject
96+ ~(Cell l k _) -> wut <$> tar' l k subject
10197 4## -> case c of
102− ~(Cell l k _) -> lus $ tar' l k subject
98+ ~(Cell l k _) -> lus <$> tar' l k subject
10399 _ -> case c of
104100 ~(Cell x ~(Cell h j _) _) -> case n of
105101 2## -> case x of
106− ~(Cell l k _) -> case tar' l k subject of
107− ~(formula@(Cell battery ~(Cell sample _ _) _)) ->
108− -- if traceShowId battery == Nock.Jets.add
109− -- then error "Found it!"
110− case (tar' h j subject) of
111− ~(Cell u v _) -> tar' u v formula
102+ ~(Cell l k _) ->
103+ tar' l k subject >>= \case
104+ ~formula@(Cell battery ~(Cell sample _ _) _) ->
105+ -- if traceShowId battery == Nock.Jets.add
106+ -- then error "Found it!"
107+ tar' h j subject >>= \case
108+ ~(Cell u v _) -> tar' u v formula
112109 5## -> case x of
113− ~(Cell l k _) -> tis (tar' h j subject) (tar' l k subject)
110+ ~(Cell l k _) -> do
111+ p <- tar' h j subject
112+ q <- tar' l k subject
113+ tis p q
114114 7## -> case x of
115− ~(Cell l k _) -> tar' h j (tar' l k subject)
115+ ~(Cell l k _) -> tar' l k subject >>= tar' h j
116116 8## -> case x of
117− ~(Cell l k _) -> tar' h j (cell (tar' l k subject) subject)
118− 9## -> tar' two (cell sigOne (cell sig x)) (tar' h j subject)
119− 6## -> case tar' sig (tar' sig (tar' four (cell four x) subject) twoThree) (cell h j) of
120− ~(Cell u v _) -> tar' u v subject
117+ ~(Cell l k _) -> do
118+ p <- tar' l k subject
119+ tar' h j (cell p subject)
120+ 9## -> tar' h j subject >>= tar' two (cell sigOne (cell sig x))
121+ 6## -> do
122+ p <- tar' four (cell four x) subject
123+ q <- tar' sig p twoThree
124+ tar' sig q (cell h j) >>= \case
125+ ~(Cell u v _) -> tar' u v subject
121126 10## -> case x of
122− ~(Cell ~(Atom b' _) ~(Cell u v _) _) -> hax b' (tar' u v subject) (tar' h j subject)
127+ ~(Cell ~(Atom b' _) ~(Cell u v _) _) -> hax b' <$> tar' u v subject <*> tar' h j subject
123128 11## -> case x of
124129 Cell _ ~(Cell u v _) _ -> tar' h j subject
125130 Atom _ _ -> tar' h j subject
src/Nock/Jam.hs+1
@@ -12,6 +12,7 @@ import Data.ByteString.Lazy (ByteString)
1212import Data.Map (Map)
1313import Data.Map qualified as M
1414import Nock
15+import Nock.Types
1516import Numeric.Natural
1617
1718type BitParser = StateT (Int, Map Int Noun) BitGet
src/Nock/Types.hs+45−33
@@ -1,22 +1,52 @@
1−module Nock.Types (pretty, hashEq, Noun, RawNoun (..), Annotation (..), atom, cell) where
1+module Nock.Types
2+ ( pretty,
3+ Noun (..),
4+ Annotation (..),
5+ atom,
6+ cell,
7+ nounEq,
8+ EqualityCache,
9+ annotation,
10+ )
11+where
212
313import Control.DeepSeq
4−import Data.Hashable
14+import Data.HashMap.Strict qualified as HM
515import Data.Text.Lazy qualified as TL
616import Data.Text.Lazy.Builder qualified as TLB
717import Data.Text.Lazy.Builder.Int qualified as TLB
8−import GHC.Conc
18+import Effectful
19+import Effectful.State.Static.Local qualified as SEL
920import GHC.Generics
1021import GHC.Natural
22+import System.Mem.StableName
1123
12−newtype Annotation = Annotation
13− { hash :: Int
14− }
24+newtype EqualityCache = EqualityCache (HM.HashMap (StableName Noun, StableName Noun) Bool)
25+ deriving newtype (Semigroup, Monoid)
26+
27+nounEq :: (SEL.State EqualityCache :> es, IOE :> es) => Noun -> Noun -> Eff es Bool
28+nounEq x y = do
29+ xName <- liftIO $ makeStableName x
30+ yName <- liftIO $ makeStableName y
31+ EqualityCache cache <- SEL.get
32+ case HM.lookup (xName, yName) cache of
33+ Just res -> pure res
34+ Nothing -> do
35+ res <- case (x, y) of
36+ (Atom xa _, Atom ya _) -> pure $ xa == ya
37+ (Cell xLhs xRhs _, Cell yLhs yRhs _) -> do
38+ lhsRes <- nounEq xLhs yLhs
39+ if lhsRes then nounEq xRhs yRhs else pure False
40+ _ -> pure False
41+ SEL.put $ EqualityCache $ HM.insert (xName, yName) res $ HM.insert (yName, xName) res $ cache
42+ pure res
43+
44+data Annotation = Annotation
1545 deriving stock (Show, Generic)
1646 deriving anyclass (NFData)
1747
1848atom :: Natural -> Noun
19−atom nat = Atom nat Annotation {hash = hash nat}
49+atom nat = Atom nat Annotation {}
2050
2151cell :: Noun -> Noun -> Noun
2252cell lhs rhs =
@@ -24,44 +54,26 @@ cell lhs rhs =
2454 lhs
2555 rhs
2656 Annotation
27− { hash = hash ((annotation lhs).hash, (annotation rhs).hash)
57+ {
2858 }
2959
30−annotation :: RawNoun ann -> ann
60+annotation :: Noun -> Annotation
3161annotation (Atom _ ann) = ann
3262annotation (Cell _ _ ann) = ann
3363
34−data RawNoun ann
35− = Atom !Natural ann
36− | Cell !(RawNoun ann) !(RawNoun ann) ann
64+data Noun
65+ = Atom !Natural Annotation
66+ | Cell !Noun !Noun Annotation
3767 deriving stock (Generic)
3868 deriving anyclass (NFData)
3969
40−instance Show (RawNoun ann) where
70+instance Show Noun where
4171 show = TL.unpack . pretty
4272
43−instance Eq (RawNoun ann) where
44− (Atom lhs _) == (Atom rhs _) = lhs == rhs
45− (Cell lhslhs lhsrhs _) == (Cell rhslhs rhsrhs _) =
46− let rhsRes = lhsrhs == rhsrhs
47− in (force rhsRes `par` lhslhs == rhslhs) && rhsRes
48− _ == _ = False
49−
50−hashEq :: Noun -> Noun -> Bool
51−hashEq (Atom lhsNat lhsAnn) (Atom rhsNat rhsAnn) =
52− let normalEq = lhsNat == rhsNat
53− in (force normalEq `par` lhsAnn.hash == rhsAnn.hash) && normalEq
54−hashEq (Cell lhslhs lhsrhs lhsAnn) (Cell rhslhs rhsrhs rhsAnn) =
55− let normalEq = hashEq lhslhs rhslhs && hashEq lhsrhs rhsrhs
56− in (force normalEq `par` lhsAnn.hash == rhsAnn.hash) && normalEq
57−hashEq _ _ = False
58−
59−type Noun = RawNoun Annotation
60−
61−pretty :: RawNoun ann -> TL.Text
73+pretty :: Noun -> TL.Text
6274pretty noun = TLB.toLazyText $ pretty' noun False
6375
64−pretty' :: RawNoun ann -> Bool -> TLB.Builder
76+pretty' :: Noun -> Bool -> TLB.Builder
6577pretty' (Atom a _) _ = TLB.decimal a
6678pretty' (Cell lhs rhs _) True = pretty' lhs False <> " " <> pretty' rhs True
6779pretty' (Cell lhs rhs _) False = "[" <> pretty' lhs False <> " " <> pretty' rhs True <> "]"
stack.yaml+1−2
@@ -23,8 +23,7 @@ nix:
2323#
2424# resolver: ./custom-snapshot.yaml
2525# resolver: https://example.com/snapshots/2018-01-01.yaml
26−resolver:
27− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/6.yaml
26+resolver: lts-22.43
2827
2928# User packages to be built.
3029# Various formats can be used as shown in the example below.
stack.yaml.lock+4−5
@@ -17,8 +17,7 @@ packages:
1717 git: https://github.com/ilyakooo0/binary-bits
1818snapshots:
1919- completed:
20− sha256: 2e7d4a730d8eb5373b2d383fac84efcf7c81e3b7a5fce71b4c2e19a1768f25a6
21− size: 640239
22− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/6.yaml
23− original:
24− url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/21/6.yaml
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+4−1
@@ -12,6 +12,8 @@ import System.FilePath.Posix
1212import System.Process.Typed
1313import Test.Tasty
1414import Test.Tasty.Golden
15+import Effectful
16+import Effectful.State.Static.Local qualified as SEL
1517
1618main :: IO ()
1719main = do
@@ -31,5 +33,6 @@ goldenTest = do
3133 $ proc "urbit" ["eval"]
3234 & setStdin (byteStringInput hoon)
3335 & setStderr nullStream
34− let result = TL.encodeUtf8 . pretty . tar $ cell (atom 0) nock
36+ noun <- runEff . SEL.evalState (mempty :: EqualityCache) . tar $ cell (atom 0) nock
37+ let result = TL.encodeUtf8 . pretty $ noun
3538 pure result
tests/golden/add-nock.nockdeleted

No changes to the content.

tests/golden/add.nock+1−1
@@ -1 +1 @@
1−2000
1+8
tests/golden/dec.nock+1−1
@@ -1 +1 @@
1−999999
1+4
tests/golden/mul.hoon+2−1
@@ -1,3 +1,4 @@
1+!=
12=>
23|%
34++ mul
@@ -33,4 +34,4 @@
3334 ?: =(0 a) b
3435 $(a (dec a), b +(b))
3536--
36−(mul 3 5)
37+(mul 3 5)
tests/golden/mul.nock+1
@@ -0,0 +1 @@
1+15