module Language.Syntactic.Functional.Sharing
(
InjDict (..)
, CodeMotionInterface (..)
, defaultInterface
, defaultInterfaceDecor
, codeMotion
) where
import Control.Monad (liftM2, mplus)
import Control.Monad.State
import Data.Maybe (isNothing)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Typeable
import Data.Constraint (Dict (..))
import Language.Syntactic
import Language.Syntactic.Functional
data InjDict sym a b = InjDict
{ InjDict sym a b -> Name -> sym (Full a)
injVariable :: Name -> sym (Full a)
, InjDict sym a b -> Name -> sym (b :-> Full (a -> b))
injLambda :: Name -> sym (b :-> Full (a -> b))
, InjDict sym a b -> sym (a :-> ((a -> b) :-> Full b))
injLet :: sym (a :-> (a -> b) :-> Full b)
}
data CodeMotionInterface sym = Interface
{ CodeMotionInterface sym
-> forall a b. ASTF sym a -> ASTF sym b -> Maybe (InjDict sym a b)
mkInjDict :: forall a b . ASTF sym a -> ASTF sym b -> Maybe (InjDict sym a b)
, CodeMotionInterface sym
-> forall a b. ASTF sym a -> ASTF sym b -> Maybe (ASTF sym b)
castExprCM :: forall a b . ASTF sym a -> ASTF sym b -> Maybe (ASTF sym b)
, CodeMotionInterface sym -> forall c. ASTF sym c -> Bool
hoistOver :: forall c. ASTF sym c -> Bool
}
defaultInterface :: forall binding sym symT
. ( binding :<: sym
, Let :<: sym
, symT ~ Typed sym
)
=> (forall a . Typeable a => Name -> binding (Full a))
-> (forall a b . Typeable a => Name -> binding (b :-> Full (a -> b)))
-> (forall a b . ASTF symT a -> ASTF symT b -> Bool)
-> (forall a . ASTF symT a -> Bool)
-> CodeMotionInterface symT
defaultInterface :: (forall a. Typeable a => Name -> binding (Full a))
-> (forall a b.
Typeable a =>
Name -> binding (b :-> Full (a -> b)))
-> (forall a b. ASTF symT a -> ASTF symT b -> Bool)
-> (forall a. ASTF symT a -> Bool)
-> CodeMotionInterface symT
defaultInterface forall a. Typeable a => Name -> binding (Full a)
var forall a b. Typeable a => Name -> binding (b :-> Full (a -> b))
lam forall a b. ASTF symT a -> ASTF symT b -> Bool
sharable forall a. ASTF symT a -> Bool
hoistOver = Interface :: forall (sym :: * -> *).
(forall a b. ASTF sym a -> ASTF sym b -> Maybe (InjDict sym a b))
-> (forall a b. ASTF sym a -> ASTF sym b -> Maybe (ASTF sym b))
-> (forall c. ASTF sym c -> Bool)
-> CodeMotionInterface sym
Interface {forall a. ASTF symT a -> Bool
forall a b.
AST symT (Full a) -> AST symT (Full b) -> Maybe (AST symT (Full b))
forall a b. ASTF symT a -> ASTF symT b -> Maybe (InjDict symT a b)
forall (sym :: * -> *) a b.
ASTF (Typed sym) a
-> ASTF (Typed sym) b -> Maybe (ASTF (Typed sym) b)
castExprCM :: forall (sym :: * -> *) a b.
ASTF (Typed sym) a
-> ASTF (Typed sym) b -> Maybe (ASTF (Typed sym) b)
mkInjDict :: forall a b. ASTF symT a -> ASTF symT b -> Maybe (InjDict symT a b)
hoistOver :: forall a. ASTF symT a -> Bool
hoistOver :: forall a. ASTF symT a -> Bool
castExprCM :: forall a b.
AST symT (Full a) -> AST symT (Full b) -> Maybe (AST symT (Full b))
mkInjDict :: forall a b. ASTF symT a -> ASTF symT b -> Maybe (InjDict symT a b)
..}
where
mkInjDict :: ASTF symT a -> ASTF symT b -> Maybe (InjDict symT a b)
mkInjDict :: ASTF symT a -> ASTF symT b -> Maybe (InjDict symT a b)
mkInjDict ASTF symT a
a ASTF symT b
b | Bool -> Bool
not (ASTF symT a -> ASTF symT b -> Bool
forall a b. ASTF symT a -> ASTF symT b -> Bool
sharable ASTF symT a
a ASTF symT b
b) = Maybe (InjDict symT a b)
forall a. Maybe a
Nothing
mkInjDict ASTF symT a
a ASTF symT b
b =
(forall sig.
(a ~ DenResult sig) =>
symT sig -> Args (AST symT) sig -> Maybe (InjDict symT a b))
-> ASTF symT a -> Maybe (InjDict symT a b)
forall (sym :: * -> *) a b.
(forall sig.
(a ~ DenResult sig) =>
sym sig -> Args (AST sym) sig -> b)
-> ASTF sym a -> b
simpleMatch
(\(Typed _) Args (AST symT) sig
_ -> (forall sig.
(b ~ DenResult sig) =>
symT sig -> Args (AST symT) sig -> Maybe (InjDict symT a b))
-> ASTF symT b -> Maybe (InjDict symT a b)
forall (sym :: * -> *) a b.
(forall sig.
(a ~ DenResult sig) =>
sym sig -> Args (AST sym) sig -> b)
-> ASTF sym a -> b
simpleMatch
(\(Typed _) Args (AST symT) sig
_ ->
let injVariable :: Name -> Typed sym (Full a)
injVariable = sym (Full a) -> Typed sym (Full a)
forall sig (sym :: * -> *).
Typeable (DenResult sig) =>
sym sig -> Typed sym sig
Typed (sym (Full a) -> Typed sym (Full a))
-> (Name -> sym (Full a)) -> Name -> Typed sym (Full a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. binding (Full a) -> sym (Full a)
forall (sub :: * -> *) (sup :: * -> *) a.
(sub :<: sup) =>
sub a -> sup a
inj (binding (Full a) -> sym (Full a))
-> (Name -> binding (Full a)) -> Name -> sym (Full a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> binding (Full a)
forall a. Typeable a => Name -> binding (Full a)
var
injLambda :: Name -> Typed sym (b :-> Full (a -> b))
injLambda = sym (b :-> Full (a -> b)) -> Typed sym (b :-> Full (a -> b))
forall sig (sym :: * -> *).
Typeable (DenResult sig) =>
sym sig -> Typed sym sig
Typed (sym (b :-> Full (a -> b)) -> Typed sym (b :-> Full (a -> b)))
-> (Name -> sym (b :-> Full (a -> b)))
-> Name
-> Typed sym (b :-> Full (a -> b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. binding (b :-> Full (a -> b)) -> sym (b :-> Full (a -> b))
forall (sub :: * -> *) (sup :: * -> *) a.
(sub :<: sup) =>
sub a -> sup a
inj (binding (b :-> Full (a -> b)) -> sym (b :-> Full (a -> b)))
-> (Name -> binding (b :-> Full (a -> b)))
-> Name
-> sym (b :-> Full (a -> b))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> binding (b :-> Full (a -> b))
forall a b. Typeable a => Name -> binding (b :-> Full (a -> b))
lam
injLet :: Typed sym (a :-> ((a -> b) :-> Full b))
injLet = sym (a :-> ((a -> b) :-> Full b))
-> Typed sym (a :-> ((a -> b) :-> Full b))
forall sig (sym :: * -> *).
Typeable (DenResult sig) =>
sym sig -> Typed sym sig
Typed (sym (a :-> ((a -> b) :-> Full b))
-> Typed sym (a :-> ((a -> b) :-> Full b)))
-> sym (a :-> ((a -> b) :-> Full b))
-> Typed sym (a :-> ((a -> b) :-> Full b))
forall a b. (a -> b) -> a -> b
$ Let (a :-> ((a -> b) :-> Full b))
-> sym (a :-> ((a -> b) :-> Full b))
forall (sub :: * -> *) (sup :: * -> *) a.
(sub :<: sup) =>
sub a -> sup a
inj (String -> Let (a :-> ((a -> b) :-> Full b))
forall a b. String -> Let (a :-> ((a -> b) :-> Full b))
Let String
"")
in InjDict (Typed sym) a b -> Maybe (InjDict (Typed sym) a b)
forall a. a -> Maybe a
Just InjDict :: forall (sym :: * -> *) a b.
(Name -> sym (Full a))
-> (Name -> sym (b :-> Full (a -> b)))
-> sym (a :-> ((a -> b) :-> Full b))
-> InjDict sym a b
InjDict {Typed sym (a :-> ((a -> b) :-> Full b))
Name -> Typed sym (b :-> Full (a -> b))
Name -> Typed sym (Full a)
forall a. Typed sym (a :-> ((a -> b) :-> Full b))
injLet :: forall a. Typed sym (a :-> ((a -> b) :-> Full b))
injLambda :: Name -> Typed sym (b :-> Full (a -> b))
injVariable :: Name -> Typed sym (Full a)
injLet :: Typed sym (a :-> ((a -> b) :-> Full b))
injLambda :: Name -> Typed sym (b :-> Full (a -> b))
injVariable :: Name -> Typed sym (Full a)
..}
) ASTF symT b
b
) ASTF symT a
a
castExprCM :: ASTF (Typed sym) a
-> ASTF (Typed sym) b -> Maybe (ASTF (Typed sym) b)
castExprCM = ASTF (Typed sym) a
-> ASTF (Typed sym) b -> Maybe (ASTF (Typed sym) b)
forall (sym :: * -> *) a b.
ASTF (Typed sym) a
-> ASTF (Typed sym) b -> Maybe (ASTF (Typed sym) b)
castExpr
defaultInterfaceDecor :: forall binding sym symI info
. ( binding :<: sym
, Let :<: sym
, symI ~ (sym :&: info)
)
=> (forall a b . info a -> info b -> Maybe (Dict (a ~ b)))
-> (forall a b . info a -> info b -> info (a -> b))
-> (forall a . info a -> Name -> binding (Full a))
-> (forall a b . info a -> info b -> Name -> binding (b :-> Full (a -> b)))
-> (forall a b . ASTF symI a -> ASTF symI b -> Bool)
-> (forall a . ASTF symI a -> Bool)
-> CodeMotionInterface symI
defaultInterfaceDecor :: (forall a b. info a -> info b -> Maybe (Dict (a ~ b)))
-> (forall a b. info a -> info b -> info (a -> b))
-> (forall a. info a -> Name -> binding (Full a))
-> (forall a b.
info a -> info b -> Name -> binding (b :-> Full (a -> b)))
-> (forall a b. ASTF symI a -> ASTF symI b -> Bool)
-> (forall a. ASTF symI a -> Bool)
-> CodeMotionInterface symI
defaultInterfaceDecor forall a b. info a -> info b -> Maybe (Dict (a ~ b))
teq forall a b. info a -> info b -> info (a -> b)
mkFunInfo forall a. info a -> Name -> binding (Full a)
var forall a b.
info a -> info b -> Name -> binding (b :-> Full (a -> b))
lam forall a b. ASTF symI a -> ASTF symI b -> Bool
sharable forall a. ASTF symI a -> Bool
hoistOver = Interface :: forall (sym :: * -> *).
(forall a b. ASTF sym a -> ASTF sym b -> Maybe (InjDict sym a b))
-> (forall a b. ASTF sym a -> ASTF sym b -> Maybe (ASTF sym b))
-> (forall c. ASTF sym c -> Bool)
-> CodeMotionInterface sym
Interface {forall a. ASTF symI a -> Bool
forall a b. ASTF symI a -> ASTF symI b -> Maybe (ASTF symI b)
forall a b. ASTF symI a -> ASTF symI b -> Maybe (InjDict symI a b)
castExprCM :: forall a b. ASTF symI a -> ASTF symI b -> Maybe (ASTF symI b)
mkInjDict :: forall a b. ASTF symI a -> ASTF symI b -> Maybe (InjDict symI a b)
hoistOver :: forall a. ASTF symI a -> Bool
hoistOver :: forall a. ASTF symI a -> Bool
castExprCM :: forall a b. ASTF symI a -> ASTF symI b -> Maybe (ASTF symI b)
mkInjDict :: forall a b. ASTF symI a -> ASTF symI b -> Maybe (InjDict symI a b)
..}
where
mkInjDict :: ASTF symI a -> ASTF symI b -> Maybe (InjDict symI a b)
mkInjDict :: ASTF symI a -> ASTF symI b -> Maybe (InjDict symI a b)
mkInjDict ASTF symI a
a ASTF symI b
b | Bool -> Bool
not (ASTF symI a -> ASTF symI b -> Bool
forall a b. ASTF symI a -> ASTF symI b -> Bool
sharable ASTF symI a
a ASTF symI b
b) = Maybe (InjDict symI a b)
forall a. Maybe a
Nothing
mkInjDict ASTF symI a
a ASTF symI b
b =
(forall sig.
(a ~ DenResult sig) =>
symI sig -> Args (AST symI) sig -> Maybe (InjDict symI a b))
-> ASTF symI a -> Maybe (InjDict symI a b)
forall (sym :: * -> *) a b.
(forall sig.
(a ~ DenResult sig) =>
sym sig -> Args (AST sym) sig -> b)
-> ASTF sym a -> b
simpleMatch
(\(_ :&: aInfo) Args (AST symI) sig
_ -> (forall sig.
(b ~ DenResult sig) =>
symI sig -> Args (AST symI) sig -> Maybe (InjDict symI a b))
-> ASTF symI b -> Maybe (InjDict symI a b)
forall (sym :: * -> *) a b.
(forall sig.
(a ~ DenResult sig) =>
sym sig -> Args (AST sym) sig -> b)
-> ASTF sym a -> b
simpleMatch
(\(_ :&: bInfo) Args (AST symI) sig
_ ->
let injVariable :: Name -> (:&:) sym info (Full a)
injVariable Name
v = binding (Full a) -> sym (Full a)
forall (sub :: * -> *) (sup :: * -> *) a.
(sub :<: sup) =>
sub a -> sup a
inj (info a -> Name -> binding (Full a)
forall a. info a -> Name -> binding (Full a)
var info a
info (DenResult sig)
aInfo Name
v) sym (Full a)
-> info (DenResult (Full a)) -> (:&:) sym info (Full a)
forall (expr :: * -> *) sig (info :: * -> *).
expr sig -> info (DenResult sig) -> (:&:) expr info sig
:&: info (DenResult sig)
info (DenResult (Full a))
aInfo
injLambda :: Name -> (:&:) sym info (b :-> Full (a -> b))
injLambda Name
v = binding (b :-> Full (a -> b)) -> sym (b :-> Full (a -> b))
forall (sub :: * -> *) (sup :: * -> *) a.
(sub :<: sup) =>
sub a -> sup a
inj (info a -> info b -> Name -> binding (b :-> Full (a -> b))
forall a b.
info a -> info b -> Name -> binding (b :-> Full (a -> b))
lam info a
info (DenResult sig)
aInfo info b
info (DenResult sig)
bInfo Name
v) sym (b :-> Full (a -> b))
-> info (DenResult (b :-> Full (a -> b)))
-> (:&:) sym info (b :-> Full (a -> b))
forall (expr :: * -> *) sig (info :: * -> *).
expr sig -> info (DenResult sig) -> (:&:) expr info sig
:&: info a -> info b -> info (a -> b)
forall a b. info a -> info b -> info (a -> b)
mkFunInfo info a
info (DenResult sig)
aInfo info b
info (DenResult sig)
bInfo
injLet :: (:&:) sym info (a :-> ((a -> b) :-> Full b))
injLet = Let (a :-> ((a -> b) :-> Full b))
-> sym (a :-> ((a -> b) :-> Full b))
forall (sub :: * -> *) (sup :: * -> *) a.
(sub :<: sup) =>
sub a -> sup a
inj (String -> Let (a :-> ((a -> b) :-> Full b))
forall a b. String -> Let (a :-> ((a -> b) :-> Full b))
Let String
"") sym (a :-> ((a -> b) :-> Full b))
-> info (DenResult (a :-> ((a -> b) :-> Full b)))
-> (:&:) sym info (a :-> ((a -> b) :-> Full b))
forall (expr :: * -> *) sig (info :: * -> *).
expr sig -> info (DenResult sig) -> (:&:) expr info sig
:&: info (DenResult sig)
info (DenResult (a :-> ((a -> b) :-> Full b)))
bInfo
in InjDict (sym :&: info) a b -> Maybe (InjDict (sym :&: info) a b)
forall a. a -> Maybe a
Just InjDict :: forall (sym :: * -> *) a b.
(Name -> sym (Full a))
-> (Name -> sym (b :-> Full (a -> b)))
-> sym (a :-> ((a -> b) :-> Full b))
-> InjDict sym a b
InjDict {(:&:) sym info (a :-> ((a -> b) :-> Full b))
Name -> (:&:) sym info (b :-> Full (a -> b))
Name -> (:&:) sym info (Full a)
injLet :: (:&:) sym info (a :-> ((a -> b) :-> Full b))
injLambda :: Name -> (:&:) sym info (b :-> Full (a -> b))
injVariable :: Name -> (:&:) sym info (Full a)
injLet :: (:&:) sym info (a :-> ((a -> b) :-> Full b))
injLambda :: Name -> (:&:) sym info (b :-> Full (a -> b))
injVariable :: Name -> (:&:) sym info (Full a)
..}
) ASTF symI b
b
) ASTF symI a
a
castExprCM :: ASTF symI a -> ASTF symI b -> Maybe (ASTF symI b)
castExprCM :: ASTF symI a -> ASTF symI b -> Maybe (ASTF symI b)
castExprCM ASTF symI a
a ASTF symI b
b =
(forall sig.
(a ~ DenResult sig) =>
symI sig -> Args (AST symI) sig -> Maybe (ASTF symI b))
-> ASTF symI a -> Maybe (ASTF symI b)
forall (sym :: * -> *) a b.
(forall sig.
(a ~ DenResult sig) =>
sym sig -> Args (AST sym) sig -> b)
-> ASTF sym a -> b
simpleMatch
(\(_ :&: aInfo) Args (AST symI) sig
_ -> (forall sig.
(b ~ DenResult sig) =>
symI sig -> Args (AST symI) sig -> Maybe (ASTF symI b))
-> ASTF symI b -> Maybe (ASTF symI b)
forall (sym :: * -> *) a b.
(forall sig.
(a ~ DenResult sig) =>
sym sig -> Args (AST sym) sig -> b)
-> ASTF sym a -> b
simpleMatch
(\(_ :&: bInfo) Args (AST symI) sig
_ -> case info a -> info b -> Maybe (Dict (a ~ b))
forall a b. info a -> info b -> Maybe (Dict (a ~ b))
teq info a
info (DenResult sig)
aInfo info b
info (DenResult sig)
bInfo of
Just Dict (a ~ b)
Dict -> ASTF symI a -> Maybe (ASTF symI a)
forall a. a -> Maybe a
Just ASTF symI a
a
Maybe (Dict (a ~ b))
_ -> Maybe (ASTF symI b)
forall a. Maybe a
Nothing
) ASTF symI b
b
) ASTF symI a
a
substitute :: forall sym a b
. (Equality sym, BindingDomain sym)
=> CodeMotionInterface sym
-> ASTF sym a
-> ASTF sym a
-> ASTF sym b
-> ASTF sym b
substitute :: CodeMotionInterface sym
-> ASTF sym a -> ASTF sym a -> ASTF sym b -> ASTF sym b
substitute CodeMotionInterface sym
iface ASTF sym a
x ASTF sym a
y ASTF sym b
a = ASTF sym b -> ASTF sym b
forall c. ASTF sym c -> ASTF sym c
subst ASTF sym b
a
where
fv :: Set Name
fv = ASTF sym a -> Set Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
AST sym sig -> Set Name
freeVars ASTF sym a
x
subst :: ASTF sym c -> ASTF sym c
subst :: ASTF sym c -> ASTF sym c
subst ASTF sym c
a
| Just ASTF sym c
y' <- CodeMotionInterface sym
-> ASTF sym a -> ASTF sym c -> Maybe (ASTF sym c)
forall (sym :: * -> *).
CodeMotionInterface sym
-> forall a b. ASTF sym a -> ASTF sym b -> Maybe (ASTF sym b)
castExprCM CodeMotionInterface sym
iface ASTF sym a
y ASTF sym c
a, ASTF sym a -> ASTF sym c -> Bool
forall (sym :: * -> *) a b.
(Equality sym, BindingDomain sym) =>
ASTF sym a -> ASTF sym b -> Bool
alphaEq ASTF sym a
x ASTF sym c
a = ASTF sym c
y'
| Bool
otherwise = ASTF sym c -> ASTF sym c
forall c. AST sym c -> AST sym c
subst' ASTF sym c
a
subst' :: AST sym c -> AST sym c
subst' :: AST sym c -> AST sym c
subst' a :: AST sym c
a@(AST sym (a :-> c)
lam :$ AST sym (Full a)
body)
| Just Name
v <- AST sym (a :-> c) -> Maybe Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
sym sig -> Maybe Name
prLam AST sym (a :-> c)
lam
, Name -> Set Name -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Name
v Set Name
fv = AST sym c
a
subst' (AST sym (a :-> c)
s :$ AST sym (Full a)
a) = AST sym (a :-> c) -> AST sym (a :-> c)
forall c. AST sym c -> AST sym c
subst' AST sym (a :-> c)
s AST sym (a :-> c) -> AST sym (Full a) -> AST sym c
forall (sym :: * -> *) a sig.
AST sym (a :-> sig) -> AST sym (Full a) -> AST sym sig
:$ AST sym (Full a) -> AST sym (Full a)
forall c. ASTF sym c -> ASTF sym c
subst AST sym (Full a)
a
subst' AST sym c
a = AST sym c
a
count :: forall sym a b
. (Equality sym, BindingDomain sym)
=> ASTF sym a
-> ASTF sym b
-> Int
count :: ASTF sym a -> ASTF sym b -> Int
count ASTF sym a
a ASTF sym b
b = ASTF sym b -> Int
forall c. ASTF sym c -> Int
cnt ASTF sym b
b
where
fv :: Set Name
fv = ASTF sym a -> Set Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
AST sym sig -> Set Name
freeVars ASTF sym a
a
cnt :: ASTF sym c -> Int
cnt :: ASTF sym c -> Int
cnt ASTF sym c
c
| ASTF sym a -> ASTF sym c -> Bool
forall (sym :: * -> *) a b.
(Equality sym, BindingDomain sym) =>
ASTF sym a -> ASTF sym b -> Bool
alphaEq ASTF sym a
a ASTF sym c
c = Int
1
| Bool
otherwise = ASTF sym c -> Int
forall sig. AST sym sig -> Int
cnt' ASTF sym c
c
cnt' :: AST sym sig -> Int
cnt' :: AST sym sig -> Int
cnt' (AST sym (a :-> sig)
lam :$ AST sym (Full a)
body)
| Just Name
v <- AST sym (a :-> sig) -> Maybe Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
sym sig -> Maybe Name
prLam AST sym (a :-> sig)
lam
, Name -> Set Name -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member Name
v Set Name
fv = Int
0
cnt' (AST sym (a :-> sig)
s :$ AST sym (Full a)
c) = AST sym (a :-> sig) -> Int
forall sig. AST sym sig -> Int
cnt' AST sym (a :-> sig)
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ AST sym (Full a) -> Int
forall c. ASTF sym c -> Int
cnt AST sym (Full a)
c
cnt' AST sym sig
_ = Int
0
data Env sym = Env
{ Env sym -> Bool
inLambda :: Bool
, Env sym -> EF (AST sym) -> Int
counter :: EF (AST sym) -> Int
, Env sym -> Set Name
dependencies :: Set Name
}
liftable :: BindingDomain sym => Env sym -> ASTF sym a -> Bool
liftable :: Env sym -> ASTF sym a -> Bool
liftable Env sym
env ASTF sym a
a = Bool
independent Bool -> Bool -> Bool
&& Maybe Name -> Bool
forall a. Maybe a -> Bool
isNothing (ASTF sym a -> Maybe Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
sym sig -> Maybe Name
prVar ASTF sym a
a) Bool -> Bool -> Bool
&& Bool
heuristic
where
independent :: Bool
independent = Set Name -> Bool
forall a. Set a -> Bool
Set.null (Set Name -> Bool) -> Set Name -> Bool
forall a b. (a -> b) -> a -> b
$ Set Name -> Set Name -> Set Name
forall a. Ord a => Set a -> Set a -> Set a
Set.intersection (ASTF sym a -> Set Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
AST sym sig -> Set Name
freeVars ASTF sym a
a) (Env sym -> Set Name
forall (sym :: * -> *). Env sym -> Set Name
dependencies Env sym
env)
heuristic :: Bool
heuristic = Env sym -> Bool
forall (sym :: * -> *). Env sym -> Bool
inLambda Env sym
env Bool -> Bool -> Bool
|| (Env sym -> EF (AST sym) -> Int
forall (sym :: * -> *). Env sym -> EF (AST sym) -> Int
counter Env sym
env (ASTF sym a -> EF (AST sym)
forall (e :: * -> *) a. e (Full a) -> EF e
EF ASTF sym a
a) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
1)
data Chosen sym a
where
Chosen :: InjDict sym b a -> ASTF sym b -> Chosen sym a
choose :: forall sym a
. (Equality sym, BindingDomain sym)
=> CodeMotionInterface sym
-> ASTF sym a
-> Maybe (Chosen sym a)
choose :: CodeMotionInterface sym -> ASTF sym a -> Maybe (Chosen sym a)
choose CodeMotionInterface sym
iface ASTF sym a
a = Env sym -> ASTF sym a -> Maybe (Chosen sym a)
forall b. Env sym -> AST sym b -> Maybe (Chosen sym a)
chooseEnvSub Env sym
initEnv ASTF sym a
a
where
initEnv :: Env sym
initEnv = Env :: forall (sym :: * -> *).
Bool -> (EF (AST sym) -> Int) -> Set Name -> Env sym
Env
{ inLambda :: Bool
inLambda = Bool
False
, counter :: EF (AST sym) -> Int
counter = \(EF AST sym (Full a)
b) -> AST sym (Full a) -> ASTF sym a -> Int
forall (sym :: * -> *) a b.
(Equality sym, BindingDomain sym) =>
ASTF sym a -> ASTF sym b -> Int
count AST sym (Full a)
b ASTF sym a
a
, dependencies :: Set Name
dependencies = Set Name
forall a. Set a
Set.empty
}
chooseEnv :: Env sym -> ASTF sym b -> Maybe (Chosen sym a)
chooseEnv :: Env sym -> ASTF sym b -> Maybe (Chosen sym a)
chooseEnv Env sym
env ASTF sym b
b
| Env sym -> ASTF sym b -> Bool
forall (sym :: * -> *) a.
BindingDomain sym =>
Env sym -> ASTF sym a -> Bool
liftable Env sym
env ASTF sym b
b
, Just InjDict sym b a
id <- CodeMotionInterface sym
-> ASTF sym b -> ASTF sym a -> Maybe (InjDict sym b a)
forall (sym :: * -> *).
CodeMotionInterface sym
-> forall a b. ASTF sym a -> ASTF sym b -> Maybe (InjDict sym a b)
mkInjDict CodeMotionInterface sym
iface ASTF sym b
b ASTF sym a
a
= Chosen sym a -> Maybe (Chosen sym a)
forall a. a -> Maybe a
Just (Chosen sym a -> Maybe (Chosen sym a))
-> Chosen sym a -> Maybe (Chosen sym a)
forall a b. (a -> b) -> a -> b
$ InjDict sym b a -> ASTF sym b -> Chosen sym a
forall (sym :: * -> *) b a.
InjDict sym b a -> ASTF sym b -> Chosen sym a
Chosen InjDict sym b a
id ASTF sym b
b
chooseEnv Env sym
env ASTF sym b
b
| CodeMotionInterface sym -> ASTF sym b -> Bool
forall (sym :: * -> *).
CodeMotionInterface sym -> forall c. ASTF sym c -> Bool
hoistOver CodeMotionInterface sym
iface ASTF sym b
b = Env sym -> ASTF sym b -> Maybe (Chosen sym a)
forall b. Env sym -> AST sym b -> Maybe (Chosen sym a)
chooseEnvSub Env sym
env ASTF sym b
b
| Bool
otherwise = Maybe (Chosen sym a)
forall a. Maybe a
Nothing
chooseEnvSub :: Env sym -> AST sym b -> Maybe (Chosen sym a)
chooseEnvSub :: Env sym -> AST sym b -> Maybe (Chosen sym a)
chooseEnvSub Env sym
env (Sym sym (a :-> b)
lam :$ AST sym (Full a)
b)
| Just Name
v <- sym (a :-> b) -> Maybe Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
sym sig -> Maybe Name
prLam sym (a :-> b)
lam
= Env sym -> AST sym (Full a) -> Maybe (Chosen sym a)
forall b. Env sym -> ASTF sym b -> Maybe (Chosen sym a)
chooseEnv (Name -> Env sym
env' Name
v) AST sym (Full a)
b
where
env' :: Name -> Env sym
env' Name
v = Env sym
env
{ inLambda :: Bool
inLambda = Bool
True
, dependencies :: Set Name
dependencies = Name -> Set Name -> Set Name
forall a. Ord a => a -> Set a -> Set a
Set.insert Name
v (Env sym -> Set Name
forall (sym :: * -> *). Env sym -> Set Name
dependencies Env sym
env)
}
chooseEnvSub Env sym
env (AST sym (a :-> b)
s :$ AST sym (Full a)
b) = Env sym -> AST sym (a :-> b) -> Maybe (Chosen sym a)
forall b. Env sym -> AST sym b -> Maybe (Chosen sym a)
chooseEnvSub Env sym
env AST sym (a :-> b)
s Maybe (Chosen sym a)
-> Maybe (Chosen sym a) -> Maybe (Chosen sym a)
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` Env sym -> AST sym (Full a) -> Maybe (Chosen sym a)
forall b. Env sym -> ASTF sym b -> Maybe (Chosen sym a)
chooseEnv Env sym
env AST sym (Full a)
b
chooseEnvSub Env sym
_ AST sym b
_ = Maybe (Chosen sym a)
forall a. Maybe a
Nothing
codeMotionM :: forall sym m a
. ( Equality sym
, BindingDomain sym
, MonadState Name m
)
=> CodeMotionInterface sym
-> ASTF sym a
-> m (ASTF sym a)
codeMotionM :: CodeMotionInterface sym -> ASTF sym a -> m (ASTF sym a)
codeMotionM CodeMotionInterface sym
iface ASTF sym a
a
| Just (Chosen InjDict sym b a
id ASTF sym b
b) <- CodeMotionInterface sym -> ASTF sym a -> Maybe (Chosen sym a)
forall (sym :: * -> *) a.
(Equality sym, BindingDomain sym) =>
CodeMotionInterface sym -> ASTF sym a -> Maybe (Chosen sym a)
choose CodeMotionInterface sym
iface ASTF sym a
a = InjDict sym b a -> ASTF sym b -> m (ASTF sym a)
forall b. InjDict sym b a -> ASTF sym b -> m (ASTF sym a)
share InjDict sym b a
id ASTF sym b
b
| Bool
otherwise = ASTF sym a -> m (ASTF sym a)
forall b. AST sym b -> m (AST sym b)
descend ASTF sym a
a
where
share :: InjDict sym b a -> ASTF sym b -> m (ASTF sym a)
share :: InjDict sym b a -> ASTF sym b -> m (ASTF sym a)
share InjDict sym b a
id ASTF sym b
b = do
ASTF sym b
b' <- CodeMotionInterface sym -> ASTF sym b -> m (ASTF sym b)
forall (sym :: * -> *) (m :: * -> *) a.
(Equality sym, BindingDomain sym, MonadState Name m) =>
CodeMotionInterface sym -> ASTF sym a -> m (ASTF sym a)
codeMotionM CodeMotionInterface sym
iface ASTF sym b
b
Name
v <- m Name
forall s (m :: * -> *). MonadState s m => m s
get; Name -> m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (Name
vName -> Name -> Name
forall a. Num a => a -> a -> a
+Name
1)
let x :: ASTF sym b
x = sym (Full b) -> ASTF sym b
forall (sym :: * -> *) sig. sym sig -> AST sym sig
Sym (InjDict sym b a -> Name -> sym (Full b)
forall (sym :: * -> *) a b. InjDict sym a b -> Name -> sym (Full a)
injVariable InjDict sym b a
id Name
v)
ASTF sym a
body <- CodeMotionInterface sym -> ASTF sym a -> m (ASTF sym a)
forall (sym :: * -> *) (m :: * -> *) a.
(Equality sym, BindingDomain sym, MonadState Name m) =>
CodeMotionInterface sym -> ASTF sym a -> m (ASTF sym a)
codeMotionM CodeMotionInterface sym
iface (ASTF sym a -> m (ASTF sym a)) -> ASTF sym a -> m (ASTF sym a)
forall a b. (a -> b) -> a -> b
$ CodeMotionInterface sym
-> ASTF sym b -> ASTF sym b -> ASTF sym a -> ASTF sym a
forall (sym :: * -> *) a b.
(Equality sym, BindingDomain sym) =>
CodeMotionInterface sym
-> ASTF sym a -> ASTF sym a -> ASTF sym b -> ASTF sym b
substitute CodeMotionInterface sym
iface ASTF sym b
b ASTF sym b
x ASTF sym a
a
ASTF sym a -> m (ASTF sym a)
forall (m :: * -> *) a. Monad m => a -> m a
return
(ASTF sym a -> m (ASTF sym a)) -> ASTF sym a -> m (ASTF sym a)
forall a b. (a -> b) -> a -> b
$ sym (b :-> ((b -> a) :-> Full a))
-> AST sym (b :-> ((b -> a) :-> Full a))
forall (sym :: * -> *) sig. sym sig -> AST sym sig
Sym (InjDict sym b a -> sym (b :-> ((b -> a) :-> Full a))
forall (sym :: * -> *) a b.
InjDict sym a b -> sym (a :-> ((a -> b) :-> Full b))
injLet InjDict sym b a
id)
AST sym (b :-> ((b -> a) :-> Full a))
-> ASTF sym b -> AST sym ((b -> a) :-> Full a)
forall (sym :: * -> *) a sig.
AST sym (a :-> sig) -> AST sym (Full a) -> AST sym sig
:$ ASTF sym b
b'
AST sym ((b -> a) :-> Full a)
-> AST sym (Full (b -> a)) -> ASTF sym a
forall (sym :: * -> *) a sig.
AST sym (a :-> sig) -> AST sym (Full a) -> AST sym sig
:$ (sym (a :-> Full (b -> a)) -> AST sym (a :-> Full (b -> a))
forall (sym :: * -> *) sig. sym sig -> AST sym sig
Sym (InjDict sym b a -> Name -> sym (a :-> Full (b -> a))
forall (sym :: * -> *) a b.
InjDict sym a b -> Name -> sym (b :-> Full (a -> b))
injLambda InjDict sym b a
id Name
v) AST sym (a :-> Full (b -> a))
-> ASTF sym a -> AST sym (Full (b -> a))
forall (sym :: * -> *) a sig.
AST sym (a :-> sig) -> AST sym (Full a) -> AST sym sig
:$ ASTF sym a
body)
descend :: AST sym b -> m (AST sym b)
descend :: AST sym b -> m (AST sym b)
descend (AST sym (a :-> b)
s :$ AST sym (Full a)
a) = (AST sym (a :-> b) -> AST sym (Full a) -> AST sym b)
-> m (AST sym (a :-> b)) -> m (AST sym (Full a)) -> m (AST sym b)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 AST sym (a :-> b) -> AST sym (Full a) -> AST sym b
forall (sym :: * -> *) a sig.
AST sym (a :-> sig) -> AST sym (Full a) -> AST sym sig
(:$) (AST sym (a :-> b) -> m (AST sym (a :-> b))
forall b. AST sym b -> m (AST sym b)
descend AST sym (a :-> b)
s) (CodeMotionInterface sym -> AST sym (Full a) -> m (AST sym (Full a))
forall (sym :: * -> *) (m :: * -> *) a.
(Equality sym, BindingDomain sym, MonadState Name m) =>
CodeMotionInterface sym -> ASTF sym a -> m (ASTF sym a)
codeMotionM CodeMotionInterface sym
iface AST sym (Full a)
a)
descend AST sym b
a = AST sym b -> m (AST sym b)
forall (m :: * -> *) a. Monad m => a -> m a
return AST sym b
a
codeMotion :: forall sym m a
. ( Equality sym
, BindingDomain sym
)
=> CodeMotionInterface sym
-> ASTF sym a
-> ASTF sym a
codeMotion :: CodeMotionInterface sym -> ASTF sym a -> ASTF sym a
codeMotion CodeMotionInterface sym
iface ASTF sym a
a = (State Name (ASTF sym a) -> Name -> ASTF sym a)
-> Name -> State Name (ASTF sym a) -> ASTF sym a
forall a b c. (a -> b -> c) -> b -> a -> c
flip State Name (ASTF sym a) -> Name -> ASTF sym a
forall s a. State s a -> s -> a
evalState Name
maxVar (State Name (ASTF sym a) -> ASTF sym a)
-> State Name (ASTF sym a) -> ASTF sym a
forall a b. (a -> b) -> a -> b
$ CodeMotionInterface sym -> ASTF sym a -> State Name (ASTF sym a)
forall (sym :: * -> *) (m :: * -> *) a.
(Equality sym, BindingDomain sym, MonadState Name m) =>
CodeMotionInterface sym -> ASTF sym a -> m (ASTF sym a)
codeMotionM CodeMotionInterface sym
iface ASTF sym a
a
where
maxVar :: Name
maxVar = Name -> Name
forall a. Enum a => a -> a
succ (Name -> Name) -> Name -> Name
forall a b. (a -> b) -> a -> b
$ Set Name -> Name
forall a. Set a -> a
Set.findMax (Set Name -> Name) -> Set Name -> Name
forall a b. (a -> b) -> a -> b
$ Name -> Set Name -> Set Name
forall a. Ord a => a -> Set a -> Set a
Set.insert Name
0 (Set Name -> Set Name) -> Set Name -> Set Name
forall a b. (a -> b) -> a -> b
$ ASTF sym a -> Set Name
forall (sym :: * -> *) sig.
BindingDomain sym =>
AST sym sig -> Set Name
allVars ASTF sym a
a