ddc-core-0.3.1.1: DDC/Core/Collect/Free.hs
-- | Collecting sets of variables and constructors.
module DDC.Core.Collect.Free
(freeX)
where
import DDC.Type.Collect
import DDC.Type.Compounds
import DDC.Core.Module
import DDC.Core.Exp
import DDC.Type.Env (Env)
import qualified DDC.Type.Env as Env
import qualified Data.Set as Set
import Data.Set (Set)
-- freeX ----------------------------------------------------------------------
-- | Collect the free Data and Witness variables in a thing (level-0).
freeX :: (BindStruct c, Ord n)
=> Env n -> c n -> Set (Bound n)
freeX tenv xx = Set.unions $ map (freeOfTreeX tenv) $ slurpBindTree xx
freeOfTreeX :: Ord n => Env n -> BindTree n -> Set (Bound n)
freeOfTreeX tenv tt
= {-# SCC freeOfTreeX #-}
case tt of
BindDef way bs ts
| isBoundExpWit $ boundLevelOfBindWay way
, tenv' <- Env.extends bs tenv
-> Set.unions $ map (freeOfTreeX tenv') ts
BindDef _ _ ts
-> Set.unions $ map (freeOfTreeX tenv) ts
BindUse bl u
| isBoundExpWit bl
, Env.member u tenv -> Set.empty
| isBoundExpWit bl -> Set.singleton u
_ -> Set.empty
-- Module ---------------------------------------------------------------------
instance BindStruct (Module a) where
slurpBindTree mm
= slurpBindTree $ moduleBody mm
-- Exp ------------------------------------------------------------------------
instance BindStruct (Exp a) where
slurpBindTree xx
= case xx of
XVar _ u
-> [BindUse BoundExp u]
XCon _ dc
-> case daConName dc of
DaConUnit -> []
DaConNamed n -> [BindCon BoundExp (UName n) Nothing]
XApp _ x1 x2 -> slurpBindTree x1 ++ slurpBindTree x2
XLAM _ b x -> [bindDefT BindLAM [b] [x]]
XLam _ b x -> [bindDefX BindLam [b] [x]]
XLet _ (LLet m b x1) x2
-> slurpBindTree m
++ slurpBindTree x1
++ [bindDefX BindLet [b] [x2]]
XLet _ (LRec bxs) x2
-> [bindDefX BindLetRec
(map fst bxs)
(map snd bxs ++ [x2])]
XLet _ (LLetRegions b bs) x2
-> [ BindDef BindLetRegions b
[bindDefX BindLetRegionWith bs [x2]]]
XLet _ (LWithRegion u) x2
-> BindUse BoundExp u : slurpBindTree x2
XCase _ x alts -> slurpBindTree x ++ concatMap slurpBindTree alts
XCast _ c x -> slurpBindTree c ++ slurpBindTree x
XType t -> slurpBindTree t
XWitness w -> slurpBindTree w
instance BindStruct LetMode where
slurpBindTree mode
= case mode of
LetStrict -> []
LetLazy Nothing -> []
LetLazy (Just ww) -> slurpBindTree ww
instance BindStruct (Cast a) where
slurpBindTree cc
= case cc of
CastWeakenEffect eff -> slurpBindTree eff
CastWeakenClosure xs -> concatMap slurpBindTree xs
CastPurify w -> slurpBindTree w
CastForget w -> slurpBindTree w
instance BindStruct (Alt a) where
slurpBindTree alt
= case alt of
AAlt PDefault x
-> slurpBindTree x
AAlt (PData _ bs) x
-> [bindDefX BindCasePat bs [x]]
instance BindStruct Witness where
slurpBindTree ww
= case ww of
WVar u -> [BindUse BoundWit u]
WCon{} -> []
WApp w1 w2 -> slurpBindTree w1 ++ slurpBindTree w2
WJoin w1 w2 -> slurpBindTree w1 ++ slurpBindTree w2
WType t -> slurpBindTree t
-- | Helper for constructing the `BindTree` for an expression or witness binder.
bindDefX :: BindStruct c
=> BindWay -> [Bind n] -> [c n] -> BindTree n
bindDefX way bs xs
= BindDef way bs
$ concatMap (slurpBindTree . typeOfBind) bs
++ concatMap slurpBindTree xs