[commit: ghc] supercompiler: Preliminary thoughts about renaming via MSG, invertRenaming (170cee5)

Max Bolingbroke <[email protected]>
Newsgroups gmane.comp.lang.haskell.cvs.ghc
Message-ID <[email protected]>
Repository : ssh://darcs.haskell.org//srv/darcs/ghc

On branch  : supercompiler

http://hackage.haskell.org/trac/ghc/changeset/170cee5a92f97563c5a7fb722fa1c530b7f9d623

>---------------------------------------------------------------

commit 170cee5a92f97563c5a7fb722fa1c530b7f9d623
Author: Max Bolingbroke <[email protected]>
Date:   Thu Apr 19 23:30:02 2012 +0100

    Preliminary thoughts about renaming via MSG, invertRenaming

>---------------------------------------------------------------

 .../supercompile/Supercompile/Core/Renaming.hs     |   32 ++++++++++++++++---
 compiler/supercompile/Supercompile/Drive/MSG.hs    |   33 +++++++++++++++++++-
 compiler/supercompile/Supercompile/Utilities.hs    |    3 ++
 3 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/compiler/supercompile/Supercompile/Core/Renaming.hs b/compiler/supercompile/Supercompile/Core/Renaming.hs
index 863f92a..1d1b369 100644
--- a/compiler/supercompile/Supercompile/Core/Renaming.hs
+++ b/compiler/supercompile/Supercompile/Core/Renaming.hs
@@ -4,6 +4,7 @@ module Supercompile.Core.Renaming (
     -- | Renamings
     Renaming, emptyRenaming,
     mkInScopeIdentityRenaming, mkIdentityRenaming, mkTyVarRenaming,
+    invertRenaming,
     InScopeSet, emptyInScopeSet, mkInScopeSet,
     
     -- | Extending the renaming
@@ -38,10 +39,15 @@ import Supercompile.Utilities
 
 import CoreSubst
 import OptCoercion (optCoercion)
-import Coercion    (CvSubst(..), CvSubstEnv, isCoVar, mkCoVarCo)
+import Coercion    (CvSubst(..), CvSubstEnv, isCoVar, mkCoVarCo, getCoVar_maybe)
 import qualified CoreSyn as CoreSyn (CoreExpr, Expr(Var))
-import Type        (mkTyVarTy)
-import Var         (Id, TyVar, CoVar, isTyVar)
+import Type        (mkTyVarTy, getTyVar_maybe)
+import Id          (mkSysLocal)
+import Var         (Id, TyVar, CoVar, isTyVar, mkTyVar, varType)
+import OccName     (occNameFS)
+import Name        (getOccName, mkSysTvName)
+import FastString  (FastString)
+import UniqFM      (ufmToList)
 import VarEnv
 
 
@@ -133,12 +139,28 @@ mkInScopeIdentityRenaming = mkIdentityRenaming . getInScopeVars
 mkTyVarRenaming :: [(TyVar, Type)] -> Renaming
 mkTyVarRenaming aas = (emptyVarEnv, mkVarEnv aas, emptyVarEnv)
 
+invertRenaming :: Renaming -> Maybe Renaming
+invertRenaming (id_subst, tv_subst, co_subst)
+  = liftM3 (,,) (traverse coreSynToVar_maybe id_subst >>= invertVarEnv (\fs uniq -> varToCoreSyn . mkSysLocal fs uniq))
+                (traverse getTyVar_maybe     tv_subst >>= invertVarEnv (\fs uniq -> mkTyVarTy    . mkTyVar (mkSysTvName uniq fs)))
+                (traverse getCoVar_maybe     co_subst >>= invertVarEnv (\fs uniq -> mkCoVarCo    . mkSysLocal fs uniq))
+  where
+    -- FIXME: this inversion relies on something of a hack because the domain of the mapping is not stored (only its Unique)
+    invertVarEnv :: (FastString -> Unique -> Type -> a)
+                 -> VarEnv Var -> Maybe (VarEnv a)
+    invertVarEnv mk env
+      | distinct (varEnvElts env) = Just (mkVarEnv [(x, mk (occNameFS (getOccName x)) u (varType x)) | (u, x) <- ufmToList env])
+      | otherwise                 = Nothing
+
 varToCoreSyn :: Var -> CoreSyn.CoreExpr
 varToCoreSyn = CoreSyn.Var
 
+coreSynToVar_maybe :: CoreSyn.CoreExpr -> Maybe Var
+coreSynToVar_maybe (CoreSyn.Var x') = Just x'
+coreSynToVar_maybe _                = Nothing
+
 coreSynToVar :: CoreSyn.CoreExpr -> Var
-coreSynToVar (CoreSyn.Var x') = x'
-coreSynToVar e                = panic "renameId" (ppr e)
+coreSynToVar = fromMaybe (panic "renameId" empty) . coreSynToVar_maybe
 
 insertIdRenaming :: Renaming -> Id -> Out Id -> Renaming
 insertIdRenaming (id_subst, tv_subst, co_subst) x x'
diff --git a/compiler/supercompile/Supercompile/Drive/MSG.hs b/compiler/supercompile/Supercompile/Drive/MSG.hs
index 7eb436b..23dfeb9 100644
--- a/compiler/supercompile/Supercompile/Drive/MSG.hs
+++ b/compiler/supercompile/Supercompile/Drive/MSG.hs
@@ -267,6 +267,37 @@ data MSGMode = MM {
 
 type MSGResult = ((Deeds, Heap, Renaming, Stack), (Heap, Stack, Anned QA), (Deeds, Heap, Renaming, Stack))
 
+-- Note [Renaming via MSG]
+-- ~~~~~~~~~~~~~~~~~~~~~~~
+--
+-- If s1 can be renamed/instantiated to s2, then taking the MSG of the two should yield:
+--  1. On the left:
+--    a) An empty stack
+--    b) A heap containing only lambdaBounds
+--    c) A Renaming that maps TyVar->TyVar and CoVar->CoVar, and which is invertible
+--       (we can't accept [x |-> z, y |-> z] because the right part of the MSG might
+--        instantiate x and y to two different things)
+--  2. On the right:
+--    a) An empty stack, or one which is an allowed instantiation
+--    b) A heap containing only lambdaBounds, or one which is an allowed instantiation
+--    c) A Renaming. We can always allow TyVar->Type and CoVar->Coercion mappings because
+--       they are not computationally relevant. We could optionally forbid non-invertible
+--       renamings like [x |-> z, y |-> z] because it means that two variables are shared
+--       here which weren't in the original term. However, this is likely not important in practice.
+--
+-- If s1 and s2 match to give type generalisation info, we expect this from the MSG:
+--  1. On the left:
+--    a) An empty stack
+--    b) A heap containing only lambdaBounds
+--  2. On the right:
+--    a) An empty stack
+--    b) A heap containing only lambdaBounds
+--
+-- The form of the Renaming is unimportant (as long as we don't care about whether 2 variables
+-- are shared or not) because we are always happy to generalise away Type/Coercion info, and
+-- we're going to satisfy the demand for the States on both sides by driving the (instantiable)
+-- common State.
+
 msg :: {- MSGMode -- ^ How to match
     -> -} State   -- ^ Tieback semantics
     -> State   -- ^ This semantics
@@ -638,7 +669,7 @@ msgPureHeap {- mm -} rn2 msg_s init_h_l init_h_r (k_bvs_l, k_fvs_l) (k_bvs_r, k_
                    (Just Nothing, Just Nothing)
                      | x_l == x_r
                      -> return (rn_l, rn_r, msg_s, hb_r) -- Right biased
-                   (Nothing, Nothing)
+                   (Nothing, Nothing) -- FIXME: I should possibly be adding lambdaBound bindings for x_l and x_r to h_l and h_r respectively
                      -> return (insertIdRenaming rn_l x_common x_l, insertIdRenaming rn_r x_common x_r, msg_s, lambdaBound)
                    _ -> Left "msgPureHeap: non-unifiable heap bindings"
                  -- If they match, we need to make a common heap binding
diff --git a/compiler/supercompile/Supercompile/Utilities.hs b/compiler/supercompile/Supercompile/Utilities.hs
index 7fc59e5..9b5371a 100644
--- a/compiler/supercompile/Supercompile/Utilities.hs
+++ b/compiler/supercompile/Supercompile/Utilities.hs
@@ -500,6 +500,9 @@ runs f g (x:xs) = go (f x) [g x] xs
           | otherwise = (b, reverse pending) : go b' [g x] xs
           where b' = f x
 
+distinct :: Ord a => [a] -> Bool
+distinct xs = length xs /= S.size (S.fromList xs)
+
 
 -- | Orders elements of a map into dependency order insofar as that is possible.
 --
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.