{-# LANGUAGE OverloadedLists #-}
module Core.Free where

import qualified Data.Set as S
import Data.Set ((\\))
import Data.Monoid ((<>), mconcat)

import Core.Core

type StringSet = S.Set String

bv :: Pat -> StringSet
bv Wildcard = []
bv PLit{}   = []
bv (Capture x) = [x]
bv (Bound x p) = [x] <> bv p
bv (PList xs) = mconcat $ map bv xs
bv (Constructor _ _ xs) = mconcat $ map bv xs
bv (Cons x y) = bv x <> bv y

fv :: Expression -> StringSet
fv (Lambda p e)  = fv e \\ bv p
fv (Var x)       = [x]
fv (If c t e)    = fv c <> fv t <> fv e
fv (List xs)     = mconcat $ map fv xs
fv (Case ca e)   = mconcat (map fv' ca) <> fv e
  where fv' (CaseArm p e) = fv e \\ bv p

fv (Let p e b)   = (fv b \\ bv p) <> fv e
fv (BinOp o r l) = fv o <> fv r <> fv l
fv Literal{}     = []
fv Unbox{}       = []
fv (Apply x y)   = fv x <> fv y
