mirror of
https://github.com/urbit/shrub.git
synced 2025-01-07 05:26:56 +03:00
Haskell <-> Hoon conversions for map and set.
This commit is contained in:
parent
7db5ef2c6c
commit
ee0def33f5
@ -1,6 +1,5 @@
|
|||||||
module Arvo.Common
|
module Arvo.Common
|
||||||
( KingId(..), ServId(..)
|
( KingId(..), ServId(..)
|
||||||
, NounTree(..), NounMap, NounSet
|
|
||||||
, Json, JsonNode(..)
|
, Json, JsonNode(..)
|
||||||
, Desk(..), Mime(..)
|
, Desk(..), Mime(..)
|
||||||
, Lane(..), Port(..), Turf(..)
|
, Lane(..), Port(..), Turf(..)
|
||||||
@ -105,23 +104,6 @@ data Mime = Mime Path File
|
|||||||
deriveNoun ''Mime
|
deriveNoun ''Mime
|
||||||
|
|
||||||
|
|
||||||
-- Trees, Maps, and Sets -------------------------------------------------------
|
|
||||||
|
|
||||||
data NounTreeNode a = HTN
|
|
||||||
{ ntnNode :: a
|
|
||||||
, ntnLeft :: NounTree a
|
|
||||||
, ntnRite :: NounTree a
|
|
||||||
}
|
|
||||||
deriving (Eq, Ord, Show)
|
|
||||||
|
|
||||||
type NounTree a = Nullable (NounTreeNode a)
|
|
||||||
|
|
||||||
type NounMap k v = NounTree (k, v)
|
|
||||||
type NounSet a = NounTree a
|
|
||||||
|
|
||||||
deriveNoun ''NounTreeNode
|
|
||||||
|
|
||||||
|
|
||||||
-- Json ------------------------------------------------------------------------
|
-- Json ------------------------------------------------------------------------
|
||||||
|
|
||||||
type Json = Nullable JsonNode
|
type Json = Nullable JsonNode
|
||||||
@ -129,7 +111,7 @@ type Json = Nullable JsonNode
|
|||||||
data JsonNode
|
data JsonNode
|
||||||
= JNA [Json]
|
= JNA [Json]
|
||||||
| JNB Bool
|
| JNB Bool
|
||||||
| JNO (NounMap Cord Json)
|
| JNO (HoonMap Cord Json)
|
||||||
| JNN Knot
|
| JNN Knot
|
||||||
| JNS Cord
|
| JNS Cord
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
module Arvo.Event where
|
module Arvo.Event where
|
||||||
|
|
||||||
import UrbitPrelude hiding (Term)
|
import UrbitPrelude hiding (Term)
|
||||||
|
import Noun.Tree (HoonSet, HoonMap)
|
||||||
|
|
||||||
import Arvo.Common (KingId(..), ServId(..))
|
import Arvo.Common (KingId(..), ServId(..))
|
||||||
import Arvo.Common (NounMap, NounSet)
|
|
||||||
import Arvo.Common (Desk, Mime)
|
import Arvo.Common (Desk, Mime)
|
||||||
import Arvo.Common (Header(..), HttpEvent)
|
import Arvo.Common (Header(..), HttpEvent)
|
||||||
import Arvo.Common (AmesDest, Ipv4, Ipv6, Port, Turf)
|
import Arvo.Common (AmesDest, Ipv4, Ipv6, Port, Turf)
|
||||||
@ -39,7 +39,7 @@ deriveNoun ''PUrl
|
|||||||
data Seed = Seed Ship Life Ring (Maybe Oath)
|
data Seed = Seed Ship Life Ring (Maybe Oath)
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
type Public = (Life, NounMap Life Pass)
|
type Public = (Life, HoonMap Life Pass)
|
||||||
|
|
||||||
data Dnses = Dnses { dPri::Cord, dSec::Cord, dTer::Cord }
|
data Dnses = Dnses { dPri::Cord, dSec::Cord, dTer::Cord }
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
@ -50,7 +50,7 @@ type ContNum = Word
|
|||||||
data EthPoint = EthPoint
|
data EthPoint = EthPoint
|
||||||
{ epOwn :: (EthAddr, EthAddr, EthAddr, EthAddr)
|
{ epOwn :: (EthAddr, EthAddr, EthAddr, EthAddr)
|
||||||
, epNet :: Maybe (Life, Pass, ContNum, (Bool, Ship), Maybe Ship)
|
, epNet :: Maybe (Life, Pass, ContNum, (Bool, Ship), Maybe Ship)
|
||||||
, epKid :: Maybe (EthAddr, NounSet Ship)
|
, epKid :: Maybe (EthAddr, HoonSet Ship)
|
||||||
}
|
}
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
@ -61,20 +61,20 @@ data EthEventId = EthEventId
|
|||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
data EthBookmark = EthBookmark
|
data EthBookmark = EthBookmark
|
||||||
{ ebHeard :: NounSet EthEventId
|
{ ebHeard :: HoonSet EthEventId
|
||||||
, ebLatestBlock :: Atom
|
, ebLatestBlock :: Atom
|
||||||
}
|
}
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
data Snap = Snap (NounMap Ship Public)
|
data Snap = Snap (HoonMap Ship Public)
|
||||||
(Dnses, NounMap Ship EthPoint)
|
(Dnses, HoonMap Ship EthPoint)
|
||||||
EthBookmark
|
EthBookmark
|
||||||
deriving (Eq, Ord, Show)
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
data Dawn = MkDawn
|
data Dawn = MkDawn
|
||||||
{ dSeed :: Seed
|
{ dSeed :: Seed
|
||||||
, dShip :: Ship
|
, dShip :: Ship
|
||||||
, dCzar :: NounMap Ship (Life, Pass)
|
, dCzar :: HoonMap Ship (Life, Pass)
|
||||||
, dTurf :: [Turf]
|
, dTurf :: [Turf]
|
||||||
, dBloq :: Bloq
|
, dBloq :: Bloq
|
||||||
, dNode :: (Maybe PUrl)
|
, dNode :: (Maybe PUrl)
|
||||||
|
@ -8,6 +8,7 @@ module Noun
|
|||||||
, module Noun.Jam
|
, module Noun.Jam
|
||||||
, module Noun.Tank
|
, module Noun.Tank
|
||||||
, module Noun.TH
|
, module Noun.TH
|
||||||
|
, module Noun.Tree
|
||||||
, _Cue
|
, _Cue
|
||||||
, LoadErr(..)
|
, LoadErr(..)
|
||||||
, loadFile
|
, loadFile
|
||||||
@ -18,6 +19,7 @@ import Control.Lens
|
|||||||
|
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Noun.Atom
|
import Noun.Atom
|
||||||
|
import Noun.Tree
|
||||||
import Noun.Conversions
|
import Noun.Conversions
|
||||||
import Noun.Convert
|
import Noun.Convert
|
||||||
import Noun.Core
|
import Noun.Core
|
||||||
|
216
pkg/king/lib/Noun/Tree.hs
Normal file
216
pkg/king/lib/Noun/Tree.hs
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
{-# LANGUAGE DuplicateRecordFields, DisambiguateRecordFields #-}
|
||||||
|
|
||||||
|
module Noun.Tree
|
||||||
|
( HoonSet, setToHoonSet, setFromHoonSet
|
||||||
|
, HoonMap, mapToHoonMap, mapFromHoonMap
|
||||||
|
) where
|
||||||
|
|
||||||
|
import ClassyPrelude
|
||||||
|
import Control.Lens hiding (non)
|
||||||
|
|
||||||
|
import Noun.Atom
|
||||||
|
import Noun.Conversions ()
|
||||||
|
import Noun.Convert
|
||||||
|
import Noun.Core
|
||||||
|
import Noun.TH
|
||||||
|
|
||||||
|
import Data.Bits (shiftR, xor)
|
||||||
|
import Data.Hash.Murmur (murmur3)
|
||||||
|
import GHC.Natural (Natural)
|
||||||
|
|
||||||
|
|
||||||
|
-- Types -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
data NounVal a = NounVal
|
||||||
|
{ non ∷ Noun
|
||||||
|
, val ∷ !a
|
||||||
|
}
|
||||||
|
|
||||||
|
data HoonTreeNode a = NTN
|
||||||
|
{ n ∷ NounVal a
|
||||||
|
, l ∷ HoonTree a
|
||||||
|
, r ∷ HoonTree a
|
||||||
|
}
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
data HoonTree a = E | Node (HoonTreeNode a)
|
||||||
|
deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
|
pattern N n l r = Node (NTN n l r)
|
||||||
|
|
||||||
|
newtype HoonSet a = HoonSet { unHoonSet ∷ HoonTree a }
|
||||||
|
deriving newtype (Eq, Ord, Show, FromNoun, ToNoun)
|
||||||
|
|
||||||
|
newtype HoonMap k v = HoonMap { unHoonMap ∷ HoonTree (k, v) }
|
||||||
|
deriving newtype (Eq, Ord, Show, FromNoun, ToNoun)
|
||||||
|
|
||||||
|
|
||||||
|
-- Instances -------------------------------------------------------------------
|
||||||
|
|
||||||
|
instance Eq (NounVal a) where
|
||||||
|
(==) = on (==) non
|
||||||
|
|
||||||
|
instance Ord (NounVal a) where
|
||||||
|
compare = comparing non
|
||||||
|
|
||||||
|
instance ToNoun (NounVal a) where
|
||||||
|
toNoun = non
|
||||||
|
|
||||||
|
instance Show a => Show (NounVal a) where
|
||||||
|
show = show . val
|
||||||
|
|
||||||
|
instance FromNoun a => FromNoun (NounVal a) where
|
||||||
|
parseNoun x = NounVal x <$> parseNoun x
|
||||||
|
|
||||||
|
instance ToNoun a => ToNoun (HoonTree a) where
|
||||||
|
toNoun E = A 0
|
||||||
|
toNoun (Node n) = toNoun n
|
||||||
|
|
||||||
|
instance FromNoun a => FromNoun (HoonTree a) where
|
||||||
|
parseNoun (A 0) = pure E
|
||||||
|
parseNoun n = Node <$> parseNoun n
|
||||||
|
|
||||||
|
deriveNoun ''HoonTreeNode
|
||||||
|
|
||||||
|
|
||||||
|
-- Mug -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
type Nat = Natural
|
||||||
|
|
||||||
|
slowMug :: Noun -> Nat
|
||||||
|
slowMug = trim 0xcafe_babe . \case
|
||||||
|
A a -> a
|
||||||
|
C h t -> mix (slowMug h) $ mix 0x7fff_ffff (slowMug t)
|
||||||
|
where
|
||||||
|
trim :: Nat -> Nat -> Nat
|
||||||
|
trim syd key =
|
||||||
|
if 0/=ham then ham else trim (succ syd) key
|
||||||
|
where
|
||||||
|
haz = muk syd (met 3 key) key
|
||||||
|
ham = mix (rsh 0 31 haz) (end 0 31 haz)
|
||||||
|
|
||||||
|
mix :: Nat -> Nat -> Nat
|
||||||
|
mix = xor
|
||||||
|
|
||||||
|
-- Murmur3
|
||||||
|
muk :: Nat -> Nat -> Nat -> Nat
|
||||||
|
muk seed len =
|
||||||
|
fromIntegral . murmur3 (word32 seed) . resize . view atomBytes
|
||||||
|
where
|
||||||
|
resize :: ByteString -> ByteString
|
||||||
|
resize buf =
|
||||||
|
case compare (length buf) (int len) of
|
||||||
|
EQ -> buf
|
||||||
|
LT -> error "bad-muk"
|
||||||
|
GT -> error "bad-muk"
|
||||||
|
-- LT -> buf <> replicate (len - length buf) 0
|
||||||
|
-- GT -> take len buf
|
||||||
|
|
||||||
|
int :: Integral i => i -> Int
|
||||||
|
int = fromIntegral
|
||||||
|
|
||||||
|
word32 :: Integral i => i -> Word32
|
||||||
|
word32 = fromIntegral
|
||||||
|
|
||||||
|
bex :: Nat -> Nat
|
||||||
|
bex = (2^)
|
||||||
|
|
||||||
|
end :: Nat -> Nat -> Nat -> Nat
|
||||||
|
end blockSize blocks n =
|
||||||
|
n `mod` (bex (bex blockSize * blocks))
|
||||||
|
|
||||||
|
rsh :: Nat -> Nat -> Nat -> Nat
|
||||||
|
rsh blockSize blocks n =
|
||||||
|
shiftR n $ fromIntegral $ (bex blockSize * blocks)
|
||||||
|
|
||||||
|
met :: Nat -> Nat -> Nat
|
||||||
|
met bloq = go 0
|
||||||
|
where
|
||||||
|
go c 0 = c
|
||||||
|
go c n = go (succ c) (rsh bloq 1 n)
|
||||||
|
|
||||||
|
-- XX TODO
|
||||||
|
mug ∷ Noun -> Nat
|
||||||
|
mug = slowMug
|
||||||
|
|
||||||
|
|
||||||
|
-- Order -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
{-
|
||||||
|
Orders in ascending double mug hash order, collisions fall back to dor.
|
||||||
|
-}
|
||||||
|
mor ∷ Noun -> Noun -> Bool
|
||||||
|
mor a b = if c == d then dor a b else c < d
|
||||||
|
where
|
||||||
|
c = mug $ A $ mug a
|
||||||
|
d = mug $ A $ mug b
|
||||||
|
|
||||||
|
{-
|
||||||
|
Orders in ascending tree depth.
|
||||||
|
-}
|
||||||
|
dor ∷ Noun -> Noun -> Bool
|
||||||
|
dor a b | a == b = True
|
||||||
|
dor (A a) (C _ _) = True
|
||||||
|
dor (C x y) (A b) = False
|
||||||
|
dor (A a) (A b) = a < b
|
||||||
|
dor (C x y) (C p q) | x == p = dor y q
|
||||||
|
dor (C x y) (C p q) = dor x p
|
||||||
|
|
||||||
|
{-
|
||||||
|
Orders in ascending +mug hash order.
|
||||||
|
|
||||||
|
Collisions fall back to dor.
|
||||||
|
-}
|
||||||
|
gor ∷ Noun -> Noun -> Bool
|
||||||
|
gor a b = if c==d then dor a b else c<d
|
||||||
|
where (c, d) = (mug a, mug b)
|
||||||
|
|
||||||
|
morVal, gorVal ∷ NounVal a -> NounVal a -> Bool
|
||||||
|
morVal = on mor non
|
||||||
|
gorVal = on gor non
|
||||||
|
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
nounVal ∷ ToNoun a => Iso' a (NounVal a)
|
||||||
|
nounVal = iso to val
|
||||||
|
where
|
||||||
|
to x = NounVal (toNoun x) x
|
||||||
|
|
||||||
|
treeToList :: ∀a. HoonTree a -> [a]
|
||||||
|
treeToList = go []
|
||||||
|
where
|
||||||
|
go :: [a] -> HoonTree a -> [a]
|
||||||
|
go acc = \case
|
||||||
|
E → acc
|
||||||
|
Node (NTN v l r) → go (go (val v : acc) l) r
|
||||||
|
|
||||||
|
setFromHoonSet :: Ord a => HoonSet a -> Set a
|
||||||
|
setFromHoonSet = setFromList . treeToList . unHoonSet
|
||||||
|
|
||||||
|
mapFromHoonMap :: Ord k => HoonMap k v -> Map k v
|
||||||
|
mapFromHoonMap = mapFromList . treeToList . unHoonMap
|
||||||
|
|
||||||
|
setToHoonSet ∷ ∀a. (Ord a, ToNoun a) ⇒ Set a → HoonSet a
|
||||||
|
setToHoonSet = HoonSet . foldr put E . fmap (view nounVal) . setToList
|
||||||
|
where
|
||||||
|
put x = \case
|
||||||
|
E → N x E E
|
||||||
|
Node a | x == n a → Node a
|
||||||
|
Node a | gorVal x (n a) → rit x a
|
||||||
|
Node a → lef x a
|
||||||
|
|
||||||
|
lef x a = put x (r a) & \case
|
||||||
|
E → error "bad-put"
|
||||||
|
Node c | morVal (n a) (n c) → N (n a) (l a) (Node c)
|
||||||
|
Node c → N (n c) (N (n a) (l a) (l c)) (r c)
|
||||||
|
|
||||||
|
rit x a = put x (l a) & \case
|
||||||
|
E → error "bad-put"
|
||||||
|
Node c | morVal (n a) (n c) → N (n a) (Node c) (r a)
|
||||||
|
Node c → N (n c) (l c) (N (n a) (r c) (r a))
|
||||||
|
|
||||||
|
mapToHoonMap ∷ (ToNoun k, ToNoun v, Ord k, Ord v) ⇒ Map k v → HoonMap k v
|
||||||
|
mapToHoonMap = muck . setToHoonSet . setFromList . mapToList
|
||||||
|
where
|
||||||
|
muck (HoonSet x) = HoonMap x
|
@ -59,6 +59,7 @@ dependencies:
|
|||||||
- megaparsec
|
- megaparsec
|
||||||
- mtl
|
- mtl
|
||||||
- multimap
|
- multimap
|
||||||
|
- murmur3
|
||||||
- network
|
- network
|
||||||
- optparse-applicative
|
- optparse-applicative
|
||||||
- para
|
- para
|
||||||
|
Loading…
Reference in New Issue
Block a user