More transformations

This commit is contained in:
Chris Penner 2021-10-22 12:52:10 -06:00
parent 6c07b36b92
commit e013511dd8
2 changed files with 130 additions and 32 deletions

View File

@ -44,6 +44,7 @@ import Data.Generics.Product
import Data.Generics.Sum
import qualified Unison.Hash as Unison
import qualified Unison.Hashing.V2.Convert as Convert
import Unison.Hashing.V1.Term (unhashComponent)
-- lookupCtor :: ConstructorMapping -> ObjectId -> Pos -> ConstructorId -> Maybe (Pos, ConstructorId)
-- lookupCtor (ConstructorMapping cm) oid pos cid =
@ -112,7 +113,7 @@ data X = MkX Y
data Y = MkY Int
-}
data Entity'
data Entity
= TComponent Unison.Hash
| DComponent Unison.Hash
| Patch ObjectId
@ -210,10 +211,30 @@ migratePatch = error "not implemented"
migrateNamespace :: HashId -> ByteString -> m _
migrateNamespace = error "not implemented"
migrateTermComponent :: HashId -> ByteString -> m _
migrateTermComponent = error "not implemented"
migrateTermComponent :: forall m v a. Codebase m v a -> Unison.Hash -> m (Sync.TrySyncResult Entity)
migrateTermComponent Codebase{..} hash = fmap (either id id) . runExceptT $ do
-- getTermComponentWithTypes :: Hash -> m (Maybe [(Term v a, Type v a)]),
component <- getTermComponentWithTypes hash >>= \case
Nothing -> error $ "Hash was missing from codebase: " <> show hash
Just component -> pure component
migrateDeclComponent :: forall m v a. Codebase m v a -> Unison.Hash -> m (Sync.TrySyncResult Entity')
let componentIDMap :: Map Reference.Id (Term v a, Type v a)
componentIDMap = Map.fromList $ Reference.componentFor hash component
let unhashed :: Map Reference.Id (v, Term v a)
unhashed = unhashComponent (fst <$> componentIDMap)
let allContainedReferences :: [Reference.Id]
allContainedReferences = foldMap (ABT.find findReferenceIds) (snd <$> Map.elems)
when (not . null $ allContainedReferences) $ throwE $ Sync.Missing allContainedReferences
-- unhashComponent :: forall v a. Var v
-- => Map Reference.Id (Term v a)
-- -> Map Reference.Id (v, Term v a)
undefined
migrateDeclComponent :: forall m v a. Codebase m v a -> Unison.Hash -> m (Sync.TrySyncResult Entity)
migrateDeclComponent Codebase{..} hash = fmap (either id id) . runExceptT $ do
declComponent :: [DD.Decl v a] <- lift (getDeclComponent hash) >>= \case
Nothing -> error "handle this" -- not non-fatal!
@ -275,34 +296,34 @@ migrateDeclComponent Codebase{..} hash = fmap (either id id) . runExceptT $ do
-- Map v (Memory.DD.DataDeclaration v a) ->
-- ResolutionResult v a [(v, Memory.Reference.Id, Memory.DD.DataDeclaration v a)]
let newComponent :: ([(v, Reference.Id, DD.DataDeclaration v a)])
let newComponent :: [(v, Reference.Id, DD.DataDeclaration v a)]
newComponent = Convert.hashDecls (Map.fromList $ Map.elems remappedReferences)
for newComponent $ \(v, newReferenceId, dd) -> do
field @"declLookup" %= Map.insert (vToReference Map.! v) newReferenceId
for_ newComponent $ \(v, newReferenceId, dd) -> do
field @"declLookup" %= Map.insert (vToOldReference Map.! v) newReferenceId
putTypeDeclaration newReference (_ d)
pure Sync.Done
structural type Ping x = P1 (Pong x)
P1 : forall x. Pong x -> Ping x
-- structural type Ping x = P1 (Pong x)
-- P1 : forall x. Pong x -> Ping x
structural type Pong x = P2 (Ping x) | P3 Nat
P2 : forall x. Ping x -> Pong x
P3 : forall x. Nat -> Pong x
-- structural type Pong x = P2 (Ping x) | P3 Nat
-- P2 : forall x. Ping x -> Pong x
-- P3 : forall x. Nat -> Pong x
end up with
decl Ping (Ref.Id #abc pos=0)
decl Pong (Ref.Id #abc pos=1)
ctor P1: #abc pos=0 cid=0
ctor P2: #abc pos=1 cid=0
ctor P3: #abc pos=1 cid=1
we unhashComponent and get:
{ X -> structural type X x = AAA (Y x)
, Y -> structural type Y x = BBB (X x) | CCC Nat }
-- end up with
-- decl Ping (Ref.Id #abc pos=0)
-- decl Pong (Ref.Id #abc pos=1)
-- ctor P1: #abc pos=0 cid=0
-- ctor P2: #abc pos=1 cid=0
-- ctor P3: #abc pos=1 cid=1
--
-- we unhashComponent and get:
-- { X -> structural type X x = AAA (Y x)
-- , Y -> structural type Y x = BBB (X x) | CCC Nat }
@ -339,13 +360,55 @@ remapReferences declMap = \case
-- recordRefsInType :: MonadState MigrationState m => Type v a -> WriterT [Reference.Id] m (Type v a)
-- recordRefsInType = _
findReferenceIds :: Type v a -> ABT.FindAction Reference.Id
findReferenceIds = ABT.out >>> \case
findTypeReferenceIds :: Type v a -> ABT.FindAction Reference.Id
findTypeReferenceIds = ABT.out >>> \case
ABT.Tm (Type.Ref (Reference.DerivedId r)) -> ABT.Found r
x -> ABT.Continue
findTermReferenceIds :: Term f v a -> [Reference.Id]
findTermReferenceIds t = flip ABT.find (ABT.out t) \case
ABT.Tm f -> ABT.Found (findReferencesInTermF f)
x -> ABT.Continue
findReferencesInTermF :: Unison.Term.F typeVar typeAnn patternAnn a -> [Reference.Id]
findReferencesInTermF = ABT.find \case
Ref (Reference.DerivedId refId) -> ABT.Found [refId]
Constructor (Reference.DerivedId refId) _conID -> ABT.Found [refId]
Request (Reference.DerivedId refId) _conID -> ABT.Found [refId]
Ann _ typ -> ABT.Found (ABT.find findTypeReferenceIds typ)
TermLink referent -> case referent of
Ref' (Reference.DerivedId refId) -> ABT.Found [refId]
-- Double check that ConType isn't part of the hash, remove it if it is.
Con' (Reference.DerivedId refId) _conID _conType -> ABT.Found [refId]
TypeLink (Reference.DerivedId refId) -> ABT.Found [refId]
Match _ matchCases -> foldMap (\MatchCase pat _ -> findReferencesInPattern pat) matchCases
_ -> ABT.Continue
findReferencesInPattern :: Traversal' () -> Pattern loc -> [Reference.Id]
findReferencesInPattern
= \case
Unbound{} -> []
Var{} -> []
Boolean{} -> []
Int{} -> []
Nat{} -> []
Float{} -> []
Text{} -> []
Char{} -> []
Constructor _loc ref _constructorId ps ->
let rs = case ref of
DerivedId refId -> [refId]
Builtin{} -> []
in rs <> foldMap findReferencesInPattern ps
As _loc p -> findReferencesInPattern p
EffectPure _loc p -> findReferencesInPattern p
EffectBind _loc ref _constructorId ps p
-> let rs = case ref of
DerivedId refId -> [refId]
Builtin{} -> []
in rs <> foldMap findReferencesInPattern (p:ps)
SequenceLiteral _loc ps -> foldMap findReferencesInPattern ps
SequenceOp _loc p _seqOp p' -> foldMap findReferencesInPattern [p, p']
-- data DataDeclaration v a = DataDeclaration {
-- modifier :: Modifier,

View File

@ -1,17 +1,20 @@
-- Based on: http://semantic-domain.blogspot.com/2015/03/abstract-binding-trees.html
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-}
module Unison.ABT where
import Unison.Prelude
import Prelude hiding (abs, cycle)
import Control.Lens (Lens', use, (.=))
import Control.Lens (Lens', use, (.=), Fold, folding, LensLike', Setter')
import Control.Monad.State (MonadState, evalState)
import qualified Data.Foldable as Foldable
import Data.Functor.Identity (runIdentity)
@ -25,12 +28,17 @@ data ABT f v r
= Var v
| Cycle r
| Abs v r
| Tm (f r) deriving (Functor, Foldable, Traversable)
| Tm (f r)
deriving (Functor, Foldable, Traversable)
-- deriving Data
-- | At each level in the tree, we store the set of free variables and
-- a value of type `a`. Variables are of type `v`.
data Term f v a = Term { freeVars :: Set v, annotation :: a, out :: ABT f v (Term f v a) }
-- deriving instance (Data a, Data v, Typeable f, Data (f (Term f v a)), Ord v) => Data (Term f v a)
-- | A class for variables.
--
-- * `Set.notMember (freshIn vs v) vs`:
@ -454,6 +462,9 @@ foreachSubterm f e = case out e of
subterms :: (Ord v, Traversable f) => Term f v a -> [Term f v a]
subterms t = runIdentity $ foreachSubterm pure t
subterms_ :: (Ord v, Traversable f) => Fold (Term f v a) (Term f v a)
subterms_ = folding subterms
-- | `visit f t` applies an effectful function to each subtree of
-- `t` and sequences the results. When `f` returns `Nothing`, `visit`
-- descends into the children of the current subtree. When `f` returns
@ -471,8 +482,22 @@ visit f t = flip fromMaybe (f t) $ case out t of
Abs x e -> abs' (annotation t) x <$> visit f e
Tm body -> tm' (annotation t) <$> traverse (visit f) body
subTermsSetter_ :: (Traversable f, Ord v) => Setter' (Term f v a) (Term f v a)
subTermsSetter_ f tm = visit (Just . f) tm
visitT :: (Traversable f, Monad m, Ord v)
=> (Term f v a) -> m (Term f v a)
-> Term f v a
-> m (Term f v a)
visitT f tm = f tm >>= \(Term )
Var _ -> pure t
Cycle body -> cycle' (annotation t) <$> visit' f body
Abs x e -> abs' (annotation t) x <$> visit' f e
Tm body -> f body >>= (fmap (tm' (annotation t)) . traverse (visit' f))
-- | Apply an effectful function to an ABT tree top down, sequencing the results.
visit' :: (Traversable f, Applicative g, Monad g, Ord v)
visit' :: (Traversable f, Monad g, Ord v)
=> (f (Term f v a) -> g (f (Term f v a)))
-> Term f v a
-> g (Term f v a)
@ -491,11 +516,21 @@ rewriteDown :: (Traversable f, Ord v)
=> (Term f v a -> Term f v a)
-> Term f v a
-> Term f v a
rewriteDown f t = let t' = f t in case out t' of
Var _ -> t'
Cycle body -> cycle' (annotation t) (rewriteDown f body)
Abs x e -> abs' (annotation t) x (rewriteDown f e)
Tm body -> tm' (annotation t) (rewriteDown f `fmap` body)
rewriteDown f tm = runIdentity $ rewriteDown (Identity . f) tm
-- | Setter' (Term f v a) (Term f v a)
rewriteDown_ :: (Traversable f, Monad m, Ord v)
=> (Term f v a -> m (Term f v a))
-> Term f v a
-> m (Term f v a)
rewriteDown_ f t = do
t' <- f t
case out t' of
Var _ -> t'
Cycle body -> cycle' (annotation t') <$> rewriteDown' f body
Abs x e -> abs' (annotation t') x <$> rewriteDown' f e
Tm body -> tm' (annotation t') <$> (rewriteDown' f `fmap` body)
data Subst f v a =
Subst { freshen :: forall m v' . Monad m => (v -> m v') -> m v'